From a95ff6f0d0bdd8a4aec1244c35f52b9e91d0f15f Mon Sep 17 00:00:00 2001 From: dlh <2773843782@qq.com> Date: Thu, 20 Aug 2026 18:49:01 +0800 Subject: [PATCH] =?UTF-8?q?fix(canvas):=20=E7=94=BB=E5=B8=83=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E7=BD=91=E6=A0=BC=20-=20=E4=BF=AE=E5=A4=8D=E7=82=B9/?= =?UTF-8?q?=E7=BA=BF=E7=BD=91=E6=A0=BC=E8=BF=87=E6=B7=A1=E4=B8=8D=E5=8F=AF?= =?UTF-8?q?=E8=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/components/canvas/infinite-canvas.tsx | 6 +++--- web/src/lib/canvas-theme.ts | 8 ++++---- web/src/lib/canvas/canvas-live-viewport.ts | 8 +++++++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/web/src/components/canvas/infinite-canvas.tsx b/web/src/components/canvas/infinite-canvas.tsx index 8366fa875..f1ee4aaed 100644 --- a/web/src/components/canvas/infinite-canvas.tsx +++ b/web/src/components/canvas/infinite-canvas.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react"; import { canvasThemes, type CanvasBackgroundMode } from "@/lib/canvas-theme"; -import { applyCanvasLiveViewport, subscribeCanvasViewportPreview } from "@/lib/canvas/canvas-live-viewport"; +import { applyCanvasLiveViewport, canvasDotPx, subscribeCanvasViewportPreview } from "@/lib/canvas/canvas-live-viewport"; import { useThemeStore } from "@/stores/use-theme-store"; import type { ViewportTransform } from "@/types/canvas"; @@ -382,7 +382,7 @@ export function InfiniteCanvas({ containerRef, viewport, backgroundMode = "dots" "--canvas-grid-size": `${48 * viewport.k}px`, "--canvas-grid-x": `${viewport.x % (48 * viewport.k)}px`, "--canvas-grid-y": `${viewport.y % (48 * viewport.k)}px`, - "--canvas-dot-size": viewport.k < 0.12 ? "0.8px" : "1.15px", + "--canvas-dot-size": canvasDotPx(viewport.k), } as React.CSSProperties} onPointerDown={handlePointerDown} onDoubleClick={(event) => { @@ -426,7 +426,7 @@ function CanvasGrid({ mode }: { mode: CanvasBackgroundMode }) { backgroundImage, backgroundSize: "var(--canvas-grid-size) var(--canvas-grid-size)", transform: "translate3d(var(--canvas-grid-x), var(--canvas-grid-y), 0)", - opacity: mode === "dots" ? 0.28 : 0.2, + opacity: 0.55, willChange: "transform", }} /> diff --git a/web/src/lib/canvas-theme.ts b/web/src/lib/canvas-theme.ts index 075110973..b017e251c 100644 --- a/web/src/lib/canvas-theme.ts +++ b/web/src/lib/canvas-theme.ts @@ -5,8 +5,8 @@ export const canvasThemes = { light: { canvas: { background: "#ffffff", - dot: "rgba(15,23,42,.14)", - line: "rgba(15,23,42,.065)", + dot: "rgba(15,23,42,.30)", + line: "rgba(15,23,42,.15)", selectionFill: "rgba(17,17,17,.10)", }, node: { @@ -68,8 +68,8 @@ export const canvasThemes = { dark: { canvas: { background: "#090a0c", - dot: "rgba(174,184,199,.18)", - line: "rgba(174,184,199,.06)", + dot: "rgba(174,184,199,.32)", + line: "rgba(174,184,199,.16)", selectionFill: "rgba(255,255,255,.12)", }, node: { diff --git a/web/src/lib/canvas/canvas-live-viewport.ts b/web/src/lib/canvas/canvas-live-viewport.ts index 4945dafd1..a2d2f1168 100644 --- a/web/src/lib/canvas/canvas-live-viewport.ts +++ b/web/src/lib/canvas/canvas-live-viewport.ts @@ -4,6 +4,12 @@ export const CANVAS_VIEWPORT_PREVIEW_EVENT = "canvas:viewport-preview"; export const CANVAS_GRAPHICS_VIEWPORT_PREVIEW_EVENT = "canvas:graphics-viewport-preview"; export const CANVAS_SELECTION_PREVIEW_EVENT = "canvas:selection-preview"; +// 空间网格点模式的点半径(像素单位)。远距(缩放 < 0.12)时用更小半径避免糊成一团。 +// 同时被 (infinite-canvas)与滚动同步(applyCanvasLiveViewport)共享,避免两处漂移。 +export function canvasDotPx(scale: number): string { + return scale < 0.12 ? "1.2px" : "2px"; +} + export function applyCanvasLiveViewport(container: HTMLDivElement | null, viewport: ViewportTransform, notify = true) { if (!container) return; const gridSize = 48 * viewport.k; @@ -17,7 +23,7 @@ export function applyCanvasLiveViewport(container: HTMLDivElement | null, viewpo container.style.setProperty("--canvas-grid-size", `${gridSize}px`); container.style.setProperty("--canvas-grid-x", `${viewport.x % gridSize}px`); container.style.setProperty("--canvas-grid-y", `${viewport.y % gridSize}px`); - container.style.setProperty("--canvas-dot-size", viewport.k < 0.12 ? "0.8px" : "1.15px"); + container.style.setProperty("--canvas-dot-size", canvasDotPx(viewport.k)); // 图形层必须逐帧跟随 DOM 世界层;浮层和滚动通知仍可按原频率节流。 container.dispatchEvent(new CustomEvent(CANVAS_GRAPHICS_VIEWPORT_PREVIEW_EVENT, { detail: viewport })); if (notify) {