欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue+vant實現(xiàn)圖片上傳添加水印

 更新時間:2025年02月11日 10:01:16   作者:愛敲代碼的小冰  
這篇文章主要為大家詳細(xì)介紹了Vue+vant實現(xiàn)圖片上傳添加水印功能,文中的示例代碼簡潔易懂,具有一定的借鑒價值,感興趣的小伙伴可以了解下

圖片上傳大家都不會陌生,就算是一個新人也會干的事兒。但說到加水印,當(dāng)初我一直以為只能是在后端實現(xiàn)。

原來,在前端也是能實現(xiàn)圖片上傳加水印的。(注:以下的代碼都來自于網(wǎng)絡(luò),只是我把兩部份代碼合在一起來實現(xiàn)我的需求而已,在最后面,我也會附上原作者的接,大家都不容易)

【注:我自己寫的注釋后面會有個"(小冰)",其他的為原作者的注釋】

<van-uploader v-model="fileList" multiple:after-read="afterRead"/>
data(){
    fileList:[], //vant中圖片上傳的雙向邦定(小冰)
    wmConfig : { //用于水印的東西,下面會用到 (小冰)
        font: "microsoft yahei", //字體
        textArray: ['張三','2021/11/26 16:44'],//水印文本內(nèi)容,允許數(shù)組最大長度3 即:3行水印
        density: 3  //密度 建議取值范圍1-5   值越大,水印越多,可能會導(dǎo)致水印重疊等問題,慎重?。?!
    }
}
methods:{
    //dataURLtoBlob 、 blobToFile 兩個方法的意思是把base64的圖片轉(zhuǎn)換成file文件
    //1,先將base64轉(zhuǎn)換為blob
    dataURLtoBlob(dataurl) {
        var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: mime });
    },
    //2,再將blob轉(zhuǎn)換為file
    blobToFile(theBlob, fileName){
        theBlob.lastModifiedDate = new Date();  // 文件最后的修改日期
        theBlob.name = fileName;                // 文件名
        return new File([theBlob], fileName, {type: theBlob.type, lastModified: Date.now()});
    },


    //這個不多說,都懂,文件上傳的方法(小冰)
    async afterRead(file){
        console.log(file)
        let base64 = file.content;
        let res = await this.base64AddWaterMaker(base64,this.wmConfig) //加水印的重點就是這個(小冰)
        file.content = res;
        let blob =  this.dataURLtoBlob(file.content);
        // 拿到文件名
        let fileName = file.file.name;
        // 2,在轉(zhuǎn)為 file類型
        let file1 = this.blobToFile(blob,fileName);
        console.log("file1:",file1);
    },


    base64AddWaterMaker  (base64Img, wmConfig)  {
        let that = this;
        if (wmConfig.textArray.length === 0) {
            console.error("****沒有水印內(nèi)容*****");
            return base64Img;
        }
        return new Promise((resolve, reject) => {
            const canvas = document.createElement("canvas");
            const ctx = canvas.getContext("2d");
            const img = new Image();
            let resultBase64 = null;
            img.onload = function() {
                canvas.width = img.width;
                canvas.height = img.height;
                //canvas繪制圖片,0 0  為左上角坐標(biāo)原點
                ctx.drawImage(img, 0, 0);
                //寫入水印
                that.drawWaterMark(ctx, img.width, img.height, wmConfig);
                resultBase64 = canvas.toDataURL("image/png");
                if (!resultBase64) {
                    reject();
                } else {
                    resolve(resultBase64);
                }
            };
            img.src = base64Img;
        });

    },
    
    drawWaterMark  (ctx, imgWidth, imgHeight, wmConfig)  {
        let fontSize;
        if (imgWidth >= 3456) {
            fontSize = 50;
        } else if (imgWidth >= 2700) {
            fontSize = 30;
        } else if (imgWidth >= 2000) {
            fontSize = 26;
        } else if (imgWidth >= 1436) {
            fontSize = 20;
        } else if (imgWidth >= 800) {
            fontSize = 12;
        } else if (imgWidth >= 500) {
            fontSize = 10;
        } else {
            fontSize = 8;
        }
        console.log(imgWidth, imgHeight, fontSize);
        ctx.fillStyle = "white";
        ctx.font = `${fontSize}px ${wmConfig.font}`;
        ctx.lineWidth = 1;
        ctx.fillStyle = "rgba(255,255,255,1)";
        ctx.textAlign = "left";
        ctx.textBaseline = "middle";
        //文字坐標(biāo)
        const maxPx = Math.max(imgWidth, imgHeight);
        const stepPx = Math.floor(maxPx / wmConfig.density);
        let arrayX = [0];//初始水印位置 canvas坐標(biāo) 0 0 點
        while (arrayX[arrayX.length - 1] < maxPx/2) {
            arrayX.push(arrayX[arrayX.length - 1] + stepPx);
        }
        arrayX.push(...arrayX.slice(1, arrayX.length).map((el) => {
            return -el;
        }));
        console.log(arrayX);
        for (let i = 0; i < arrayX.length; i++) {
            for (let j = 0; j < arrayX.length; j++) {
                ctx.save();
                ctx.translate(imgWidth / 2, imgHeight / 2); ///畫布旋轉(zhuǎn)原點 移到 圖片中心
                ctx.rotate(-Math.PI / 5);
                if (wmConfig.textArray.length > 3) {
                    wmConfig.textArray = wmConfig.textArray.slice(0, 3);
                }
                wmConfig.textArray.forEach((el, index) => {
                    let offsetY = fontSize * index + 2;
                    ctx.fillText(el, arrayX[i], arrayX[j] + offsetY);
                });
                ctx.restore();
            }
        }
    }
}

代碼就是這些,然而,在此中,我是把圖片加水印和圖片base64轉(zhuǎn)file兩個不同的博文混在一起寫的。

圖片加水印 :JavaScript實現(xiàn)為圖片添加水印的方法

base64轉(zhuǎn)file:JS中將圖片base64轉(zhuǎn)file文件的兩種方式

順便我也把file文件轉(zhuǎn)base64的封裝函數(shù)也發(fā)一下。當(dāng)然,這個我也是在網(wǎng)上找的。

function fileToBase64(file, callback) { //callback 是一個回調(diào)函數(shù),而回調(diào)函數(shù)往這兒走一回,它結(jié)果就是base64
    const fileReader = new FileReader()
    fileReader.readAsDataURL(file)
    fileReader.onload = function () {
        callback(this.result)
    }
},
function callbaseFun(res){
    console.log(res,'res打印出來就是base64')
},

//---------------------------分割線--------------------

第二種方法,跟上面的方法差不多,只是這種方法可以隨意去調(diào)整水印的位置和大小什么的。

//將base64轉(zhuǎn)化為二進(jìn)制
dataURItoBlob(base64Data) {
     var date = new Date();
     //console.log('將base64轉(zhuǎn)化為二進(jìn)制', date.getMinutes(), date.getSeconds())
     var byteString;
     if (base64Data.split(',')[0].indexOf('base64') >= 0)
         byteString = atob(base64Data.split(',')[1]);
     else
         byteString = unescape(base64Data.split(',')[1]);
     var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
     var ia = new Uint8Array(byteString.length);
     for (var i = 0; i < byteString.length; i++) {
         ia[i] = byteString.charCodeAt(i);
     }
     return new Blob([ia], { type: mimeString });
},
//將base64轉(zhuǎn)化為二進(jìn)制
dataURItoBlob(base64Data) {
     var date = new Date();
     //console.log('將base64轉(zhuǎn)化為二進(jìn)制', date.getMinutes(), date.getSeconds())
     var byteString;
     if (base64Data.split(',')[0].indexOf('base64') >= 0)
         byteString = atob(base64Data.split(',')[1]);
     else
         byteString = unescape(base64Data.split(',')[1]);
     var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
     var ia = new Uint8Array(byteString.length);
     for (var i = 0; i < byteString.length; i++) {
         ia[i] = byteString.charCodeAt(i);
     }
     return new Blob([ia], { type: mimeString });
},
//Base64轉(zhuǎn)Canvas
async imgToCanvas(base64) {
     var date = new Date();
     //console.log('Base64轉(zhuǎn)Canvas', date.getMinutes(), date.getSeconds())
     // 創(chuàng)建img元素
     const img = document.createElement('img')
     img.setAttribute('src', base64)
     await new Promise((resolve) => (img.onload = resolve))
     // 創(chuàng)建canvas DOM元素,并設(shè)置其寬高和圖片一樣
     const canvas = document.createElement('canvas')
     //console.log(img.height)
     //console.log(img.width)
     canvas.width = img.width
     canvas.height = img.height
     // 坐標(biāo)(0,0) 表示從此處開始繪制,相當(dāng)于偏移。
     canvas.getContext('2d').drawImage(img, 0, 0)
     return canvas
},
//寫入水印
addWatermark(canvas, txt1, txt2, txt3, tex4) {
     //alert(canvas.height)
     var date = new Date();
     //console.log('寫入水印', date.getMinutes(), date.getSeconds())
     const ctx = canvas.getContext('2d')
     //ctx.font = '50px Arial'
     //ctx.strokeText(text, 0, 0)
     ctx.font = '20px Arial'
     ctx.fillStyle = 'white'
     ctx.fillText(txt1, 20, canvas.height - 240)
     ctx.fillText(txt2, 20, canvas.height - 200)
     ctx.fillText(txt3, 20, canvas.height - 160)
     ctx.fillText(tex4, 20, canvas.height - 120)
     ctx.fillText(tex4, 20, canvas.height - 80)
     return canvas
},
//Canvas轉(zhuǎn)圖片文件(Image)
convasToImg(canvas) {
     var date = new Date();
     //console.log('Canvas轉(zhuǎn)圖片文件(Image)', date.getMinutes(), date.getSeconds())
     // 新建Image對象,可以理解為DOM
     let image = new Image()
     // canvas.toDataURL 返回的是一串Base64編碼的URL
     // 指定格式 PNG
     image.src = canvas.toDataURL('image/png')
     return image
},
//圖片文件(Image)轉(zhuǎn)文件(File)
base64ToFile(urlData, fileName) {
     var date = new Date();
     //console.log('圖片文件(Image)轉(zhuǎn)文件(File)', date.getMinutes(), date.getSeconds())
     let arr = urlData.split(',');
     let mime = arr[0].match(/:(.*?);/)[1];
     let bytes = atob(arr[1]); // 解碼base64
     let n = bytes.length
     let ia = new Uint8Array(n);
     while (n--) {
         ia[n] = bytes.charCodeAt(n);
     }
     return new File([ia], fileName, { type: mime });
},
//file對象轉(zhuǎn)base64
fileToBase64(file, callback) { //callback 是一個回調(diào)函數(shù),而回調(diào)函數(shù)往這兒走一回,它結(jié)果就是base64
     var date = new Date();
     //console.log('file對象轉(zhuǎn)base64', date.getMinutes(), date.getSeconds())
     return new Promise((resolve, reject) => {
         const fileReader = new FileReader()
         fileReader.readAsDataURL(file)
         fileReader.onload = function () {
             let res = callback(this.result)
             resolve(res)
         }
     })
},
callbaseFun(res) {
     //console.log('上傳的方法')
     return new Promise((resolve, reject) => {
         let that = this;
         //console.log(res, 'base64')
         let str = res.split(',');
         str[0] = 'data:image/jpeg;base64';
         let r = str.toString();
         let url = "/ServerAPI/ServerBase64API.ashx"
         var obj = {
             imgbase64: r,
             method: "ServerBase64png",
             Module: "DaKa",
             id: "a4e89358-9465-4295-87ea-4d0af2bd9133"
         }
         jQuery.ajax({
             url: url,
             type: 'POST',
             data: obj,
             dataType: 'json',
             timeout: 8000,
         })
             .done(res => {
                 var date = new Date();
                 //console.log('上傳成功', date.getMinutes(), date.getSeconds())
                 //console.log('成功時執(zhí)行')
                 resolve(res)
             })
             .fail(err => {
                 //console.log(err, '上傳失敗')
                 reject({ msg: '上傳失敗' })
             })
     })
},
async oneUpload(e){
     let base64 = e.content;
     let tempCanvas = await this.imgToCanvas(base64)  //得到canvas的值
     const canvas = this.addWatermark(tempCanvas , '水印1' , '水印2' , '水印3'); //這兒水印的參數(shù)是根據(jù) addWatermark()方法里面的 ctx.fillText(txt1, 20, canvas.height - 240) 進(jìn)行修改
     const img = this.convasToImg(canvas); //Canvas轉(zhuǎn)圖片文件(Image)
     let newFile = this.base64ToFile(img.src) //圖片文件轉(zhuǎn)file對象
     let res = await this.fileToBase64(newFile, this.callbaseFun) //file轉(zhuǎn)base64, 注意 第二個參數(shù)是一個回調(diào)函數(shù),也就是說回調(diào)函數(shù)里面的參數(shù)就是base64的值
}

到此這篇關(guān)于Vue+vant實現(xiàn)圖片上傳添加水印的文章就介紹到這了,更多相關(guān)Vue vant圖片加水印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于vue-upload-component封裝一個圖片上傳組件的示例

    基于vue-upload-component封裝一個圖片上傳組件的示例

    這篇文章主要介紹了基于vue-upload-component封裝一個圖片上傳組件的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • Avue自定義formslot調(diào)用rules自定義規(guī)則方式

    Avue自定義formslot調(diào)用rules自定義規(guī)則方式

    在Avue框架中,使用formslot自定義表格列時可能會遇到無法調(diào)用Avue的自定義校驗規(guī)則的問題,這通常發(fā)生在嘗試通過formslot自定義設(shè)置列的場景中,解決這一問題的一個有效方法是將自定義列與Avue的校驗規(guī)則通過特定方式連接起來
    2024-10-10
  • Vue實現(xiàn)購物車詳情頁面的方法

    Vue實現(xiàn)購物車詳情頁面的方法

    這篇文章主要介紹了Vue實戰(zhàn)之購物車詳情頁面的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-08-08
  • vue init webpack myproject構(gòu)建項目 ip不能訪問的解決方法

    vue init webpack myproject構(gòu)建項目 ip不能訪問的解決方法

    下面小編就為大家分享一篇vue init webpack myproject構(gòu)建項目 ip不能訪問的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-03-03
  • vue基礎(chǔ)知識--axios合并請求和slot

    vue基礎(chǔ)知識--axios合并請求和slot

    這篇文章主要介紹了vue中的axios和slot,文中代碼非常詳細(xì),對大家的工作學(xué)習(xí)有所幫助,感興趣的朋友可以參考下
    2020-06-06
  • Vue項目代碼之路由拆分、Vuex模塊拆分、element按需加載詳解

    Vue項目代碼之路由拆分、Vuex模塊拆分、element按需加載詳解

    這篇文章主要介紹了Vue項目代碼之路由拆分、Vuex模塊拆分、element按需加載,項目較大路由較多時,路由拆分是一個不錯的代碼優(yōu)化方案,按不同業(yè)務(wù)分為多個模塊,結(jié)構(gòu)清晰便于統(tǒng)一管理,本文通過示例給大家詳細(xì)講解,需要的朋友可以參考下
    2022-11-11
  • 詳解Vue Elementui中的Tag與頁面其它元素相互交互的兩三事

    詳解Vue Elementui中的Tag與頁面其它元素相互交互的兩三事

    這篇文章主要介紹了詳解Vue Elementui中的Tag與頁面其它元素相互交互的兩三事,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 一次vue項目優(yōu)化的實際操作記錄

    一次vue項目優(yōu)化的實際操作記錄

    用vue開發(fā)項目上線以后,發(fā)現(xiàn)首頁加載速度非常慢,如果項目比較大,甚至可能出現(xiàn)10s以上的等待,下面這篇文章主要給大家介紹了關(guān)于vue項目優(yōu)化的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • vue.js+element-ui動態(tài)配置菜單的實例

    vue.js+element-ui動態(tài)配置菜單的實例

    今天小編就為大家分享一篇vue.js+element-ui動態(tài)配置菜單的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • 關(guān)于vue-cli3+webpack熱更新失效及解決

    關(guān)于vue-cli3+webpack熱更新失效及解決

    這篇文章主要介紹了關(guān)于vue-cli3+webpack熱更新失效及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04

最新評論