canvas畫以中心點旋轉的矩形
阿新 • • 發佈:2021-10-14
<template> <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>