From 1810e2a4fe385eb142f0697b864fc2bdd5f12d46 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Mon, 13 Jul 2026 14:25:15 +0800 Subject: [PATCH 1/9] test1 --- src/Web/index.html | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/Web/index.html b/src/Web/index.html index 80951b4..e2d4943 100644 --- a/src/Web/index.html +++ b/src/Web/index.html @@ -336,20 +336,50 @@ ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; + // 逐段渲染(直线版 -- 保留备用) + // const lastIdx = pts.length - 1; + // for (let i = 0; i < lastIdx; i++) { + // const alphaStart = i / lastIdx; + // const alphaEnd = (i + 1) / lastIdx; + // const a0 = pts[i]; + // const a1 = pts[i + 1]; + // + // const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); + // segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); + // segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); + // + // ctx.beginPath(); + // ctx.moveTo(a0.x, a0.y); + // ctx.lineTo(a1.x, a1.y); + // ctx.strokeStyle = segGrad; + // ctx.stroke(); + // } + + // 逐段渲染(Catmull-Rom → Cubic Bezier 曲线版) + // 每段的透明度基于数组索引位置,而非空间位置 const lastIdx = pts.length - 1; for (let i = 0; i < lastIdx; i++) { - const alphaStart = i / lastIdx; - const alphaEnd = (i + 1) / lastIdx; const a0 = pts[i]; const a1 = pts[i + 1]; + // Catmull-Rom 控制点:CP1 = P_i + (P_{i+1} - P_{i-1}) / 6 + // CP2 = P_{i+1} - (P_{i+2} - P_i) / 6 + const prev = i > 0 ? pts[i - 1] : a0; + const next = i < lastIdx - 1 ? pts[i + 2] : a1; + const cp1x = a0.x + (a1.x - prev.x) / 6; + const cp1y = a0.y + (a1.y - prev.y) / 6; + const cp2x = a1.x - (next.x - a0.x) / 6; + const cp2y = a1.y - (next.y - a0.y) / 6; + + const alphaStart = i / lastIdx; + const alphaEnd = (i + 1) / lastIdx; const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); ctx.beginPath(); ctx.moveTo(a0.x, a0.y); - ctx.lineTo(a1.x, a1.y); + ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, a1.x, a1.y); ctx.strokeStyle = segGrad; ctx.stroke(); } From d197be530b8374e8c6e63ce9846d8141e642a15d Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Mon, 13 Jul 2026 15:12:08 +0800 Subject: [PATCH 2/9] test2 --- src/ConfigManager.cs | 3 ++ src/ControlPanelWindow.xaml | 4 ++ src/ControlPanelWindow.xaml.cs | 9 ++++ src/MainWindow.xaml.cs | 5 ++ src/OverlayManager.cs | 1 + src/Resources/Strings.en.resx | 6 +++ src/Resources/Strings.ja.resx | 6 +++ src/Resources/Strings.resx | 6 +++ src/Web/index.html | 90 +++++++++++++++++----------------- 9 files changed, 85 insertions(+), 45 deletions(-) diff --git a/src/ConfigManager.cs b/src/ConfigManager.cs index 7e5a9eb..c8ff05b 100644 --- a/src/ConfigManager.cs +++ b/src/ConfigManager.cs @@ -72,6 +72,7 @@ public static class ConfigManager public static double EffectOpacity { get; set; } = 1.0; public static double EffectSpeed { get; set; } = 1.0; public static bool UseLinkedAnimationSpeed { get; set; } = true; + public static bool ApplyCurveDraw { get; set; } = false; public static double TrailAnimationSpeed { get; set; } = 1.0; public static double ClickAnimationSpeed { get; set; } = 1.0; public static int TrailRefreshRate { get; set; } = 40; @@ -130,6 +131,7 @@ public static void Load() EffectOpacity = Math.Clamp(Convert.ToDouble(key.GetValue("EffectOpacity", 1.0)), 0.1, 1.0); EffectSpeed = Math.Clamp(Convert.ToDouble(key.GetValue("EffectSpeed", 1.0)), 0.2, 3.0); UseLinkedAnimationSpeed = Convert.ToBoolean(key.GetValue("UseLinkedAnimationSpeed", true)); + ApplyCurveDraw = Convert.ToBoolean(key.GetValue("ApplyCurveDraw", false)); TrailAnimationSpeed = Math.Clamp(Convert.ToDouble(key.GetValue("TrailAnimationSpeed", EffectSpeed)), 0.2, 3.0); ClickAnimationSpeed = Math.Clamp(Convert.ToDouble(key.GetValue("ClickAnimationSpeed", EffectSpeed)), 0.2, 3.0); TrailRefreshRate = Math.Clamp(Convert.ToInt32(key.GetValue("TrailRefreshRate", 40)), 10, 240); @@ -532,6 +534,7 @@ public static void ResetAndClear() EffectOpacity = 1.0; EffectSpeed = 1.0; UseLinkedAnimationSpeed = true; + ApplyCurveDraw = false; TrailAnimationSpeed = 1.0; ClickAnimationSpeed = 1.0; TrailRefreshRate = 40; diff --git a/src/ControlPanelWindow.xaml b/src/ControlPanelWindow.xaml index 03f3cda..571210e 100644 --- a/src/ControlPanelWindow.xaml +++ b/src/ControlPanelWindow.xaml @@ -524,6 +524,10 @@ Checked="LinkedAnimationSpeed_Changed" Unchecked="LinkedAnimationSpeed_Changed"/> + + + diff --git a/src/ControlPanelWindow.xaml.cs b/src/ControlPanelWindow.xaml.cs index 2e9e43a..f292419 100644 --- a/src/ControlPanelWindow.xaml.cs +++ b/src/ControlPanelWindow.xaml.cs @@ -584,6 +584,7 @@ private void LoadSettingsCore() SliderScale.Value = ConfigManager.EffectScale; SliderOpacity.Value = ConfigManager.EffectOpacity * 100; CheckLinkedAnimationSpeed.IsChecked = ConfigManager.UseLinkedAnimationSpeed; + CheckApplyCurveDraw.IsChecked = ConfigManager.ApplyCurveDraw; SliderSpeed.Value = ConfigManager.EffectSpeed; SliderTrailAnimSpeed.Value = ConfigManager.TrailAnimationSpeed; SliderClickAnimSpeed.Value = ConfigManager.ClickAnimationSpeed; @@ -1317,6 +1318,7 @@ private void ConfirmVisualReset_Click(object sender, RoutedEventArgs e) App.Overlay?.UpdateColor(ConfigManager.ParticleColor); App.Overlay?.UpdateEffectSettings(effectScale, effectOpacity, trailSp, clickSp); App.Overlay?.UpdateTrailRefreshRate(trailRefreshRate); + App.Overlay?.SetCurveDraw(CheckApplyCurveDraw.IsChecked ?? false); VisualResetOverlay.Visibility = Visibility.Collapsed; System.Windows.MessageBox.Show( @@ -1423,6 +1425,7 @@ private void SaveSettings_Click(object sender, RoutedEventArgs e) ConfigManager.Save("ClickTriggerType", clickType); ConfigManager.Save("EnableMiddleClickTrigger", middleClickEnabled); ConfigManager.Save("ScreenshotCompatibilityMode", screenshotCompatibilityEnabled); + ConfigManager.Save("ApplyCurveDraw", CheckApplyCurveDraw.IsChecked ?? false); string sidebarBackgroundPath = TxtSidebarBackgroundPath?.Text?.Trim() ?? string.Empty; if (!string.IsNullOrWhiteSpace(sidebarBackgroundPath)) @@ -1484,6 +1487,7 @@ private void SaveSettings_Click(object sender, RoutedEventArgs e) App.Overlay?.RefreshEnvironmentFilterState(); App.Overlay?.UpdateTouchMode(isTouchscreenEnabled); App.Overlay?.UpdateScreenshotCompatibilityMode(screenshotCompatibilityEnabled); + App.Overlay?.SetCurveDraw(CheckApplyCurveDraw.IsChecked ?? false); if (!previousEnabledScreenIds.SetEquals(selectedIds)) { App.Overlay?.RefreshScreenSelection(); @@ -1694,6 +1698,11 @@ private void EffectSlider_ValueChanged(object sender, RoutedPropertyChangedEvent if (!IsLoaded) return; } + private void CurveDraw_Changed(object sender, RoutedEventArgs e) + { + if (!IsLoaded) return; + } + private void LinkedAnimationSpeed_Changed(object sender, RoutedEventArgs e) { if (!IsLoaded || _suspendLinkedAnimationUiHandlers) diff --git a/src/MainWindow.xaml.cs b/src/MainWindow.xaml.cs index 14ca5cb..1ef778e 100644 --- a/src/MainWindow.xaml.cs +++ b/src/MainWindow.xaml.cs @@ -213,6 +213,11 @@ public void UpdateTrailRefreshRate(int hz) _ = hz; } + public void SetCurveDraw(bool enabled) + { + ExecuteScript($"window.ApplyCurveDraw = {(enabled ? "true" : "false")};"); + } + public void UpdateTouchMode(bool enabled) { ConfigManager.IsTouchscreenMode = enabled; diff --git a/src/OverlayManager.cs b/src/OverlayManager.cs index 6f59a6a..d6f20a3 100644 --- a/src/OverlayManager.cs +++ b/src/OverlayManager.cs @@ -146,6 +146,7 @@ public void UpdateScreenshotCompatibilityMode(bool enabled) ForEachOverlay(w => w.UpdateScreenshotCompatibilityMode(enabled)); SyncScreenshotCompatCaptureSurfaces(); } + public void SetCurveDraw(bool enabled) => ForEachOverlay(w => w.SetCurveDraw(enabled)); public bool IsEffectSuppressedByEnvironment() => _isSuppressedByEnvironment; public void RefreshEnvironmentFilterState() { diff --git a/src/Resources/Strings.en.resx b/src/Resources/Strings.en.resx index 0b7d3c8..a8fc855 100644 --- a/src/Resources/Strings.en.resx +++ b/src/Resources/Strings.en.resx @@ -586,6 +586,12 @@ Download now? When off, trail and click speeds are independent of trail refresh rate below. + + Use curved trail lines + + + Render trails as curves for smoother visuals at lower refresh rates. + Global opacity diff --git a/src/Resources/Strings.ja.resx b/src/Resources/Strings.ja.resx index 20b087c..f0720ce 100644 --- a/src/Resources/Strings.ja.resx +++ b/src/Resources/Strings.ja.resx @@ -586,6 +586,12 @@ オフにするとトレイルとクリックの速度を個別に設定できます(下の更新率とは別)。 + + 曲線トレイルを使用 + + + トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。 + 全体の不透明度 diff --git a/src/Resources/Strings.resx b/src/Resources/Strings.resx index fcafb17..7d8f9eb 100644 --- a/src/Resources/Strings.resx +++ b/src/Resources/Strings.resx @@ -586,6 +586,12 @@ 关闭此项后可单独加快或减慢拖尾衰减与移动粒子,而不影响点击波纹与爆发粒子,与下方「拖尾刷新率」不同。 + + 采用曲线拖尾 + + + 点击后拖尾渲染变为曲线,适合在低刷新率下使用以获得更好视觉体验。 + 全局不透明度 diff --git a/src/Web/index.html b/src/Web/index.html index e2d4943..74b1878 100644 --- a/src/Web/index.html +++ b/src/Web/index.html @@ -336,54 +336,54 @@ ctx.shadowOffsetX = 0; ctx.shadowOffsetY = 0; - // 逐段渲染(直线版 -- 保留备用) - // const lastIdx = pts.length - 1; - // for (let i = 0; i < lastIdx; i++) { - // const alphaStart = i / lastIdx; - // const alphaEnd = (i + 1) / lastIdx; - // const a0 = pts[i]; - // const a1 = pts[i + 1]; - // - // const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); - // segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); - // segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); - // - // ctx.beginPath(); - // ctx.moveTo(a0.x, a0.y); - // ctx.lineTo(a1.x, a1.y); - // ctx.strokeStyle = segGrad; - // ctx.stroke(); - // } - - // 逐段渲染(Catmull-Rom → Cubic Bezier 曲线版) - // 每段的透明度基于数组索引位置,而非空间位置 const lastIdx = pts.length - 1; - for (let i = 0; i < lastIdx; i++) { - const a0 = pts[i]; - const a1 = pts[i + 1]; - - // Catmull-Rom 控制点:CP1 = P_i + (P_{i+1} - P_{i-1}) / 6 - // CP2 = P_{i+1} - (P_{i+2} - P_i) / 6 - const prev = i > 0 ? pts[i - 1] : a0; - const next = i < lastIdx - 1 ? pts[i + 2] : a1; - const cp1x = a0.x + (a1.x - prev.x) / 6; - const cp1y = a0.y + (a1.y - prev.y) / 6; - const cp2x = a1.x - (next.x - a0.x) / 6; - const cp2y = a1.y - (next.y - a0.y) / 6; - - const alphaStart = i / lastIdx; - const alphaEnd = (i + 1) / lastIdx; - const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); - segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); - segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); + // 每段的透明度基于数组索引位置,而非空间位置 + if (window.ApplyCurveDraw) { + // 逐段渲染(Catmull-Rom → Cubic Bezier 曲线版) + for (let i = 0; i < lastIdx; i++) { + const a0 = pts[i]; + const a1 = pts[i + 1]; + + // Catmull-Rom 控制点:CP1 = P_i + (P_{i+1} - P_{i-1}) / 6 + // CP2 = P_{i+1} - (P_{i+2} - P_i) / 6 + const prev = i > 0 ? pts[i - 1] : a0; + const next = i < lastIdx - 1 ? pts[i + 2] : a1; + const cp1x = a0.x + (a1.x - prev.x) / 6; + const cp1y = a0.y + (a1.y - prev.y) / 6; + const cp2x = a1.x - (next.x - a0.x) / 6; + const cp2y = a1.y - (next.y - a0.y) / 6; + + const alphaStart = i / lastIdx; + const alphaEnd = (i + 1) / lastIdx; + const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); + segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); + segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); - ctx.beginPath(); - ctx.moveTo(a0.x, a0.y); - ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, a1.x, a1.y); - ctx.strokeStyle = segGrad; - ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(a0.x, a0.y); + ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, a1.x, a1.y); + ctx.strokeStyle = segGrad; + ctx.stroke(); + } + } else { + // 逐段渲染(直线版) + for (let i = 0; i < lastIdx; i++) { + const alphaStart = i / lastIdx; + const alphaEnd = (i + 1) / lastIdx; + const a0 = pts[i]; + const a1 = pts[i + 1]; + + const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); + segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); + segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); + + ctx.beginPath(); + ctx.moveTo(a0.x, a0.y); + ctx.lineTo(a1.x, a1.y); + ctx.strokeStyle = segGrad; + ctx.stroke(); + } } - ctx.shadowColor = 'transparent'; } From 0efac2160d35ea887cdc28b2ce7cdc9e9b4e0778 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Mon, 13 Jul 2026 15:36:01 +0800 Subject: [PATCH 3/9] final --- src/ControlPanelWindow.xaml | 2 +- src/Resources/Strings.en.resx | 2 +- src/Resources/Strings.ja.resx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ControlPanelWindow.xaml b/src/ControlPanelWindow.xaml index 571210e..c3916f7 100644 --- a/src/ControlPanelWindow.xaml +++ b/src/ControlPanelWindow.xaml @@ -526,7 +526,7 @@ - + diff --git a/src/Resources/Strings.en.resx b/src/Resources/Strings.en.resx index a8fc855..00c69d8 100644 --- a/src/Resources/Strings.en.resx +++ b/src/Resources/Strings.en.resx @@ -590,7 +590,7 @@ Download now? Use curved trail lines - Render trails as curves for smoother visuals at lower refresh rates. + Render trails as curves for smoother visuals at lower refresh rates. Recommended for 60Hz and above. Global opacity diff --git a/src/Resources/Strings.ja.resx b/src/Resources/Strings.ja.resx index f0720ce..4879bf2 100644 --- a/src/Resources/Strings.ja.resx +++ b/src/Resources/Strings.ja.resx @@ -590,7 +590,7 @@ 曲線トレイルを使用 - トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。 + トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。60Hz以上のリフレッシュレートでの使用を推奨します。 全体の不透明度 From e1dc06d14b9497ba4a28fecf5fc39d795e1ab604 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Mon, 13 Jul 2026 16:49:37 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BASpark.csproj | 1 + src/ControlPanelWindow.xaml | 2 +- src/Resources/Strings.en.resx | 2 +- src/Resources/Strings.ja.resx | 2 +- src/Resources/Strings.resx | 2 +- tests/BASpark.Tests/BASpark.Tests.csproj | 1 + 6 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/BASpark.csproj b/src/BASpark.csproj index 2e05bcd..0975012 100644 --- a/src/BASpark.csproj +++ b/src/BASpark.csproj @@ -22,6 +22,7 @@ app.manifest Static + true diff --git a/src/ControlPanelWindow.xaml b/src/ControlPanelWindow.xaml index c3916f7..c899ff5 100644 --- a/src/ControlPanelWindow.xaml +++ b/src/ControlPanelWindow.xaml @@ -526,7 +526,7 @@ - + diff --git a/src/Resources/Strings.en.resx b/src/Resources/Strings.en.resx index 00c69d8..48179a7 100644 --- a/src/Resources/Strings.en.resx +++ b/src/Resources/Strings.en.resx @@ -590,7 +590,7 @@ Download now? Use curved trail lines - Render trails as curves for smoother visuals at lower refresh rates. Recommended for 60Hz and above. + Render trails as curves for smoother visuals at lower refresh rates. Recommended for 60Hz and above. If GPU usage is too high, try lowering the refresh rate and enabling this feature — the visual impact is minimal. Global opacity diff --git a/src/Resources/Strings.ja.resx b/src/Resources/Strings.ja.resx index 4879bf2..76ca4d0 100644 --- a/src/Resources/Strings.ja.resx +++ b/src/Resources/Strings.ja.resx @@ -590,7 +590,7 @@ 曲線トレイルを使用 - トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。60Hz以上のリフレッシュレートでの使用を推奨します。 + トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。60Hz以上のリフレッシュレートでの使用を推奨します。 GPU使用率が高い場合は、リフレッシュレートを下げてこの機能を有効にしてみてください。見た目への影響は最小限です。 全体の不透明度 diff --git a/src/Resources/Strings.resx b/src/Resources/Strings.resx index 7d8f9eb..21d97bd 100644 --- a/src/Resources/Strings.resx +++ b/src/Resources/Strings.resx @@ -590,7 +590,7 @@ 采用曲线拖尾 - 点击后拖尾渲染变为曲线,适合在低刷新率下使用以获得更好视觉体验。 + 点击后拖尾渲染变为曲线,适合在低刷新率下使用以获得更好视觉体验。建议在60Hz及以上刷新率时开启。 如果发现该应用显卡占用过高,可以降低刷新率同时开启该功能,对视觉效果影响不大。 全局不透明度 diff --git a/tests/BASpark.Tests/BASpark.Tests.csproj b/tests/BASpark.Tests/BASpark.Tests.csproj index 3adf019..73414c3 100644 --- a/tests/BASpark.Tests/BASpark.Tests.csproj +++ b/tests/BASpark.Tests/BASpark.Tests.csproj @@ -5,6 +5,7 @@ enable enable false + true From fbd0fd39f76d9f61ea4873117860c69513184b95 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Mon, 13 Jul 2026 16:57:22 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=86=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E7=9A=84=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/BASpark.csproj | 1 - tests/BASpark.Tests/BASpark.Tests.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/src/BASpark.csproj b/src/BASpark.csproj index 0975012..2e05bcd 100644 --- a/src/BASpark.csproj +++ b/src/BASpark.csproj @@ -22,7 +22,6 @@ app.manifest Static - true diff --git a/tests/BASpark.Tests/BASpark.Tests.csproj b/tests/BASpark.Tests/BASpark.Tests.csproj index 73414c3..3adf019 100644 --- a/tests/BASpark.Tests/BASpark.Tests.csproj +++ b/tests/BASpark.Tests/BASpark.Tests.csproj @@ -5,7 +5,6 @@ enable enable false - true From f5f0497c91185051b2df5b29a5f0c5491a5c4f49 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Fri, 17 Jul 2026 10:50:41 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BA=A0=E6=AD=A3?= =?UTF-8?q?=E4=BA=86=E5=8A=9F=E8=83=BD=E8=AF=B4=E6=98=8E=EF=BC=8C=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E4=BF=AE=E6=94=B9XAML=20=E7=A1=AC=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E6=96=87=E6=9C=AC=EF=BC=8C=E8=A1=A5=E4=B8=8A=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=20CurveDraw=20=E6=9C=AC=E5=9C=B0=E5=8C=96=E6=98=A0?= =?UTF-8?q?=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Resources/Strings.en.resx | 2 +- src/Resources/Strings.ja.resx | 2 +- src/Resources/Strings.resx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Resources/Strings.en.resx b/src/Resources/Strings.en.resx index 48179a7..b9c56b0 100644 --- a/src/Resources/Strings.en.resx +++ b/src/Resources/Strings.en.resx @@ -590,7 +590,7 @@ Download now? Use curved trail lines - Render trails as curves for smoother visuals at lower refresh rates. Recommended for 60Hz and above. If GPU usage is too high, try lowering the refresh rate and enabling this feature — the visual impact is minimal. + Recommended for 60Hz and above Global opacity diff --git a/src/Resources/Strings.ja.resx b/src/Resources/Strings.ja.resx index 76ca4d0..99781ac 100644 --- a/src/Resources/Strings.ja.resx +++ b/src/Resources/Strings.ja.resx @@ -590,7 +590,7 @@ 曲線トレイルを使用 - トレイルを曲線で描画し、低リフレッシュレートでの視覚体験を向上させます。60Hz以上のリフレッシュレートでの使用を推奨します。 GPU使用率が高い場合は、リフレッシュレートを下げてこの機能を有効にしてみてください。見た目への影響は最小限です。 + 60Hz以上のリフレッシュレートでの使用を推奨します 全体の不透明度 diff --git a/src/Resources/Strings.resx b/src/Resources/Strings.resx index 21d97bd..1d36971 100644 --- a/src/Resources/Strings.resx +++ b/src/Resources/Strings.resx @@ -590,7 +590,7 @@ 采用曲线拖尾 - 点击后拖尾渲染变为曲线,适合在低刷新率下使用以获得更好视觉体验。建议在60Hz及以上刷新率时开启。 如果发现该应用显卡占用过高,可以降低刷新率同时开启该功能,对视觉效果影响不大。 + 建议在60Hz及以上刷新率开启 全局不透明度 From ca09c764c1522daaddcb4ef74c151e2098708827 Mon Sep 17 00:00:00 2001 From: zhengziyu54188 Date: Fri, 17 Jul 2026 10:52:00 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=BF=AE=E6=94=B9XAML=20?= =?UTF-8?q?=E7=A1=AC=E7=BC=96=E7=A0=81=E6=96=87=E6=9C=AC=EF=BC=8C=E8=A1=A5?= =?UTF-8?q?=E4=B8=8A=E7=BC=BA=E5=A4=B1=E7=9A=84=20CurveDraw=20=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=8C=96=E6=98=A0=E5=B0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ControlPanelWindow.xaml | 2 +- src/UiLocalizer.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ControlPanelWindow.xaml b/src/ControlPanelWindow.xaml index c899ff5..f24ae04 100644 --- a/src/ControlPanelWindow.xaml +++ b/src/ControlPanelWindow.xaml @@ -526,7 +526,7 @@ - + diff --git a/src/UiLocalizer.cs b/src/UiLocalizer.cs index 3b56a73..5d481c7 100644 --- a/src/UiLocalizer.cs +++ b/src/UiLocalizer.cs @@ -93,6 +93,8 @@ public static void ApplyControlPanel(ControlPanelWindow w) w.TxtVisualOpacity.Text = Localization.Get("Visual_Opacity"); w.CheckLinkedAnimationSpeed.Content = Localization.Get("Visual_LinkedSpeed"); w.TxtLinkedSpeedHint.Text = Localization.Get("Visual_LinkedSpeedHint"); + w.CheckApplyCurveDraw.Content = Localization.Get("Visual_CurveDraw"); + w.TxtCurveDrawHint.Text = Localization.Get("Visual_CurveDrawHint"); w.TxtAnimSpeed.Text = Localization.Get("Visual_AnimSpeed"); w.TxtTrailAnimSpeed.Text = Localization.Get("Visual_TrailAnimSpeed"); w.TxtClickAnimSpeed.Text = Localization.Get("Visual_ClickAnimSpeed"); From 642864c946127e708edcc9e2a734d011eff1cf87 Mon Sep 17 00:00:00 2001 From: yutou-official Date: Fri, 14 Aug 2026 14:18:06 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=8D=E5=90=AF?= =?UTF-8?q?=E5=90=8E=20ApplyCurveDraw=20=E6=9C=AA=E5=9B=9E=E5=A1=AB?= =?UTF-8?q?=E5=88=B0=E7=89=B9=E6=95=88=E5=B1=82=E5=AF=BC=E8=87=B4=E6=9B=B2?= =?UTF-8?q?=E7=BA=BF=E6=8B=96=E5=B0=BE=E4=B8=8D=E7=94=9F=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MainWindow.xaml.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MainWindow.xaml.cs b/src/MainWindow.xaml.cs index 1ef778e..9794b99 100644 --- a/src/MainWindow.xaml.cs +++ b/src/MainWindow.xaml.cs @@ -443,6 +443,7 @@ private async System.Threading.Tasks.Task InitWebView() UpdateColor(ConfigManager.ParticleColor); ConfigManager.GetAnimationSpeedsForOverlay(out double trailSp, out double clickSp); UpdateEffectSettings(ConfigManager.EffectScale, ConfigManager.EffectOpacity, trailSp, clickSp); + SetCurveDraw(ConfigManager.ApplyCurveDraw); SyncInputContext(InputModeMouse); if (_overlayRuntimePaused) { From 04f664ceeb24f78390870fc65d0184fa97005df4 Mon Sep 17 00:00:00 2001 From: yutou-official Date: Tue, 18 Aug 2026 12:14:12 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E5=B0=86=E8=BE=89=E5=85=89=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E8=BF=81=E7=A7=BB=E4=BA=86=E8=BF=87=E6=9D=A5=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E8=A7=A3=E5=86=B3=E4=BA=86=E5=B0=BE=E8=BF=B9=E9=80=8F?= =?UTF-8?q?=E6=98=8E=E5=BA=A6=E4=B8=8D=E5=8F=97=E6=9B=B4=E6=94=B9=E7=9A=84?= =?UTF-8?q?bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Web/index.html | 96 ++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/src/Web/index.html b/src/Web/index.html index 74b1878..a83f95e 100644 --- a/src/Web/index.html +++ b/src/Web/index.html @@ -330,59 +330,63 @@ // 逐段渲染:每段的透明度基于数组索引位置,而非空间位置 // 防止当鼠标锐角转动时,尾迹变淡后突然出现的问题 - ctx.lineWidth = 5.0; - ctx.shadowColor = `rgba(${this.color}, 0.6)`; - ctx.shadowBlur = 3; - ctx.shadowOffsetX = 0; - ctx.shadowOffsetY = 0; + const glowPasses = [ + { lineWidth: 9, alphaMul: this.alpha(0.05) }, // 外层辉光 + { lineWidth: 6.0, alphaMul: this.alpha(0.5) }, // 内层辉光 + { lineWidth: 4.5, alphaMul: this.alpha(1.0) }, // 核心线 + ]; const lastIdx = pts.length - 1; // 每段的透明度基于数组索引位置,而非空间位置 if (window.ApplyCurveDraw) { // 逐段渲染(Catmull-Rom → Cubic Bezier 曲线版) - for (let i = 0; i < lastIdx; i++) { - const a0 = pts[i]; - const a1 = pts[i + 1]; - - // Catmull-Rom 控制点:CP1 = P_i + (P_{i+1} - P_{i-1}) / 6 - // CP2 = P_{i+1} - (P_{i+2} - P_i) / 6 - const prev = i > 0 ? pts[i - 1] : a0; - const next = i < lastIdx - 1 ? pts[i + 2] : a1; - const cp1x = a0.x + (a1.x - prev.x) / 6; - const cp1y = a0.y + (a1.y - prev.y) / 6; - const cp2x = a1.x - (next.x - a0.x) / 6; - const cp2y = a1.y - (next.y - a0.y) / 6; - - const alphaStart = i / lastIdx; - const alphaEnd = (i + 1) / lastIdx; - const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); - segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); - segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); - - ctx.beginPath(); - ctx.moveTo(a0.x, a0.y); - ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, a1.x, a1.y); - ctx.strokeStyle = segGrad; - ctx.stroke(); - } + for (const pass of glowPasses) { + ctx.lineWidth = pass.lineWidth; + for (let i = 0; i < lastIdx; i++) { + const a0 = pts[i]; + const a1 = pts[i + 1]; + + // Catmull-Rom 控制点:CP1 = P_i + (P_{i+1} - P_{i-1}) / 6 + // CP2 = P_{i+1} - (P_{i+2} - P_i) / 6 + const prev = i > 0 ? pts[i - 1] : a0; + const next = i < lastIdx - 1 ? pts[i + 2] : a1; + const cp1x = a0.x + (a1.x - prev.x) / 6; + const cp1y = a0.y + (a1.y - prev.y) / 6; + const cp2x = a1.x - (next.x - a0.x) / 6; + const cp2y = a1.y - (next.y - a0.y) / 6; + + const alphaStart = (i / lastIdx) * pass.alphaMul; + const alphaEnd = ((i + 1) / lastIdx) * pass.alphaMul; + const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); + segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); + segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); + + ctx.beginPath(); + ctx.moveTo(a0.x, a0.y); + ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, a1.x, a1.y); + ctx.strokeStyle = segGrad; + ctx.stroke(); + }} } else { // 逐段渲染(直线版) - for (let i = 0; i < lastIdx; i++) { - const alphaStart = i / lastIdx; - const alphaEnd = (i + 1) / lastIdx; - const a0 = pts[i]; - const a1 = pts[i + 1]; - - const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); - segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); - segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); - - ctx.beginPath(); - ctx.moveTo(a0.x, a0.y); - ctx.lineTo(a1.x, a1.y); - ctx.strokeStyle = segGrad; - ctx.stroke(); - } + for (const pass of glowPasses) { + ctx.lineWidth = pass.lineWidth; + for (let i = 0; i < lastIdx; i++) { + const alphaStart = (i / lastIdx) * pass.alphaMul; + const alphaEnd = ((i + 1) / lastIdx) * pass.alphaMul; + const a0 = pts[i]; + const a1 = pts[i + 1]; + + const segGrad = ctx.createLinearGradient(a0.x, a0.y, a1.x, a1.y); + segGrad.addColorStop(0, `rgba(${this.color}, ${alphaStart})`); + segGrad.addColorStop(1, `rgba(${this.color}, ${alphaEnd})`); + + ctx.beginPath(); + ctx.moveTo(a0.x, a0.y); + ctx.lineTo(a1.x, a1.y); + ctx.strokeStyle = segGrad; + ctx.stroke(); + }} } ctx.shadowColor = 'transparent'; }