vue实现上传图片添加水印

实现效果:可添加logo.(注:这里主要实现添加水印.图片上传用的vant的上传)

大致思路:
将上传的file文件转成base64(代码如下)

   const reader = new FileReader();
        reader.readAsDataURL(file);//file转base64

再将图片用canvas绘制添加文字logo:

            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            if (ctx == null) return
            const img = new Image();

            if (e.target == null) return
            img.src = e.target.result as string;

            img.onload = () => {
                let imgWidth = img.width;
                let imgHeight = img.height;
                canvas.width = imgWidth;//画布宽度
                canvas.height = imgHeight;//画布高度

                let imgurl = ""

                ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致
/**
这基础上在进行添加水印
具体看全代码
*/
.....
            }
<template>
    <div>
        <van-uploader :after-read="afterRead" />
         <!--  图片回显 -->
        <img :src="data.imgurl" alt="">
    </div>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
import { showToast } from 'vant';
import { onMounted, defineProps } from 'vue';
const props = defineProps({
    //logo图
    logoUrl: {
        type: String,
        default: require('@/assets/panda.png'),
        required: false
    },
    options: {
        type: Object,
        default() {
            return {
                imgurlTop: 0
            }
        },
        required: false
    },
    title: {
        type: String,// 如果可能存在多个类型,则可以写成 [String,Number]
        default: '限定制作',
        required: false// 是否必传 ,在不声明为true 的情况下,所有prop 默认为非必填。
    }
})
let data = reactive({
    imgurl: "",
    newimg: props.logoUrl
});
onMounted(() => {
    console.log("_++++_", props.title, props.options)
})
const afterRead = (file: any) => {
    // 此时可以自行将文件上传至服务器
    showToast('上传成功!');
    // data.imgurl = file.content;
    watermark(file.file).then(res => {

        data.imgurl = res as string
    })
};


const getBase64Image = (src: string) => {
    return new Promise(resolve => {
        const img = new Image()
        img.crossOrigin = ''
        console.log(src)
        img.src = src
        img.onload = function () {
            const canvas = document.createElement('canvas')
            canvas.width = img.width
            canvas.height = img.height
            const ctx = canvas.getContext('2d')
            ctx?.drawImage(img, 0, 0, img.width, img.height)
            const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase()
            const dataURL = canvas.toDataURL('image/' + ext)
            resolve(dataURL)
        }
    })
}





const watermark = (file: any) => {

    return new Promise(resolve => {
        const reader = new FileReader();
        reader.readAsDataURL(file);//file转base64
        reader.onload = (e) => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            if (ctx == null) return
            const img = new Image();

            if (e.target == null) return
            img.src = e.target.result as string;

            img.onload = () => {

                let imgWidth = img.width;
                let imgHeight = img.height;
                // let fontsize = imgWidth > imgHeight ? imgHeight / 20 : imgWidth / 20;//设定文字大小随图片大小变化
                canvas.width = imgWidth;//画布宽度
                canvas.height = imgHeight;//画布高度


                let imgurl = ""

                ctx.drawImage(img, 0, 0, imgWidth, imgHeight);//绘制图片大小和先前图片一致

                /**
                 * 再添加logo图片
                 * as string 是 TypeScript 中的语法,用于将 data.newimg 强制转换为字符串类型。它告诉编译器将变量视为指定的类型,以便进行类型检查和代码补全等操作。
                 * 
                 * smallImg.setAttribute('crossOrigin', 'anonymous')解决图片跨域
                 */
                const smallImg = new Image();
                getBase64Image(data.newimg as string).then(res => {
                    smallImg.src = res as string
                })
                // // 
                smallImg.onload = () => {
                    console.log(smallImg.width, smallImg.height)
                    ctx.shadowOffsetX = 0;//用来设定阴影在 X轴的延伸距
                    ctx.shadowOffsetY = 0;//用来设定阴影在 Y轴的延伸距
                    //设置logo的位置
                    ctx.drawImage(smallImg, imgWidth - smallImg.width / 7, imgHeight - smallImg.height / 7, smallImg.width / 7, smallImg.height / 7);
                    let fontsize = smallImg.width > smallImg.height ? smallImg.height / 20 : smallImg.width / 20;//设定文字大小随图片大小变化
                    ctx.textBaseline = 'bottom';//水印对其的基准线
                    ctx.font = `${fontsize}px Verdana`;//文字大小     
                    ctx.shadowOffsetX = -1;//用来设定阴影在 X轴的延伸距
                    ctx.shadowOffsetY = -1;//用来设定阴影在 Y轴的延伸距
                    ctx.shadowBlur = 0;//设定阴影的模糊程度 默认0
                    ctx.shadowColor = "rgba(0, 0, 0, 0.95)";//设定阴影颜色效果
                    ctx.fillStyle = "#fff";//设置字体颜色
                    //修改文字的位置
                    ctx.fillText(props.title, imgWidth - ctx.measureText(props.title).width - smallImg.width / 7 - 10, imgHeight - 20);
                    imgurl = canvas.toDataURL(file.type); //输出压缩后的base64
                    resolve(imgurl)
                }


            }

        }
    })
}

</script>
<style lang="less" scoped></style>

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌寒1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值