2025-06-09 10:25:54 +08:00
|
|
|
|
<script setup>
|
|
|
|
|
|
import {
|
|
|
|
|
|
inject,
|
|
|
|
|
|
ref,
|
|
|
|
|
|
provide,
|
|
|
|
|
|
onMounted,
|
|
|
|
|
|
computed,
|
|
|
|
|
|
watch,
|
|
|
|
|
|
onUnmounted,
|
|
|
|
|
|
} from "vue";
|
|
|
|
|
|
import { OperationType } from "../utils/layerHelper";
|
|
|
|
|
|
import BrushPanel from "./BrushPanel.vue";
|
|
|
|
|
|
import { BrushStore } from "../store/BrushStore";
|
|
|
|
|
|
// 提供brushStore给子组件
|
|
|
|
|
|
provide("brushStore", BrushStore);
|
|
|
|
|
|
|
|
|
|
|
|
const toolManager = inject("toolManager");
|
|
|
|
|
|
const layerManager = inject("layerManager");
|
2025-06-18 11:05:23 +08:00
|
|
|
|
const isShowLayerPanel = inject("isShowLayerPanel", ref(false));
|
2025-06-09 10:25:54 +08:00
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
|
activeTool: String,
|
|
|
|
|
|
canvasWidth: Number,
|
|
|
|
|
|
canvasHeight: Number,
|
|
|
|
|
|
canvasColor: String,
|
|
|
|
|
|
brushSize: Number,
|
2025-06-18 11:05:23 +08:00
|
|
|
|
enabledRedGreenMode: Boolean,
|
2025-06-09 10:25:54 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits([
|
|
|
|
|
|
"update:canvasWidth",
|
|
|
|
|
|
"update:canvasHeight",
|
|
|
|
|
|
"update:canvasColor",
|
|
|
|
|
|
"update:brushSize",
|
|
|
|
|
|
"canvas-size-change",
|
|
|
|
|
|
"canvas-color-change",
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// 笔刷面板相关状态
|
|
|
|
|
|
const showBrushPanel = ref(false);
|
|
|
|
|
|
const brushPanelRef = ref(null);
|
|
|
|
|
|
|
|
|
|
|
|
// 计算属性
|
2025-06-18 11:05:23 +08:00
|
|
|
|
// const shouldShowBrushSettings = computed(() => {
|
|
|
|
|
|
// return props.activeTool === OperationType.DRAW;
|
|
|
|
|
|
// });
|
2025-06-09 10:25:54 +08:00
|
|
|
|
|
2025-06-22 13:52:28 +08:00
|
|
|
|
function updateCanvasSize(
|
|
|
|
|
|
{ width, height } = { width: props.width, height: props.height }
|
|
|
|
|
|
) {
|
2025-06-09 10:25:54 +08:00
|
|
|
|
if (!layerManager) {
|
|
|
|
|
|
console.warn("LayerManager 未初始化,无法调整背景层尺寸");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-22 13:52:28 +08:00
|
|
|
|
layerManager.resizeCanvas(width, height);
|
|
|
|
|
|
|
|
|
|
|
|
// // 检查画布上是否有除了背景层的其他元素
|
|
|
|
|
|
// const hasOtherElements = layerManager.layers.value.some((layer) => {
|
|
|
|
|
|
// if (layer.isBackground) return false;
|
|
|
|
|
|
// // 检查普通图层是否有对象
|
|
|
|
|
|
// if (layer.fabricObjects && layer.fabricObjects.length > 0) return true;
|
|
|
|
|
|
// // 检查固定图层是否有对象
|
|
|
|
|
|
// if (layer.isFixed && layer.fabricObjects && layer.fabricObjects.length > 0)
|
|
|
|
|
|
// return true;
|
|
|
|
|
|
// return false;
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
// if (hasOtherElements) {
|
|
|
|
|
|
// // 有其他元素时使用等比缩放命令
|
|
|
|
|
|
// layerManager.resizeCanvasWithScale(width, height);
|
|
|
|
|
|
// } else {
|
|
|
|
|
|
// // 只有背景层时使用普通调整命令
|
|
|
|
|
|
// layerManager.resizeCanvas(width, height);
|
|
|
|
|
|
// }
|
2025-06-09 10:25:54 +08:00
|
|
|
|
|
|
|
|
|
|
emit("canvas-size-change");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateCanvasColor() {
|
|
|
|
|
|
if (!layerManager) {
|
|
|
|
|
|
console.warn("LayerManager 未初始化,无法更改背景色");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新背景层颜色而不是画布颜色
|
|
|
|
|
|
layerManager.updateBackgroundColor(props.canvasColor);
|
|
|
|
|
|
|
|
|
|
|
|
emit("canvas-color-change");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 切换笔刷面板显示状态
|
|
|
|
|
|
function toggleBrushPanel() {
|
2025-06-18 11:05:23 +08:00
|
|
|
|
// 如果笔刷没有激活 则激活笔刷工具
|
|
|
|
|
|
if (toolManager?.activeTool !== OperationType.DRAW) {
|
|
|
|
|
|
toolManager.setToolWithCommand(OperationType.DRAW);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-09 10:25:54 +08:00
|
|
|
|
showBrushPanel.value = !showBrushPanel.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理笔刷大小变化
|
|
|
|
|
|
function handleBrushSizeChange(event) {
|
|
|
|
|
|
const newSize = parseFloat(event.target.value);
|
|
|
|
|
|
emit("update:brushSize", newSize);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理笔刷设置变化,将BrushStore的数据同步到brushManager
|
|
|
|
|
|
function syncBrushStoreToManager() {
|
|
|
|
|
|
if (!toolManager?.brushManager) return;
|
|
|
|
|
|
|
|
|
|
|
|
const brushManager = toolManager.brushManager;
|
|
|
|
|
|
|
|
|
|
|
|
// 检查画笔是否正在更新中
|
|
|
|
|
|
if (brushManager.isUpdatingBrush) {
|
|
|
|
|
|
console.warn("画笔正在更新中,请稍候...");
|
|
|
|
|
|
// 延迟重试,确保在画笔更新完成后应用最新设置
|
|
|
|
|
|
setTimeout(syncBrushStoreToManager, 100);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听BrushStore的变化,更新brushManager
|
|
|
|
|
|
const size = BrushStore.state.size;
|
|
|
|
|
|
const color = BrushStore.state.color;
|
|
|
|
|
|
const type = BrushStore.state.type;
|
|
|
|
|
|
const opacity = BrushStore.state.opacity;
|
|
|
|
|
|
const textureEnabled = BrushStore.state.textureEnabled;
|
|
|
|
|
|
const texturePath = BrushStore.state.texturePath;
|
|
|
|
|
|
const textureScale = BrushStore.state.textureScale;
|
|
|
|
|
|
|
|
|
|
|
|
// 将所有更改一次性应用,减少updateBrush调用次数
|
|
|
|
|
|
let needsUpdate = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
brushManager.brushSize &&
|
|
|
|
|
|
typeof brushManager.setBrushSize === "function" &&
|
|
|
|
|
|
brushManager.getBrushSize() !== size
|
|
|
|
|
|
) {
|
|
|
|
|
|
brushManager.brushSize.value = size; // 直接设置值,避免触发updateBrush
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
brushManager.brushColor &&
|
|
|
|
|
|
typeof brushManager.setBrushColor === "function" &&
|
|
|
|
|
|
brushManager.getBrushColor() !== color
|
|
|
|
|
|
) {
|
|
|
|
|
|
brushManager.brushColor.value = color; // 直接设置值,避免触发updateBrush
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
typeof brushManager.setBrushType === "function" &&
|
|
|
|
|
|
brushManager.getCurrentBrushType() !== type
|
|
|
|
|
|
) {
|
|
|
|
|
|
brushManager.setBrushType(type);
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof brushManager.setBrushOpacity === "function") {
|
|
|
|
|
|
brushManager.setBrushOpacity(opacity);
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 同步材质相关设置
|
|
|
|
|
|
if (textureEnabled && texturePath) {
|
|
|
|
|
|
if (typeof brushManager.setTexturePath === "function") {
|
|
|
|
|
|
brushManager.setTexturePath(texturePath);
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
typeof brushManager.setTextureScale === "function" &&
|
|
|
|
|
|
brushManager.getTextureScale() !== textureScale
|
|
|
|
|
|
) {
|
|
|
|
|
|
brushManager.textureScale.value = textureScale; // 直接设置值,避免触发updateBrush
|
|
|
|
|
|
needsUpdate = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 只在有变化时调用一次updateBrush,减少重绘次数
|
|
|
|
|
|
if (needsUpdate && typeof brushManager.updateBrush === "function") {
|
|
|
|
|
|
brushManager.updateBrush();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 点击外部时关闭笔刷面板
|
|
|
|
|
|
function handleClickOutside(event) {
|
2025-06-18 11:05:23 +08:00
|
|
|
|
// if (isShowLayerPanel.value) {
|
|
|
|
|
|
// // 如果点击的是图层面板或其内部元素,则不关闭
|
|
|
|
|
|
// if (event.target.closest(".layers-panel")) {
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// // 关闭图层面板
|
|
|
|
|
|
// isShowLayerPanel.value = false;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
if (showBrushPanel.value) {
|
|
|
|
|
|
// 检查是否点击了笔刷选择器按钮
|
|
|
|
|
|
if (event.target.closest(".brush-selector")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否点击了笔刷面板或其内部元素
|
|
|
|
|
|
if (event.target.closest(".brush-panel")) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果都不是,则关闭面板
|
|
|
|
|
|
if (showBrushPanel.value) {
|
|
|
|
|
|
showBrushPanel.value = false;
|
|
|
|
|
|
}
|
2025-06-09 10:25:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-18 11:05:23 +08:00
|
|
|
|
function showLayerPanel() {
|
|
|
|
|
|
isShowLayerPanel.value = !isShowLayerPanel.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-09 10:25:54 +08:00
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
// 获取工具管理器和笔刷管理器
|
|
|
|
|
|
const brushManager = toolManager?.brushManager;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置初始的可用笔刷类型
|
|
|
|
|
|
if (brushManager) {
|
|
|
|
|
|
const availableBrushes = brushManager.getBrushTypes();
|
|
|
|
|
|
BrushStore.setAvailableBrushes(availableBrushes);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化BrushStore与brushManager的数据同步
|
|
|
|
|
|
BrushStore.setBrushSize(brushManager.brushSize?.value || 5);
|
|
|
|
|
|
BrushStore.setBrushColor(brushManager.brushColor?.value || "#000000");
|
|
|
|
|
|
BrushStore.setBrushType(brushManager.getCurrentBrushType() || "pencil");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 添加点击外部关闭面板的事件监听
|
|
|
|
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
|
|
|
|
|
|
|
|
|
|
// 监听BrushStore的变化,同步到brushManager
|
|
|
|
|
|
const unwatch = watch(
|
|
|
|
|
|
() => [
|
|
|
|
|
|
BrushStore.state.size,
|
|
|
|
|
|
BrushStore.state.color,
|
|
|
|
|
|
BrushStore.state.type,
|
|
|
|
|
|
BrushStore.state.opacity,
|
|
|
|
|
|
BrushStore.state.textureEnabled,
|
|
|
|
|
|
BrushStore.state.texturePath,
|
|
|
|
|
|
BrushStore.state.textureScale,
|
|
|
|
|
|
],
|
|
|
|
|
|
syncBrushStoreToManager,
|
|
|
|
|
|
{ deep: true }
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 组件卸载时移除事件监听
|
|
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
|
|
|
|
unwatch();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div class="canvas-header">
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<div class="canvas-header-wrapper">
|
|
|
|
|
|
<span class="canvas-title">Canvas</span>
|
|
|
|
|
|
<!-- 默认设置 -->
|
|
|
|
|
|
<!-- v-if="
|
2025-06-09 10:25:54 +08:00
|
|
|
|
!activeTool ||
|
|
|
|
|
|
activeTool === OperationType.SELECT ||
|
|
|
|
|
|
activeTool === OperationType.PAN
|
2025-06-18 11:05:23 +08:00
|
|
|
|
" -->
|
|
|
|
|
|
<div class="canvas-settings" v-if="!props.enabledRedGreenMode">
|
|
|
|
|
|
<div class="setting-group">
|
2025-06-22 13:52:28 +08:00
|
|
|
|
<span class="setting-label">{{ $t("宽度") }}</span>
|
|
|
|
|
|
<a-input-number
|
2025-06-18 11:05:23 +08:00
|
|
|
|
:value="canvasWidth"
|
|
|
|
|
|
class="setting-input"
|
2025-06-22 13:52:28 +08:00
|
|
|
|
:min="1"
|
|
|
|
|
|
:max="9999"
|
|
|
|
|
|
:step="1"
|
|
|
|
|
|
@change="
|
|
|
|
|
|
(value) => {
|
|
|
|
|
|
$emit('update:canvasWidth', value);
|
|
|
|
|
|
updateCanvasSize({ width: value, height: canvasHeight });
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="setting-group">
|
2025-06-22 13:52:28 +08:00
|
|
|
|
<span class="setting-label">{{ $t("高度") }}</span>
|
|
|
|
|
|
<a-input-number
|
2025-06-18 11:05:23 +08:00
|
|
|
|
:value="canvasHeight"
|
|
|
|
|
|
class="setting-input"
|
2025-06-22 13:52:28 +08:00
|
|
|
|
:min="1"
|
|
|
|
|
|
:max="9999"
|
|
|
|
|
|
:step="1"
|
|
|
|
|
|
@change="
|
|
|
|
|
|
(value) => {
|
|
|
|
|
|
$emit('update:canvasHeight', value);
|
|
|
|
|
|
updateCanvasSize({ width: canvasWidth, height: value });
|
|
|
|
|
|
}
|
|
|
|
|
|
"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="setting-group">
|
2025-06-22 13:52:28 +08:00
|
|
|
|
<span class="setting-label">{{ $t("颜色") }}</span>
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<div class="color-picker-wrapper">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="color"
|
|
|
|
|
|
:value="canvasColor"
|
|
|
|
|
|
class="color-picker"
|
|
|
|
|
|
@input="$emit('update:canvasColor', $event.target.value)"
|
|
|
|
|
|
@change="updateCanvasColor"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<span class="color-dropdown">▼</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-09 10:25:54 +08:00
|
|
|
|
</div>
|
2025-06-18 11:05:23 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- <div class="setting-group">
|
|
|
|
|
|
<span class="setting-label">颜色:</span>
|
2025-06-09 10:25:54 +08:00
|
|
|
|
<div class="color-picker-wrapper">
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="color"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
:value="BrushStore.state.color"
|
2025-06-09 10:25:54 +08:00
|
|
|
|
class="color-picker"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
@input="BrushStore.setBrushColor($event.target.value)"
|
2025-06-09 10:25:54 +08:00
|
|
|
|
/>
|
|
|
|
|
|
<span class="color-dropdown">▼</span>
|
|
|
|
|
|
</div>
|
2025-06-18 11:05:23 +08:00
|
|
|
|
</div> -->
|
2025-06-09 10:25:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<!-- 导出设置 -->
|
|
|
|
|
|
<!-- <div class="setting-group export-group">
|
|
|
|
|
|
<span class="export-model-select">exportModel.select:</span>
|
|
|
|
|
|
<span class="export-model-dropdown">▼</span>
|
|
|
|
|
|
</div> -->
|
2025-06-09 10:25:54 +08:00
|
|
|
|
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<!-- 绘图工具设置 -->
|
2025-06-22 13:52:28 +08:00
|
|
|
|
<div class="canvas-settings gap-20">
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="btn"
|
|
|
|
|
|
:class="{ active: showBrushPanel }"
|
|
|
|
|
|
@click="toggleBrushPanel"
|
2025-06-22 13:52:28 +08:00
|
|
|
|
v-if="!props.enabledRedGreenMode"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
>
|
|
|
|
|
|
<!-- <span class="setting-label">笔刷:</span>/ -->
|
|
|
|
|
|
<div class="brush-selector">
|
|
|
|
|
|
<SvgIcon name="CBrushTop" size="22"></SvgIcon>
|
|
|
|
|
|
<!-- <div
|
2025-06-09 10:25:54 +08:00
|
|
|
|
class="brush-preview"
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
backgroundColor: BrushStore.state.color,
|
|
|
|
|
|
height: BrushStore.state.type === 'marker' ? '4px' : '2px',
|
|
|
|
|
|
opacity: BrushStore.state.opacity,
|
|
|
|
|
|
}"
|
2025-06-18 11:05:23 +08:00
|
|
|
|
></div> -->
|
|
|
|
|
|
<!-- <span class="brush-dropdown">▼</span> -->
|
2025-06-09 10:25:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 笔刷面板 -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
v-if="showBrushPanel"
|
|
|
|
|
|
class="brush-panel-container"
|
|
|
|
|
|
ref="brushPanelRef"
|
|
|
|
|
|
>
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<Teleport to="body">
|
|
|
|
|
|
<BrushPanel />
|
|
|
|
|
|
</Teleport>
|
2025-06-09 10:25:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<div
|
|
|
|
|
|
class="btn"
|
|
|
|
|
|
:class="{ active: isShowLayerPanel }"
|
|
|
|
|
|
@click="showLayerPanel"
|
|
|
|
|
|
>
|
|
|
|
|
|
<SvgIcon name="CLayout" size="26"></SvgIcon>
|
2025-06-09 10:25:54 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
2025-06-18 11:05:23 +08:00
|
|
|
|
<style scoped lang="less">
|
2025-06-09 10:25:54 +08:00
|
|
|
|
.canvas-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
border-bottom: 1px solid #e0e0e0;
|
|
|
|
|
|
user-select: none;
|
2025-06-18 11:05:23 +08:00
|
|
|
|
height: 52px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
.canvas-header-wrapper {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex: auto;
|
|
|
|
|
|
}
|
2025-06-09 10:25:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.canvas-title {
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
margin-right: 30px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2025-06-18 11:05:23 +08:00
|
|
|
|
color: #333;
|
|
|
|
|
|
// &:before {
|
|
|
|
|
|
// // /* content: "⟳";
|
|
|
|
|
|
// // margin-right: 5px;
|
|
|
|
|
|
// // font-size: 14px; */
|
|
|
|
|
|
// }
|
2025-06-09 10:25:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.canvas-settings {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
2025-06-18 11:05:23 +08:00
|
|
|
|
gap: 8px;
|
|
|
|
|
|
color: #213547;
|
|
|
|
|
|
.btn {
|
|
|
|
|
|
width: 32px;
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
background-color: #f0f0f0;
|
|
|
|
|
|
|
|
|
|
|
|
&.active,
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
color: #1890ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
// color: #1890ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.gap-20 {
|
|
|
|
|
|
gap: 20px;
|
2025-06-09 10:25:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.setting-group {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.setting-label {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.setting-input {
|
2025-06-22 13:52:28 +08:00
|
|
|
|
width: 80px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.setting-input :deep(.ant-input-number-input) {
|
2025-06-09 10:25:54 +08:00
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.setting-select {
|
|
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
|
border: 1px solid #ddd;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.font-select {
|
|
|
|
|
|
width: 150px;
|
|
|
|
|
|
padding: 4px 8px;
|
|
|
|
|
|
border: 1px solid #ddd;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.color-picker-wrapper {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.color-picker {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
background: none;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.color-dropdown {
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.size-slider {
|
|
|
|
|
|
width: 100px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.size-value {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
min-width: 30px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.brush-selector {
|
2025-06-22 13:52:28 +08:00
|
|
|
|
display: block;
|
2025-06-09 10:25:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.brush-preview {
|
|
|
|
|
|
width: 20px;
|
|
|
|
|
|
height: 2px;
|
|
|
|
|
|
background-color: #000;
|
|
|
|
|
|
border-radius: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.brush-dropdown,
|
|
|
|
|
|
.export-model-dropdown {
|
|
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.export-model-select {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.export-group {
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 笔刷面板 */
|
|
|
|
|
|
.brush-panel-container {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: calc(100% + 5px);
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
width: 600px;
|
|
|
|
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|