vue之圖片上傳解決圖片壓縮和ios拍攝的角度旋轉的問題

來源:互聯網
上載者:User

vue之圖片上傳解決圖片壓縮和拍攝的角度旋轉的問題

參考Exif.js 提供了 JavaScript 讀取映像的未經處理資料的功能擴充,例如:拍照方向、相機裝置型號、拍攝時間、ISO 速度、GPS 地理位置等資料。(地址:http://code.ciaoca.com/javascript/exif-js/),結合vue的使用,相容pc端和移動端,實現單張或者多張圖片上傳,圖片壓縮,解決拍攝角度旋轉的問題。

效果圖:


vue檔案:

<template>    <div class="add_tuzhi add_tuzhi_textarea">        <div class="add_tuzhi_com mb bg-fff">            <input id="plus_sent_pic" type="file"  @change="handleFileChange" ref="inputer"  class="trans_file" accept="image/png, image/jpeg, image/gif, image/jpg" multiple>            <div class="add_img clearfix">                <div class="add_img_list" v-for="(data,index) in imgData" @click="delImg(index)">                    <img :src="data" >                    <span class="tuzhi_sel"></span>                </div>                <template v-if="img_loading">                    <div class="add_img_list">                        <p class="map_loading">圖片上傳中</p>                    </div>                </template>                <template v-else>                     <label for="plus_sent_pic" class="add_img_list" v-if="num<9">                        <div class="tuzhi_add">                            <p><span>{{num}}</span>/9</p>                        </div>                    </label>                 </template>                                   </div>        </div>    </div></template><script>import EXIF from '../../common/js/small-exif.js';export default {    data () {        return {            num:0,  //上傳圖片數量                  base64:'' ,  //壓縮後的圖片                   imgData:[],   //圖片            data:{base64:''},            imgType:2,     //圖片上傳的狀態  0:圖片已經成功上傳  1表示圖片在上傳中 2表示圖片還沒上傳,            img_loading:false,            Orientation:''  ,    //圖片的拍攝角度        }    },    mounted:function(){    },    methods:{        delImg(id,index){   //刪除圖片            this.imgData.splice(index, 1);            if(this.num>=1){                this.num-=1;            }         },        handleFileChange () {  //擷取映像            let that=this;            let inputDOM = this.$refs.inputer;            // 通過DOM取檔案資料            for(let i in inputDOM.files){                this.file= inputDOM.files[i];                this.imgPreview(this.file);                EXIF.getData(this.file, function() {                      that.Orientation = EXIF.getTag(this, 'Orientation');                });            }        },        imgPreview (file) {   //base64 格式            this.imgType=1;            this.img_loading=true;            let self = this;            let imgContent={};            imgContent.name=file.name;            // 看支援不支援FileReader            if (!file || !window.FileReader) return;            if (/^image/.test(file.type)) {                // 建立一個reader                var reader = new FileReader();                // 將圖片將轉成 base64 格式                reader.readAsDataURL(file);                // 讀取成功後的回調                reader.onloadend = function () {                    let IMG = new Image();                    IMG.src = this.result;                    IMG.onload = function(){                        let w = this.naturalWidth,                            h = this.naturalHeight,                            resizeW = 0,                            resizeH = 0;                        //壓縮設定                        let maxSize = {                            width:1280,      //圖片最大寬度                            height:1280,     //圖片最大高度                            level:0.6       //圖片儲存品質                        };                        //計算縮放比例                        if(w > maxSize.width || h > maxSize.height){                            let multiple = Math.max(w / maxSize.width , h / maxSize.height);                            resizeW = w / multiple;                            resizeH = h / multiple;                        }else{                            resizeW = w;                            resizeH = h;                        }                        let canvas = document.createElement("canvas"),                            cxt = canvas.getContext('2d');                        //根據拍攝的角度進行圖片旋轉調整                        if (self.Orientation == 3) {                            canvas.width = resizeW;                            canvas.height = resizeH;                            cxt.rotate(Math.PI);                            cxt.drawImage(IMG, 0, 0, -resizeW, -resizeH)                        } else if (self.Orientation == 8) {                            canvas.width = resizeH;                            canvas.height = resizeW;                            cxt.rotate(Math.PI * 3 / 2);                            cxt.drawImage(IMG, 0, 0, -resizeW, resizeH)                        } else if (self.Orientation == 6) {                            canvas.width = resizeH;                            canvas.height = resizeW;                            cxt.rotate(Math.PI / 2);                            cxt.drawImage(IMG, 0, 0, resizeW, -resizeH)                        } else {                            canvas.width = resizeW;                            canvas.height = resizeH;                            cxt.drawImage(IMG, 0, 0, resizeW, resizeH)                        }                        //base64,最終輸出的壓縮檔                        self.base64 = canvas.toDataURL('image/jpeg',maxSize.level);                        self.num+=1;                        self.imgType=0;                        self.img_loading=false;                        self.imgData.push(self.base64 )                    }                };            }        }    }}</script><style scoped src="./approach_add.css"></style>

css檔案:

@charset "utf-8";.add_tuzhi{    height: 100%;    overflow-y: scroll;    padding-bottom: 2rem;}.trans_file{    display: none;}.add_img{    padding: 0.213333rem;}.add_img_list{    float: left;    width: 3.893333333333333rem;    height: 3.893333333333333rem;    position: relative;    padding: 0.213333rem;    box-sizing: border-box;}.add_img_list img{    width: 100%;    height: 100%;}.add_img_list .tuzhi_sel{    position: absolute;    width: 0.64rem;    height: 0.64rem;    right:0;    top:0;    background: url(./colse.png);    background-size: 100% 100%;}.add_img_list .tuzhi_add{    display: block;    width:100%;    height: 100%;    position: relative;    background:url(./add.png);    background-size: 100% 100%;}.add_img_list .tuzhi_add p{    color: #ccc;    font-size: 0.554667rem;    position: absolute;    left: 1.28rem;    bottom:0.32rem;}.add_img_list .map_loading{    width:100%;    text-align:center;    height: 3.466666666666333rem;    line-height: 3.466666666666333rem;    color:#333;    font-size: 0.554667rem;    border:1px  #dedede dashed;}

封裝好的exif-js檔案:

var EXIF = {};var TiffTags = EXIF.TiffTags = {    0x0112: "Orientation"};function imageHasData(img) {    return !!(img.exifdata);}function getImageData(img, callback) {    function handleBinaryFile(binFile) {        var data = findEXIFinJPEG(binFile);        img.exifdata = data || {};        if (callback) {            callback.call(img);        }    }    if (window.FileReader && (img instanceof window.Blob || img instanceof window.File)) {        var fileReader = new FileReader();        fileReader.onload = function (e) {            handleBinaryFile(e.target.result);        };        fileReader.readAsArrayBuffer(img);    }}function findEXIFinJPEG(file) {    var dataView = new DataView(file);    if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) {        return false; // not a valid jpeg    }    var offset = 2,        length = file.byteLength,        marker;    while (offset < length) {        if (dataView.getUint8(offset) != 0xFF) {            return false; // not a valid marker, something is wrong        }        marker = dataView.getUint8(offset + 1);        if (marker == 225) {            return readEXIFData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2);        } else {            offset += 2 + dataView.getUint16(offset + 2);        }    }}function readTags(file, tiffStart, dirStart, strings, bigEnd) {    var entries = file.getUint16(dirStart, !bigEnd),        tags = {},        entryOffset, tag,        i;    for (i = 0; i < entries; i++) {        entryOffset = dirStart + i * 12 + 2;        tag = strings[file.getUint16(entryOffset, !bigEnd)];        tags[tag] = readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd);    }    return tags;}function readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd) {    var type = file.getUint16(entryOffset + 2, !bigEnd),        numValues = file.getUint32(entryOffset + 4, !bigEnd),        valueOffset = file.getUint32(entryOffset + 8, !bigEnd) + tiffStart,        offset,        vals, val, n,        numerator, denominator;    switch (type) {        case 1: // byte, 8-bit unsigned int        case 7: // undefined, 8-bit byte, value depending on field            if (numValues == 1) {                return file.getUint8(entryOffset + 8, !bigEnd);            } else {                offset = numValues > 4 ? valueOffset : (entryOffset + 8);                vals = [];                for (n = 0; n < numValues; n++) {                    vals[n] = file.getUint8(offset + n);                }                return vals;            }        case 2: // ascii, 8-bit byte            offset = numValues > 4 ? valueOffset : (entryOffset + 8);            return getStringFromDB(file, offset, numValues - 1);        case 3: // short, 16 bit int            if (numValues == 1) {                return file.getUint16(entryOffset + 8, !bigEnd);            } else {                offset = numValues > 2 ? valueOffset : (entryOffset + 8);                vals = [];                for (n = 0; n < numValues; n++) {                    vals[n] = file.getUint16(offset + 2 * n, !bigEnd);                }                return vals;            }        case 4: // long, 32 bit int            if (numValues == 1) {                return file.getUint32(entryOffset + 8, !bigEnd);            } else {                vals = [];                for (n = 0; n < numValues; n++) {                    vals[n] = file.getUint32(valueOffset + 4 * n, !bigEnd);                }                return vals;            }        case 5: // rational = two long values, first is numerator, second is denominator            if (numValues == 1) {                numerator = file.getUint32(valueOffset, !bigEnd);                denominator = file.getUint32(valueOffset + 4, !bigEnd);                val = new Number(numerator / denominator);                val.numerator = numerator;                val.denominator = denominator;                return val;            } else {                vals = [];                for (n = 0; n < numValues; n++) {                    numerator = file.getUint32(valueOffset + 8 * n, !bigEnd);                    denominator = file.getUint32(valueOffset + 4 + 8 * n, !bigEnd);                    vals[n] = new Number(numerator / denominator);                    vals[n].numerator = numerator;                    vals[n].denominator = denominator;                }                return vals;            }        case 9: // slong, 32 bit signed int            if (numValues == 1) {                return file.getInt32(entryOffset + 8, !bigEnd);            } else {                vals = [];                for (n = 0; n < numValues; n++) {                    vals[n] = file.getInt32(valueOffset + 4 * n, !bigEnd);                }                return vals;            }        case 10: // signed rational, two slongs, first is numerator, second is denominator            if (numValues == 1) {                return file.getInt32(valueOffset, !bigEnd) / file.getInt32(valueOffset + 4, !bigEnd);            } else {                vals = [];                for (n = 0; n < numValues; n++) {                    vals[n] = file.getInt32(valueOffset + 8 * n, !bigEnd) / file.getInt32(valueOffset + 4 + 8 * n, !bigEnd);                }                return vals;            }    }}function getStringFromDB(buffer, start, length) {    var outstr = "";    for (var n = start; n < start + length; n++) {        outstr += String.fromCharCode(buffer.getUint8(n));    }    return outstr;}function readEXIFData(file, start) {    if (getStringFromDB(file, start, 4) != "Exif") {        return false;    }    var bigEnd,        tags, tag,        exifData, gpsData,        tiffOffset = start + 6;    // test for TIFF validity and endianness    if (file.getUint16(tiffOffset) == 0x4949) {        bigEnd = false;    } else if (file.getUint16(tiffOffset) == 0x4D4D) {        bigEnd = true;    } else {        return false;    }    if (file.getUint16(tiffOffset + 2, !bigEnd) != 0x002A) {        return false;    }    var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd);    if (firstIFDOffset < 0x00000008) {        return false;    }    tags = readTags(file, tiffOffset, tiffOffset + firstIFDOffset, TiffTags, bigEnd);    return tags;}EXIF.getData = function (img, callback) {    if ((img instanceof Image || img instanceof HTMLImageElement) && !img.complete) return false;    if (!imageHasData(img)) {        getImageData(img, callback);    } else {        if (callback) {            callback.call(img);        }    }    return true;}EXIF.getTag = function (img, tag) {    if (!imageHasData(img)) return;    return img.exifdata[tag];}export default EXIF


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.