欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解vue项目中实现图片裁剪功能

程序员文章站 2022-04-28 17:23:01
演示地址 前言 vue版本:3.6.3 cropperjs: 1.5.1 elementui https://element.ele...

演示地址

前言

使用 cropperjs插件 和 原生canvas 两种方式实现图片裁剪功能

使用cropperjs插件

安装cropperjs

yarn install cropperjs

初始化一个canvas元素,并在上面绘制图片

<canvas :id="data.src" ref="canvas"></canvas>
// 在canvas上绘制图片
drawimg () {
 this.$nexttick(() => {
 // 获取canvas节点
 let canvas = document.getelementbyid(this.data.src)
 if (canvas) {
 // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
 let parentele = canvas.parentelement
 canvas.width = parentele.offsetwidth
 canvas.height = 2 * parentele.offsetwidth / 3
 let ctx = canvas.getcontext('2d')
 ctx.clearrect(0, 0, canvas.width, canvas.height)
 let img = new image()
 img.crossorigin = 'anonymous'
 img.src = this.data.src
 img.onload = function () {
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 }
 }
 })
}

如果遇到canvas跨域绘制图片报错,设置图片img.crossorigin = 'anonymous',并且服务器响应头设置access-control-allow-origin:*

创建cropperjs

// 引入
import cropper from 'cropperjs'

// 显示裁剪框
initcropper () {
 let cropper = new cropper(this.$refs.canvas, {
 checkcrossorigin: true,
 viewmode: 2,
 aspectratio: 3 / 2
 })
}

更多方法和属性,参考官网:

具体实现,可以查看源码的cropper.vue 或 cropper.one.vue组件:

cropper.vue组件:https://github.com/my729/picture-crop-demo/blob/master/src/components/cropper.vue
cropper.one.vue组件:https://github.com/my729/picture-crop-demo/blob/master/src/components/cropper.one.vue

使用canvas实现图片裁剪

支持鼠标绘制裁剪框,并移动裁剪框

思路:

  • 在canvas上绘制图片为背景
  • 监听鼠标点击、移动、松开事件

canvas的ispointinpath()方法: 如果给定的点的坐标位于路径之内的话(包括路径的边),否则返回 false

具体实现可查看源码cropper.canvas.vue组件: https://github.com/my729/picture-crop-demo/blob/master/src/components/cropper.canvas.vue

cropimg () {
 let canvas = document.getelementbyid(this.data.img_url)
 let ctx = canvas.getcontext('2d')
 let img = new image()
 img.onload = function () {
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 }
 img.src = this.data.src
 let drag = false // 是否拖动矩形
 let flag = false // 是否绘制矩形
 let rectwidth = 0 // 绘制矩形的宽
 let rectheight = 0 // 绘制矩形的高
 let clickx = 0 // 矩形开始绘制x坐标
 let clicky = 0 // 矩形开始绘制y坐标
 let dragx = 0 // 当要拖动矩形点击时x坐标
 let dragy = 0 // 当要拖动矩形点击时y坐标
 let newrectx = 0 // 拖动变化后矩形开始绘制的x坐标
 let newrecty = 0 // 拖动变化后矩形开始绘制的y坐标
 // 鼠标按下
 canvas.onmousedown = e => {
 // 每次点击前如果有绘制好的矩形框,通过路径绘制出来,用于下面的判断
 ctx.beginpath()
 ctx.setlinedash([6, 6])
 ctx.moveto(newrectx, newrecty)
 ctx.lineto(newrectx + rectwidth, newrecty)
 ctx.lineto(newrectx + rectwidth, newrecty + rectheight)
 ctx.lineto(newrectx, newrecty + rectheight)
 ctx.lineto(newrectx, newrecty)
 ctx.strokestyle = 'green'
 ctx.stroke()
 // 每次点击,通过判断鼠标点击的点在矩形框内还是外,来决定重新绘制还是移动矩形框
 if (ctx.ispointinpath(e.offsetx, e.offsety)) {
 drag = true
 dragx = e.offsetx
 dragy = e.offsety
 clickx = newrectx
 clicky = newrecty
 } else {
 ctx.clearrect(0, 0, canvas.width, canvas.height)
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 flag = true
 clickx = e.offsetx
 clicky = e.offsety
 newrectx = e.offsetx
 newrecty = e.offsety
 }
 }
 // 鼠标抬起
 canvas.onmouseup = () => {
 if (flag) {
 flag = false
 this.surecrop(clickx, clicky, rectwidth, rectheight)
 }
 if (drag) {
 drag = false
 this.surecrop(newrectx, newrecty, rectwidth, rectheight)
 }
 }
 // 鼠标移动
 canvas.onmousemove = (e) => {
 if (flag) {
 ctx.clearrect(0, 0, canvas.width, canvas.height)
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 rectwidth = e.offsetx - clickx
 rectheight = e.offsety - clicky

 ctx.beginpath()
 ctx.strokestyle = '#ff0000'
 ctx.strokerect(clickx, clicky, rectwidth, rectheight)
 ctx.closepath()
 }
 if (drag) {
 ctx.clearrect(0, 0, canvas.width, canvas.height)
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 ctx.beginpath()
 newrectx = clickx + e.offsetx - dragx
 newrecty = clicky + e.offsety - dragy
 ctx.strokestyle = 'yellow'
 ctx.strokerect(newrectx, newrecty, rectwidth, rectheight)
 ctx.closepath()
 }
 }
},
// 拿到裁剪后的参数,可自行处理图片
surecrop (x, y, width, height) {
 let canvas = document.getelementbyid(this.data.img_url + 'after')
 // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
 let parentele = canvas.parentelement
 canvas.width = parentele.offsetwidth
 canvas.height = 2 * parentele.offsetwidth / 3
 let ctx = canvas.getcontext('2d')
 let img = new image()
 img.src = this.data.src
 img.onload = function () {
 ctx.beginpath()
 ctx.moveto(x, y)
 ctx.lineto(x + width, y)
 ctx.lineto(x + width, y + height)
 ctx.lineto(x, y + height)
 ctx.clip()
 ctx.drawimage(img, 0, 0, canvas.width, canvas.height)
 }
 ctx.stroke()
}

源码地址

https://github.com/my729/picture-crop-demo

可以直接clone项目,本地运行查看代码和效果

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。