<template>
<!--canvas要绑定键盘事件,首先要具有焦点(focus)。canvas、div等要具有焦点,元素要添加【tabindex="0"】属性-->
<canvas
id="cvs"
width="600"
height="600"
style="background-color: rgba(0, 0, 0, 0.1); outline: none"
tabindex="0"
></canvas>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
@Options({
components: {},
})
export default class Home extends Vue {
private rectangle: Array<Array<number>> = [];
mounted(): void {
let cvs = document.getElementById("cvs") as HTMLCanvasElement;
let ctx = cvs.getContext("2d") as CanvasRenderingContext2D;
cvs.onmousedown = (ev) => {
this.rectangle = [];
let onkeyDownMousePosition: Array<number> = [];
let onkeyDownRectPosition: Array<Array<number>> = [];
let onkeyDownStatus = false;
cvs.onmousemove = (event) => {
if (onkeyDownStatus) {
// 旋转
let angle = this.point3_angle(
[ev.offsetX, ev.offsetY],
onkeyDownMousePosition,
[event.offsetX, event.offsetY]
);
this.rectangle = [
this.point2angle_point(
[ev.offsetX, ev.offsetY],
onkeyDownRectPosition[0],
angle
),
this.point2angle_point(
[ev.offsetX, ev.offsetY],
onkeyDownRectPosition[1],
angle
),
this.point2angle_point(
[ev.offsetX, ev.offsetY],
onkeyDownRectPosition[2],
angle
),
this.point2angle_point(
[ev.offsetX, ev.offsetY],
onkeyDownRectPosition[3],
angle
),
];
} else {
// 缩放
const x = event.offsetX - ev.offsetX;
const y = event.offsetY - ev.offsetY;
this.rectangle = [
[ev.offsetX + x, ev.offsetY + y],
[ev.offsetX - x, ev.offsetY + y],
[ev.offsetX - x, ev.offsetY - y],
[ev.offsetX + x, ev.offsetY - y],
];
onkeyDownMousePosition = [event.offsetX, event.offsetY];
onkeyDownRectPosition = [...this.rectangle];
}
this.drawerCanvas(ctx, [ev.offsetX, ev.offsetY]);
};
cvs.onkeydown = (event) => {
onkeyDownStatus = event.shiftKey;
};
cvs.onkeyup = (event) => {
onkeyDownStatus = event.shiftKey;
};
};
cvs.onmouseup = () => {
cvs.onkeydown = null;
cvs.onkeyup = null;
cvs.onmousemove = null;
};
}
// 根据中心点、起点、终点算弧度
private point3_angle(
center: Array<number>,
start: Array<number>,
end: Array<number>
): number {
let endAngle = Math.atan2(end[1] - center[1], end[0] - center[0]);
let startAngle = Math.atan2(start[1] - center[1], start[0] - center[0]);
return endAngle - startAngle;
}
// 根据中心点、起点、旋转弧度算终点
private point2angle_point(
center: Array<number>,
start: Array<number>,
angle: number
): Array<number> {
const r = Math.sqrt(
Math.pow(start[0] - center[0], 2) + Math.pow(start[1] - center[1], 2)
);
const endAngle =
this.point3_angle(center, [center[0] + 1, center[1]], start) + angle;
let cosVal = Math.cos(endAngle);
let sinVal = Math.sin(endAngle);
if (cosVal > 1 || cosVal < -1) {
cosVal = 0;
}
if (sinVal > 1 || sinVal < -1) {
sinVal = 0;
}
return [cosVal * r + center[0], sinVal * r + center[1]];
}
private drawerCanvas(ctx: CanvasRenderingContext2D, center: Array<number>) {
const r = 3;
ctx.clearRect(0, 0, 600, 600);
ctx.lineWidth = 1;
ctx.strokeStyle = "rgb(0,255,0)";
ctx.setLineDash([3, 3]);
ctx.beginPath();
this.rectangle.forEach((li) => {
ctx.lineTo(li[0], li[1]);
});
ctx.closePath();
ctx.lineTo(center[0], center[1]);
ctx.stroke();
ctx.setLineDash([]);
this.rectangle.forEach((li) => {
ctx.clearRect(li[0] - r, li[1] - r, 2 * r, 2 * r);
ctx.beginPath();
ctx.arc(li[0], li[1], r, 0, 2 * Math.PI, true);
ctx.stroke();
});
}
}
</script>