移動端圖片上傳裁切(版權歸秒為所有,僅為搬運)
阿新 • • 發佈:2019-01-30
<!DOCTYPE html> <html lang="en"> <head> <meta name="viewport" content="width=device-width,user-scalable=no" /> <meta name="description" content="本次公開課節選自《妙味移動端原生技法精粹揭祕》遠端課程,想要了解詳情的同學可以訪問:http://www.miaov.com/index.php/news/newsDetail/nid/155 檢視課程詳情。三週的系統課程,帶你玩轉原生H5移動端web開發"> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> body { margin: 0; } html, body { height: 100%; } .wrap { position: relative; height: 100%; overflow: hidden; } .page { position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: #ccc; } .pageHide { -webkit-transform: translateY(100%); transform: translateY(100%); } .fileBtn { position: absolute; left: 50%; top: 50%; width: 200px; height: 50px; font: 20px/50px "宋體"; text-align: center; border: 1px solid #179e16; border-radius: 5px; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); background: #1aad19; color: #fff; } #file { display: none; } #select { position: absolute; left: 0; top: 0; width: 200px; height: 200px; border: 2px solid #6f0; background: rgba(255, 255, 255, .1); } .left-top { position: absolute; left: -4px; top: -4px; width: 40px; height: 40px; border-left: 4px solid #6f0; border-top: 4px solid #6f0; } .right-top { position: absolute; right: -4px; top: -4px; width: 40px; height: 40px; border-right: 4px solid #6f0; border-top: 4px solid #6f0; } .left-bottom { position: absolute; left: -4px; bottom: -4px; width: 40px; height: 40px; border-left: 4px solid #6f0; border-bottom: 4px solid #6f0; } .right-bottom { position: absolute; right: -4px; bottom: -4px; width: 40px; height: 40px; border-right: 4px solid #6f0; border-bottom: 4px solid #6f0; } #mask { position: absolute; left: 0; width: 100%; bottom: 0; height: 30px; background: rgba(0, 0, 0, 0.5); text-align: center; font: 20px/30px "宋體"; } #mask a { color: #fff; } #img { position: absolute; display: none; } </style> </head> <body> <div class="wrap"> <div class="page"> <label class="fileBtn"> 點選上傳圖片 <input type="file" id="file" accept="image/*" name=""> </label> </div> <div class="page pageHide"> <canvas id="c"></canvas> <div id="select"> <div class="left-top"></div> <div class="right-top"></div> <div class="left-bottom"></div> <div class="right-bottom"></div> </div> <div id="mask"> <a href="javascript:;" id="saveBtn">儲存</a> </div> <img src="" id="img"> </div> </div> <!-- 本次公開課節選自《妙味移動端原生技法精粹揭祕》遠端課程,想要了解詳情的同學可以訪問:http://www.miaov.com/index.php/news/newsDetail/nid/155 檢視課程詳情。三週的系統課程,帶你玩轉原生H5移動端web開發 --> <script type="text/javascript" src="MTween.js"></script> <script type="text/javascript"> console.log('本次公開課節選自《妙味移動端原生技法精粹揭祕》遠端課程,想要了解詳情的同學可以訪問:http://www.miaov.com/index.php/news/newsDetail/nid/155 檢視課程詳情。三週的系統課程,帶你玩轉原生H5移動端web開發'); /* 答應大家的 https://github.com/motao314/mScroll 移動端滑屏元件 移動端圖片上傳裁切: 1. 圖片上傳 2. 檔案大小限制 3. 圖片讀取 4. 把讀取過後圖片顯示在canvas中 5. 封裝多指操作函式 6. 多值操作canvas中的圖縮放 未實現的功能: 1. 單指拖拽封裝 2. 單指拖拽canvas中的畫面移動 3. 單指拖拽選框中,移動選框 4. 單指拖拽選框的周邊,改變選框的大小 5. canvas的圖片裁切 */ (function(){ var file = document.querySelector('#file'); var page = document.querySelectorAll('.page'); var c = document.querySelector('#c'); var cxt = c.getContext("2d"); var maxSize = 10*1024*1024; page[1].addEventListener('touchstart', function(e) { e.preventDefault(); }); c.width = document.documentElement.clientWidth; c.height = document.documentElement.clientHeight; file.onchange = function(){ //console.log(this.files[0]); if(this.files[0].size > maxSize){ alert("對不起,您傳的檔案有點太大了"); return; } var reader = new FileReader(); reader.onload = function(e){ //console.log(e.target.result); var img = new Image(); img.src = e.target.result; img.onload = function(){ var imgW = img.width; var imgH = img.height; var scale = 1; var scaleW = 1; var scaleH = 1; var x = 0; var y = 0; var startLeft = 0;//按下時手指座標 var startTop = 0;//按下時手指座標 var startW = 0;//按下時圖片寬度 var satrtH = 0;//按下時圖片高度 var isDrag = true; var isSelectDrag = true; var minW = 100; var minH = 100; /* 如果圖片較大 超出了我一屏的大小 */ if(imgW > c.width||imgH > c.height){ scaleW = c.width/imgW; scaleH = c.height/imgH; //計算一個縮放比例 scale = Math.min(scaleW,scaleH); } imgW *= scale; imgH *= scale; x = (c.width - imgW)/2; y = (c.height - imgH)/2; //縮放整張圖片的尺寸,並且把圖片居中顯示了 cxt.drawImage(img,x,y,imgW,imgH); /* 雙指縮放圖片 */ gesture({ el:page[1], start: function(){ startLeft = x; startTop = y; startW = imgW; startH = imgH; isDrag = false; isSelectDrag = false; }, change: function(e){ //根據手指縮放比例重新計算圖片尺寸 imgW = startW*e.scale; imgH = startH*e.scale; //根據新的圖片尺寸重新計算圖片位置 x = startLeft + (startW -imgW)/2; y = startTop + (startH -imgH)/2; /* cxt.clearRect(x,y,width,height); 清除canvas原先的畫面 */ cxt.clearRect(0,0,c.width,c.height); cxt.drawImage(img,x,y,imgW,imgH); } }); /* 單指拖拽圖片移動 */ drag({ el: c, start: function(){ isDrag = true; startLeft = x; startTop = y; }, move: function(e){ if(isDrag){ x = startLeft + e.disPoint.x; y = startTop + e.disPoint.y; cxt.clearRect(0,0,c.width,c.height); cxt.drawImage(img,x,y,imgW,imgH); } }, end: function(e){ } }); /* 單指拖拽選框移動 */ var select = document.querySelector('#select'); css(select,"translateX",(page[1].clientWidth - select.offsetWidth)/2); css(select,"translateY",(page[1].clientHeight - select.offsetHeight)/2); var startSelect = {}; var isResize = false; drag({ el:select, start: function(){ if(isResize){ isSelectDrag = false; return; } isSelectDrag = true; startSelect = { x: css(this, "translateX"), y: css(this, "translateY") } }, move: function(e){ if(!isSelectDrag){ return; } css(this, "translateX",startSelect.x + e.disPoint.x); css(this, "translateY",startSelect.y + e.disPoint.y); }, end: function(){ } }); /* 單指拖拽選框周邊,改變選框的大小 */ /* 左上角拖拽 1. 拿到手指移動的距離 2. 元素start時的寬高 - 手指移動距離 = 元素當前的寬高 3. 元素當前的位置 4. 最一個最小值限制 */ var leftTop = document.querySelector('.left-top'); drag({ el:leftTop, start: function(){ isResize = true; startSelect = { x: css(select,"translateX"), y: css(select,"translateY"), w: css(select,"width"), h: css(select,"height") }; }, move: function(e){ var width = startSelect.w - e.disPoint.x; var height = startSelect.h - e.disPoint.y; if(width > minW){ css(select,"width",width); css(select,"translateX",startSelect.x + e.disPoint.x); } if(height > minH){ css(select,"height",height); css(select,"translateY",startSelect.y + e.disPoint.y); } }, end: function(){ isResize = false; } }); /* 右上角 */ var rightTop = document.querySelector('.right-top'); drag({ el:rightTop, start: function(){ isResize = true; startSelect = { y: css(select,"translateY"), w: css(select,"width"), h: css(select,"height") }; }, move: function(e){ var width = startSelect.w + e.disPoint.x; var height = startSelect.h - e.disPoint.y; if(width > minW){ css(select,"width",width); } if(height > minH){ css(select,"height",height); css(select,"translateY",startSelect.y + e.disPoint.y); } }, end: function(){ isResize = false; } }); /* 右下角 */ var rightBottom = document.querySelector('.right-bottom'); drag({ el:rightBottom, start: function(){ isResize = true; startSelect = { w: css(select,"width"), h: css(select,"height") }; }, move: function(e){ var width = startSelect.w + e.disPoint.x; var height = startSelect.h + e.disPoint.y; if(width > minW){ css(select,"width",width); } if(height > minH){ css(select,"height",height); } }, end: function(){ isResize = false; } }); /* 左下角 */ var leftBottom = document.querySelector('.left-bottom'); drag({ el:leftBottom, start: function(){ isResize = true; startSelect = { x: css(select,"translateX"), w: css(select,"width"), h: css(select,"height") }; }, move: function(e){ var width = startSelect.w - e.disPoint.x; var height = startSelect.h + e.disPoint.y; if(width > minW){ css(select,"width",width); css(select,"translateX",startSelect.x + e.disPoint.x); } if(height > minH){ css(select,"height",height); } }, end: function(){ isResize = false; } }); }; page[1].className = "page"; }; reader.readAsDataURL(this.files[0]);//把檔案讀取成dataURI }; /* 點選儲存按鈕 裁切圖片 1. 獲取到選框對應的canvas中的畫面的座標以及大小 2. 利用canvas中的 dataImage,把對應的畫面截取出來 3. 清空canvas,把擷取的畫面重新放入canvas 4. 生成dataUrl 5. 把dataUrl新增到img中 */ var saveBtn = document.querySelector('#saveBtn'); saveBtn.addEventListener('touchstart', function(e) { var img = document.querySelector('#img'); var rect = select.getBoundingClientRect(); //getImageData(x,y,w,h) 獲取canvas中的畫面 var imgData = cxt.getImageData(rect.left,rect.top,rect.width,rect.height); cxt.clearRect(0,0,c.width,c.height); //putImageData(imgData,x,y);向canvas中新增畫面 c.width = rect.width; c.height = rect.height; cxt.putImageData(imgData,0,0); var url = c.toDataURL("image/png"); img.src = url; img.style.display = "block"; c.style.display = "none"; mask.style.display = "none"; select.style.display = "none"; //console.log(); }); img.addEventListener('touchstart', function(e) { e.stopPropagation(); }); })(); function drag(init){ var el = init.el; var isDrag = false; var startPoint = {};//手指按下時在頁面中座標 el.addEventListener('touchstart', function(e) { if(e.touches.length < 2){ isDrag = true; startPoint = { x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY }; init.start&&init.start.call(el,e); } }); el.addEventListener('touchmove', function(e) { if(e.touches.length < 2&&isDrag){ var nowPoint = { x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY }; e.disPoint = { x: nowPoint.x - startPoint.x, y: nowPoint.y - startPoint.y }; init.move&&init.move.call(el,e); } }); el.addEventListener('touchend', function(e) { if(isDrag){ isDrag = false; init.end&&init.end.call(el,e); } }); } function gesture(init){ var isGesture = false;//判斷使用者是否在進行多指操作 var el = init.el; var start = []; el.addEventListener('touchstart', function(e) { //e.touches 當前螢幕上手指列表 當手指個數>=2時認定使用者在進行多指操作 if(e.touches.length >= 2){ isGesture = true; start[0] = { x:e.touches[0].pageX, y:e.touches[0].pageY }; start[1] = { x:e.touches[1].pageX, y:e.touches[1].pageY } init.start&&init.start.call(el,e); } }); el.addEventListener('touchmove', function(e) { //e.touches 當前螢幕上手指列表 if(e.touches.length >= 2&&isGesture){ var startDis = getDis(start[0],start[1]);//手指按下時兩根手指之間的距離 var now = []; now[0] = { x:e.touches[0].pageX, y:e.touches[0].pageY }; now[1] = { x:e.touches[1].pageX, y:e.touches[1].pageY }; var nowDis = getDis(now[0],now[1]); e.scale = nowDis/startDis; init.change&&init.change.call(el,e); } }); el.addEventListener('touchend', function(e) { //e.touches 當前螢幕上手指列表 if(isGesture){ init.end&&init.end.call(el,e); } }); } //alert(Math.sqrt(100*100+100*100)); //計算兩個座標點之間的距離 function getDis(point,point2){ var x = point.x - point2.x; var y = point.y - point2.y; return Math.sqrt((x*x + y*y)); } </script> </body> </html>