fix: 修复多个已知问题
This commit is contained in:
@@ -345,7 +345,224 @@
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- 阴影设置 -->
|
||||
<div class="brush-section">
|
||||
<div class="section-header">
|
||||
<span>{{ $t("阴影设置") }}</span>
|
||||
</div>
|
||||
|
||||
<div class="property-list">
|
||||
<!-- 阴影开关 -->
|
||||
<div class="property-item">
|
||||
<div class="checkbox-property">
|
||||
<span>{{ $t("启用阴影") }}</span>
|
||||
<div class="toggle-switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
:checked="brushStore.state.shadowEnabled"
|
||||
@change="
|
||||
(e) =>
|
||||
handleShadowPropertyChange(
|
||||
'shadowEnabled',
|
||||
e.target.checked
|
||||
)
|
||||
"
|
||||
id="shadow-enabled"
|
||||
/>
|
||||
<label for="shadow-enabled"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 阴影控制组 - 仅在启用阴影时显示 -->
|
||||
<template v-if="brushStore.state.shadowEnabled">
|
||||
<!-- 阴影颜色 -->
|
||||
<div class="property-item">
|
||||
<div class="color-property">
|
||||
<div class="color-header">
|
||||
<span>{{ $t("阴影颜色") }}</span>
|
||||
<div
|
||||
class="color-preview"
|
||||
:style="{ backgroundColor: brushStore.state.shadowColor }"
|
||||
></div>
|
||||
</div>
|
||||
<div class="color-row">
|
||||
<input
|
||||
type="color"
|
||||
:value="brushStore.state.shadowColor"
|
||||
@input="
|
||||
(e) =>
|
||||
handleShadowPropertyChange(
|
||||
'shadowColor',
|
||||
e.target.value
|
||||
)
|
||||
"
|
||||
class="color-picker"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 阴影宽度 -->
|
||||
<div class="property-item">
|
||||
<div class="slider-property">
|
||||
<div class="slider-header">
|
||||
<span>{{ $t("阴影宽度") }}</span>
|
||||
<span class="slider-value"
|
||||
>{{ brushStore.state.shadowWidth }}px</span
|
||||
>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input
|
||||
type="range"
|
||||
:value="brushStore.state.shadowWidth"
|
||||
@input="
|
||||
(e) =>
|
||||
handleShadowPropertyChange(
|
||||
'shadowWidth',
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
"
|
||||
:min="0"
|
||||
:max="50"
|
||||
:step="1"
|
||||
class="property-slider"
|
||||
/>
|
||||
</div>
|
||||
<div class="property-presets">
|
||||
<button
|
||||
v-for="preset in [0, 5, 10, 15, 20]"
|
||||
:key="preset"
|
||||
@click="handleShadowPropertyChange('shadowWidth', preset)"
|
||||
:class="{
|
||||
active:
|
||||
Math.abs(brushStore.state.shadowWidth - preset) < 0.1,
|
||||
}"
|
||||
>
|
||||
{{ preset }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 阴影X偏移 -->
|
||||
<div class="property-item">
|
||||
<div class="slider-property">
|
||||
<div class="slider-header">
|
||||
<span>{{ $t("阴影X偏移") }}</span>
|
||||
<span class="slider-value"
|
||||
>{{ brushStore.state.shadowOffsetX }}px</span
|
||||
>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input
|
||||
type="range"
|
||||
:value="brushStore.state.shadowOffsetX"
|
||||
@input="
|
||||
(e) =>
|
||||
handleShadowPropertyChange(
|
||||
'shadowOffsetX',
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
"
|
||||
:min="-50"
|
||||
:max="50"
|
||||
:step="1"
|
||||
class="property-slider"
|
||||
/>
|
||||
</div>
|
||||
<div class="property-presets">
|
||||
<button
|
||||
v-for="preset in [-10, -5, 0, 5, 10]"
|
||||
:key="preset"
|
||||
@click="
|
||||
handleShadowPropertyChange('shadowOffsetX', preset)
|
||||
"
|
||||
:class="{
|
||||
active:
|
||||
Math.abs(brushStore.state.shadowOffsetX - preset) <
|
||||
0.1,
|
||||
}"
|
||||
>
|
||||
{{ preset }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 阴影Y偏移 -->
|
||||
<div class="property-item">
|
||||
<div class="slider-property">
|
||||
<div class="slider-header">
|
||||
<span>{{ $t("阴影Y偏移") }}</span>
|
||||
<span class="slider-value"
|
||||
>{{ brushStore.state.shadowOffsetY }}px</span
|
||||
>
|
||||
</div>
|
||||
<div class="slider-container">
|
||||
<input
|
||||
type="range"
|
||||
:value="brushStore.state.shadowOffsetY"
|
||||
@input="
|
||||
(e) =>
|
||||
handleShadowPropertyChange(
|
||||
'shadowOffsetY',
|
||||
parseFloat(e.target.value)
|
||||
)
|
||||
"
|
||||
:min="-50"
|
||||
:max="50"
|
||||
:step="1"
|
||||
class="property-slider"
|
||||
/>
|
||||
</div>
|
||||
<div class="property-presets">
|
||||
<button
|
||||
v-for="preset in [-10, -5, 0, 5, 10]"
|
||||
:key="preset"
|
||||
@click="
|
||||
handleShadowPropertyChange('shadowOffsetY', preset)
|
||||
"
|
||||
:class="{
|
||||
active:
|
||||
Math.abs(brushStore.state.shadowOffsetY - preset) <
|
||||
0.1,
|
||||
}"
|
||||
>
|
||||
{{ preset }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 阴影预览 -->
|
||||
<div class="property-item">
|
||||
<div class="shadow-preview-container">
|
||||
<div class="shadow-preview-title">{{ $t("阴影预览") }}</div>
|
||||
<div class="shadow-preview-box">
|
||||
<div
|
||||
class="shadow-preview-element"
|
||||
:style="{
|
||||
backgroundColor: brushStore.state.color,
|
||||
width: `${Math.max(
|
||||
20,
|
||||
Math.min(60, brushStore.state.size)
|
||||
)}px`,
|
||||
height: `${Math.max(
|
||||
20,
|
||||
Math.min(60, brushStore.state.size)
|
||||
)}px`,
|
||||
boxShadow: brushStore.state.shadowEnabled
|
||||
? `${brushStore.state.shadowOffsetX}px ${brushStore.state.shadowOffsetY}px ${brushStore.state.shadowWidth}px ${brushStore.state.shadowColor}`
|
||||
: 'none',
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 笔刷预设 -->
|
||||
<div class="brush-section">
|
||||
<div class="section-header">
|
||||
@@ -625,6 +842,14 @@ const debouncedPropertyCommand = debounce((propId, value) => {
|
||||
commandManager.execute(command, { nonUndoable: true });
|
||||
}, 200);
|
||||
|
||||
// 处理阴影属性变化的防抖函数
|
||||
const debouncedShadowCommand = debounce((propId, value) => {
|
||||
// 通知工具管理器更新阴影
|
||||
if (toolManager?.brushManager) {
|
||||
toolManager.brushManager.updateShadow();
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// 处理属性变化
|
||||
function handlePropertyChange(propId, value) {
|
||||
// 直接更新UI,通过防抖函数延迟创建命令
|
||||
@@ -632,6 +857,25 @@ function handlePropertyChange(propId, value) {
|
||||
debouncedPropertyCommand(propId, value);
|
||||
}
|
||||
|
||||
// 处理阴影属性变化
|
||||
function handleShadowPropertyChange(propId, value) {
|
||||
// 更新BrushStore中的阴影属性
|
||||
if (propId === "shadowEnabled") {
|
||||
BrushStore.setShadowEnabled(value);
|
||||
} else if (propId === "shadowColor") {
|
||||
BrushStore.setShadowColor(value);
|
||||
} else if (propId === "shadowWidth") {
|
||||
BrushStore.setShadowWidth(value);
|
||||
} else if (propId === "shadowOffsetX") {
|
||||
BrushStore.setShadowOffsetX(value);
|
||||
} else if (propId === "shadowOffsetY") {
|
||||
BrushStore.setShadowOffsetY(value);
|
||||
}
|
||||
|
||||
// 通知笔刷管理器更新阴影设置
|
||||
debouncedShadowCommand(propId, value);
|
||||
}
|
||||
|
||||
// 使用命令设置笔刷类型
|
||||
function setBrushTypeWithCommand(type) {
|
||||
const command = new BrushTypeCommand({
|
||||
@@ -1761,4 +2005,65 @@ const brushStore = BrushStore;
|
||||
background-color: rgba(244, 67, 54, 1);
|
||||
transform: scale(1.2) !important;
|
||||
}
|
||||
|
||||
/* 阴影设置样式 */
|
||||
.shadow-preview-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.shadow-preview-title {
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.shadow-preview-box {
|
||||
background: repeating-conic-gradient(#f5f5f5 0% 25%, #ffffff 0% 50%) 50% /
|
||||
10px 10px;
|
||||
border-radius: 8px;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 120px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.shadow-preview-element {
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.brush-panel {
|
||||
width: 95%;
|
||||
right: 2.5%;
|
||||
max-height: 75vh;
|
||||
}
|
||||
|
||||
.shadow-preview-box {
|
||||
min-height: 100px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.property-presets {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.brush-type-grid,
|
||||
.presets-container,
|
||||
.texture-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user