uni-app canvasToTempFilePath 第一次显示不全
uni-app canvasToTempFilePath 第一次显示不全
| 项目 | 内容 |
|---|---|
| 产品分类 | uniapp/App |
| PC开发环境操作系统 | Windows |
| PC开发环境操作系统版本号 | windows 10 |
| HBuilderX类型 | 正式 |
| HBuilderX版本号 | 3.3.11 |
| 手机系统 | Android |
| 手机系统版本号 | Android 10 |
| 手机厂商 | 华为 |
| 手机机型 | mater 10 |
| 页面类型 | vue |
| vue版本 | vue2 |
| 打包方式 | 云端 |
| 项目创建方式 | HBuilderX |
示例代码:
<template>
<view class="content">
<button @click="chooseImage" type="primary">选择图片</button>
<image :src="imgUrl" mode="scaleToFill"></image>
<view class="inputBox">
<input type="text" placeholder="输入水印文字" v-model="text" />
<view style="width: 10px;"></view>
<button type="default" size="mini" @click="createWatermark">生成图片</button>
</view>
<canvas style="border: 1px solid green;position: absolute;left: -5000px;" :style="{'width':w,'height': h}"
canvas-id="myCanvas" ref="mycanvas"></canvas>
<image :src="newImage" mode="scaleToFill" @click="previewImage"></image>
</view>
</template>
<script>
import watermark from '../../common/warterMark.js'
export default {
data() {
return {
imgUrl: "",
newImage: "",
text: '',
w: 100,
h: 100
}
},
onLoad() {
},
methods: {
chooseImage() {
uni.chooseImage({
count: 1,
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
this.imgUrl = tempFilePaths[0]
}
})
},
createWatermark() {
if (!this.imgUrl) {
uni.showToast({
title: '请选择图片',
icon: "error"
});
return
}
if (!this.text) {
uni.showToast({
title: '请输入水印文字',
icon: "error"
});
return
}
this.newImage = ''
let date = this.text;
let that = this;
uni.showLoading({
title: "生成中..."
})
uni.getImageInfo({
src: this.imgUrl,
success: (res) => {
that.w = res.width + 'px';
that.h = res.height + 'px';
let ctx = uni.createCanvasContext('myCanvas')
//初始化画布
ctx.fillRect(0, 0, that.w, that.h);
ctx.drawImage(that.imgUrl, 0, 0, res.width, res.height);
ctx.setFontSize(40);
ctx.setFillStyle("rgba(255,255,255,.6)");
ctx.fillText(date, 40, 50);
ctx.draw(false, () => {
setTimeout(() => {
uni.canvasToTempFilePath({
fileType: 'jpg', // 保存成的文件类型
quality: 0.75, // 图片质量
canvasId: 'myCanvas',
success: (res) => {
console.log(res.tempFilePath);
that.newImage = res.tempFilePath
},
complete() {
uni.hideLoading()
},
fail: (err) => {
uni.showModal({
content: err
})
}
})
}, 100)
})
},
fail: (err) => {
uni.showModal({
title: '',
content: err,
showCancel: false,
cancelText: '',
confirmText: '',
});
}
})
},
previewImage() {
if (this.newImage) {
uni.previewImage({
urls: [this.newImage]
})
}
}
}
}
</script>
<style lang="scss">
.content {
padding: 10px;
display: flex;
flex-direction: column;
flex: 1;
padding-top: 30px;
button {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
}
image {
width: 100%;
min-height: 200rpx;
border: 1px solid #eee;
}
.inputBox {
display: flex;
align-items: center;
height: 100rpx;
input {
border: 1px solid #eee;
padding: 5rpx 20rpx;
flex: 1;
height: 50rpx;
font-size: 26rpx !important;
}
button {
margin-top: 10 !important;
width: 200rpx;
}
}
}
</style>
更多关于uni-app canvasToTempFilePath 第一次显示不全的实战教程也可以访问 https://www.itying.com/category-93-b0.html
3 回复
已验证,andorid版本确实存在,ios没有问题
更多关于uni-app canvasToTempFilePath 第一次显示不全的实战教程也可以访问 https://www.itying.com/category-93-b0.html
看了你的代码,是如下错误用法导致:
依赖 canvas 大小的操作,在 canvas 大小更改未完成之时进行,出现了不确定性。
正确用法:
在 canvas 大小修改成功之后进行操作:
that.w = res.width + ‘px’;
that.h = res.height + ‘px’;
that.$nextTick(function() {
…这里写依赖变更后大小的其他操作
…另外draw内的setTimeout不需要
})
相关知识点:
修改数据并不能同步修改视图
修改 canvas 大小会导致 canvas 上绘制内容清空(不过框架会自动恢复之前的内容)
根本原因是 canvas 组件的实际渲染尺寸与样式尺寸不一致,且绘图未完成时过早调用了 canvasToTempFilePath。
- 错误:canvas 标签只设置了
style的宽高(如'100px'),未设置width和height属性(纯数字)。组件默认宽高为 300×150,导致绘制内容按此尺寸渲染,但转换时取的是样式尺寸,造成截取不全。 - 错误:在
ctx.draw的回调中又嵌套setTimeout(100),延迟不可靠,且绘制可能尚未完全完成(Android 上首次绘制常有延迟)。
严格按以下方式修正即可:
- canvas 标签同时设置
width和height属性(纯数字),例如:<canvas canvas-id="myCanvas" :style="{'width': w + 'px', 'height': h + 'px'}" :width="res.width" :height="res.height"></canvas>

