一、圖片的選擇
二、圖片從手機相機選擇、拍照
三、圖片選擇後的裁剪
四、圖片在頁面的顯示效果
五、圖片的刪除
六、base64圖片轉化爲file類型的文件
七、圖片的上傳vue
首先安裝cropperjs 和exif-js 裁剪依賴這兩個包
cnpm install --save cropperjs exif-jsios
圖片選擇後的裁剪web
initilize(opt) { let self = this; this.options = opt; //建立dom this.createElement(); this.resultObj = opt.resultObj; //初始化裁剪對象 this.cropper = new Cropper(this.preview, { aspectRatio: opt.aspectWithRatio / opt.aspectHeightRatio, autoCropArea: opt.autoCropArea || 0.8, viewMode: 2, guides: true, cropBoxResizable: true, //是否經過拖動來調整剪裁框的大小 cropBoxMovable: true, //是否經過拖拽來移動剪裁框。 dragCrop: false, dragMode: "move", //‘crop’: 能夠產生一個新的裁剪框3 ‘move’: 只能夠移動3 ‘none’: 什麼也不處理 center: true, zoomable: true, //是否容許放大圖像。 zoomOnTouch: true, //是否能夠經過拖動觸摸來放大圖像。 scalable: true, // minCropBoxHeight: 750, // minCropBoxWidth: 750, background: false, checkOrientation: true, checkCrossOrigin: true, zoomable: false, zoomOnWheel: false, center: false, toggleDragModeOnDblclick: false, ready: function() { if (opt.aspectRatio == "Free") { let cropBox = self.cropper.cropBox; cropBox.querySelector("span.cropper-view-box").style.outline = "none"; self.cropper.disable(); } } }); }, //建立一些必要的DOM,用於圖片裁剪 createElement() { //初始化圖片爲空對象 this.preview = null; let str = '<div><img id="clip_image" src="originUrl"></div><button type="button" id="cancel_clip">取消</button><button type="button" id="clip_button">肯定</button>'; str += '<div class="crop_loading"><div class="crop_content"><div class="crop_text">圖片修剪中...</div></div></div>'; str += '<div class="crop_success"><div class="crop_success_text">上傳成功</div></div></div>'; let body = document.getElementsByTagName("body")[0]; this.reagion = document.createElement("div"); this.reagion.id = "clip_container"; this.reagion.className = "container"; this.reagion.innerHTML = str; body.appendChild(this.reagion); this.preview = document.getElementById("clip_image"); //綁定一些方法 this.initFunction(); }, //初始化一些函數綁定 initFunction() { let self = this; this.clickBtn = document.getElementById("clip_button"); this.cancelBtn = document.getElementById("cancel_clip"); //肯定事件 this.addEvent(this.clickBtn, "click", function() { self.crop(); }); //取消事件 this.addEvent(this.cancelBtn, "click", function() { self.destoried(); }); //清空input的值 this.addEvent(this.fileObj, "click", function() { this.value = ""; }); }, //外部接口,用於input['file']對象change時的調用 clip(e, opt) { let self = this; this.fileObj = e.srcElement; let files = e.target.files || e.dataTransfer.files; if (!files.length) return false; //不是圖片直接返回 //調用初始化方法 this.initilize(opt); //獲取圖片文件資源 this.picValue = files[0]; //調用方法轉成url格式 this.originUrl = this.getObjectURL(this.picValue); //每次替換圖片要從新獲得新的url if (this.cropper) { this.cropper.replace(this.originUrl); } }, //圖片轉碼方法 getObjectURL(file) { let url = null; if (window.createObjectURL != undefined) { // basic url = window.createObjectURL(file); } else if (window.URL != undefined) { // mozilla(firefox) url = window.URL.createObjectURL(file); } else if (window.webkitURL != undefined) { // webkit or chrome url = window.webkitURL.createObjectURL(file); } return url; }, //點擊肯定進行裁剪 crop() { let self = this; let image = new Image(); let croppedCanvas; let roundedCanvas; // Crop document.querySelector(".crop_loading").style.display = "block"; setTimeout(function() { croppedCanvas = self.cropper.getCroppedCanvas(); // Round roundedCanvas = self.getRoundedCanvas(croppedCanvas); let imgData = roundedCanvas.toDataURL(); image.src = imgData; //判斷圖片是否大於100k,不大於直接上傳,反之壓縮 if (imgData.length < 100 * 1024) { // self.resultObj.src = imgData; //圖片上傳 self.postImg(imgData); } else { image.onload = function() { //壓縮處理 let data = self.compress(image, self.Orientation); // self.resultObj.src = data; //圖片上傳 self.postImg(data); }; } }, 20); }, //獲取裁剪圖片資源 getRoundedCanvas(sourceCanvas) { let canvas = document.createElement("canvas"); let context = canvas.getContext("2d"); let width = sourceCanvas.width; let height = sourceCanvas.height; canvas.width = width; canvas.height = height; context.imageSmoothingEnabled = true; context.drawImage(sourceCanvas, 0, 0, width, height); context.globalCompositeOperation = "destination-in"; context.beginPath(); context.rect(0, 0, width, height); context.fill(); return canvas; }, //銷燬原來的對象 destoried() { let self = this; //移除事件 this.removeEvent(this.clickBtn, "click", null); this.removeEvent(this.cancelBtn, "click", null); this.removeEvent(this.fileObj, "click", null); //移除裁剪框 this.reagion.parentNode.removeChild(this.reagion); //銷燬裁剪對象 this.cropper.destroy(); this.cropper = null; }, //圖片上傳 postImg(imageData) { console.log(imageData); this.$emit("callback", imageData); //這邊寫圖片的上傳 let self = this; self.destoried(); this.imgList.push(imageData); }, //圖片旋轉 rotateImg(img, direction, canvas) { //最小與最大旋轉方向,圖片旋轉4次後回到原方向 const min_step = 0; const max_step = 3; if (img == null) return; //img的高度和寬度不能在img元素隱藏後獲取,不然會出錯 let height = img.height; let width = img.width; let step = 2; if (step == null) { step = min_step; } if (direction == "right") { step++; //旋轉到原位置,即超過最大值 step > max_step && (step = min_step); } else { step--; step < min_step && (step = max_step); } //旋轉角度以弧度值爲參數 let degree = (step * 90 * Math.PI) / 180; let ctx = canvas.getContext("2d"); switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0); break; } }, //圖片壓縮 compress(img, Orientation) { let canvas = document.createElement("canvas"); let ctx = canvas.getContext("2d"); //瓦片canvas let tCanvas = document.createElement("canvas"); let tctx = tCanvas.getContext("2d"); let initSize = img.src.length; let width = img.width; let height = img.height; //若是圖片大於四百萬像素,計算壓縮比並將大小壓至400萬如下 let ratio; if ((ratio = (width * height) / 4000000) > 1) { console.log("大於400萬像素"); 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); //若是圖片像素大於100萬則使用瓦片繪製 let count; if ((count = (width * height) / 1000000) > 1) { count = ~~(Math.sqrt(count) + 1); //計算要分紅多少塊瓦片 // 計算每塊瓦片的寬和高 let nw = ~~(width / count); let nh = ~~(height / count); tCanvas.width = nw; tCanvas.height = nh; for (let i = 0; i < count; i++) { for (let 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); } //修復ios上傳圖片的時候 被旋轉的問題 if (Orientation != "" && Orientation != 1) { switch (Orientation) { case 6: //須要順時針(向左)90度旋轉 this.rotateImg(img, "left", canvas); break; case 8: //須要逆時針(向右)90度旋轉 this.rotateImg(img, "right", canvas); break; case 3: //須要180度旋轉 this.rotateImg(img, "right", canvas); //轉兩次 this.rotateImg(img, "right", canvas); break; } } //進行最小壓縮 let ndata = canvas.toDataURL("image/png", 0.1); console.log("壓縮前:" + initSize); console.log("壓縮後:" + ndata.length); console.log( "壓縮率:" + ~~((100 * (initSize - ndata.length)) / initSize) + "%" ); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata; }, //添加事件 addEvent(obj, type, fn) { if (obj.addEventListener) { obj.addEventListener(type, fn, false); } else { obj.attachEvent("on" + type, fn); } }, //移除事件 removeEvent(obj, type, fn) { if (obj.removeEventListener) { obj.removeEventListener(type, fn, false); } else { obj.detachEvent("on" + type, fn); } }
圖片在頁面的顯示效果
暫無
圖片的刪除
base64圖片轉化爲file類型的文件
bytes = window.atob(this.imgList[i].split(',')[1]);chrome
var array = []; array.push(bytes.charCodeAt(j)); var blob = new Blob([new Uint8Array(array)], {type: 'image/jpeg'}); form.append("file", blob, Date.now() + '.jpg');
圖片的上傳
暫無npm
最終效果:
圖片裁剪參考:https://blog.csdn.net/ch83430...canvas
ps: 須要源碼的請聯繫我(請尊重一下別人的勞動成果,源碼須要付費10 哦。):
微信