优化和封装canvas画板

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_40816649/article/details/102682055

针对上一篇的canvas画板的优化和封装

为了方便以后的使用我将canvas画板封装成了一个对象,使用的时候只需引入之后new成对象即可使用。并有清空画板、改变画笔颜色、粗细、历史上一笔、下一笔等功能
html

<template>
  <div class="canvas">
    <div class="btnBox">
      <div class="item">
        <el-button @click="drawCanvas.resetCanvas()">清空canvas</el-button>
      </div>
      <div class="item">
        <el-color-picker 
          @change="drawCanvas.setColor(color)" 
          v-model="color" />
      </div>
      <div class="item">
        <el-slider 
          v-model="size"
          :max="15"
          :min="1"
          input-size="mini"
          @change="drawCanvas.setPenSize(size)" 
          @input="drawCanvas.setPenSize(size)"
          show-input />
        <div 
          class="size" 
          :style="{
            width: size * 2 + 'px', 
            height: size * 2 + 'px',
            background: color
          }"></div>
      </div>
      <div class="item">
        <el-button @click="drawCanvas.init(list)">初始化</el-button>
      </div>
      <div class="item">
        <el-button @click="front">前一笔</el-button>
      </div>
      <div class="item">
        <el-button @click="after">后一笔</el-button>
      </div>
    </div>
    <canvas width="500" height="300" id="canvas" ref="canvas"></canvas>
  </div>
</template>

<script>
import Draw from "../util/drawClass";
export default {
  name: "canvas",
  components: {},
  data() {
    return {
      drawCanvas: null,
      color: "#409EFF",
      size: 2
    };
  },
  mounted() {
    this.drawCanvas = new Draw("canvas", [], '#999999', this.color, this.size); //不能直接在data赋值响因为刚完成响应式转换还没有dom元素
  },
  computed: {
    list() {
      return this.$store.state.canvasList;
    }
  },
  watch: {
    list(value) {
      console.log(value);
    }
  },
  methods: {
    front() {
      const res = this.drawCanvas.front();
      if (res.code === 404) this.$message.warning(res.msg);
    },
    after() {
      const res = this.drawCanvas.after();
      if (res.code === 404) this.$message.warning(res.msg);
    }
  }
};
</script>

<style lang="scss">
.btnBox {
  margin: 0 auto 20px auto;
  width: 300px;
  padding: 10px;
  box-sizing: border-box;
  .item{
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    .el-button{
      width: 100%
    }
    .size{
      margin: 0 10px;
      border-radius: 50%;
    }
    .el-slider{
      flex: 1;
      .el-slider__runway.show-input{
        margin-right: 110px;
      }
      .el-slider__input{
        width: 95px
      }
    }
  }
}
</style>

 封装的对象

import store from '../vuex_study_module/store'

/**
 * canvas画板
 * 兼容移动端touch事件
 * ----------传入的参数-----------
 * @tag          canvas的id
 * @historyList  历史纪录的点
 * @background   背景色
 * @color        画笔颜色
 * @size         画笔大小
 * ----------提供的方法-----------
 * @resetCanvas  清空canvas的方法
 * @init         还原所有画笔的画布 options {[{size: String,color: Number,list: [[12,13],[14,15]]}]}
 * @after        后一步画布
 * @front        前一步画布
 * @getPointList 获取画笔记录
 * @setColor     设置颜色 options String
 * @setPenSize   设置画笔的大小 options Number
 */

export default class Draw {
  constructor(tag, historyList, background, color, size) {
    this.canvas           = document.getElementById(tag)
    this.ctx              = this.canvas.getContext("2d")
    this.width            = this.canvas.offsetWidth
    this.height           = this.canvas.offsetHeight
    this.canvas.width     = this.width
    this.canvas.height    = this.height
    this.canvasOffsetTop  = this.canvas.offsetTop//移动端canvas距离顶部的距离
    this.canvasOffsetLeft = this.canvas.offsetLeft//移动端canvas距离左边的距离
    this.startPosition    = []//当前的点
    this.isdraw           = false//是否在作画
    this.history          = historyList ? historyList : []//所有的历史画笔集合
    this.isInit           = false//是否为初始化
    this.currentPen       = []//当前画笔
    this.drawStep         = 0//当前第几笔画
    this.penSize          = size//画笔大小
    this.penColor         = color//画笔颜色
    this.backGround       = background ? background : '#999999'//画布背景色
    this.ctx.fillStyle    = this.backGround
    this.ctx.lineWidth    = size * 2 + 1//线的宽度
    this.ctx.strokeStyle  = color//点的颜色

    this.ctx.fillRect(0, 0, this.width, this.height)//画布大小
    this.canvas.addEventListener('touchmove', function (e) { //禁止页面滚动
      e.preventDefault();
    }, {passive: false}); //passive 参数不能省略,用来兼容ios和android
    this.canvas.removeEventListener('touchend', function (e) { //解除页面滚动
      e.preventDefault();
    }, {passive: false});
    this.canvas.onmousedown = res => {
      //指针在canvas上点击
      this.isdraw = true;
      this.startPosition[0] = res.offsetX;
      this.startPosition[1] = res.offsetY;
      this.drawLine(this.startPosition[0], this.startPosition[1]);
    }
    this.canvas.onmouseup = res => {
      //指针在canvas上放开
      if (!this.isdraw) return;
      this.clear();
    }
    this.canvas.onmouseout = res => {
      //指针移出canvas
      if (!this.isdraw) return;
      this.clear();
    }
    this.canvas.onmousemove = res => {
      //指针在canvas移动
      if (!this.isdraw) return;
      this.drawLine(res.offsetX, res.offsetY);
    }
    this.canvas.ontouchstart = res => {
      // 手指触摸开始
      this.isdraw = true;
      this.startPosition[0] = res.changedTouches[0].pageX - this.canvasOffsetLeft;
      this.startPosition[1] = res.changedTouches[0].pageY - this.canvasOffsetTop;
      this.drawLine(this.startPosition[0], this.startPosition[1]);
    }
    this.canvas.ontouchmove = res => {
      //手指触摸移动
      if (!this.isdraw) return;
      this.drawLine(res.changedTouches[0].pageX - this.canvasOffsetLeft, res.changedTouches[0].pageY - this.canvasOffsetTop);
    }
    this.canvas.ontouchend = res => {
      // 手指触摸结束
      if (!this.isdraw) return;
      this.clear();
    }
  }

  drawLine(X, Y) {
    //画图
    if (!this.isdraw) return;
    this.ctx.beginPath();//画圆
    this.ctx.arc(X, Y, this.penSize, 0, 2 * Math.PI)
    this.ctx.closePath();
    this.ctx.fillStyle = this.penColor;
    this.ctx.fill();
    this.ctx.beginPath()//画线
    this.ctx.moveTo(this.startPosition[0], this.startPosition[1] + 0.5);
    this.ctx.lineTo(X, Y + 0.5);
    this.ctx.stroke();
    this.ctx.save();
    this.startPosition = [X, Y];
    if (!this.isInit) this.currentPen.push(this.startPosition)
  }
  clear() {
    // 停止画笔
    this.isdraw = false;
    this.startPosition = [];
    this.history.push({size: this.penSize,color: this.penColor,list: this.currentPen});
    this.currentPen = [];
    this.drawStep = this.history.length - 1
    store.commit('setPenList', this.history)
  }
  historyDrawPen(penList = []) {
    // 画历史画笔
    this.history = penList
    this.isdraw = true
    this.isInit = true
    this.resetCanvas()
    for(let i = 0;i < penList.length;i++) {
      if (this.drawStep < i) break;
      if (penList[i].list.length == 0) {
        this.resetCanvas()
      } else {
        this.setColor(penList[i].color)
        this.setPenSize(penList[i].size)
        this.startPosition = [];//避免画笔的最后一点会和下一个画笔的前一点链接起来
        for(let j = 0;j < penList[i].list.length;j++) {
          this.drawLine(penList[i].list[j][0], penList[i].list[j][1])
        }
      }
    }
    this.isdraw = false
    this.isInit = false
    this.startPosition = []
  }

  getHistoryPoint() {
    // 返回画笔记录
    return this.history
  }
  setColor(color) {
    // 设置画笔的颜色
    this.ctx.strokeStyle = color
    this.penColor = color
  }
  setPenSize(size) {
    // 设置画笔的粗细
    this.penSize = size
    this.ctx.lineWidth = size * 2 + 1
  }
  resetCanvas() {
    //清空canvas
    this.currentPen = [];
    this.ctx.fillStyle = this.backGround;
    this.ctx.fillRect(0, 0, this.width, this.height)
    if (this.isInit) return
    this.history.push({size: this.penSize,color: this.penColor,list: []});
    this.drawStep = this.history.length - 1
    store.commit('setPenList',this.history)
  }
  init(penList) {
    // 初始化画布
    this.drawStep = penList ? penList.length - 1 : 0
    this.historyDrawPen(penList)
  }
  after() {
    // 下一笔
    if (this.drawStep >= this.history.length - 1) return {code: 404, msg: '没有下一个笔画了'}
    this.drawStep = this.drawStep + 1
    this.historyDrawPen(this.history)
    return {code: 200, msg: '恢复下一笔'}
  }
  front() {
    // 上一笔
    if (this.drawStep < 0) return {code: 404, msg: '没有前一个笔画了'}
    this.drawStep = this.drawStep - 1
    this.historyDrawPen(this.history)
    return {code: 200, msg: '恢复前一笔'}
  }
}

猜你喜欢

转载自blog.csdn.net/qq_40816649/article/details/102682055