最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

原來,在前端也是能實現(xiàn)圖片上傳加水印的。(注:以下的代碼都來自于網(wǎng)絡,只是我把兩部份代碼合在一起來實現(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   值越大,水印越多,可能會導致水印重疊等問題,慎重?。?!
    }
}
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  為左上角坐標原點
                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";
        //文字坐標
        const maxPx = Math.max(imgWidth, imgHeight);
        const stepPx = Math.floor(maxPx / wmConfig.density);
        let arrayX = [0];//初始水印位置 canvas坐標 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ā)一下。當然,這個我也是在網(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)化為二進制
dataURItoBlob(base64Data) {
     var date = new Date();
     //console.log('將base64轉(zhuǎ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)化為二進制
dataURItoBlob(base64Data) {
     var date = new Date();
     //console.log('將base64轉(zhuǎ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元素,并設置其寬高和圖片一樣
     const canvas = document.createElement('canvas')
     //console.log(img.height)
     //console.log(img.width)
     canvas.width = img.width
     canvas.height = img.height
     // 坐標(0,0) 表示從此處開始繪制,相當于偏移。
     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) 進行修改
     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的值
}

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

相關文章

  • Vue格式化數(shù)據(jù)后切換頁面出現(xiàn)NaN問題及解決

    Vue格式化數(shù)據(jù)后切換頁面出現(xiàn)NaN問題及解決

    這篇文章主要介紹了Vue格式化數(shù)據(jù)后切換頁面出現(xiàn)NaN問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • vue中v-if和v-show使用區(qū)別源碼分析

    vue中v-if和v-show使用區(qū)別源碼分析

    這篇文章主要為大家介紹了vue中v-if和v-show使用區(qū)別源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Vuejs監(jiān)聽vuex中值的變化的方法示例

    Vuejs監(jiān)聽vuex中值的變化的方法示例

    這篇文章主要介紹了Vuejs監(jiān)聽vuex中值的變化的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • Vue渲染過程淺析

    Vue渲染過程淺析

    這篇文章主要介紹了Vue渲染過程淺析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Vue中String() 和 .toString()的區(qū)別小結(jié)

    Vue中String() 和 .toString()的區(qū)別小結(jié)

    本文主要介紹了Vue中String()和.toString()的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2026-02-02
  • 一文了解Vue 3 的 generate 是這樣生成 render 函數(shù)的

    一文了解Vue 3 的 generate 是這樣生成 render&n

    本文介紹generate階段是如何根據(jù)javascript AST抽象語法樹生成render函數(shù)字符串的,本文中使用的vue版本為3.4.19,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • 使用vue.js制作分頁組件

    使用vue.js制作分頁組件

    本文給大家分享的是個人在使用vue.js制作的文章和評論的分頁組件,并使用webpack打包起來,這里推薦給大家,有需要的小伙伴可以參考下
    2016-06-06
  • Vue封裝全局toast組件的完整實例

    Vue封裝全局toast組件的完整實例

    組件(Component)是 Vue.js 最強大的功能之一,組件可以擴展 HTML 元素,封裝可重用的代碼,這篇文章主要給大家介紹了關于Vue封裝全局toast組件,需要的朋友可以參考下
    2021-07-07
  • vue3 teleport的使用案例詳解

    vue3 teleport的使用案例詳解

    這篇文章主要介紹了vue3 teleport的使用demo,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • 基于vue3+antDesign2+echarts?實現(xiàn)雷達圖效果

    基于vue3+antDesign2+echarts?實現(xiàn)雷達圖效果

    這篇文章主要介紹了基于vue3+antDesign2+echarts?實現(xiàn)雷達圖,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08

最新評論

桐梓县| 罗山县| 拉萨市| 怀仁县| 平舆县| 隆安县| 兴山县| 定安县| 鲜城| 凭祥市| 和平县| 柳林县| 库车县| 乃东县| 阿鲁科尔沁旗| 青河县| 图们市| 双辽市| 合江县| 定西市| 二连浩特市| 乌审旗| 浙江省| 英德市| 蚌埠市| 永春县| 麻城市| 治县。| 高要市| 凌云县| 锦州市| 中阳县| 普格县| 阳朔县| 高安市| 江山市| 花垣县| 定兴县| 白朗县| 呈贡县| 扶绥县|