广告位联系
返回顶部
分享到

Vue实现简单基础的图片裁剪功能

JavaScript 来源:互联网 作者:佚名 发布时间:2022-09-20 08:30:12 人浏览
摘要

近日,在写公司项目的时候接到一个需求:对已加载的大图中可截取部分图片用来入库或者布控,说白了就是截图嘛,于是我使用了vue-cropper来完成。完成后因为前边也没自己实现过,

近日,在写公司项目的时候接到一个需求:对已加载的大图中可截取部分图片用来入库或者布控,说白了就是截图嘛,于是我使用了vue-cropper来完成。完成后因为前边也没自己实现过,所以就想看看是如何实现的。因此本文写的是最简易基础的实现方法用作学习,肯定有考虑不周的地方,还请大家谅解。工作中还是使用成熟的轮子为好。

一、准备工作

本文中我所使用的环境为vue2 。现在可以在随便一个vue项目中新建一个vue文件开始了。

二、基本结构

在本文中会使用到两个canvas,一个用来绘制我们要加载的图片,一个用来绘制矩形框选区域,就像下面这样,并且在两个canvas身上分别加上ref属性。

html

1

2

3

4

5

6

7

8

9

10

11

<template>

  <div>

    <div class="wrap">

      <canvas id="canvas" ref="imgCanvas"></canvas>

      <canvas

        id="drawCanvas"

        ref="drawCanvas"

      ></canvas>

    </div>

  </div>

</template>

下方样式设置两个canvas重叠

1

2

3

4

5

6

7

8

9

10

<style>

#drawCanvas {

  position: absolute;

  top: 0;

  left: 0;

}

.wrap {

  position: relative;

}

</style>

三、添加功能

首先我们需要将两个canvas的宽高都设置为相同的,由于上面没有设置canvas的宽高,因此我们在data选项中添加好需要的宽高数据 width: 500,height: 300,稍后将它设置为canvas的大小,请记住,不要用css设置canvas的大小,这其实是将canvas拉伸了。然后在data中添加 ctx 和 imgCtx两个属性用于保存上下文。 接着在mounted生命周期中对canvas进行操作,并且获取到要加载的图片

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

let imgCanvas = this.$refs.imgCanvas;//绘制图片的canvas

let drawCanvas = this.$refs.drawCanvas;//绘制框选款的canvas

//设置两个canvas的宽高

imgCanvas.width = this.width;

imgCanvas.height = this.height;

drawCanvas.width = this.width;

drawCanvas.height = this.height;

//获取两个canvas的上下文并且保存在data中

this.ctx = drawCanvas.getContext("2d");

this.imgCtx = imgCanvas.getContext("2d");

//加载图片

let img = new Image();

img.src = "https://www.auok.ltd/background.jpg";

img.crossOrigin = "anonymous";

img.onload = () => {

  console.log("加载完成", img);

  //图片加载完成后开始绘制图片

  this.imgCtx.drawImage(img, 0, 0, this.width, this.height);

};

以上步骤搞定后现在的页面中应该如下面一样了

接下来让我们给drawCanvas添加事件监听。需要监听的事件有以下几个

  • 鼠标按下
  • 鼠标抬起
  • 鼠标移动
  • 鼠标移出

我们来改写一下模板结构,像下面这样

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<template>

  <div>

    <div class="wrap">

      <canvas id="canvas" ref="imgCanvas"></canvas>

      <canvas

        id="drawCanvas"

        ref="drawCanvas"

        @mousedown="onMouseDown"

        @mousemove="onMouseMove"

        @mouseup="onMouseUp"

        @mouseleave="onMouseLeave"

      ></canvas>

    </div>

    <img :src="curSrc" alt="" style="margin: 10px 10px 0 0" />

    <canvas id="outCanvas"></canvas>

  </div>

</template>

然后在methods中添加对应的onMouseDown、onMouseUp、onMouseMove、onMouseLeave四个方法。然后我们来编写这四个方法就好

onMouseDown

这个方法是鼠标按下事件的监听处理函数。主要负责以下几点

  • 清除drawCanvas
  • 获取鼠标按下时的位置
  • 设置一下绘制线条的样式

代码如下: 编写这个方法前我们要现在data中增加ddownPoint和down两个属性用来存储点的位置和标识鼠标是否按下。

1

2

3

4

5

6

7

onMouseDown(e) {

     console.log("鼠标按下", e.offsetX, e.offsetY);

     this.downPoint = [e.offsetX, e.offsetY];

     this.down = true;

     this.ctx.strokeStyle = "#fff";

     this.ctx.lineWidth = 2;

   }

onMouseMove

鼠标按下了,下面就要移动了。此方法是鼠标移动的监听处理函数。负责以下几点

  • 获取鼠标移动的位置
  • 绘制矩形选框
  • 绘制遮罩层

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

onMouseMove(e) {

//鼠标未按下不执行操作

   if (!this.down) {

     return;

   }

 console.log("鼠标移动", e.offsetX, e.offsetY);

 //当前鼠标移动的位置

 let movePoint = [e.offsetX, e.offsetY];

   this.ctx.fillStyle = "rgba(0,0,0,.5)";//设置遮罩层填充颜色

   //清空drawCanvas

   this.ctx.clearRect(0, 0, this.width, this.height);

   //使用设置的填充颜色来设置drawCanvas的颜色

   this.ctx.fillRect(0, 0, this.width, this.height);

   //清除指定区域的颜色,因为需要绘制的选框中间是没有颜色的,不然的话选框区域都是遮罩层的颜色。如下图

   this.ctx.clearRect(

     downPoint[0],

     downPoint[1],

     movePoint[0] - this.downPoint[0],

     movePoint[1] - this.downPoint[1]

   );

   //绘制描边矩形 四个参数是x坐标 , y坐标 , 矩形的长,矩形的宽

   this.ctx.strokeRect(

     downPoint[0],

     downPoint[1],

     movePoint[0] - this.downPoint[0],

     movePoint[1] - this.downPoint[1]

   );

 },

onMouseUp

这个方法是鼠标松开按键的事件处理函数,主要负责

  • 获取鼠标松开的坐标
  • 获取框选部分的图片 上面的步骤中截图区域已经选择完成。接下来就是要获取截图部分的图片了。

代码如下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

onMouseUp(e) {

    console.log("鼠标抬起", e.offsetX, e.offsetY);

    //获取坐标

    let upPoint = [e.offsetX, e.offsetY];

    //重置鼠标按下状态

    this.down = false;

    //获取指定区域的图片数据

    let cutImgData = this.imgCtx.getImageData(

      this.downPoint[0],

      this.downPoint[1],

      upPoint[0] - this.downPoint[0],

      upPoint[1] - this.downPoint[1]

    );

    //获取返回的图片数据中的宽高

    let { width, height } = cutImgData;

    console.log(cutImgData);

    //创建一个用于放置图片的canvas用来输出图片

    let outCanvas = document.createElement("canvas");

    let outCtx = outCanvas.getContext("2d");

    outCanvas.height = height;

    outCanvas.width = width;

    //将图片放置到canvas上

    outCtx.putImageData(cutImgData, 0, 0);

    //以blob的形式输出图片

    outCanvas.toBlob((blob) => {

      this.curSrc = URL.createObjectURL(blob);

}

通过调用getImageData获取了图片指定区域的数据,然后将获取到的图片数据使用putImageData放到创建好的canvas中,再通过canvas的toBlob或者toDataURL方法就可以输入图片的二进制数据或者base64字符串了,这里我用的是blob,再通过URL.createObjectURL获取到图片的本地地址,这种形式:blob:http://localhost:8080/e835d581-cdfe-48ff-b562-743bfcd4970d,可以用来显示或者上传。 在模板中添加一个img标签,并且在data中添加cruSrc属性,最后就如下图

1

<img :src="curSrc" alt="" style="margin: 10px 10px 0 0" />

onMouseLeave

这个方法是在鼠标移出canvas区域后重置canvas的状态的。将鼠标状态down重置为false,然后再清除canvas。

四、总结

如果要实际的实现一个和vue-cropper功能差不多的是比较复杂,要考虑很多东西,比如图像的缩放比例、选框的移动及大小调整之类的。这些部分还没有写。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://juejin.cn/post/7144203397334302757
相关文章
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计