canvas 实现图片放大缩小、移动和截取(pc端、移动端)

canvas 实现图片放大缩小、移动和截取(pc端、移动端)

代码需求:

1、图片上传
2、图片放大、缩小、移动
3、截图生成新的图片

input[type=file] 、 canvas画布

canvas和input的基础我就不多说了,不懂得可以先自行学习一下基本操作
我参考了这个博主的文章,大家不会的可以先看看:
https://blog.csdn.net/cysear/article/details/89185239#comments_13156603

下面直接上代码

html

<div>
      <div class="custom_box">
          <p>此商品需要進行定制,需要添加圖片才能下單;上傳不大於15MB的JPEG或PNG格式檔案;p>
          <div class="img">
              <img  id="img_preview">
          div>
          <div class="clipContent">
              上传图片
              <input type="file" id="file">
          div>
      div>
      <div class="cover-wrap" id="content">	
          <div class="clipBgn" >
              
              <div class="closeB">
                  <div class="close">div>
              div>
              <div class="canvas_box">
                  <div class="can_wrap">
                      <canvas id="canvas" width="335" height="340">canvas>
                  div>
              div>
              <div>注意:顯示內容是大致預覽div>
              <div class="clipButton">
                  <div id="clipBtn">保存圖片div>
              div>
          div>
      div>
  div>

css

body {
     
  margin: 0px;
  padding: 0;
}
.custom_box {
     
  margin: 10px 20px;
  border: 1px #D5D9D9 solid;
  border-radius: 6px;
  text-align: center;
  padding: 10px 20px;
  font-size: 12px;
}
.custom_box .img {
     
  height: 150px;
  margin: 10px 0;
}
.custom_box .img img {
     
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border: 1px solid;
}
.custom_box .clipContent {
     
  width: 100%;
  height: 36px;
  line-height: 36px;
  position: relative;
  border-radius: 4px;
  background-color: #b4282d;
  color: #FFFFFF;
  font-size: 14px;
}
.custom_box .clipContent input[type=file] {
     
  position: absolute;
  left: 0;
  top: 0;
  background-color: aqua;
  line-height: 36px;
  right: 0;
  width: 100%;
  opacity: 0;
}
.cover-wrap {
     
  position: fixed;
  width: 100%;
  text-align: center;
  min-height: 150px;
  top: 0;
  left: 0;
  z-index: 2;
  display: none;
}
.cover-wrap .clipBgn {
     
  margin-top: 40px;
  background-color: #fff;
  padding: 10px 0;
  font-size: 12px;
}
.cover-wrap .clipBgn .closeB {
     
  position: relative;
  height: 25px;
}
.cover-wrap .clipBgn .closeB .close {
     
  background-image: url(../images/close.png);
  background-repeat: no-repeat;
  background-size: 22px;
  width: 22px;
  height: 22px;
  position: absolute;
  right: 5px;
  top: 5px;
}
.cover-wrap .clipBgn .canvas_box {
     
  margin-top: 15px;
}
.cover-wrap .clipBgn .canvas_box .can_wrap {
     
  position: relative;
  user-select: none;
  margin: 0 auto;
}
.cover-wrap .clipBgn .canvas_box .can_wrap #scaleDragCanvas {
     
  margin-top:20px;
  touch-action: manipulation;
  user-select: none;
  cursor: move;
}
.cover-wrap .clipBgn .clipButton {
     
  text-align: center;
}
.cover-wrap .clipBgn .clipButton #clipBtn {
     
  width: 120px;
  height: 36px;
  border-radius: 4px;
  background-color: #b4282d;
  color: #FFFFFF;
  font-size: 14px;
  text-align: center;
  line-height: 36px;
  outline: none;
  margin: 15px auto;
}

js 这里使用的jQuery

$(function(){
     
	// 首先做图片上传事件
	var imgs ;
    $('#file').change(function(){
     
        //console.log('事件响应');
        var file = $("#file").get(0).files[0];
        // 处理图片的格式和大小
        var size = file.size/1024 ;
        var type = file.type.substring(file.type.lastIndexOf("/")+1);
        if(size > 15000)
        alert('上傳文件過大!');
        else if( type !== "jpeg" && type !=="jpg" && type !== "png")
        alert('上傳圖片的格式不正確!');
        else{
     
            var reader = new FileReader();
            reader.onload = function(e){
     
                imgs.src = e.target.result;
            }
            reader.readAsDataURL(file);
            int();
        }
    });
    var myCanvas, context;
    var imgX = 0, imgY = 0, imgScale = 0.2, MINIMUM_SCALE = 0.2;
    var  posl= {
     }, dragging = false;
    var pcFlag = true;
    function int(){
     
        myCanvas = document.getElementById('scaleDragCanvas'); //画布对象
        context = myCanvas.getContext('2d');//画布显示二维图片
        isPc();
        loadImg();
        canvasEventsInit();
    };
    function loadImg() {
     
        imgs = new Image();
        imgs.onload = function () {
     
            console.log(imgs);
            // imgs的尺寸对比canvas进行等比例的多小
            if(imgs.width < 80 ||  imgs.height < 80 || imgs.width > 10000 || imgs.height > 10000){
     
                alert('图片宽度和高度必须在80 x 80像素到10000 x 10000像素范围内!');
            }else{
     
                show();
                // 设置居中位置摆放
                if(imgs.width* imgScale < myCanvas.width){
     
                    imgX = (myCanvas.width - imgs.width* imgScale)/2;
                }
                if(imgs.height* imgScale < myCanvas.height){
     
                    imgY = (myCanvas.height - imgs.height* imgScale)/2;
                }
                drawImage();
            }
        }
    };
    function drawImage() {
     
        context.clearRect(0, 0, myCanvas.width, myCanvas.height);
        context.drawImage(
            imgs, //规定要使用的图像、画布或视频。
            0, 0, //开始剪切的 x 坐标位置。
            imgs.width, imgs.height,  //被剪切图像的高度。
            imgX, imgY,//在画布上放置图像的 x 、y坐标位置。
            imgs.width * imgScale, imgs.height * imgScale  //要使用的图像的宽度、高度
        );
    };
    /*事件注册*/
    function canvasEventsInit() {
     
        var pageX, pageY, initX, initY;
        var start = [], pos ={
     };
        if(pcFlag){
     
            myCanvas.onmousedown  = function (event) {
     
                dragging = true;
                pos = windowToCanvas(event.clientX, event.clientY);  //坐标转换,将窗口坐标转换成canvas的坐标
            };
            myCanvas.onmousemove  = function (evt) {
       //移动
                if(dragging){
     
                    posl = windowToCanvas(evt.clientX, evt.clientY);
                    var x = posl.x - pos.x; 
                    var y = posl.y - pos.y;
                    imgX  += x;
                    imgY  += y;
                    pos = JSON.parse(JSON.stringify(posl));
                    drawImage();  //重新绘制图片
                }
            };
            myCanvas.onmouseup  = function () {
     
                dragging = false;
            };
            myCanvas.onmousewheel = myCanvas.onwheel = function (event) {
         //滚轮放大缩小
                var pos = windowToCanvas (event.clientX, event.clientY);
                //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.05;
                        imgX = (1-imgScale)*newPos.x+(pos.x-newPos.x);
                        imgY = (1-imgScale)*newPos.y+(pos.y-newPos.y);
                } else {
     //  缩小
                    imgScale -= 0.05;
                    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);
                }
                drawImage();   //重新绘制图片
            };
        }else{
     
            // 兼容移动端
            myCanvas.ontouchstart = function (event) {
     
                dragging = true;
                if(event.touches && event.touches.length < 2) {
     
                    let touch = event.touches[0];
                    pos = windowToCanvas(touch.clientX, touch.clientY);  //坐标转换,将窗口坐标转换成canvas的坐标
                }else{
     
                    let touches = event.touches;
                    //手指按下时的手指所在的X,Y坐标  
                    pageX = touches[0].pageX;
                    pageY = touches[0].pageY;
                    //初始位置的X,Y 坐标  
                    initX = event.target.offsetLeft;
                    initY = event.target.offsetTop;
                    //记录初始 一组数据 作为缩放使用
                    if (touches.length >= 2) {
      //判断是否有两个点在屏幕上
                        start = touches; //得到第一组两个点
                    };
                }
            };
            myCanvas.ontouchmove = function (evt) {
       //移动
                if(dragging ){
     
                    if(evt.touches && evt.touches.length < 2) {
     
                        let touch = evt.touches[0];
                        posl = windowToCanvas(touch.clientX, touch.clientY);
                        var x = posl.x - pos.x; var  y = posl.y - pos.y;
                        imgX  += x;
                        imgY  += y;
                        pos = JSON.parse(JSON.stringify(posl));
                    }else{
     
                        let touches = evt.touches;
                        // 2 根 手指执行 目标元素放大操作
                        //得到第二组两个点
                        var now = touches;
                        pos = windowToCanvas (now[0].clientX, now[0].clientY);
                        var newPos = {
     
                            x:((pos.x-imgX)/imgScale).toFixed(2) , 
                            y:((pos.y-imgY)/imgScale).toFixed(2)
                        };
                        // Math.abs(touches[0].pageX-touches[1].pageX)
                        //当前距离变小, getDistance 是勾股定理的一个方法
                        if(getDistance(now[0], now[1]) < getDistance(start[0], start[1])){
     
                            // 缩小
                            imgScale -=0.03;
                            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);
                        }else if(getDistance(now[0], now[1]) > getDistance(start[0], start[1])){
     
                            // 放大
                            if(imgScale < 1) {
     
                                imgScale +=0.03;
                                imgX = (1-imgScale)*newPos.x+(pos.x-newPos.x);
                                imgY = (1-imgScale)*newPos.y+(pos.y-newPos.y);
                            }
                        }
                        start = now;
                    }
                    drawImage();  //重新绘制图片
                }
            };
            myCanvas.ontouchend = function () {
     
                dragging  = false;
            };
        }
    };
    /*坐标转换*/
    function windowToCanvas(x,y) {
     
        var box = myCanvas.getBoundingClientRect();  //这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离
        return {
     
            x: x - box.left - (box.width - myCanvas.width) / 2,
            y: y - box.top - (box.height - myCanvas.height) / 2
        };
    };
    //缩放 勾股定理方法-求两点之间的距离
    function getDistance(p1, p2) {
     
        var x = p2.pageX - p1.pageX,
        y = p2.pageY - p1.pageY;
        return Math.sqrt((x * x) + (y * y));
    };
    function isPc(){
      // 判断pc或者移动端
        var userAgentInfo = navigator.userAgent;
        var Agents = ["Android", "iPhone",
                "SymbianOS", "Windows Phone",
                "iPad", "iPod"];
        for (var i = 0; i < Agents.length ; i++){
     
            if(userAgentInfo.indexOf(Agents[i]) > 0){
     
                pcFlag = false;
                break;
            }
        };
        return pcFlag;
    };
    $('#clipBtn').click(function(){
      // canvas截图
        dataURL = context.canvas.toDataURL('image/png');
        $('#img_preview').attr("src", dataURL)
        var bb = document.getElementById("img_preview");
        $('#img_preview').attr("src", dataURL);
	    if(dataURL){
     
	            close();
        }
    });
    function show(){
     
        $('.toast').css('display', 'inline-block');
        $('.cover-wrap').css('display', 'inline-block');
        $('body').attr('style','overflow:hidden');
    };
    function close (){
     
        $('.toast').css('display', 'none');
        $('.cover-wrap').css('display', 'none');
        $('body').removeAttr('style');
    };
    $('.close').click(function(){
     
        close();
    });
})

结尾: 新手小白也就只能看着大神写的改改,还有很多需要修改的地方,希望有人能给我指点一二。

你可能感兴趣的:(canvas,html)