详解vue项目中实现图片裁剪功能
演示地址
前言
- vue版本:3.6.3
- cropperjs: 1.5.1
- elementui https://element.eleme.io/#/zh-cn
使用 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项目,本地运行查看代码和效果
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。