成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

vue下實(shí)現(xiàn)input實(shí)現(xiàn)圖片上傳,壓縮,拼接以及旋轉(zhuǎn)

Invoker / 3083人閱讀

摘要:背景作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎軀一震,以為會(huì)是一個(gè)棘手的問題,當(dāng)你讀完這篇文章的時(shí)候,你會(huì)發(fā)現(xiàn)都是你瞎操作了,真相就是這么簡(jiǎn)單

背景

作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎軀一震,以為會(huì)是一個(gè)棘手的問題,當(dāng)你讀完這篇文章的時(shí)候,你會(huì)發(fā)現(xiàn)都是你瞎操作了,真相就是這么簡(jiǎn)單,下面進(jìn)入正題:

圖片文件上傳

現(xiàn)在很多項(xiàng)目實(shí)現(xiàn)在系統(tǒng)內(nèi)保存圖片,大多數(shù)只是在系統(tǒng)數(shù)據(jù)庫內(nèi)保存對(duì)應(yīng)圖片的url,而實(shí)際的圖片資源會(huì)放在阿里等圖片服務(wù)器上,當(dāng)然,也有一些項(xiàng)目會(huì)選擇在自己的數(shù)據(jù)庫中保存圖片base64格式的字符串,下面講一些這兩種方法的具體實(shí)現(xiàn),實(shí)現(xiàn)以一個(gè)vue實(shí)例來說明:

首先,我們先要從用戶那里獲取圖片資源,這個(gè)時(shí)候,我們需要用到html的標(biāo)簽,type值為file,指定input標(biāo)簽為文件類型的表單輸入,并將其 accept屬性設(shè)置為"image/*",指定只接受圖片資源的文件;

接下來,我們就要獲取用戶選擇的文件,當(dāng)用戶選擇完文件的時(shí)候,就會(huì)觸發(fā)input標(biāo)簽的change事件,我們可以通過監(jiān)聽該事件,并獲取事件對(duì)象event,來獲取圖片文件:

 

當(dāng)點(diǎn)擊獲取文件后,我們可以通過$event對(duì)象,獲取$event.target.files[0]來獲取圖片資源文件對(duì)象,至于為什么要加索引值,是因?yàn)槲募蟼鱥nput表單是支持多文件上傳的,只需要在input標(biāo)簽上增加multiple屬性;我們可以看看下圖文件對(duì)象的一些屬性:

觀察后發(fā)現(xiàn),文件對(duì)象中存在一個(gè)size屬性,表明圖片的大小,我們可以通過驗(yàn)證該屬性的值是否為空,來達(dá)到檢驗(yàn)文件是否已經(jīng)被我們獲取到指定操作;

fileChange(el, index) {
    if (!el.target.files[0].size) return;
}

至此,我們已經(jīng)獲取到我們想要的文件對(duì)象,接下來,我們實(shí)現(xiàn)圖片壓縮功能,命名為compress函數(shù):

圖片壓縮

首先,我們要對(duì)我們的圖片資源進(jìn)行壓縮,第一步肯定是獲取圖片資源吶,獲取后對(duì)其簡(jiǎn)單的校驗(yàn);

 compress(event) {
        var file = event.target.files;
        var reader = new FileReader(), imgFile = file[0];
        if (imgFile.type.indexOf("image") == 0) {
          reader.readAsDataURL(imgFile);
        } else {
          this.$Message.infor("文件類型僅為圖片")
        }
 }

這里可能有些人對(duì)FileReader對(duì)象不了解,F(xiàn)ileReader 對(duì)象允許Web應(yīng)用程序異步讀取存儲(chǔ)在用戶計(jì)算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對(duì)象指定要讀取的文件或數(shù)據(jù),這里我們主要是用于監(jiān)聽onload來判斷是否讀取完成,讀取完成時(shí),我們把讀取的結(jié)果賦值給我們新創(chuàng)建的Image對(duì)象,作為后面壓縮的對(duì)象;這是時(shí)候,我們會(huì)發(fā)現(xiàn),我們讀取后的結(jié)果其實(shí)是一個(gè)base64格式的字符串
(很長(zhǎng)..,我就意思意思)

此時(shí),我們會(huì)發(fā)現(xiàn),base64的字符串在這里就出現(xiàn)了,它可以作為一個(gè)值復(fù)制給標(biāo)簽的src屬性,同樣可以達(dá)到渲染圖片的目標(biāo),因此也有人選擇保存該格式的圖片;但是著并非主流的方式,同時(shí)也會(huì)造成我們數(shù)據(jù)庫過于冗余;

 compress(event) {
        var file = event.target.files;
        var reader = new FileReader(), imgFile = file[0];
        if (imgFile.type.indexOf("image") == 0) {
          reader.readAsDataURL(imgFile);
        } else {
          this.$Message.infor("文件類型僅為圖片")
        }
        let img = new Image();
        reader.onload = function (e) {
          img.src = e.target.result;
        };
 }

圖片進(jìn)行壓縮,我們主要是利用canvas是實(shí)現(xiàn)該功能,通過canvas.getContext("2d").drawImage()方法重新繪制圖片,并利用canvas.toDataURL(type, encoderOptions)方法返回一個(gè)包含圖片展示的 dataURI,type為圖片格式,encoderOptions為圖片的清晰度,0到1遞增,這個(gè)壓縮的過程不難理解,思路就是獲取圖片的高寬,計(jì)算其像素大小,并與以一個(gè)自己設(shè)定的界限值進(jìn)行比較,來看一下我們大小是否需要壓縮,如例子中的ratio表示圖片寬高的壓縮比例 ,我們是可以實(shí)現(xiàn)不改寬高來修改圖片的文件大小,通過drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)重新繪制圖片,他可以傳進(jìn)九個(gè)參數(shù),分別代表著繪制到上下文的元素,源圖像的矩形選擇框的左上角 X 坐標(biāo),源圖像的矩形選擇框的左上角 Y 坐標(biāo),源圖像的矩形選擇框的寬度,源圖像的矩形選擇框的高度,目標(biāo)畫布的左上角在目標(biāo)canvas上 X 軸的位置,目標(biāo)畫布的左上角在目標(biāo)canvas上 Y 軸的位置,在目標(biāo)畫布上繪制圖像的寬度,在目標(biāo)畫布上繪制圖像的高度;

整個(gè)函數(shù)實(shí)現(xiàn)如下:

compress(event) {
        var file = event.target.files;
        var reader = new FileReader(), imgFile = file[0];
        if (imgFile.type.indexOf("image") == 0) {
          reader.readAsDataURL(imgFile);
        } else {
          this.$Message.infor("文件類型僅為圖片")
        }
        let img = new Image();
        reader.onload = function (e) {
          img.src = e.target.result;
        };
        var imgP = new Promise((resolve, reject) => {
          img.onload = () => {
            var canvas = document.createElement("canvas");
            var ctx = canvas.getContext("2d");
            //    瓦片canvas
            var tCanvas = document.createElement("canvas");
            var tctx = tCanvas.getContext("2d");
            var initSize = img.src.length;
            var width = img.width;
            var height = img.height;
            //圖片像素大于400萬像素,計(jì)算壓縮到400萬以下
            var ratio;
            if ((ratio = width * height / 4000000) > 1) {
              ratio = Math.sqrt(ratio);
              width /= ratio;
              height /= ratio;
            } else {
              ratio = 1;
            }
            canvas.width = width;
            canvas.height = height;
            ctx.fillStyle = "#fff";
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            //如果圖片太大則使用瓦片繪制
            var count;
            if ((count = width * height / 1000000 > 1)) {
              count = ~~(Math.sqrt(count) + 1);//計(jì)算分成的瓦片數(shù)
              var nw = ~~(width / count);
              var nh = ~~(height / count);
              tCanvas.width = nw;
              tCanvas.height = nh;
              for (var i = 0; i < count; i++) {
                for (var j = 0; j < count; j++) {
                  tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                  ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
                }
              }
            } else {
              ctx.drawImage(img, 0, 0, width, height)
            }
            //進(jìn)行最小壓縮
            var ndata = canvas.toDataURL("image/jpeg", 0.3);
            tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
            resolve(ndata)
          }
        })
        return Promise.all([imgP])
      }
圖片拼接

需要注意的一點(diǎn)了,上面壓縮的過程使用了瓦片繪制,可能會(huì)導(dǎo)致拼接過程中不緊湊而產(chǎn)生一條間隙,這個(gè)只需要調(diào)整一下繪制瓦片的坐標(biāo)位置即可,該思想同樣可以用于處理圖片拼接的問題,可按照上面思路進(jìn)行拼接,這里就不再舉例子說明了,瓦片繪制就是圖片拼接的過程;

圖片旋轉(zhuǎn)

壓縮和拼接都講完啦,在對(duì)圖片進(jìn)行處理,大家都有自己的見解了,或許你們還會(huì)這么說,那如果我上傳圖片的時(shí)候,像把那些橫著排的照片,也放成豎起來,要怎么處理,竟調(diào)整圖片放置的方向,該怎么處理,這就需要用到canvas的rotate方法去實(shí)現(xiàn)了,老方法,我們先獲取圖片對(duì)象,因?yàn)橹暗膲嚎s是放回一個(gè)promise對(duì)象,data參數(shù)為img的base64格式,所以我們把旋轉(zhuǎn)函數(shù)的參數(shù)定義為圖片來源;

rotate(imgData) {
        var img = new Image();
        img.src = imgData;
        var imgR = new Promise((resolve, reject) => {
         img.onload = ()=>{
            console.log(img.width)
             console.log(img.naturalWidth)
          }
        })
      },

這里需要注意的是,每次我們新建一個(gè)image對(duì)象,想要獲取其一些響應(yīng)的屬性值,一定要在onload方法中,確保圖片已經(jīng)加載完畢,上面的console中輸出了兩個(gè)值,width和naturalWidth,在某中條件下,他們會(huì)是相等的,比如我們上面,也會(huì)存在不一致的時(shí)候,因?yàn)閚aturalWidth返回的依然是圖片的真實(shí)尺寸,而width返回的是給img標(biāo)簽規(guī)定的尺寸,所以我們需要獲取的是naturalWidth;

rotate(imgData) {
        var img = new Image();
        img.src = imgData;
        var imgR = new Promise((resolve, reject) => {
          img.onload = () => {
            let degree = 0, drawHeight, drawWidth;
            drawHeight = img.naturalHeight;
            drawWidth = img.naturalWidth;
            let maxSide = Math.max(drawWidth, drawHeight);
            if (maxSide === drawWidth) {//判斷需要旋轉(zhuǎn)的角度
              degree = 90;
            } else {
              degree = 360;
            }
            var canvas = document.createElement("canvas");
            canvas.width = drawWidth;
            canvas.height = drawHeight;
            var context = canvas.getContext("2d");
            context.translate(drawWidth/2,drawHeight/2)//這一行和下下一行的作用是修改選擇中心
            context.rotate(degree*Math.PI/180);//旋轉(zhuǎn)圖片
            context.translate(-drawWidth/2,-drawHeight/2)//這一行和上上一行的作用是修改選擇中心
            context.drawImage(img, 0, 0, drawWidth, drawHeight);
            var ndata = canvas.toDataURL("image/jpeg", 1);
            context.width = context.height = 0;
            resolve(ndata)

          }
        })

        return Promise.all([imgR])
      }

旋轉(zhuǎn)效果如下,寬大于高的,即是橫排的圖片,就會(huì)發(fā)生旋轉(zhuǎn);

總結(jié)

在vue下利用canvas實(shí)現(xiàn)上述功能后,發(fā)現(xiàn)了canvas在圖片處理這塊的強(qiáng)大功能,對(duì)于前端上傳圖片性能的優(yōu)化會(huì)有很大的幫助;經(jīng)過上述的時(shí)間,發(fā)現(xiàn)要實(shí)現(xiàn)用戶的上傳圖片前的裁剪功能,以及可以利用canvas來實(shí)現(xiàn),主要是利用drawImage控制裁剪的長(zhǎng)度,起點(diǎn)坐標(biāo)就可以實(shí)現(xiàn),著實(shí)好用!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/53331.html

相關(guān)文章

  • vue實(shí)現(xiàn)input實(shí)現(xiàn)圖片上傳壓縮,拼接以及旋轉(zhuǎn)

    摘要:背景作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎軀一震,以為會(huì)是一個(gè)棘手的問題,當(dāng)你讀完這篇文章的時(shí)候,你會(huì)發(fā)現(xiàn)都是你瞎操作了,真相就是這么簡(jiǎn)單 背景 作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎...

    megatron 評(píng)論0 收藏0
  • vue實(shí)現(xiàn)input實(shí)現(xiàn)圖片上傳,壓縮,拼接以及旋轉(zhuǎn)

    摘要:背景作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎軀一震,以為會(huì)是一個(gè)棘手的問題,當(dāng)你讀完這篇文章的時(shí)候,你會(huì)發(fā)現(xiàn)都是你瞎操作了,真相就是這么簡(jiǎn)單 背景 作為一名前端工作人員,相信大家在開發(fā)系統(tǒng)的時(shí)候,經(jīng)常有遇到需要這么一種需求,就是需要為用戶保存上傳的圖片,很多小白遇到這個(gè)問題的時(shí)候,都會(huì)虎...

    ChristmasBoy 評(píng)論0 收藏0
  • 移動(dòng)端圖片上傳旋轉(zhuǎn)壓縮的解決方案

    摘要:上傳的文件經(jīng)過就可以實(shí)現(xiàn)預(yù)覽圖片了,這方面不清楚的可以查看進(jìn)階系列文件上傳下載旋轉(zhuǎn)旋轉(zhuǎn)需要用到的方法。 前言 在手機(jī)上通過網(wǎng)頁 input 標(biāo)簽拍照上傳圖片,有一些手機(jī)會(huì)出現(xiàn)圖片旋轉(zhuǎn)了90度d的問題,包括 iPhone 和個(gè)別三星手機(jī)。這些手機(jī)豎著拍的時(shí)候才會(huì)出現(xiàn)這種問題,橫拍出來的照片就正常顯示。因此,可以通過獲取手機(jī)拍照角度來對(duì)照片進(jìn)行旋轉(zhuǎn),從而解決這個(gè)問題。 Orientatio...

    blair 評(píng)論0 收藏0
  • vue前端上傳文件到阿里云oss的兩種方式,put文件流上傳,multipartUpload直接上傳

    摘要:引入阿里云的上傳圖片文件調(diào)用后臺(tái)接口獲取阿里云上傳下載通行證初始化權(quán)限去掉對(duì)的校驗(yàn)選擇文件傳到上的名字調(diào)用上傳方法上傳文件進(jìn)度調(diào)用后臺(tái)添加文件的接口上傳成功上傳失敗彈出上傳失敗的消息如果傳到阿里云的圖片要展示出來要在的圖片路徑后面 引入阿里云oss的js 上傳圖片/文件 mounted () { this.initConfig() // 調(diào)用后臺(tái)接口獲取阿里云上傳下載通行證 } ...

    K_B_Z 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<