From 956f1f6c5645177a9e2606b43ce3ddc753de863b Mon Sep 17 00:00:00 2001 From: ymk Date: Tue, 19 Aug 2025 16:56:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=96=87=E5=AD=97=E9=98=B4?= =?UTF-8?q?=E5=BD=B1=E6=95=88=E6=9E=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dictionary/en.json | 5 ++ dictionary/zh.json | 5 ++ src/components/FullEditor.tsx | 9 +- src/components/common/BackgroundSelector.tsx | 8 +- src/components/common/Effects.tsx | 93 ++++++++++++++++++++ src/components/common/PreviewToolbar.tsx | 17 ++-- src/components/common/TextSetting.tsx | 14 ++- src/components/common/ThreeTools.ts | 65 ++++++++++++-- src/components/editor/OnlyPage.tsx | 7 +- 9 files changed, 193 insertions(+), 30 deletions(-) create mode 100644 src/components/common/Effects.tsx diff --git a/dictionary/en.json b/dictionary/en.json index 932a9f2..e8e0e4d 100644 --- a/dictionary/en.json +++ b/dictionary/en.json @@ -89,6 +89,11 @@ "faqQuestion1": "Why do text characters sometimes appear as question marks in the preview?", "faqAnswer1": "Because the selected font doesn't support the language of the text. Try changing the font or uploading a custom font that supports the language." }, + "Effects": { + "title": "Effects", + "shadowOption": "Shadow", + "shadowOptionHelp": "Shadow works only with Pure Color background" + }, "Footer": { "copyright": "© {year} Screen Designer. All rights reserved." }, diff --git a/dictionary/zh.json b/dictionary/zh.json index 7d2f7c3..5f97dc2 100644 --- a/dictionary/zh.json +++ b/dictionary/zh.json @@ -89,6 +89,11 @@ "faqQuestion1": "为什么预览框内的文字内容会显示问号?", "faqAnswer1": "因为该内容的语言没有被选中字体支持,建议更换字体或者上传自定义字体" }, + "Effects": { + "title": "特效", + "shadowOption": "阴影", + "shadowOptionHelp": "阴影只在纯色背景下有效" + }, "Footer": { "copyright": "© {year} 3D文字设计工具 版权所有" }, diff --git a/src/components/FullEditor.tsx b/src/components/FullEditor.tsx index c1da4f3..842180c 100644 --- a/src/components/FullEditor.tsx +++ b/src/components/FullEditor.tsx @@ -7,12 +7,13 @@ import PreviewToolbar from "./common/PreviewToolbar"; import { useState } from "react"; import { useTranslations } from "next-intl"; import TextSetting, { TextProp } from "./common/TextSetting"; +import Effects, { EffectProp } from "./common/Effects"; /** * 全特性工具栏 * @returns */ -export default function Page({ textProp, backgroundProp }: { textProp: TextProp | undefined, backgroundProp: BackgroundProp | undefined }) { +export default function Page({ textProp, backgroundProp, effectProp }: { textProp: TextProp | undefined, backgroundProp: BackgroundProp | undefined, effectProp: EffectProp | undefined }) { const t = useTranslations("TextEditor"); @@ -22,9 +23,11 @@ export default function Page({ textProp, backgroundProp }: { textProp: TextProp } satisfies BackgroundProp; textProp = textProp || TextProp.default(t("defaultText")); + effectProp = effectProp || { enableShadow: true, shadowColor: "#000000" } satisfies EffectProp; const [background, setBackground] = useState(backgroundProp!); const [text, setText] = useState(textProp!); + const [effect, setEffect] = useState(effectProp); return ( @@ -34,10 +37,12 @@ export default function Page({ textProp, backgroundProp }: { textProp: TextProp setBackground={setBackground} /> + + - + ); diff --git a/src/components/common/BackgroundSelector.tsx b/src/components/common/BackgroundSelector.tsx index df0ca30..d344bb1 100644 --- a/src/components/common/BackgroundSelector.tsx +++ b/src/components/common/BackgroundSelector.tsx @@ -83,7 +83,7 @@ export default function BackgroundSelector({ }; return ( - + {t("title")} @@ -95,14 +95,14 @@ export default function BackgroundSelector({ id="color-picker" value={color || "black"} onChange={handleColorChange} - className="w-1/3 h-10 rounded-md cursor-pointer" + className="w-1/3 h-8 rounded-md cursor-pointer" /> {color && ()} @@ -117,7 +117,7 @@ export default function BackgroundSelector({ accept="image/*" onChange={handleImageUpload} className="block w-full text-sm text-muted-foreground - file:mr-4 file:py-2 file:px-4 + file:mr-4 file:py-1 file:px-2 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-primary file:text-primary-foreground diff --git a/src/components/common/Effects.tsx b/src/components/common/Effects.tsx new file mode 100644 index 0000000..0c3a82a --- /dev/null +++ b/src/components/common/Effects.tsx @@ -0,0 +1,93 @@ +'use client' +import { Box, Checkbox, Flex, Heading, IconButton, Tooltip } from "@radix-ui/themes"; +import { useTranslations } from "next-intl"; +import { useEffect, useState } from "react"; +import { BackgroundProp } from "./BackgroundSelector"; +import { CircleQuestionMarkIcon } from "lucide-react"; +export interface EffectProp { + enableShadow: boolean; + shadowColor: string; +} +export default function EffectsPage({ + effect, + setEffect, + background +}: { + effect: EffectProp; + setEffect: (e: EffectProp) => void; + background: BackgroundProp +}) { + const t = useTranslations("Effects"); + + // const [shadowValid, setShadowValid] = useState(true); + // useEffect(() => { + // setShadowValid(!background.image); + // }, [background]) + + return ( + + {t("title")} + + + + setEffect({ ...effect, enableShadow: !effect.enableShadow })} /> + {t("shadowOption")} + setEffect({ ...effect, shadowColor: e.target.value })} + className="w-1/3 h-8 rounded-md cursor-pointer" + /> + + setEffect({ ...effect, shadowColor: e.target.value })} + className="w-1/3 h-8 rounded-md cursor-pointer pl-4" + /> + + + {/* + handleBackgroundTypeChange("color")} className="cursor-pointer" /> + {t("colorOption")} + + + + {color && ()} + + + + + handleBackgroundTypeChange("image")} className="cursor-pointer" /> + {t("imageOption")} + + + + */} + + + ); +} diff --git a/src/components/common/PreviewToolbar.tsx b/src/components/common/PreviewToolbar.tsx index f227257..c96afd2 100644 --- a/src/components/common/PreviewToolbar.tsx +++ b/src/components/common/PreviewToolbar.tsx @@ -4,9 +4,10 @@ import { useLocale, useTranslations } from "next-intl"; import { Eye, Download, Share } from "lucide-react"; import { BackgroundProp } from "./BackgroundSelector"; import { Text, Flex, Button, Select, AlertDialog, Code, AspectRatio } from "@radix-ui/themes"; -import { getPicture, resize, init as threeInit, updateBackground, updateTextProps } from "./ThreeTools"; +import { getPicture, resize, init as threeInit, updateBackground, updateEffectProp, updateTextProp } from "./ThreeTools"; import { TextProp } from "./TextSetting"; import { encodeText, getShareLink } from "@/lib/utils"; +import { EffectProp } from "./Effects"; const Sizes = [ "1920x1080", @@ -27,9 +28,11 @@ const AspectRatios = Sizes.map(o => { export default function PreviewToolbar({ background, text, + effect }: { background: BackgroundProp; text: TextProp; + effect: EffectProp }) { let host = process.env.NEXT_PUBLIC_HOST?.substring("https://".length); const t = useTranslations("PreviewBar"); @@ -70,12 +73,17 @@ export default function PreviewToolbar({ useEffect(() => { - updateTextProps(text); + updateTextProp(text); console.log("text change", text); }, [text]); + useEffect(() => { + updateEffectProp(effect); + console.log("effect change", effect); + }, [effect]); + const generateImage = async (w: number, h: number): Promise => { return new Promise((resolve, reject) => { @@ -126,9 +134,6 @@ export default function PreviewToolbar({ } }); - - - } const handleDownload = async () => { @@ -228,7 +233,7 @@ export default function PreviewToolbar({ }, [handleFullScreen]); return ( - + {t("tipsTitle")}: {t("mouseLeft")} diff --git a/src/components/common/TextSetting.tsx b/src/components/common/TextSetting.tsx index 47e7f22..ec6a4b9 100644 --- a/src/components/common/TextSetting.tsx +++ b/src/components/common/TextSetting.tsx @@ -167,16 +167,14 @@ export default function TextSetting({ setFontWeightEnabled(map); }; - - return ( - + {t("title")}