当前位置:Gxlcms > JavaScript > 详解vue项目中实现图片裁剪功能

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

时间:2021-07-01 10:21:17 帮助过:13人阅读

演示地址

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

  1. yarn install cropperjs

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

  1. <canvas :id="data.src" ref="canvas"></canvas>
  1. // 在canvas上绘制图片
  2. drawImg () {
  3. this.$nextTick(() => {
  4. // 获取canvas节点
  5. let canvas = document.getElementById(this.data.src)
  6. if (canvas) {
  7. // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
  8. let parentEle = canvas.parentElement
  9. canvas.width = parentEle.offsetWidth
  10. canvas.height = 2 * parentEle.offsetWidth / 3
  11. let ctx = canvas.getContext('2d')
  12. ctx.clearRect(0, 0, canvas.width, canvas.height)
  13. let img = new Image()
  14. img.crossOrigin = 'Anonymous'
  15. img.src = this.data.src
  16. img.onload = function () {
  17. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  18. }
  19. }
  20. })
  21. }

如果遇到canvas跨域绘制图片报错,设置图片img.crossOrigin = 'Anonymous',并且服务器响应头设置Access-Control-Allow-Origin:*

创建cropperjs

  1. // 引入
  2. import Cropper from 'cropperjs'
  3. // 显示裁剪框
  4. initCropper () {
  5. let cropper = new Cropper(this.$refs.canvas, {
  6. checkCrossOrigin: true,
  7. viewMode: 2,
  8. aspectRatio: 3 / 2
  9. })
  10. }

更多方法和属性,参考官网: 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

  1. cropImg () {
  2. let canvas = document.getElementById(this.data.img_url)
  3. let ctx = canvas.getContext('2d')
  4. let img = new Image()
  5. img.onload = function () {
  6. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  7. }
  8. img.src = this.data.src
  9. let drag = false // 是否拖动矩形
  10. let flag = false // 是否绘制矩形
  11. let rectWidth = 0 // 绘制矩形的宽
  12. let rectHeight = 0 // 绘制矩形的高
  13. let clickX = 0 // 矩形开始绘制X坐标
  14. let clickY = 0 // 矩形开始绘制Y坐标
  15. let dragX = 0 // 当要拖动矩形点击时X坐标
  16. let dragY = 0 // 当要拖动矩形点击时Y坐标
  17. let newRectX = 0 // 拖动变化后矩形开始绘制的X坐标
  18. let newRectY = 0 // 拖动变化后矩形开始绘制的Y坐标
  19. // 鼠标按下
  20. canvas.onmousedown = e => {
  21. // 每次点击前如果有绘制好的矩形框,通过路径绘制出来,用于下面的判断
  22. ctx.beginPath()
  23. ctx.setLineDash([6, 6])
  24. ctx.moveTo(newRectX, newRectY)
  25. ctx.lineTo(newRectX + rectWidth, newRectY)
  26. ctx.lineTo(newRectX + rectWidth, newRectY + rectHeight)
  27. ctx.lineTo(newRectX, newRectY + rectHeight)
  28. ctx.lineTo(newRectX, newRectY)
  29. ctx.strokeStyle = 'green'
  30. ctx.stroke()
  31. // 每次点击,通过判断鼠标点击的点在矩形框内还是外,来决定重新绘制还是移动矩形框
  32. if (ctx.isPointInPath(e.offsetX, e.offsetY)) {
  33. drag = true
  34. dragX = e.offsetX
  35. dragY = e.offsetY
  36. clickX = newRectX
  37. clickY = newRectY
  38. } else {
  39. ctx.clearRect(0, 0, canvas.width, canvas.height)
  40. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  41. flag = true
  42. clickX = e.offsetX
  43. clickY = e.offsetY
  44. newRectX = e.offsetX
  45. newRectY = e.offsetY
  46. }
  47. }
  48. // 鼠标抬起
  49. canvas.onmouseup = () => {
  50. if (flag) {
  51. flag = false
  52. this.sureCrop(clickX, clickY, rectWidth, rectHeight)
  53. }
  54. if (drag) {
  55. drag = false
  56. this.sureCrop(newRectX, newRectY, rectWidth, rectHeight)
  57. }
  58. }
  59. // 鼠标移动
  60. canvas.onmousemove = (e) => {
  61. if (flag) {
  62. ctx.clearRect(0, 0, canvas.width, canvas.height)
  63. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  64. rectWidth = e.offsetX - clickX
  65. rectHeight = e.offsetY - clickY
  66. ctx.beginPath()
  67. ctx.strokeStyle = '#FF0000'
  68. ctx.strokeRect(clickX, clickY, rectWidth, rectHeight)
  69. ctx.closePath()
  70. }
  71. if (drag) {
  72. ctx.clearRect(0, 0, canvas.width, canvas.height)
  73. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  74. ctx.beginPath()
  75. newRectX = clickX + e.offsetX - dragX
  76. newRectY = clickY + e.offsetY - dragY
  77. ctx.strokeStyle = 'yellow'
  78. ctx.strokeRect(newRectX, newRectY, rectWidth, rectHeight)
  79. ctx.closePath()
  80. }
  81. }
  82. },
  83. // 拿到裁剪后的参数,可自行处理图片
  84. sureCrop (x, y, width, height) {
  85. let canvas = document.getElementById(this.data.img_url + 'after')
  86. // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
  87. let parentEle = canvas.parentElement
  88. canvas.width = parentEle.offsetWidth
  89. canvas.height = 2 * parentEle.offsetWidth / 3
  90. let ctx = canvas.getContext('2d')
  91. let img = new Image()
  92. img.src = this.data.src
  93. img.onload = function () {
  94. ctx.beginPath()
  95. ctx.moveTo(x, y)
  96. ctx.lineTo(x + width, y)
  97. ctx.lineTo(x + width, y + height)
  98. ctx.lineTo(x, y + height)
  99. ctx.clip()
  100. ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
  101. }
  102. ctx.stroke()
  103. }

源码地址

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

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

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

人气教程排行