diff --git a/src/App.css b/src/App.css
index 22ea286..11233c9 100644
--- a/src/App.css
+++ b/src/App.css
@@ -64,7 +64,7 @@ code {
padding: 0;
}
-.cards li + li {
+.cards li+li {
padding-top: 10px;
}
@@ -93,6 +93,7 @@ code {
}
/* Give space to see the svg below */
+
@media all and (max-width: 850px) {
.cards {
margin-bottom: calc(100vh - 80px);
@@ -100,8 +101,7 @@ code {
}
@media all and (max-width: 450px) {
- .cards,
- .sticky {
+ .cards, .sticky {
width: 100vw;
min-width: 0;
}
@@ -134,3 +134,31 @@ code {
margin-left: 50%;
transform: translate(-50%, 0);
}
+
+/* TODO! */
+
+.grid {
+ /* color: red; */
+ color: #ccc;
+}
+
+.grid-main {
+ stroke: currentColor;
+ stroke-width: calc(var(--grid-stroke) / 2.5);
+}
+
+.grid-sub {
+ stroke: currentColor;
+ stroke-width: calc(var(--grid-stroke) / 5);
+}
+
+.grid-dashed {
+ stroke-dasharray: calc(var(--grid-stroke) / 2.5);
+}
+
+.grid-label {
+ fill: #666;
+ font-family: 'Courier New', Courier, monospace;
+ 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 3bb65eb..7b258e5 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,84 @@ function SVGViewer({
}
}
+ 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
+
+ // 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');
+ }
+ }
+ 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(
+
+ );
+
+ if (isMultipleOfPow10Scale) {
+ const labelCoordinates = {} as any; // TODO TS to fix
+ 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(
+ {currAxisValue}
+ );
+ }
+ }
+ data.grid.push(gridElements.lines, gridElements.labels);
+ })
+
return (