请帮我实现一个可拖拽、缩放、旋转的绘制多边形的vue组件
时间: 2024-06-11 22:05:11 浏览: 74
基于Vue实现拖拽效果
以下是一个可拖拽、缩放、旋转的绘制多边形的vue组件的实现:
```
<template>
<div class="polygon-wrapper">
<canvas ref="canvas"></canvas>
</div>
</template>
<script>
export default {
name: 'Polygon',
props: {
width: {
type: Number,
default: 300
},
height: {
type: Number,
default: 300
},
fillColor: {
type: String,
default: '#000'
},
strokeColor: {
type: String,
default: '#000'
},
strokeWidth: {
type: Number,
default: 2
},
points: {
type: Array,
default: () => []
}
},
data() {
return {
canvas: null,
context: null,
isDragging: false,
isResizing: false,
isRotating: false,
startX: 0,
startY: 0,
lastX: 0,
lastY: 0,
currentX: 0,
currentY: 0,
rotation: 0,
scale: 1,
centerX: 0,
centerY: 0,
polygonPoints: []
}
},
watch: {
points: {
handler() {
this.redraw()
},
deep: true
}
},
mounted() {
this.canvas = this.$refs.canvas
this.context = this.canvas.getContext('2d')
this.canvas.width = this.width
this.canvas.height = this.height
this.canvas.style.width = this.width + 'px'
this.canvas.style.height = this.height + 'px'
this.canvas.addEventListener('mousedown', this.onMouseDown)
this.canvas.addEventListener('mousemove', this.onMouseMove)
this.canvas.addEventListener('mouseup', this.onMouseUp)
this.canvas.addEventListener('mouseleave', this.onMouseLeave)
this.redraw()
},
methods: {
redraw() {
this.context.clearRect(0, 0, this.width, this.height)
this.context.save()
this.context.translate(this.centerX, this.centerY)
this.context.rotate(this.rotation)
this.context.scale(this.scale, this.scale)
this.context.translate(-this.centerX, -this.centerY)
this.context.fillStyle = this.fillColor
this.context.strokeStyle = this.strokeColor
this.context.lineWidth = this.strokeWidth
this.context.beginPath()
this.polygonPoints.forEach((point, index) => {
if (index === 0) {
this.context.moveTo(point.x, point.y)
} else {
this.context.lineTo(point.x, point.y)
}
})
this.context.closePath()
this.context.fill()
this.context.stroke()
this.context.restore()
},
getPolygonPoints() {
return this.points.map(point => {
const x = point.x * this.scale + this.centerX
const y = point.y * this.scale + this.centerY
return {
x: x,
y: y
}
})
},
onMouseDown(event) {
const { offsetX, offsetY } = event
const { left, top } = this.canvas.getBoundingClientRect()
const x = offsetX - left
const y = offsetY - top
this.startX = x
this.startY = y
const polygonPoints = this.getPolygonPoints()
const distance = this.getDistanceFromCenter(x, y, polygonPoints)
const angle = this.getAngleFromCenter(x, y, polygonPoints)
if (distance < 10) {
this.isDragging = true
} else if (distance > 10 && distance < 20) {
this.isResizing = true
} else if (distance > 20 && distance < 30) {
this.isRotating = true
}
this.lastX = x
this.lastY = y
},
onMouseMove(event) {
if (this.isDragging) {
const { offsetX, offsetY } = event
const { left, top } = this.canvas.getBoundingClientRect()
const x = offsetX - left
const y = offsetY - top
const dx = x - this.lastX
const dy = y - this.lastY
this.centerX += dx
this.centerY += dy
this.lastX = x
this.lastY = y
this.redraw()
} else if (this.isResizing) {
const { offsetX, offsetY } = event
const { left, top } = this.canvas.getBoundingClientRect()
const x = offsetX - left
const y = offsetY - top
const polygonPoints = this.getPolygonPoints()
const distance = this.getDistanceFromCenter(x, y, polygonPoints)
this.scale = distance / 20
this.redraw()
} else if (this.isRotating) {
const { offsetX, offsetY } = event
const { left, top } = this.canvas.getBoundingClientRect()
const x = offsetX - left
const y = offsetY - top
const polygonPoints = this.getPolygonPoints()
const angle = this.getAngleFromCenter(x, y, polygonPoints)
this.rotation = angle
this.redraw()
}
},
onMouseUp(event) {
this.isDragging = false
this.isResizing = false
this.isRotating = false
},
onMouseLeave(event) {
this.isDragging = false
this.isResizing = false
this.isRotating = false
},
getDistanceFromCenter(x, y, polygonPoints) {
const centerX = this.getCenterX(polygonPoints)
const centerY = this.getCenterY(polygonPoints)
return Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2))
},
getAngleFromCenter(x, y, polygonPoints) {
const centerX = this.getCenterX(polygonPoints)
const centerY = this.getCenterY(polygonPoints)
return Math.atan2(y - centerY, x - centerX)
},
getCenterX(polygonPoints) {
return polygonPoints.reduce((sum, point) => sum + point.x, 0) / polygonPoints.length
},
getCenterY(polygonPoints) {
return polygonPoints.reduce((sum, point) => sum + point.y, 0) / polygonPoints.length
}
},
beforeDestroy() {
this.canvas.removeEventListener('mousedown', this.onMouseDown)
this.canvas.removeEventListener('mousemove', this.onMouseMove)
this.canvas.removeEventListener('mouseup', this.onMouseUp)
this.canvas.removeEventListener('mouseleave', this.onMouseLeave)
}
}
</script>
<style>
.polygon-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
border: 1px solid #ccc;
}
</style>
```
使用方法:
```
<template>
<div>
<polygon :width="400" :height="400" :points="points" />
</div>
</template>
<script>
import Polygon from './components/Polygon.vue'
export default {
name: 'App',
components: {
Polygon
},
data() {
return {
points: [
{ x: 100, y: 100 },
{ x: 200, y: 100 },
{ x: 200, y: 200 },
{ x: 100, y: 200 }
]
}
}
}
</script>
```
阅读全文