From d26cc8fc46094170b93453fdbfac3de7edbbca83 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Thu, 30 Apr 2020 21:59:09 +0100 Subject: [PATCH 1/4] quick draft to add a visual coordinates grid (proof of concept for PR) --- src/App.css | 30 +++++++++++++++++-- src/SVGViewer.tsx | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/App.css b/src/App.css index 22ea286..1fe492d 100644 --- a/src/App.css +++ b/src/App.css @@ -26,6 +26,9 @@ min-width: 400px; height: 100vh; justify-content: center; + /* TODO! */ + padding-right: 20px; + padding-bottom: 50px; } .viewer-wrapper .svg-viewer { @@ -64,7 +67,7 @@ code { padding: 0; } -.cards li + li { +.cards li+li { padding-top: 10px; } @@ -93,6 +96,7 @@ code { } /* Give space to see the svg below */ + @media all and (max-width: 850px) { .cards { margin-bottom: calc(100vh - 80px); @@ -100,8 +104,7 @@ code { } @media all and (max-width: 450px) { - .cards, - .sticky { + .cards, .sticky { width: 100vw; min-width: 0; } @@ -134,3 +137,24 @@ code { margin-left: 50%; transform: translate(-50%, 0); } + +/* TODO! */ + +.grid-main { + stroke: #ccc; +} + +.grid-sub-x { + stroke: #ccc; +} + +.grid-sub-y { + stroke: #ccc; +} + +.grid-label { + fill: #666; + font-family: 'Courier New', Courier, monospace; + font-size: 14px; + font-weight: 600; +} \ No newline at end of file diff --git a/src/SVGViewer.tsx b/src/SVGViewer.tsx index 3bb65eb..6842244 100644 --- a/src/SVGViewer.tsx +++ b/src/SVGViewer.tsx @@ -570,6 +570,7 @@ function SVGViewer({ return prev; }, { + grid: [] as React.ReactNode[], elems: [] as React.ReactNode[], overlay: [] as React.ReactNode[], current: { x: 0, y: 0 }, @@ -607,8 +608,82 @@ function SVGViewer({ } } + const gridDeltaX = bounds[2] - bounds[0] - 50; + const gridDeltaY = bounds[3] - bounds[1] - 50; + const gridStep = 20; // TODO! + const gridIntervalsY = gridDeltaX / gridStep; // TODO! + const gridIntervalsX = gridDeltaY / gridStep; // TODO! + + // main X axis + data.grid.push( + + ); + // main Y axis + data.grid.push([ + , + (0,0) + ]); + // sub X axis + for (let i = 1; i < gridIntervalsX; i++) { + const currY = i * gridStep; + data.grid.push( + + ); + if (i % 5 === 0) { + data.grid.push( + {currY} + ); + } + } + for (let i = 1; i < gridIntervalsY; i++) { + const currX = i * gridStep; + data.grid.push( + + ); + if (i % 5 === 0) { + data.grid.push( + {currX} + ); + } + } + return ( + {data.grid} {data.elems} {data.overlay} From c053c1fa316d887c2a604b82d52ad90489adacb9 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Sun, 3 May 2020 11:05:35 +0100 Subject: [PATCH 2/4] better grid in SVGViewer --- src/App.css | 20 +++++---- src/SVGViewer.tsx | 102 ++++++++++++++++++++++++---------------------- 2 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/App.css b/src/App.css index 1fe492d..75fe759 100644 --- a/src/App.css +++ b/src/App.css @@ -26,9 +26,6 @@ min-width: 400px; height: 100vh; justify-content: center; - /* TODO! */ - padding-right: 20px; - padding-bottom: 50px; } .viewer-wrapper .svg-viewer { @@ -140,16 +137,23 @@ code { /* TODO! */ +.grid { + /* color: red; */ + color: #ccc; +} + .grid-main { - stroke: #ccc; + stroke: currentColor; + stroke-width: calc(var(--grid-stroke) / 2.5); } -.grid-sub-x { - stroke: #ccc; +.grid-sub { + stroke: currentColor; + stroke-width: calc(var(--grid-stroke) / 5); } -.grid-sub-y { - stroke: #ccc; +.grid-dashed { + stroke-dasharray: calc(var(--grid-scale) / 50); } .grid-label { diff --git a/src/SVGViewer.tsx b/src/SVGViewer.tsx index 6842244..1b99538 100644 --- a/src/SVGViewer.tsx +++ b/src/SVGViewer.tsx @@ -608,82 +608,86 @@ function SVGViewer({ } } - const gridDeltaX = bounds[2] - bounds[0] - 50; - const gridDeltaY = bounds[3] - bounds[1] - 50; - const gridStep = 20; // TODO! - const gridIntervalsY = gridDeltaX / gridStep; // TODO! - const gridIntervalsX = gridDeltaY / gridStep; // TODO! + const gridXMin = bounds[0]; + const gridXMax = bounds[2]; + const gridYMin = bounds[1]; + const gridYMax = bounds[3]; + const gridDeltaX = bounds[2] - bounds[0]; + const gridDeltaY = bounds[3] - bounds[1]; + const gridTenScaleX = Math.pow(10, Math.floor(Math.log10(gridDeltaX))); + const gridTenScaleY = Math.pow(10, Math.floor(Math.log10(gridDeltaY))); + const gridTenScale = Math.min(gridTenScaleX, gridTenScaleY); + const gridStep = gridTenScale / 5; + const gridFirstLineX = gridXMin - (gridXMin % gridStep); + const gridFirstLineY = gridYMin - (gridYMin % gridStep); + const gridIntervalsY = gridDeltaX / gridStep; + const gridIntervalsX = gridDeltaY / gridStep; - // main X axis - data.grid.push( - - ); - // main Y axis - data.grid.push([ - , - (0,0) - ]); // sub X axis for (let i = 1; i < gridIntervalsX; i++) { - const currY = i * gridStep; + const currY = gridFirstLineY + i * gridStep; + const isYYY = currY % gridTenScale === 0; + const classNames = [] + if (currY === 0) { + classNames.push('grid-main'); + } else { + classNames.push('grid-sub'); + if (!isYYY) { + classNames.push('grid-dashed'); + } + } data.grid.push( ); - if (i % 5 === 0) { + if (isYYY) { data.grid.push( - {currY} + {currY} ); } } for (let i = 1; i < gridIntervalsY; i++) { - const currX = i * gridStep; + const currX = gridFirstLineX + i * gridStep; + const isXXX = currX % gridTenScale === 0; + const classNames = [] + if (currX === 0) { + classNames.push('grid-main'); + } else { + classNames.push('grid-sub'); + if (!isXXX) { + classNames.push('grid-dashed'); + } + } data.grid.push( ); - if (i % 5 === 0) { + if (isXXX) { data.grid.push( - {currX} + {currX} ); } } return ( - {data.grid} + {/* + // @ts-ignore */} + + {data.grid} + {data.elems} {data.overlay} From 11f90ca66213519defebe08fa8cead3b829575e2 Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Sun, 3 May 2020 12:26:44 +0100 Subject: [PATCH 3/4] improved code for grid generation (not final yet) --- src/SVGViewer.tsx | 134 +++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 68 deletions(-) diff --git a/src/SVGViewer.tsx b/src/SVGViewer.tsx index 1b99538..2a35859 100644 --- a/src/SVGViewer.tsx +++ b/src/SVGViewer.tsx @@ -608,84 +608,82 @@ function SVGViewer({ } } - const gridXMin = bounds[0]; - const gridXMax = bounds[2]; - const gridYMin = bounds[1]; - const gridYMax = bounds[3]; - const gridDeltaX = bounds[2] - bounds[0]; - const gridDeltaY = bounds[3] - bounds[1]; - const gridTenScaleX = Math.pow(10, Math.floor(Math.log10(gridDeltaX))); - const gridTenScaleY = Math.pow(10, Math.floor(Math.log10(gridDeltaY))); - const gridTenScale = Math.min(gridTenScaleX, gridTenScaleY); - const gridStep = gridTenScale / 5; - const gridFirstLineX = gridXMin - (gridXMin % gridStep); - const gridFirstLineY = gridYMin - (gridYMin % gridStep); - const gridIntervalsY = gridDeltaX / gridStep; - const gridIntervalsX = gridDeltaY / gridStep; + const gridProps = { + 'x': { + min: bounds[0], + max: bounds[2], + delta: bounds[2] - bounds[0], + }, + 'y': { + min: bounds[1], + max: bounds[3], + delta: bounds[3] - bounds[1], + } + } as any; // TODO TS to fix - // sub X axis - for (let i = 1; i < gridIntervalsX; i++) { - const currY = gridFirstLineY + i * gridStep; - const isYYY = currY % gridTenScale === 0; - const classNames = [] - if (currY === 0) { - classNames.push('grid-main'); - } else { - classNames.push('grid-sub'); - if (!isYYY) { - classNames.push('grid-dashed'); + // we need the labels to be always on top of the lines, but since SVG doesn't support z-index via CSS + // we need to generate them separately and then push them in the right order in the "data.grid" element + const gridElements = { + lines: [], + labels: [], + } as any; // TODO TS to fix + + // TODO: discuss in PR if is really needed, or we can assume they have the same scale + // TODO explain what the "power of ten scale" is + const gridTenScaleX = Math.pow(10, Math.floor(Math.log10(gridProps['x'].delta))); + const gridTenScaleY = Math.pow(10, Math.floor(Math.log10(gridProps['y'].delta))); + gridProps['scalePow10'] = Math.min(gridTenScaleX, gridTenScaleY); + + // TODO explain what a "step" is + gridProps['step'] = gridProps['scalePow10'] / 5; + + ['x', 'y'].forEach((axis) => { + // not very elegant, but it works + // TODO alternative, use some "magic" code that uses "object.keys(gridProps) and works out the "other" key ? + const otherAxis = axis === 'x' ? 'y' : 'x'; + const firstLine = gridProps[otherAxis].min - (gridProps[otherAxis].min % gridProps['step']); + const intervals = gridProps[otherAxis].delta / gridProps['step']; + + for (let i = 1; i < intervals; i++) { + const currAxisValue = firstLine + i * gridProps['step']; + const isMultipleOfPow10Scale = currAxisValue % gridProps['scalePow10'] === 0; + const classNames = [] + if (currAxisValue === 0) { + classNames.push('grid-main'); + } else { + classNames.push('grid-sub'); + if (!isMultipleOfPow10Scale) { + classNames.push('grid-dashed'); + } } - } - data.grid.push( - - ); - if (isYYY) { - data.grid.push( - {currY} + const lineCoordinates = {} as any; // TODO TS to fix + lineCoordinates[`${axis}1`] = gridProps[axis].min; + lineCoordinates[`${axis}2`] = gridProps[axis].max; + lineCoordinates[`${otherAxis}1`] = currAxisValue; + lineCoordinates[`${otherAxis}2`] = currAxisValue; + + gridElements.lines.push( + ); - } - } - for (let i = 1; i < gridIntervalsY; i++) { - const currX = gridFirstLineX + i * gridStep; - const isXXX = currX % gridTenScale === 0; - const classNames = [] - if (currX === 0) { - classNames.push('grid-main'); - } else { - classNames.push('grid-sub'); - if (!isXXX) { - classNames.push('grid-dashed'); + + if (isMultipleOfPow10Scale) { + const labelCoordinates = {} as any; // TODO TS to fix + labelCoordinates[axis] = -20; // TODO use a better calculation based on the scale factor + labelCoordinates[otherAxis] = currAxisValue; + + gridElements.labels.push( + {currAxisValue} + ); } } - data.grid.push( - - ); - if (isXXX) { - data.grid.push( - {currX} - ); - } - } + data.grid.push(gridElements.lines, gridElements.labels); + }) return ( {/* // @ts-ignore */} - + {data.grid} {data.elems} From 227fb5621dc2dd96f31579756e1302b5a5afaebf Mon Sep 17 00:00:00 2001 From: Cristiano Rastelli Date: Sun, 3 May 2020 12:34:54 +0100 Subject: [PATCH 4/4] small improvements to the usage of the scaling factor --- src/App.css | 4 ++-- src/SVGViewer.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/App.css b/src/App.css index 75fe759..11233c9 100644 --- a/src/App.css +++ b/src/App.css @@ -153,12 +153,12 @@ code { } .grid-dashed { - stroke-dasharray: calc(var(--grid-scale) / 50); + stroke-dasharray: calc(var(--grid-stroke) / 2.5); } .grid-label { fill: #666; font-family: 'Courier New', Courier, monospace; - font-size: 14px; + font-size: calc(10px * var(--grid-scale-factor-pow10) / 100); font-weight: 600; } \ No newline at end of file diff --git a/src/SVGViewer.tsx b/src/SVGViewer.tsx index 2a35859..7b258e5 100644 --- a/src/SVGViewer.tsx +++ b/src/SVGViewer.tsx @@ -668,7 +668,7 @@ function SVGViewer({ if (isMultipleOfPow10Scale) { const labelCoordinates = {} as any; // TODO TS to fix - labelCoordinates[axis] = -20; // TODO use a better calculation based on the scale factor + labelCoordinates[axis] = -10 * gridProps['scalePow10'] / 100; // TODO use a better calculation based on the grid[x/y].delta which is more precise? labelCoordinates[otherAxis] = currAxisValue; gridElements.labels.push( @@ -683,7 +683,7 @@ function SVGViewer({ {/* // @ts-ignore */} - + {data.grid} {data.elems}