返回
基于Taro框架实现图片裁剪组件的详细指南
前端
2024-02-05 12:54:20
- 参数说明
在开始构建组件之前,我们需要先定义组件的参数,以便在使用组件时能够灵活地配置不同的裁剪选项。
参数名 | 类型 | 默认值 | |
---|---|---|---|
src | String | - | 待裁剪的图片地址 |
width | Number | 300 | 裁剪框的宽度 |
height | Number | 300 | 裁剪框的高度 |
aspectRatio | Number | 1 | 裁剪框的宽高比 |
rotatable | Boolean | false | 是否允许旋转图片 |
zoomable | Boolean | false | 是否允许缩放图片 |
dragable | Boolean | false | 是否允许拖拽图片 |
outputType | String | 'base64' | 输出图片的类型,可选值:'base64'、'blob' |
2. 界面布局
接下来,我们需要设计组件的界面布局,以便用户能够直观地操作裁剪组件。
<template>
<div class="image-cropper">
<div class="image-container">
<canvas id="canvas"></canvas>
</div>
<div class="controls">
<button @click="rotateImage">旋转</button>
<button @click="zoomIn">放大</button>
<button @click="zoomOut">缩小</button>
<button @click="exportImage">导出</button>
</div>
</div>
</template>
在这个布局中,我们定义了一个包含画布(canvas)的容器和一个包含控制按钮的容器。
3. 初始化
在组件的初始化函数中,我们需要进行以下操作:
- 获取组件的参数
- 创建一个新的Canvas对象
- 将待裁剪的图片加载到Canvas中
- 初始化裁剪框
- 初始化控制按钮
export default {
props: {
src: String,
width: {
type: Number,
default: 300
},
height: {
type: Number,
default: 300
},
aspectRatio: {
type: Number,
default: 1
},
rotatable: {
type: Boolean,
default: false
},
zoomable: {
type: Boolean,
default: false
},
dragable: {
type: Boolean,
default: false
},
outputType: {
type: String,
default: 'base64'
}
},
data() {
return {
canvas: null,
ctx: null,
image: null,
cropRect: {
x: 0,
y: 0,
width: this.width,
height: this.height
},
rotateAngle: 0
}
},
mounted() {
this.initCanvas()
this.loadImage()
this.initCropRect()
this.initControls()
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvas
this.ctx = this.canvas.getContext('2d')
},
loadImage() {
const image = new Image()
image.onload = () => {
this.image = image
this.drawCanvas()
}
image.src = this.src
},
initCropRect() {
const canvasWidth = this.canvas.width
const canvasHeight = this.canvas.height
const cropRectWidth = Math.min(canvasWidth, canvasHeight * this.aspectRatio)
const cropRectHeight = Math.min(canvasHeight, canvasWidth / this.aspectRatio)
this.cropRect.width = cropRectWidth
this.cropRect.height = cropRectHeight
this.cropRect.x = (canvasWidth - cropRectWidth) / 2
this.cropRect.y = (canvasHeight - cropRectHeight) / 2
},
initControls() {
const controls = this.$refs.controls
const buttons = controls.querySelectorAll('button')
buttons.forEach(button => {
button.addEventListener('click', this[button.id])
})
},
rotateImage() {
this.rotateAngle += 90
this.drawCanvas()
},
zoomIn() {
this.cropRect.width *= 1.1
this.cropRect.height *= 1.1
this.drawCanvas()
},
zoomOut() {
this.cropRect.width *= 0.9
this.cropRect.height *= 0.9
this.drawCanvas()
},
exportImage() {
const imageData = this.ctx.getImageData(this.cropRect.x, this.cropRect.y, this.cropRect.width, this.cropRect.height)
const canvas = document.createElement('canvas')
canvas.width = this.cropRect.width
canvas.height = this.cropRect.height
const ctx = canvas.getContext('2d')
ctx.putImageData(imageData, 0, 0)
const dataURL = canvas.toDataURL(this.outputType)
this.$emit('export', dataURL)
}
}
}
4. 图片的拖拽功能
为了允许用户拖拽图片,我们需要在组件的mounted函数中添加以下代码:
mounted() {
// ...其他代码
const imageContainer = this.$refs.imageContainer
const image = imageContainer.querySelector('img')
// 监听图片的mousedown事件
image.addEventListener('mousedown', (e) => {
// 计算鼠标相对于图片的偏移量
const offsetX = e.clientX - image.offsetLeft
const offsetY = e.clientY - image.offsetTop
// 记录鼠标按下的位置
this.dragStartX = offsetX
this.dragStartY = offsetY
// 设置图片的capture属性,以便在拖拽图片时仍然能够捕捉鼠标事件
image.setCapture()
// 监听鼠标的mousemove和mouseup事件
document.addEventListener('mousemove', this.onDragMove)
document.addEventListener('mouseup', this.onDragEnd)
})
}
在onDragMove和onDragEnd函数中,我们需要更新图片的位置并重新绘制Canvas:
onDragMove(e) {
// 计算鼠标移动的距离
const dx = e.clientX - this.dragStartX
const dy = e.clientY - this.dragStartY
// 更新图片的位置
this.image.style.left = `${this.image.offsetLeft + dx}px`
this.image.style.top = `${this.image.offsetTop + dy}px`
// 重新绘制Canvas
this.drawCanvas()
}
onDragEnd() {
// 释放鼠标的capture属性
this.image.releaseCapture()
// 移除鼠标的mousemove和mouseup事件监听器
document.removeEventListener('mousemove', this.onDragMove)
document.removeEventListener('mouseup', this.onDragEnd)
}
5. 图片的缩放功能
为了允许用户缩放图片,我们需要在组件的mounted函数中添加以下代码:
mounted() {
// ...其他代码
const imageContainer = this.$refs.imageContainer
const image = imageContainer.querySelector('img')
// 监听图片的wheel事件
image.addEventListener('wheel', (e) => {
// 计算鼠标相对于图片的偏移量
const offsetX = e.clientX - image.offsetLeft
const offsetY = e.clientY - image.offsetTop
// 计算缩放的比例
const scale = e.deltaY > 0 ? 1.1 : 0.9
// 更新图片的宽高
this.image.style.width = `${this.image.offsetWidth * scale}px`
this.image.style.height = `${this.image.offsetHeight * scale}px`
// 重新计算裁剪框的位置和宽高
this.cropRect.width *= scale