canvas圖片編輯操作:縮放、移動、儲存(PC端+移動端)
阿新 • • 發佈:2020-08-11
最近在寫canvas關於圖片的操作,看了網上的程式碼基本都是不行的,於是就自己寫了一個。
html程式碼
<canvas id="myCanvas" width="375px" height="500px"></canvas> <a id="save"> 點選儲存 </a>
移動端操作: Js程式碼
var canvas = document.getElementById('myCanvas'); //畫布物件 var context = canvas.getContext('2d'); //畫布顯示二維圖片 var saveBtn = document.getElementById('save'); var img, //圖片是否載入完成; imgX = 0, imgY = 0, dragging = false, posl = {}, scale = 1, pos = { x: 0, y: 0 }, newPos = { x: 0, y: 0 }; loadImg(); function drawImage(params) { context.clearRect(0, 0, canvas.width, canvas.height); // 保證 imgX 在 [img.width*(1-scale),0] 區間內 if (imgX < img.width * (1 - scale)) { imgX = img.width * (1 - scale); } else if (imgX > 0) { imgX = 0 } // 保證 imgY 在 [img.height*(1-scale),0] 區間內 if (imgY < img.height * (1 - scale)) { imgY = img.height * (1 - scale); } else if (imgY > 0) { imgY = 0 } context.drawImage( img, //規定要使用的影象、畫布或視訊。 0, 0, //開始剪下的 x 座標位置。 img.width, img.height, //被剪下影象的高度。 imgX, imgY, //在畫布上放置影象的 x 、y座標位置。 img.width * scale, img.height * scale //要使用的影象的寬度、高度 ); } function loadImg() { img = new Image(); img.onload = function () { drawImage(); } img.src = './test.jpg' } var start, end = 0; canvas.addEventListener('touchstart', function (e) { e.preventDefault() if (e.touches.length === 1) { dragging = true; pos = windowToCanvas(e.touches[0].clientX, e.touches[0].clientY); //座標轉換,將視窗座標轉換成canvas的座標 } if (e.touches.length === 2) { var t1 = e.touches[0]; var t2 = e.touches[1]; var pos1 = { x: t1.clientX, y: t1.clientY } var pos2 = { x: t2.clientX, y: t2.clientY } pos = windowToCanvas((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2); } }); canvas.addEventListener('touchmove', function (e) { e.preventDefault() if (e.touches.length === 1) { // 加上dragging區分pos和posl的值,一個為雙指,這裡為單指的值 if (dragging) { posl = windowToCanvas(e.touches[0].clientX, e.touches[0].clientY); var x = posl.x - pos.x; var y = posl.y - pos.y; imgX += x; imgY += y; pos = JSON.parse(JSON.stringify(posl)); drawImage(); //重新繪製圖片 } } // 雙指中有可能存在移動,所以不加dragging判斷,都是用的同一個中心點 if (e.touches.length === 2) { posl = JSON.parse(JSON.stringify(pos)); var s1 = end; var t1 = e.touches[0]; var t2 = e.touches[1]; var pos1 = { x: t1.clientX, y: t1.clientY } var pos2 = { x: t2.clientX, y: t2.clientY } pos = windowToCanvas((pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2); end = Math.sqrt(Math.pow((pos1.x - pos2.x), 2) + Math.pow((pos1.y - pos2.y), 2)); var pianX = posl.x - pos.x; var pianY = posl.y - pos.y; newPos = { x: ((pos.x - imgX + pianX) / scale), y: ((pos.y - imgY + pianY) / scale) }; // 縮小 if (s1 > end) { scale = scale - 0.05; imgX = (1 - scale) * newPos.x + (pos.x - newPos.x); imgY = (1 - scale) * newPos.y + (pos.y - newPos.y); if (scale < 1) { //最小縮放1 scale = 1; drawImage(); //重新繪製圖片 return } // drawImage(); //重新繪製圖片 // 放大 } else { scale = scale + 0.05; imgX = (1 - scale) * newPos.x + (pos.x - newPos.x); imgY = (1 - scale) * newPos.y + (pos.y - newPos.y); // drawImage(); } drawImage(); } }); canvas.addEventListener('touchend', function (e) { e.preventDefault() if (e.touches.length === 1) { dragging = false; } }) saveBtn.addEventListener('click', function (e) { var imgUrl = canvas.toDataURL(); var imgName = prompt('下載的圖片名稱:'); if (imgName != null) { saveBtn.download = imgName; saveBtn.href = imgUrl; } }) function windowToCanvas(x, y) { var box = canvas.getBoundingClientRect(); //這個方法返回一個矩形物件,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離 return { x: x - box.left - (box.width - canvas.width) / 2, y: y - box.top - (box.height - canvas.height) / 2 }; }
PC端操作: Js程式碼
var canvas = document.getElementById('scaleDragCanvas'); //畫布物件 var context = canvas.getContext('2d'); //畫布顯示二維圖片 var saveBtn = document.getElementById('save'); var img, imgX = 0, imgY = 0, imgScale = 1; var MINIMUM_SCALE = 1.0, pos = {}, posl = {}, dragging = false; loadImg(); canvasEventsInit(); function loadImg() { img = new Image(); img.onload = function () { drawImage(); } img.src = './test.jpg'; } function drawImage() { context.clearRect(0, 0, canvas.width, canvas.height); // 保證 imgX 在 [img.width*(1-imgScale),0] 區間內 if (imgX < img.width * (1 - imgScale)) { imgX = img.width * (1 - imgScale); } else if (imgX > 0) { imgX = 0 } // 保證 imgY 在 [img.height*(1-imgScale),0] 區間內 if (imgY < img.height * (1 - imgScale)) { imgY = img.height * (1 - imgScale); } else if (imgY > 0) { imgY = 0 } context.drawImage( img, //規定要使用的影象、畫布或視訊。 0, 0, //開始剪下的 x 座標位置。 img.width, img.height, //被剪下影象的高度。 imgX, imgY, //在畫布上放置影象的 x 、y座標位置。 img.width * imgScale, img.height * imgScale //要使用的影象的寬度、高度 ); } /*事件註冊*/ function canvasEventsInit() { canvas.onmousedown = function (event) { dragging = true; pos = windowToCanvas(event.clientX, event.clientY); //座標轉換,將視窗座標轉換成canvas的座標 }; saveBtn.addEventListener('click', function (e) { var imgUrl = canvas.toDataURL(); var imgName = prompt('下載的圖片名稱:'); if (imgName != null) { saveBtn.download = imgName; saveBtn.href = imgUrl; } }) canvas.onmousemove = function (evt) { //移動 if (dragging) { posl = windowToCanvas(evt.clientX, evt.clientY); var x = posl.x - pos.x, y = posl.y - pos.y; imgX += x; imgY += y; pos = JSON.parse(JSON.stringify(posl)); drawImage(); //重新繪製圖片 } }; canvas.onmouseup = function () { dragging = false; }; canvas.onmousewheel = canvas.onwheel = function (event) { //滾輪放大縮小 var pos = windowToCanvas(event.clientX, event.clientY); console.log(pos) event.wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltalY * (-40)); //獲取當前滑鼠的滾動情況 var newPos = { x: ((pos.x - imgX) / imgScale).toFixed(2), y: ((pos.y - imgY) / imgScale).toFixed(2) }; if (event.wheelDelta > 0) { // 放大 imgScale += 0.1; imgX = (1 - imgScale) * newPos.x + (pos.x - newPos.x); imgY = (1 - imgScale) * newPos.y + (pos.y - newPos.y); } else { // 縮小 imgScale -= 0.1; if (imgScale < MINIMUM_SCALE) { //最小縮放1 imgScale = MINIMUM_SCALE; } imgX = (1 - imgScale) * newPos.x + (pos.x - newPos.x); imgY = (1 - imgScale) * newPos.y + (pos.y - newPos.y); console.log(imgX, imgY); } drawImage(); //重新繪製圖片 }; } /*座標轉換*/ } } function windowToCanvas(x, y) { var box = canvas.getBoundingClientRect(); //這個方法返回一個矩形物件,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離 return { x: x - box.left - (box.width - canvas.width) / 2, y: y - box.top - (box.height - canvas.height) / 2 }; }