import { useCallback, useEffect, useRef } from "react"; const primaryLineColor = "rgb(203,213,245)"; const subLineColor = "rgb(226,231,232)"; export default function GridLayer(props: { width: number; height: number; leftPadding: number; rightPadding: number; topPadding: number; bottomPadding: number; columns: number; rows: number; colCellNum: number; rowCellNum: number; visibility: 'hidden' | 'visible'; }) { const xStartPx = props.leftPadding; const xEndPx = props.width - props.rightPadding; const xStepPx = (props.width - props.leftPadding - props.rightPadding) / props.columns; const xUnitPx = xStepPx / props.colCellNum; const yStartPx = props.topPadding; const yEndPx = props.height - props.bottomPadding; const yStepPx = (props.height - props.topPadding - props.bottomPadding) / props.rows; const yUnitPx = yStepPx / props.rowCellNum; const canvasRef = useRef(null); const drawGrid = useCallback( (ctx: CanvasRenderingContext2D) => { ctx.resetTransform(); ctx.clearRect(0, 0, props.width, props.height); ctx.beginPath(); ctx.strokeStyle = subLineColor; for (let i = 1; i < props.columns * props.colCellNum; ++i) { if (i % props.colCellNum === 0) continue; ctx.moveTo(xStartPx + xUnitPx * i, yStartPx); ctx.lineTo(xStartPx + xUnitPx * i, yEndPx); } for (let j = 1; j < props.rows * props.rowCellNum; ++j) { if (j % props.rowCellNum === 0) continue; ctx.moveTo(xStartPx, yStartPx + yUnitPx * j); ctx.lineTo(xEndPx, yStartPx + yUnitPx * j); } ctx.stroke() ctx.beginPath(); ctx.strokeStyle = primaryLineColor; for (let i = 0; i <= props.columns; ++i) { ctx.moveTo(xStartPx + xStepPx * i, yStartPx); ctx.lineTo(xStartPx + xStepPx * i, yEndPx); } for (let j = 0; j <= props.rows; ++j) { ctx.moveTo(xStartPx, yStartPx + yStepPx * j); ctx.lineTo(xEndPx, yStartPx + yStepPx * j); } ctx.stroke() ctx.beginPath(); ctx.strokeStyle = "#999"; // 偏移原点 const xOffset = (xEndPx - xStartPx) / 2; const yOffset = yStepPx * 2; const yMax = yEndPx - yStartPx - yOffset; ctx.translate(xStartPx + xOffset, yStartPx + yOffset); // 绘制原点交叉线 ctx.moveTo(-xOffset, 0); ctx.lineTo(xOffset, 0); ctx.moveTo(0, -yOffset); ctx.lineTo(0, yMax); ctx.stroke() // 绘制x轴y轴 单位数值 ctx.beginPath(); ctx.fillStyle = "#333333"; ctx.textAlign = "center"; ctx.font = "normal 14px system"; for (let index = -4; index < 5; index++) { ctx.fillText((index * 10).toString(), xStepPx * index, yMax + 20); } for (let index = -1; index < 5; index++) { ctx.fillText((index * 10).toString(), -xOffset - (index > 0 ? 18 : 14), yStepPx * index + 4); } }, [props.colCellNum, props.columns, props.height, props.rowCellNum, props.rows, props.width, xEndPx, xStartPx, xStepPx, xUnitPx, yEndPx, yStartPx, yStepPx, yUnitPx] ); useEffect(() => { // 获取canvas的2D绘图上下文 const canvas = canvasRef.current; if (!canvas) return; const context = canvas.getContext("2d"); if (!context) return; // 使用context对象进行绘图 drawGrid(context); }, [drawGrid]); return (
); }