228 lines
7.4 KiB
Vue
228 lines
7.4 KiB
Vue
<template>
|
|
<div class="tool-mid-box-left">
|
|
<!-- 工具循环 -->
|
|
<div class="tool-box-cell-box-left" v-for="item in tools" :key="item.shapeType">
|
|
<!-- <el-tooltip :content="item.name" placement="top-end">
|
|
<div class="tool-box-cell" @click="clickAppliance(item.shapeType)">
|
|
<img :src="item.shapeType === currentShapType ? item.iconActive : item.icon" :alt="item.name" />
|
|
</div>
|
|
</el-tooltip> -->
|
|
<el-tooltip :content="item.name" placement="top-end">
|
|
<div class="tool-box-cell" @click="clickAppliance(item.shapeType)">
|
|
<img
|
|
:src="(
|
|
// 当前是该工具
|
|
item.shapeType === currentShapType
|
|
// 当前在选颜色 / 粗细时保持上一个绘图工具高亮
|
|
|| (['colorSelector','brushSize'].includes(currentShapType) && item.shapeType === lastDrawingTool)
|
|
)
|
|
? item.iconActive
|
|
: item.icon"
|
|
:alt="item.name"
|
|
/>
|
|
|
|
</div>
|
|
</el-tooltip>
|
|
|
|
<!-- 颜色选择器 -->
|
|
<div v-if="item.shapeType === 'colorSelector' && currentShapType === 'colorSelector' && colorSelectorControl"
|
|
class="tool-popup">
|
|
<el-color-picker ref="colorPickerRef" v-model="selectedColor" v-model:visible="colorVisible" show-alpha
|
|
@change="handleColorChange" />
|
|
</div>
|
|
|
|
<!-- 画笔大小选择器 -->
|
|
<div v-if="item.shapeType === 'brushSize' && currentShapType === 'brushSize' && brushSizeControl"
|
|
class="tool-popup">
|
|
<el-select ref="brushSizeRef" v-model="selectedThickness" placeholder="画笔粗细" size="small"
|
|
@change="handleThicknessChange" v-model:visible="brushSizeVisible" style="width: 60px">
|
|
<el-option v-for="size in thicknessOptions" :key="size" :label="size + 'px'" :value="size" />
|
|
</el-select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, nextTick, onMounted, onBeforeUnmount } from "vue";
|
|
|
|
const props = defineProps({
|
|
canvas: {
|
|
type: Object,
|
|
required: true,
|
|
validator: (value) => value && typeof value.setDrawingTool === "function",
|
|
},
|
|
});
|
|
|
|
// 工具图标导入
|
|
import pen from "./image/pencil.svg";
|
|
import penActive from "./image/pencil-active.svg";
|
|
import eraser from "./image/eraser.svg";
|
|
import eraserActive from "./image/eraser-active.svg";
|
|
import ellipse from "./image/ellipse.svg";
|
|
import ellipseActive from "./image/ellipse-active.svg";
|
|
import rectangle from "./image/rectangle.svg";
|
|
import rectangleActive from "./image/rectangle-active.svg";
|
|
import straight from "./image/straight.svg";
|
|
import straightActive from "./image/straight-active.svg";
|
|
import brushSize from "./image/brushSize.svg";
|
|
import brushSizeActive from "./image/brushSize-active.svg";
|
|
import colorSelector from "./image/colorSelector.svg";
|
|
import colorSelectorActive from "./image/colorSelector-active.svg";
|
|
|
|
const tools = ref([
|
|
{ name: "笔", icon: pen, iconActive: penActive, shapeType: "pencil" },
|
|
{ name: "圆形", icon: ellipse, iconActive: ellipseActive, shapeType: "circle" },
|
|
{ name: "矩形", icon: rectangle, iconActive: rectangleActive, shapeType: "rectangle" },
|
|
{ name: "直线", icon: straight, iconActive: straightActive, shapeType: "line" },
|
|
{ name: "选色器", icon: colorSelector, iconActive: colorSelectorActive, shapeType: "colorSelector" },
|
|
{ name: "画笔大小", icon: brushSize, iconActive: brushSizeActive, shapeType: "brushSize" },
|
|
{ name: "橡皮擦", icon: eraser, iconActive: eraserActive, shapeType: "eraser" },
|
|
]);
|
|
|
|
// 状态
|
|
const selectedColor = ref("#ffcc00");
|
|
const selectedThickness = ref(2);
|
|
const thicknessOptions = [1, 2, 4, 8, 16];
|
|
|
|
const colorSelectorControl = ref(false);
|
|
const brushSizeControl = ref(false);
|
|
const colorVisible = ref(false);
|
|
const brushSizeVisible = ref(false);
|
|
|
|
const currentShapType = ref("pencil"); // 当前点击的工具
|
|
const lastDrawingTool = ref("pencil"); // 记录最后一个绘图工具
|
|
|
|
// refs
|
|
const colorPickerRef = ref();
|
|
const brushSizeRef = ref();
|
|
|
|
// 颜色选择逻辑
|
|
const handleColorChange = (color) => {
|
|
props.canvas?.setColor(color);
|
|
colorSelectorControl.value = false;
|
|
colorVisible.value = false;
|
|
};
|
|
|
|
// 粗细选择逻辑
|
|
const handleThicknessChange = (size) => {
|
|
props.canvas?.setThickness(size);
|
|
brushSizeControl.value = false;
|
|
brushSizeVisible.value = false;
|
|
};
|
|
|
|
// 点击工具逻辑
|
|
function clickAppliance(type) {
|
|
// 点击同一个工具时切换关闭
|
|
if (currentShapType.value === type) {
|
|
if (type === "colorSelector") {
|
|
colorSelectorControl.value = !colorSelectorControl.value;
|
|
colorVisible.value = colorSelectorControl.value;
|
|
} else if (type === "brushSize") {
|
|
brushSizeControl.value = !brushSizeControl.value;
|
|
brushSizeVisible.value = brushSizeControl.value;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// 切换到新工具
|
|
currentShapType.value = type;
|
|
lastDrawingTool.value = type; // 记录最新绘图工具
|
|
if (type === "colorSelector") {
|
|
colorSelectorControl.value = true;
|
|
brushSizeControl.value = false;
|
|
nextTick(() => {
|
|
colorVisible.value = true;
|
|
});
|
|
} else if (type === "brushSize") {
|
|
brushSizeControl.value = true;
|
|
colorSelectorControl.value = false;
|
|
nextTick(() => {
|
|
brushSizeVisible.value = true;
|
|
});
|
|
} else {
|
|
colorSelectorControl.value = false;
|
|
brushSizeControl.value = false;
|
|
colorVisible.value = false;
|
|
brushSizeVisible.value = false;
|
|
props.canvas?.setDrawingTool(type);
|
|
}
|
|
|
|
}
|
|
|
|
// 点击工具栏外部关闭弹窗
|
|
function handleClickOutside(event) {
|
|
const toolBox = document.querySelector(".tool-mid-box-left");
|
|
if (!toolBox.contains(event.target)) {
|
|
// colorSelectorControl.value = false;
|
|
brushSizeControl.value = false;
|
|
// colorVisible.value = false;
|
|
brushSizeVisible.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (!props.canvas || typeof props.canvas.setDrawingTool !== "function") {
|
|
console.error("Invalid canvas prop passed to ToolBox");
|
|
}
|
|
document.addEventListener("click", handleClickOutside);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
document.removeEventListener("click", handleClickOutside);
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.tool-mid-box-left {
|
|
width: 40px;
|
|
display: flex;
|
|
border-radius: 4px;
|
|
background-color: white;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
flex-direction: column;
|
|
padding: 4px 0;
|
|
box-shadow: 0 8px 24px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.tool-box-cell {
|
|
width: 24px;
|
|
height: 24px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
position: relative;
|
|
}
|
|
|
|
.tool-box-cell-box-left {
|
|
width: 32px;
|
|
height: 32px;
|
|
user-select: none;
|
|
cursor: pointer;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
border-radius: 2px;
|
|
position: relative;
|
|
|
|
&:hover {
|
|
background: rgba(33, 35, 36, 0.1);
|
|
}
|
|
}
|
|
|
|
/* 弹出层样式:显示在图标右侧 */
|
|
.tool-popup {
|
|
position: absolute;
|
|
left: 40px;
|
|
/* 距离工具栏宽度 */
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
background: white;
|
|
padding: 6px;
|
|
border-radius: 4px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
z-index: 1000;
|
|
}
|
|
</style> |