uni-app小程序图片加水印;使用canvas上传图片加水印

1,653 阅读2分钟

微信小程序上传图片成功后要有带时间地点的水印,设置canvas输出大小会极大的提高uni.canvasToTempFilePath()方法的速度

<template>
    <view>
        <u-form :model="form" ref="uForm" border-bottom="false" label-width='auto'>
            <u-form-item label="水印照片:" label-position="top" prop="imgList">
                <view class="u-upload">
                    <view v-for="(photo,index) in photoData" class="u-list-item u-preview-wrap" :key="index"
                        style="width:160rpx,height:160rpx">
                        <view>
                            <view class="u-delete-icon" @tap.stop="deletePhoto(index)" style="background:#fa3534">
                                <u-icon class="u-icon" name="close" size="20" color="#ffffff"></u-icon>
                            </view>
                            <image class="u-preview-image" :src="photo" mode="aspectFill"
                                @click="previewPhoto(photo,index)">
                            </image>
                        </view>
                    </view>
                    <view style="display: inline-block;" @tap="btnAddPhoto">
                        <slot name="addBtn"></slot>
                        <view class="u-list-item u-add-wrap" hover-class="u-add-wrap__hover" hover-stay-time="150"
                            style="width:160rpx,height:160rpx">
                            <u-icon name="plus" class="u-add-btn" size="40"></u-icon>
                            <view class="u-add-tips">选择图片</view>
                        </view>
                    </view>
                    //控制显示
                    <view v-if="show">
                        <canvas :style="{width:canvasWidth,height:canvasHeight}" canvas-id="myCanvas"></canvas>
                    </view>
                </view>
            </u-form-item>
        </u-form>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                // 上传现场图片
                photoData: [],
                photoArray: [],
                canvasWidth: '',
                canvasHeight: '',
                show: false,
                photoIndex: 0,
                imgList: [],
                form: {
                    imgList: '',
                },
                // 上传域名
                action: '',
                formData: {},
                upFileName: "",
                // 设备高度
                sysInfoHeight: '',
                sysInfoWidth: '',
                imgUrl: ''
            }
        },
        methods: {
            // 获取地址
            async getAddress() {
                // 腾讯地图
                return new Promise((resolve, reject) => {
                    try {
                        let address = ''
                        uni.getLocation({
                            type: 'gcj02',
                            success(res) {
                                let latitude, longitude;
                                latitude = res.latitude.toString();
                                longitude = res.longitude.toString();
                                uni.request({
                                    header: {
                                        "Content-Type": "application/text"
                                    },
                                    url: 'https://apis.map.qq.com/ws/geocoder/v1/?location=' +
                                        latitude + ',' +
                                        longitude + '&key=XXX', //key为腾讯地图的提供的key
                                    success(re) {
                                        if (re.statusCode === 200) {
                                            address = re.data.result
                                            resolve(address)
                                        } else {
                                            reject("获取信息失败,请重试!")
                                        }
                                    }
                                });
                            }
                        });
                    } catch (e) {}
                })
            },
            // 上传图片
            // 添加图片事件
            btnAddPhoto() {
                this.photoIndex = 0;
                this.show = true
                let ctx = uni.createCanvasContext('myCanvas');
                uni.chooseImage({
                    count: 1, //一次只能上传一张
                    sourceType: ['album', 'camera'],
                    success: res => {
                        this.photoArray = res.tempFilePaths;
                        uni.showLoading({
                            title: "图片加载中..."
                        })
                        this.callAddWaterMart();
                    }
                })
            },
            // 调用添加水印的函数
            callAddWaterMart() {
                this.addWaterMark(() => {
                    if (this.photoIndex < this.photoArray.length - 1) {
                        this.photoIndex++;
                        this.callAddWaterMart()
                    } else {
                        uni.hideLoading()
                    }
                })
            },
            // 上传
            uploadImg(tempFilePath) {
                uni.uploadFile({
                    url: '上传域名',
                    filePath: tempFilePath,
                    name: 'file',
                    formData: {
                        'user': 'test'
                    },
                    success: (uploadFileRes) => {
                        this.show = false
                        this.imgList.push(JSON.parse(uploadFileRes.data).message)
                    },
                    fail: (err) => {}
                });
            },
            // 添加水印
            async addWaterMark(callback) {
                let res = await this.getAddress()
                let address = res.address
                uni.getImageInfo({
                    src: this.photoArray[this.photoIndex],
                    success: res => {
                        // 设置画布高度和宽度
                        this.canvasWidth = `${res.width}px`;
                        this.canvasHeight = `${res.height}px`;
                        //获取当前时间
                        let newDate = new Date();
                        let year = newDate.getFullYear() //年
                        let month = newDate.getMonth() + 1 //月
                        let day = newDate.getDate() //日
                        let hour = newDate.getHours()
                        let minute = newDate.getMinutes()
                        let second = newDate.getSeconds()
                        let roleNameInfo = '拍摄时间:' + year + '年' + month + '月' + day + '日 ' + hour + ':' +
                            minute + ':' + second
                        var ctx = uni.createCanvasContext('myCanvas');
                        ctx.clearRect(0, 0, res.width, res.height);
                        ctx.beginPath();
                        ctx.drawImage(this.photoArray[this.photoIndex], 0, 0, res.width, res.height);
                        // 为图片添加水印                
                        ctx.beginPath();
                        ctx.setFontSize(24); //水印字体大小
                        ctx.setFillStyle("rgba(255,255,255,0.5)"); //水印颜色
                        // 水印位置
                        ctx.fillText(address, 60, res.height - 90);
                        ctx.fillText(roleNameInfo, 60, res.height - 60);
                        // 开始绘制添加水印的图片并显示在页面中
                        ctx.draw(false, () => {
                            setTimeout(() => {
                                uni.canvasToTempFilePath({
                                    canvasId: "myCanvas",
                                    // 设置输出的图片的宽度高度,会加快输出图片时间
                                    destWidth: this.sysInfoWidth,
                                    destHeight: this.sysInfoHeight,
                                    fileType: 'jpg', //jpg为了压缩
                                    quality: 0.8, //图片的质量
                                    success: res => {
                                        this.photoData.push(res.tempFilePath);
                                        this.uploadImg(res.tempFilePath)
                                        callback();
                                    },
                                    fail: (err) => {
                                        uni.hideLoading()
                                        this.$u.toast("上传错误")
                                    }
                                })
                            }, 500)
                        });
                    },
                    fail: (err) => {
                        console.log(err)
                    }
                })
            },
            // 预览图片
            previewPhoto(url, index) {
                uni.previewImage({
                    current: url,
                    urls: this.photoData.map(item => item)
                })
            },
            // 删除图片
            deletePhoto(index) {
                this.photoArray.splice(index, 1);
                this.photoData.splice(index, 1);
                this.imgList.splice(index, 1);
            },
        },
        async onLoad(e) {
            this.imgUrl = '图片上传位置路径'
            // 获取设备系统信息
            uni.getSystemInfo({
                success: (res) => {
                    this.sysInfoWidth = `${res.screenWidth}px`
                    this.sysInfoHeight = `${res.screenHeight}px`
                },
                fail: (err) => {}
            });
        }
    }
</script>

<style lang="scss" scoped>
    canvas {
        border: solid 1px gray;
        position: absolute;
        top: -5000px;
        z-index: -1
    }

    .u-upload {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
    }

    .u-list-item {
        width: 160rpx;
        height: 160rpx;
        overflow: hidden;
        margin: 10rpx;
        background: rgb(244, 245, 246);
        position: relative;
        border-radius: 10rpx;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .u-add-wrap {
        flex-direction: column;
        color: $u-content-color;
        font-size: 26rpx;
    }

    .u-add-tips {
        margin-top: 20rpx;
        line-height: 40rpx;
    }

    .u-add-wrap__hover {
        background-color: rgb(235, 236, 238);
    }

    .u-preview-wrap {
        border: 1px solid rgb(235, 236, 238);
    }

    .u-preview-image {
        display: block;
        width: 160rpx;
        height: 160rpx;
        border-radius: 10rpx;
    }

    .u-icon {
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }


    .u-delete-icon {
        position: absolute;
        top: 10rpx;
        right: 10rpx;
        z-index: 10;
        background-color: $u-type-error;
        border-radius: 100rpx;
        width: 44rpx;
        height: 44rpx;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }
</style>
```
```