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


Posted in Javascript onJune 07, 2019

演示地址

https://my729.github.io/picture-crop-demo/dist/#/

前言

  • vue版本:3.6.3 https://cli.vuejs.org/zh/
  • cropperjs: 1.5.1 https://github.com/fengyuanchen/cropperjs
  • 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
 })
}

更多方法和属性,参考官网: https://github.com/fengyuanchen/cropperjs

具体实现,可以查看源码的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项目,本地运行查看代码和效果

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

Javascript 相关文章推荐
EasyUi datagrid 实现表格分页
Feb 10 Javascript
JavaScript使用位运算符判断奇数和偶数的方法
Jun 01 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
Jan 12 Javascript
基于JS实现新闻列表无缝向上滚动实例代码
Jan 22 Javascript
JS弹出窗口插件zDialog简单用法示例
Jun 12 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
May 24 Javascript
新手vue构建单页面应用实例代码
Sep 18 Javascript
JS跳转手机站url的若干注意事项
Oct 18 Javascript
JavaScript实现JSON合并操作示例【递归深度合并】
Sep 07 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
May 07 Javascript
Javascript 对象(object)合并操作实例分析
Jul 30 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
Sep 04 Javascript
sortable+element 实现表格行拖拽的方法示例
Jun 07 #Javascript
利用Vue-draggable组件实现Vue项目中表格内容的拖拽排序
Jun 07 #Javascript
Vue中实现权限控制的方法示例
Jun 07 #Javascript
vue 父组件中调用子组件函数的方法
Jun 06 #Javascript
通过seajs实现JavaScript的模块开发及按模块加载
Jun 06 #Javascript
小试小程序云开发(小结)
Jun 06 #Javascript
怎么使用javascript深度拷贝一个数组
Jun 06 #Javascript
You might like
我用php+mysql写的留言本
2006/10/09 PHP
PHP入门学习的几个不错的实例代码
2008/07/13 PHP
PHP集成FCK的函数代码
2008/09/27 PHP
Swoole扩展的6种模式深入详解
2021/03/04 PHP
很可爱的输入框
2008/08/03 Javascript
event.keyCode键码值表 附只能输入特定的字符串代码
2009/05/15 Javascript
通过javascript把图片转化为字符画
2013/10/24 Javascript
instanceof和typeof运算符的区别详解
2014/01/06 Javascript
js获取checkbox复选框选中的选项实例
2014/08/24 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
js时间日期格式化封装函数
2014/12/02 Javascript
jquery图片播放浏览插件prettyPhoto使用详解
2014/12/19 Javascript
jQuery实现的图片分组切换焦点图插件
2015/01/06 Javascript
JavaScript编程中容易出BUG的几点小知识
2015/01/31 Javascript
JS实现图片延迟加载并淡入淡出效果的简单方法
2016/08/25 Javascript
JS原生带小白点轮播图实例讲解
2017/07/22 Javascript
Vue起步(无cli)的啊教程详解
2019/04/11 Javascript
EasyUI 数据表格datagrid列自适应内容宽度的实现
2019/07/18 Javascript
javascript设计模式 ? 命令模式原理与用法实例分析
2020/04/20 Javascript
JS实现单张或多张图片持续无缝滚动的示例代码
2020/05/10 Javascript
[00:56]2014DOTA2国际邀请赛 DK、iG 赛前探访
2014/07/10 DOTA
对于Python异常处理慎用“except:pass”建议
2015/04/02 Python
Python使用try except处理程序异常的三种常用方法分析
2018/09/05 Python
python实现画五角星和螺旋线的示例
2019/01/20 Python
pyqt5 获取显示器的分辨率的方法
2019/06/18 Python
python GUI库图形界面开发之PyQt5访问系统剪切板QClipboard类详细使用方法与实例
2020/02/27 Python
python简单利用字典破解zip文件口令
2020/09/07 Python
python中pickle模块浅析
2020/12/29 Python
Django权限控制的使用
2021/01/07 Python
在什么时候需要使用"常引用"
2015/12/31 面试题
实体的生命周期
2013/08/31 面试题
Java Servlet API中forward() 与redirect()的区别
2014/04/20 面试题
《逃家小兔》教学反思
2014/02/23 职场文书
《最佳路径》教学反思
2014/04/13 职场文书
2015年教师节广播稿
2015/08/19 职场文书
python实现简单的聊天小程序
2021/07/07 Python