canvas图片编辑操作:缩放、移动、保存(PC端+移动端)
阅读原文时间:2023年07月09日阅读:1

最近在写canvas关于图片的操作,看了网上的代码基本都是不行的,于是就自己写了一个。

html代码


点击保存

移动端操作: 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  
  };  
}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器