|
@@ -1,5 +1,10 @@
|
|
|
<template>
|
|
|
<el-card class="box-card">
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" @click="clickA()">翻转</el-button>
|
|
|
+ <el-button type="primary" @click="clickB()">旋转45°</el-button>
|
|
|
+ <el-button type="primary" @click="clickC()">旋转-45°</el-button>
|
|
|
+ </div>
|
|
|
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)">
|
|
|
<canvas ref="canvas" width="500" height="500" style="border: 1px solid #ccc"></canvas>
|
|
|
</div>
|
|
@@ -7,6 +12,8 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
+import { ElMessage } from "element-plus";
|
|
|
+
|
|
|
const imgs = [
|
|
|
{ name: "p1", url: "/img/miao.png" },
|
|
|
{ name: "p2", url: "/img/miao2.png" },
|
|
@@ -19,12 +26,12 @@ const width = ref(500);
|
|
|
const height = ref(500);
|
|
|
/** 图片数据 名字 位置等 */
|
|
|
const imagesData = ref([]);
|
|
|
+let clickCoordinate = { x: 0, y: 0 };
|
|
|
+let target = ref(undefined);
|
|
|
/** 图片拖拽 */
|
|
|
const init = () => {
|
|
|
ctx.value = canvas.value.getContext("2d");
|
|
|
/** 当前点击的信息 */
|
|
|
- let clickCoordinate = { x: 0, y: 0 };
|
|
|
- let target = ref("");
|
|
|
imgs.forEach((item) => {
|
|
|
let img = new Image();
|
|
|
img.src = item.url;
|
|
@@ -35,76 +42,149 @@ const init = () => {
|
|
|
const x = Math.random() * (width.value - w);
|
|
|
const y = Math.random() * (height.value - h);
|
|
|
const selectStatus = false;
|
|
|
- const obj = { img, name, x, y, w, h, selectStatus };
|
|
|
+ const angle = 0;
|
|
|
+ const obj = { img, name, x, y, w, h, selectStatus, angle };
|
|
|
imagesData.value.push(obj);
|
|
|
drawByObj(obj);
|
|
|
};
|
|
|
});
|
|
|
- function drawByObj(obj) {
|
|
|
- if (obj.selectStatus) {
|
|
|
- drawGuideByObj(obj);
|
|
|
- }
|
|
|
- ctx.value.drawImage(obj.img, obj.x, obj.y, obj.w, obj.h);
|
|
|
- }
|
|
|
- function drawGuideByObj(obj) {
|
|
|
- ctx.value.beginPath();
|
|
|
- ctx.value.lineWidth = 4;
|
|
|
- ctx.value.strokeStyle = "green";
|
|
|
- ctx.value.rect(obj.x, obj.y, obj.w, obj.h);
|
|
|
- ctx.value.stroke();
|
|
|
- }
|
|
|
canvas.value.addEventListener("mousedown", mousedownFn, false);
|
|
|
- function mousedownFn(e) {
|
|
|
- clickCoordinate.x = e.offsetX - canvas.value.offsetLeft;
|
|
|
- clickCoordinate.y = e.offsetY - canvas.value.offsetTop;
|
|
|
- checkElement();
|
|
|
- if (target.value == undefined) return;
|
|
|
- canvas.value.addEventListener("mousemove", mousemoveFn, false);
|
|
|
- canvas.value.addEventListener("mouseup", mouseupFn, false);
|
|
|
+};
|
|
|
+onMounted(() => {
|
|
|
+ init();
|
|
|
+});
|
|
|
+const drawByObj = (obj) => {
|
|
|
+ if (obj.selectStatus) {
|
|
|
+ drawGuideByObj(obj);
|
|
|
}
|
|
|
- /** 判断点击的是哪个 */
|
|
|
- function checkElement() {
|
|
|
- imagesData.value.forEach((item, index) => {
|
|
|
- drawGuideByObj(item);
|
|
|
- if (ctx.value.isPointInPath(clickCoordinate.x, clickCoordinate.y)) {
|
|
|
- console.log("点击的元素是:", item.name);
|
|
|
- target.value = index;
|
|
|
- item.selectStatus = true;
|
|
|
- return;
|
|
|
- } else {
|
|
|
- item.selectStatus = false;
|
|
|
- // 清空画布
|
|
|
- ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
- // 清空画布以后重新绘制
|
|
|
- imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+ ctx.value.save(); // 保存旧的坐标系状态
|
|
|
+ ctx.value.translate(obj.x + obj.w / 2, obj.y + obj.h / 2); // 坐标原点移动到旋转中心
|
|
|
+ ctx.value.rotate((obj.angle * Math.PI) / 180); // 旋转坐标系
|
|
|
+ ctx.value.translate(-(obj.x + obj.w / 2), -(obj.y + obj.h / 2)); // 坐标原点还原
|
|
|
+ ctx.value.drawImage(obj.img, obj.x, obj.y, obj.w, obj.h);
|
|
|
+ ctx.value.restore(); // 还原之前的坐标系状态
|
|
|
+};
|
|
|
+const drawGuideByObj = (obj) => {
|
|
|
+ ctx.value.save(); // 保存旧的坐标系状态
|
|
|
+ ctx.value.beginPath();
|
|
|
+ ctx.value.lineWidth = 4;
|
|
|
+ ctx.value.strokeStyle = "green";
|
|
|
+ ctx.value.translate(obj.x + obj.w / 2, obj.y + obj.h / 2); // 坐标原点移动到旋转中心
|
|
|
+ ctx.value.rotate((obj.angle * Math.PI) / 180); // 旋转坐标系
|
|
|
+ ctx.value.translate(-(obj.x + obj.w / 2), -(obj.y + obj.h / 2)); // 坐标原点还原
|
|
|
+ ctx.value.rect(obj.x, obj.y, obj.w, obj.h); // 以新坐标系为参照,画出矩形。
|
|
|
+ ctx.value.stroke();
|
|
|
+ ctx.value.restore(); // 还原之前的坐标系状态
|
|
|
+};
|
|
|
+const mousedownFn = (e) => {
|
|
|
+ clickCoordinate.x = e.offsetX - canvas.value.offsetLeft;
|
|
|
+ clickCoordinate.y = e.offsetY - canvas.value.offsetTop;
|
|
|
+ checkElement();
|
|
|
+ if (target.value == undefined) return;
|
|
|
+ canvas.value.addEventListener("mousemove", mousemoveFn, false);
|
|
|
+ canvas.value.addEventListener("mouseup", mouseupFn, false);
|
|
|
+};
|
|
|
+/** 判断点击的是哪个 */
|
|
|
+const checkElement = () => {
|
|
|
+ imagesData.value.forEach((item, index) => {
|
|
|
+ drawGuideByObj(item);
|
|
|
+ if (ctx.value.isPointInPath(clickCoordinate.x, clickCoordinate.y)) {
|
|
|
+ console.log("点击的元素是:", item.name);
|
|
|
+ target.value = index;
|
|
|
+ item.selectStatus = true;
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ item.selectStatus = false;
|
|
|
+ // 清空画布
|
|
|
+ ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
+ // 清空画布以后重新绘制
|
|
|
+ imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+const mousemoveFn = (e) => {
|
|
|
+ // 计算点击位置和图片原点位置的差
|
|
|
+ let sx = clickCoordinate.x - imagesData.value[target.value].x;
|
|
|
+ let sy = clickCoordinate.y - imagesData.value[target.value].y;
|
|
|
+ // 计算移动元素的坐标
|
|
|
+ imagesData.value[target.value].x = e.offsetX - canvas.value.offsetLeft - sx;
|
|
|
+ imagesData.value[target.value].y = e.offsetY - canvas.value.offsetTop - sy;
|
|
|
+ // 重新赋值点击位置
|
|
|
+ clickCoordinate.x = e.offsetX - canvas.value.offsetLeft;
|
|
|
+ clickCoordinate.y = e.offsetY - canvas.value.offsetTop;
|
|
|
+ // 清空画布
|
|
|
+ ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
+ // 清空画布以后重新绘制
|
|
|
+ imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+};
|
|
|
+const mouseupFn = () => {
|
|
|
+ // 鼠标抬起以后移除事件
|
|
|
+ canvas.value.removeEventListener("mousemove", mousemoveFn, false);
|
|
|
+ canvas.value.removeEventListener("mouseup", mouseupFn, false);
|
|
|
+ target.value = undefined;
|
|
|
+};
|
|
|
+const clickA = () => {
|
|
|
+ if (imagesData.value && imagesData.value.length > 0) {
|
|
|
+ let status = true;
|
|
|
+ for (let i = 0; i < imagesData.value.length; i++) {
|
|
|
+ if (imagesData.value[i].selectStatus) {
|
|
|
+ status = false;
|
|
|
+ break;
|
|
|
}
|
|
|
- });
|
|
|
+ }
|
|
|
+ if (status) {
|
|
|
+ return ElMessage("请选中元素");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ElMessage("请添加元素");
|
|
|
}
|
|
|
- function mousemoveFn(e) {
|
|
|
- // 计算点击位置和图片原点位置的差
|
|
|
- let sx = clickCoordinate.x - imagesData.value[target.value].x;
|
|
|
- let sy = clickCoordinate.y - imagesData.value[target.value].y;
|
|
|
- // 计算移动元素的坐标
|
|
|
- imagesData.value[target.value].x = e.offsetX - canvas.value.offsetLeft - sx;
|
|
|
- imagesData.value[target.value].y = e.offsetY - canvas.value.offsetTop - sy;
|
|
|
- // 重新赋值点击位置
|
|
|
- clickCoordinate.x = e.offsetX - canvas.value.offsetLeft;
|
|
|
- clickCoordinate.y = e.offsetY - canvas.value.offsetTop;
|
|
|
- // 清空画布
|
|
|
- ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
- // 清空画布以后重新绘制
|
|
|
- imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+};
|
|
|
+const clickB = () => {
|
|
|
+ if (imagesData.value && imagesData.value.length > 0) {
|
|
|
+ let status = true;
|
|
|
+ for (let i = 0; i < imagesData.value.length; i++) {
|
|
|
+ if (imagesData.value[i].selectStatus) {
|
|
|
+ imagesData.value[i].angle = imagesData.value[i].angle + 45;
|
|
|
+ status = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (status) {
|
|
|
+ return ElMessage("请选中元素");
|
|
|
+ } else {
|
|
|
+ // 清空画布
|
|
|
+ ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
+ // 清空画布以后重新绘制
|
|
|
+ imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ElMessage("请添加元素");
|
|
|
}
|
|
|
- function mouseupFn(e) {
|
|
|
- // 鼠标抬起以后移除事件
|
|
|
- canvas.value.removeEventListener("mousemove", mousemoveFn, false);
|
|
|
- canvas.value.removeEventListener("mouseup", mouseupFn, false);
|
|
|
- target.value = undefined;
|
|
|
+};
|
|
|
+const clickC = () => {
|
|
|
+ if (imagesData.value && imagesData.value.length > 0) {
|
|
|
+ let status = true;
|
|
|
+ for (let i = 0; i < imagesData.value.length; i++) {
|
|
|
+ if (imagesData.value[i].selectStatus) {
|
|
|
+ imagesData.value[i].angle = imagesData.value[i].angle - 45;
|
|
|
+ status = false;
|
|
|
+ console.log(imagesData.value);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (status) {
|
|
|
+ return ElMessage("请选中元素");
|
|
|
+ } else {
|
|
|
+ console.log(imagesData.value);
|
|
|
+ // 清空画布
|
|
|
+ ctx.value.clearRect(0, 0, width.value, height.value);
|
|
|
+ // 清空画布以后重新绘制
|
|
|
+ imagesData.value.forEach((i) => drawByObj(i));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return ElMessage("请添加元素");
|
|
|
}
|
|
|
};
|
|
|
-onMounted(() => {
|
|
|
- init();
|
|
|
-});
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped></style>
|