最实用,无后顾之忧----vue移动端或web端手写签批橡皮擦功能,基于vue-drawing-canvas组件

本文介绍了一种基于vue-drawing-canvas组件实现的手写签批橡皮擦功能,通过消除法避免了传统白色覆盖法的缺陷。详细步骤包括下载组件、在画布上设置属性,并修改组件源码,利用白色笔触消除黑色画笔痕迹,仅对画过的内容起作用,不影响其他区域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

市面上的其它组件都是直接用白色来覆盖,实现了橡皮擦功能,但是有缺陷,就是遇到不是白底的,例如其它颜色或者透明色,就用白色覆盖不掉了,而且白色还容易给别的地方涂改成白色了,很鸡肋。我这个方法是消除法,把黑色的内容用白色的抵消掉,只对画笔画过的内容起作用,其它地方不会覆盖,也不会消除。
在这里插入图片描述

1.下载组件

npm install --save-dev vue-drawing-canvas**
页面使用

 <template>
  <vue-drawing-canvas ref="VueCanvasDrawing" />
</template>

<script>
  import VueDrawingCanvas from "vue-drawing-canvas";

  export default {
    name: "MyComponent",
    components: {
      VueDrawingCanvas,
    },
  };

我的页面使用,和上面一样,只不过用了一些属性

<vue-drawing-canvas
      v-if="isShowCanvas"
      class="esign-atra"
      ref="VueCanvasDrawing"
      :image.sync="image"
      :width="esignWidth"
      :height="esignHeight"
      :stroke-type="strokeType"
      :line-cap="lineCap"
      :line-join="lineJoin"
      :fill-shape="fillShape"
      :eraser="eraser"
      :lineWidth="line"
      :color="color"
      :background-color="backgroundColor"
      :background-image="backgroundImage"
      :watermark="watermark"
      :initialImage="initialImage"
      saveAs="png"
      :styles="{
        }"
      :lock="disabled"
      @mousemove.native="getCoordinate($event)"
      :additional-images="additionalImages"
    />

页面展现,我这边是后台返回的图片,所以用img展现

<img v-for="(item,index) in esignImageList"
             :key="index"
             :src="item.bs64"
             :style="[{ 
              position:'absolute',
              marginLeft: '20px',
              zIndex: 9,
              width: esignWidth + 'px',
              height:esignHeight+ 'px',
             }]">

2.重点

修改的地方:node_modules
找到vue_drawing_canvas.esm.js这个文件
其实我们在画布上画的黑色的区域都是由无数个点构成,每个点都有(x,y)
要想实现橡皮擦功能,分两步
第一步,将画笔变成白色。
在startDraw这个方法中判断切换到橡皮擦的属性eraser,然后将笔的颜色变成白色。

startDraw(event) {
      if (!this.lock) {
        this.drawing = true;
        let coordinate = this.getCoordinates(event);
        this.strokes = {
          type: this.eraser ? 'eraser' : this.strokeType,
          from: coordinate,
          coordinates: [],
          ///////////// 判断切换到橡皮擦的属性eraser,然后将笔的颜色变成白色
          color: this.eraser ? '#fff' : this.color,
          ////////////
          width: this.lineWidth,
          fill: this.eraser || this.strokeType === 'dash' || this.strokeType === 'line' ? false : this.fillShape,
          lineCap: this.lineCap,
          lineJoin: this.lineJoin
        };
        this.guides = [];
      }
    },

第二步,将白色笔画过的区域从黑色的区域的数组中筛选出来
在stopDraw方法中,计算白色笔画过的区域的最近和最远的点。然后从黑色笔画过的区域中减去这些白色重合的点,是不是就达到了橡皮擦的作用。

        // 获取画笔在画布上x轴延伸最左边的点,y轴最上面的点,也就是x最小,y最小的点
		getMin(arr, type) {
			var min = arr.length === 0 ? arr[0] : arr[0][type];
			 for(var i = 1, ilen = arr.length; i < ilen; i+=1) {
			   if(arr[i][type] < min) {
			     min = arr[i][type];
			   }
			 }
			 return min;
		},
		 // 获取画笔在画布上x轴延伸最右边的点,y轴最下面的点,也就是x最大,y最大
		getMax(arr, type) {
			 var max = arr.length === 0 ? arr[0] : arr[0][type];
			 for(var i = 1,ilen = arr.length; i < ilen; i++) {
			   if(arr[i][type] > max) {
			     max = arr[i][type];
			   }
			 }
			 return max;
		},
		// 在画笔停下的时候,计算橡皮擦擦过的线经过的最远和最近的点,然后将其从黑色笔的数组中去掉。
    stopDraw() {
      if (this.drawing) {
        this.strokes.coordinates = this.guides.length > 0 ? this.guides : this.strokes.coordinates;
        // 判断是否点开橡皮擦,橡皮擦时执行下列逻辑
        if (this.strokes.type === 'eraser') {
        // images就是那个最终生效的数组
          const imagesCopy = JSON.parse(JSON.stringify(this.images))
           imagesCopy.forEach((item) => {
            if (item.type === 'dash') {
              const minX = this.getMin(item.coordinates, 'x')
              const maxX = this.getMax(item.coordinates, 'x')
              const minY = this.getMin(item.coordinates, 'y')
              const maxY = this.getMax(item.coordinates, 'y')
              // 这一步,将黑色区域的数组this.strokes.coordinates与白色区域的数组重合的地方筛选出来,然后重新往最终展现的数组里push,也就是images
              let arr = this.strokes.coordinates.filter(_item => _item.x < maxX + 1 && _item.x > minX - 1 && _item.y < maxY + 1 && _item.y > minY - 1)
              this.images.push({
                color: this.strokes.color,
                fill: this.strokes.fill,
                from: this.strokes.from,
                lineCap:this.strokes.lineCap,
                lineJoin: this.strokes.lineJoin,
                type: this.strokes.type,
                width: this.strokes.width,
                coordinates: arr
              });
            }
          })
        } else {
        // 不是橡皮擦的正常push
          this.images.push(this.strokes);
        }
        this.redraw(true);
        this.drawing = false;
        this.trash = [];
      }
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值