fix(canvas): 画布背景 - 降低点阵密度与亮度并优化缩放显示
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
|
||||
import { canvasThemes, type CanvasBackgroundMode } from "@/lib/canvas-theme";
|
||||
import { applyCanvasLiveViewport, canvasDotPx, subscribeCanvasViewportPreview } from "@/lib/canvas/canvas-live-viewport";
|
||||
import { applyCanvasLiveViewport, canvasDotGridPx, canvasDotPx, subscribeCanvasViewportPreview } from "@/lib/canvas/canvas-live-viewport";
|
||||
import { useThemeStore } from "@/stores/use-theme-store";
|
||||
import type { ViewportTransform } from "@/types/canvas";
|
||||
|
||||
@@ -382,6 +382,9 @@ export function InfiniteCanvas({ containerRef, viewport, backgroundMode = "lines
|
||||
"--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-grid-size": `${canvasDotGridPx(viewport.k)}px`,
|
||||
"--canvas-dot-grid-x": `${viewport.x % canvasDotGridPx(viewport.k)}px`,
|
||||
"--canvas-dot-grid-y": `${viewport.y % canvasDotGridPx(viewport.k)}px`,
|
||||
"--canvas-dot-size": canvasDotPx(viewport.k),
|
||||
} as React.CSSProperties}
|
||||
onPointerDown={handlePointerDown}
|
||||
@@ -422,11 +425,11 @@ function CanvasGrid({ mode }: { mode: CanvasBackgroundMode }) {
|
||||
data-canvas-grid-layer
|
||||
className="pointer-events-none absolute"
|
||||
style={{
|
||||
inset: "calc(-1 * var(--canvas-grid-size))",
|
||||
inset: mode === "dots" ? "calc(-1 * var(--canvas-dot-grid-size))" : "calc(-1 * var(--canvas-grid-size))",
|
||||
backgroundImage,
|
||||
backgroundSize: "var(--canvas-grid-size) var(--canvas-grid-size)",
|
||||
transform: "translate3d(var(--canvas-grid-x), var(--canvas-grid-y), 0)",
|
||||
opacity: 0.46,
|
||||
backgroundSize: mode === "dots" ? "var(--canvas-dot-grid-size) var(--canvas-dot-grid-size)" : "var(--canvas-grid-size) var(--canvas-grid-size)",
|
||||
transform: mode === "dots" ? "translate3d(var(--canvas-dot-grid-x), var(--canvas-dot-grid-y), 0)" : "translate3d(var(--canvas-grid-x), var(--canvas-grid-y), 0)",
|
||||
opacity: mode === "dots" ? 0.34 : 0.46,
|
||||
willChange: "transform",
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,7 @@ export const canvasThemes = {
|
||||
light: {
|
||||
canvas: {
|
||||
background: "#ffffff",
|
||||
dot: "rgba(15,23,42,.30)",
|
||||
dot: "rgba(15,23,42,.20)",
|
||||
line: "rgba(15,23,42,.15)",
|
||||
selectionFill: "rgba(17,17,17,.10)",
|
||||
},
|
||||
@@ -71,7 +71,7 @@ export const canvasThemes = {
|
||||
dark: {
|
||||
canvas: {
|
||||
background: "#0b0b0b",
|
||||
dot: "rgba(178,178,178,.27)",
|
||||
dot: "rgba(178,178,178,.18)",
|
||||
line: "rgba(178,178,178,.14)",
|
||||
selectionFill: "rgba(255,255,255,.12)",
|
||||
},
|
||||
|
||||
@@ -4,15 +4,20 @@ 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)时用更小半径避免糊成一团。
|
||||
// 同时被 <CanvasGrid>(infinite-canvas)与滚动同步(applyCanvasLiveViewport)共享,避免两处漂移。
|
||||
// 空间网格点模式的点半径(像素单位)。远距时使用更小半径,避免点阵糊成一团。
|
||||
export function canvasDotPx(scale: number): string {
|
||||
return scale < 0.12 ? "0.8px" : "1.25px";
|
||||
return scale < 0.12 ? "0.6px" : "0.8px";
|
||||
}
|
||||
|
||||
// 点阵在缩小时不再无限压缩到屏幕像素,避免密集视觉噪声。
|
||||
export function canvasDotGridPx(scale: number): number {
|
||||
return Math.max(48 * scale, 32);
|
||||
}
|
||||
|
||||
export function applyCanvasLiveViewport(container: HTMLDivElement | null, viewport: ViewportTransform, notify = true) {
|
||||
if (!container) return;
|
||||
const gridSize = 48 * viewport.k;
|
||||
const dotGridSize = canvasDotGridPx(viewport.k);
|
||||
const committedScale = Number(container.style.getPropertyValue("--canvas-committed-scale")) || viewport.k;
|
||||
container.style.setProperty("--canvas-live-x", `${viewport.x}px`);
|
||||
container.style.setProperty("--canvas-live-y", `${viewport.y}px`);
|
||||
@@ -23,6 +28,9 @@ 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-grid-size", `${dotGridSize}px`);
|
||||
container.style.setProperty("--canvas-dot-grid-x", `${viewport.x % dotGridSize}px`);
|
||||
container.style.setProperty("--canvas-dot-grid-y", `${viewport.y % dotGridSize}px`);
|
||||
container.style.setProperty("--canvas-dot-size", canvasDotPx(viewport.k));
|
||||
// 图形层必须逐帧跟随 DOM 世界层;浮层和滚动通知仍可按原频率节流。
|
||||
container.dispatchEvent(new CustomEvent<ViewportTransform>(CANVAS_GRAPHICS_VIEWPORT_PREVIEW_EVENT, { detail: viewport }));
|
||||
|
||||
Reference in New Issue
Block a user