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'),未设置 widthheight 属性(纯数字)。组件默认宽高为 300×150,导致绘制内容按此尺寸渲染,但转换时取的是样式尺寸,造成截取不全。
  • 错误:在 ctx.draw 的回调中又嵌套 setTimeout(100),延迟不可靠,且绘制可能尚未完全完成(Android 上首次绘制常有延迟)。

严格按以下方式修正即可:

  1. canvas 标签同时设置 widthheight 属性(纯数字),例如:
    <canvas canvas-id="myCanvas" :style="{'width': w + 'px', 'height': h + 'px'}" 
           :width="res.width" :height="res.height"></canvas>
回到顶部