项目初始化
This commit is contained in:
228
src/components/ToolBox/index.vue
Normal file
228
src/components/ToolBox/index.vue
Normal file
@@ -0,0 +1,228 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user