# picture-crop-demo
> 在vue项目中实现图片裁剪功能
## 演示地址
[https://my729.github.io/picture-crop-demo/dist/index.html](https://my729.github.io/picture-crop-demo/dist/index.html)
## 前言
* vue版本:2.6.10 [https://cli.vuejs.org/zh/](https://cli.vuejs.org/zh/)
* cropperjs: 1.5.1 [https://github.com/fengyuanchen/cropperjs](https://github.com/fengyuanchen/cropperjs)
* elementUI [https://element.eleme.io/#/zh-CN](https://element.eleme.io/#/zh-CN)
> 使用 cropperjs插件 和 原生canvas 两种方式实现图片裁剪功能
## 使用cropperjs插件
### 安装cropperjs
``` bash
yarn install cropperjs
```
## 初始化一个canvas元素,并在上面绘制图片
```html
<canvas :id="data.src" ref="canvas"></canvas>
```
``` js
// 在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
```js
// 引入
import Cropper from 'cropperjs'
// 显示裁剪框
initCropper () {
let cropper = new Cropper(this.$refs.canvas, {
checkCrossOrigin: true,
viewMode: 2,
aspectRatio: 3 / 2
})
}
```
> 更多方法和属性,参考官网: [https://github.com/fengyuanchen/cropperjs](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
`cropper.two.vue组件:`https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.two.vue
## 使用canvas实现图片裁剪
> 支持鼠标绘制裁剪框,并移动裁剪框
#### 思路:
* 在canvas上绘制图片为背景
* 监听鼠标点击、移动、松开事件
> canvas的isPointInPath()方法:
> 如果给定的点的坐标位于路径之内的话(包括路径的边),否则返回 false
具体实现可查看源码`cropper.canvas.vue组件`: https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.canvas.vue
```js
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()
}
```
#### 可以直接clone项目,本地运行查看代码和效果
## Project setup
```
yarn install
```
### Compiles and hot-reloads for development
```
yarn run serve
```
### Compiles and minifies for production
```
yarn run build
```
### Lints and fixes files
```
yarn run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
没有合适的资源?快使用搜索试试~ 我知道了~
vue项目中实现图片裁剪功能,预览地址.zip
共26个文件
js:5个
vue:5个
css:2个
需积分: 5 0 下载量 31 浏览量
2024-01-05
21:50:48
上传
评论
收藏 1.1MB ZIP 举报
温馨提示
vue项目中实现图片裁剪功能,预览地址
资源推荐
资源详情
资源评论
收起资源包目录
vue项目中实现图片裁剪功能,预览地址.zip (26个子文件)
zyqmv
yarn.lock 316KB
babel.config.js 53B
src
App.vue 3KB
assets
logo.png 7KB
main.js 378B
components
cropper.vue 3KB
cropper.one.vue 3KB
cropper.two.vue 3KB
cropper.canvas.vue 5KB
dist
js
chunk-vendors.669b5cce.js 784KB
app.1671c993.js 12KB
app.1671c993.js.map 60KB
chunk-vendors.669b5cce.js.map 3MB
css
chunk-vendors.3d44b8f4.css 224KB
app.347fccdc.css 860B
favicon.ico 4KB
index.html 855B
fonts
element-icons.535877f5.woff 28KB
element-icons.732389de.ttf 55KB
package.json 970B
public
favicon.ico 4KB
index.html 571B
package-lock.json 3KB
vue.config.js 36B
.gitignore 208B
README.md 7KB
共 26 条
- 1
资源评论
张呱呱_
- 粉丝: 1149
- 资源: 135
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功