Match LibTV toolbar icons and edge glow
This commit is contained in:
parent
78c7395e75
commit
4acf95490d
@ -3154,11 +3154,11 @@ function CharacterPresetToolbar({
|
||||
onToolAction: (action: ImageToolbarAction, option?: string) => void;
|
||||
}) {
|
||||
const [toolbarMenu, setToolbarMenu] = useState<SceneToolbarMenu>(null);
|
||||
const iconActions: Array<{ action: ImageToolbarAction; icon: string; label: string }> = [
|
||||
{ action: "annotate", icon: "⌁", label: "标注" },
|
||||
{ action: "rotate", icon: "↔", label: "旋转" },
|
||||
{ action: "download", icon: "↓", label: "下载" },
|
||||
{ action: "preview", icon: "↗", label: "预览" },
|
||||
const iconActions: Array<{ action: Extract<ImageToolbarAction, "annotate" | "rotate" | "download" | "preview">; label: string }> = [
|
||||
{ action: "annotate", label: "标注" },
|
||||
{ action: "rotate", label: "旋转" },
|
||||
{ action: "download", label: "下载" },
|
||||
{ action: "preview", label: "预览" },
|
||||
];
|
||||
const activeToolbarMenu = toolbarMenu;
|
||||
|
||||
@ -3191,13 +3191,13 @@ function CharacterPresetToolbar({
|
||||
<div className="h-9 w-px bg-white/8" />
|
||||
{iconActions.map((item) => (
|
||||
<button
|
||||
className="flex h-10 w-10 items-center justify-center rounded-[8px] text-[28px] text-white/84 hover:bg-white/8"
|
||||
className="flex h-10 w-10 items-center justify-center rounded-[8px] text-white/84 hover:bg-white/8"
|
||||
key={item.action}
|
||||
onClick={() => onToolAction(item.action)}
|
||||
title={item.label}
|
||||
type="button"
|
||||
>
|
||||
{item.icon}
|
||||
<ImageToolbarActionGlyph action={item.action} />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@ -3216,6 +3216,43 @@ function CharacterPresetToolbar({
|
||||
);
|
||||
}
|
||||
|
||||
function ImageToolbarActionGlyph({ action }: { action: Extract<ImageToolbarAction, "annotate" | "rotate" | "download" | "preview"> }) {
|
||||
if (action === "annotate") {
|
||||
return (
|
||||
<svg aria-hidden="true" className="h-[26px] w-[26px]" fill="none" viewBox="0 0 26 26">
|
||||
<path d="M5.2 19.2c4.8-1.4 4.1-6.6 8.1-8.8l4.5-2.5 2.2 3.8-4.5 2.6c-3.8 2.1-4.6 5.8-9.6 7" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" />
|
||||
<path d="m16.8 8.6 2.3 4" stroke="currentColor" strokeLinecap="round" strokeWidth="2" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "rotate") {
|
||||
return (
|
||||
<svg aria-hidden="true" className="h-[26px] w-[26px]" fill="none" viewBox="0 0 26 26">
|
||||
<path d="M13 5v16" stroke="currentColor" strokeLinecap="round" strokeWidth="2" />
|
||||
<path d="M6.4 11.2c1.2-2.1 3.7-3.4 6.6-3.4 4.2 0 7.6 2.2 7.6 5s-3.4 5-7.6 5c-2.9 0-5.4-1.1-6.6-3.1" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
if (action === "download") {
|
||||
return (
|
||||
<svg aria-hidden="true" className="h-[26px] w-[26px]" fill="none" viewBox="0 0 26 26">
|
||||
<path d="M13 4.5v11" stroke="currentColor" strokeLinecap="round" strokeWidth="2.1" />
|
||||
<path d="m8.8 11.5 4.2 4.2 4.2-4.2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.1" />
|
||||
<path d="M6.5 20.5h13" stroke="currentColor" strokeLinecap="round" strokeWidth="2.1" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<svg aria-hidden="true" className="h-[26px] w-[26px]" fill="none" viewBox="0 0 26 26">
|
||||
<path d="M9.4 5.6H5.8v3.6M16.6 5.6h3.6v3.6M9.4 20.4H5.8v-3.6M16.6 20.4h3.6v-3.6" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.1" />
|
||||
<path d="M8 8 5.8 5.8M18 8l2.2-2.2M8 18l-2.2 2.2M18 18l2.2 2.2" stroke="currentColor" strokeLinecap="round" strokeWidth="2.1" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function StoryScriptScene() {
|
||||
return (
|
||||
<div className="pointer-events-none absolute inset-0 z-30" data-canvas-overlay="true">
|
||||
@ -3595,6 +3632,15 @@ function PresetComposerPanel({
|
||||
|
||||
function CharacterThreeViewScene() {
|
||||
const [toolbarMenu, setToolbarMenu] = useState<SceneToolbarMenu>(null);
|
||||
const sceneActions: Array<{
|
||||
action: Extract<ImageToolbarAction, "annotate" | "rotate" | "download" | "preview">;
|
||||
message: string;
|
||||
}> = [
|
||||
{ action: "annotate", message: "绘制编辑待接入。" },
|
||||
{ action: "rotate", message: "对比预览待接入。" },
|
||||
{ action: "download", message: "下载素材待接入。" },
|
||||
{ action: "preview", message: "全屏预览待接入。" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="pointer-events-none absolute inset-0 z-30" data-canvas-overlay="true">
|
||||
@ -3606,14 +3652,14 @@ function CharacterThreeViewScene() {
|
||||
<SceneTool active={toolbarMenu === "hd"} kind="hd" label="高清" dropdown onClick={() => setToolbarMenu((current) => current === "hd" ? null : "hd")} />
|
||||
<SceneTool active={toolbarMenu === "crop"} kind="crop" label="宫格切分" dropdown onClick={() => setToolbarMenu((current) => current === "crop" ? null : "crop")} />
|
||||
<div className="h-9 w-px bg-white/8" />
|
||||
{["⌁", "↔", "↓", "↗"].map((item, index) => (
|
||||
{sceneActions.map((item) => (
|
||||
<button
|
||||
className="flex h-10 w-10 items-center justify-center rounded-[8px] text-[28px] text-white/84 hover:bg-white/8"
|
||||
key={item}
|
||||
onClick={() => toast.info(["绘制编辑待接入。", "对比预览待接入。", "下载素材待接入。", "全屏预览待接入。"][index])}
|
||||
className="flex h-10 w-10 items-center justify-center rounded-[8px] text-white/84 hover:bg-white/8"
|
||||
key={item.action}
|
||||
onClick={() => toast.info(item.message)}
|
||||
type="button"
|
||||
>
|
||||
{item}
|
||||
<ImageToolbarActionGlyph action={item.action} />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
@ -4424,6 +4470,21 @@ function CloneEdges({ edges, nodes }: { edges: CloneEdge[]; nodes: CloneNode[] }
|
||||
const nodeMap = new Map(nodes.map((node) => [node.id, node]));
|
||||
return (
|
||||
<svg className="pointer-events-none absolute left-0 top-0 overflow-visible" style={{ height: CANVAS_EXTENT, width: CANVAS_EXTENT }}>
|
||||
<defs>
|
||||
<linearGradient id="libtv-edge-flow" x1="0%" x2="100%" y1="0%" y2="0%">
|
||||
<stop offset="0%" stopColor="#34a7ff" stopOpacity="0" />
|
||||
<stop offset="36%" stopColor="#39adff" stopOpacity="0.95" />
|
||||
<stop offset="68%" stopColor="#73c9ff" stopOpacity="1" />
|
||||
<stop offset="100%" stopColor="#b9ecff" stopOpacity="0" />
|
||||
</linearGradient>
|
||||
<filter colorInterpolationFilters="sRGB" height="240%" id="libtv-edge-glow" width="240%" x="-70%" y="-70%">
|
||||
<feGaussianBlur in="SourceGraphic" result="blur" stdDeviation="3" />
|
||||
<feMerge>
|
||||
<feMergeNode in="blur" />
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
{edges.map((edge) => {
|
||||
const source = nodeMap.get(edge.source);
|
||||
const target = nodeMap.get(edge.target);
|
||||
@ -4433,16 +4494,38 @@ function CloneEdges({ edges, nodes }: { edges: CloneEdge[]; nodes: CloneNode[] }
|
||||
const endX = target.x;
|
||||
const endY = target.y + target.height / 2;
|
||||
const curve = Math.max(90, Math.abs(endX - startX) * 0.42);
|
||||
const path = `M ${startX} ${startY} C ${startX + curve} ${startY}, ${endX - curve} ${endY}, ${endX} ${endY}`;
|
||||
return (
|
||||
<path
|
||||
d={`M ${startX} ${startY} C ${startX + curve} ${startY}, ${endX - curve} ${endY}, ${endX} ${endY}`}
|
||||
fill="none"
|
||||
key={edge.id}
|
||||
stroke="#7c86ff"
|
||||
strokeLinecap="round"
|
||||
strokeOpacity="0.95"
|
||||
strokeWidth="4"
|
||||
/>
|
||||
<g key={edge.id}>
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
stroke="#ffffff"
|
||||
strokeLinecap="round"
|
||||
strokeOpacity="0.62"
|
||||
strokeWidth="2.6"
|
||||
/>
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
filter="url(#libtv-edge-glow)"
|
||||
stroke="#2f9fff"
|
||||
strokeLinecap="round"
|
||||
strokeOpacity="0.34"
|
||||
strokeWidth="5.4"
|
||||
/>
|
||||
<path
|
||||
d={path}
|
||||
fill="none"
|
||||
filter="url(#libtv-edge-glow)"
|
||||
stroke="url(#libtv-edge-flow)"
|
||||
strokeDasharray="42 190"
|
||||
strokeLinecap="round"
|
||||
strokeWidth="4.2"
|
||||
>
|
||||
<animate attributeName="stroke-dashoffset" dur="1.55s" from="0" repeatCount="indefinite" to="-232" />
|
||||
</path>
|
||||
</g>
|
||||
);
|
||||
})}
|
||||
</svg>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user