canvas实现移动端画笔功能

移动端touch事件有以下几个属性

  1. ClientX Y 相对于视口的坐标
  2. pageX Y 相对于页面左上角原点的坐标
  3. screenX Y 相对于屏幕的坐标标
  4. movementX Y 相对于上一次坐标的坐标

 然而就是没有offset X Y

 

实现方法:

  1. 获得触摸点的pageX Y
  2. 通过offsetTop  left计算元素左上角的顶点位置
  3. 计算相对坐标

 

代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>canvas画笔</title>
<style>
html,
body {
    width: 100%;
    height: 100%;
}

* {
    margin: 0;
    padding: 0;
}

#canvas {
    position:relative;
    top: 10%;
    left: 5%;
    width: 90%;
    height: 80%;
}

#canvas canvas {
    display: block;
}

#clearCanvas,
#saveCanvas {
    position: absolute;
    bottom: 0;
    z-index: 1;
    width: 50%;
    height: 60px;
    border: 1px solid #dedede;
    line-height: 60px;
    text-align: center;
}

#clearCanvas {
    left: 0;
}

#saveCanvas {
    right: 0;
}

.errorCanvas {
    width: 100%;
    height: 100%;
    text-align: center;
    transform: translateY(40%);
}
</style>
<script>
window.onload = function () {
  new lineCanvas({
    el: document.querySelector('#canvas'),
    clearEl: document.querySelector('#clearCanvas'),
    saveEl: document.querySelector('#saveCanvas'),
    // lineWidth: 1, // 线条粗细
     color: '#0000ff', // 线条颜色
     lineShadowColor: '#0000ff', // 线条阴影颜色
    // background: '#fff'
  });
}

function lineCanvas(obj) {
  this.lineWidth = 5;
  this.color = '#000';  // 线条颜色
  this.lineShadowColor = '#000'; //线条阴影颜色
  this.shadowBlur = 1; //线条阴影大小
  this.background = '#fff';
  // 获取元素相对于body的offsetTop 和 offsetLeft
  this.offsetLeft_body = getOffsetTopByBody(obj.el)[0];
  this.offsetTop_body = getOffsetTopByBody(obj.el)[1];
  
  for (var i in obj) {
    this[i] = obj[i];
  };

  this.canvas = document.createElement('canvas');
  if (!(this.canvas.getContext && this.canvas.getContext('2d'))) {
    this.section = document.createElement('section');
    this.section.className = 'errorCanvas';
    this.section.innerHTML = '对不起,当前浏览器暂不支持此功能!'
    this.el.prepend(this.section);
    return
  }
  this.canvas.width = this.el.clientWidth;
  this.canvas.height = this.el.clientHeight;
  this.el.prepend(this.canvas);

  this.cxt = this.canvas.getContext('2d');
  this.cxt.fillStyle = this.background;
  this.cxt.fillRect(0, 0, this.canvas.width, this.canvas.height);
  this.cxt.strokeStyle = this.color;
  this.cxt.lineWidth = this.lineWidth;
  this.cxt.lineCap = 'round'; // 线条末端添加圆形线帽,减少线条的生硬感
  this.cxt.lineJoin = 'round'; // 线条交汇时为原型边角
  // 利用阴影,消除锯齿
  this.cxt.shadowBlur = this.shadowBlur;
  this.cxt.shadowColor = this.lineShadowColor;

  // 开始绘制
  this.canvas.addEventListener('touchstart', function (e) {
    this.cxt.beginPath();
    this.cxt.moveTo(e.changedTouches[0].pageX-this.offsetLeft_body, e.changedTouches[0].pageY-this.offsetTop_body);
  }.bind(this), false);

  // 绘制中
  this.canvas.addEventListener('touchmove', function (e) {
    this.cxt.lineTo(e.changedTouches[0].pageX-this.offsetLeft_body, e.changedTouches[0].pageY-this.offsetTop_body);
    this.cxt.stroke();
  }.bind(this), false);

  // 结束绘制
  this.canvas.addEventListener('touchend', function (e) {
    this.cxt.closePath();
  }.bind(this), false);

  // 清除画布
  this.clearEl.addEventListener('click', function () {
    this.cxt.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }.bind(this), false);

  // 保存图片
  this.saveEl.addEventListener('click', function () {
    var imgBase64 = this.canvas.toDataURL();
    var imgPng = this.canvas.toDataURL('image/png');
    var imgJpg = this.canvas.toDataURL('image/jpeg', 0.8);
    console.log(imgPng);
  }.bind(this), false);
  
   // 获取元素相对于body的offsetTop 和 offsetLeft
  function getOffsetTopByBody (el) {
        let offsetTop = 0
        let offsetLeft = 0
        while (el && el.tagName !== 'BODY') {
            offsetTop += el.offsetTop
            offsetLeft+= el.offsetLeft
            el = el.offsetParent
        }
        return [offsetLeft,offsetTop]
   }
}
</script>
</head>
<body>

<div id="canvas">
    <p id="clearCanvas">清除</p>
    <p id="saveCanvas">保存</p>
</div>

</body>
</html>

  

  

实现效果:

 

posted @ 2020-11-09 14:50  北巷听雨  阅读(1373)  评论(0编辑  收藏  举报
返回顶端