Skip to content

Commit

Permalink
Wip fit to view
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaBobs committed Aug 24, 2024
1 parent e7b7227 commit 40ac78d
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 50 deletions.
71 changes: 69 additions & 2 deletions src/crocheting/CrochetingData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,85 @@ export class CrochetingData {
#cells: Map<string, CrochetingCell> = new Map();

toggleCell(x: number, y: number) {
const cellKey = `${x},${y}`;
const cellKey = this.getKey(x, y);

const existingCell = this.#cells.get(cellKey);

if (existingCell) {
this.#cells.delete(cellKey);

const aboveAffected = this.getVerticalCellRegion(x, y + 1);
this.markCellRegion(aboveAffected);

const belowAffected = this.getVerticalCellRegion(x, y - 1);
this.markCellRegion(belowAffected);
} else {
this.#cells.set(cellKey, { x, y, color: "green" });
this.#cells.set(cellKey, { x, y, color: "lightblue" });

const affected = this.getVerticalCellRegion(x, y);
this.markCellRegion(affected);
}
}

markCellRegion(region: CrochetingCell[]) {
if (region.length === 0) return;

if (region.length === 1) {
region[0].content = undefined;
return;
}

const reversed = [...region].reverse();
for (let i = 0; i < reversed.length; i++) {
if (i % 2 === 0) {
reversed[i].content = "X";
} else {
reversed[i].content = undefined;
}
}

reversed.last()!.content = undefined;
}

getVerticalCellRegion(x: number, y: number) {
let maximumY = y;

while (this.#cells.has(this.getKey(x, maximumY + 1))) {
maximumY++;
}

const cells: CrochetingCell[] = [];
let iteratingY = maximumY;
let cell = this.#cells.get(this.getKey(x, iteratingY--));
while (cell != null) {
cells.push(cell);
cell = this.#cells.get(this.getKey(x, iteratingY--));
}

return cells;
}

getBoundingRectangle() {
let minX = Number.MAX_SAFE_INTEGER;
let minY = Number.MAX_SAFE_INTEGER;
let maxX = Number.MIN_SAFE_INTEGER;
let maxY = Number.MIN_SAFE_INTEGER;

for (const cell of this.getCells()) {
minX = Math.min(minX, cell.x);
minY = Math.min(minY, cell.y);
maxX = Math.max(maxX, cell.x);
maxY = Math.max(maxY, cell.y);
}

return { minX, minY, maxX, maxY };
}

getCells() {
return [...this.#cells.values()];
}

getKey(x: number, y: number) {
return `${x},${y}`;
}
}
115 changes: 67 additions & 48 deletions src/crocheting/CrochetingRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ export function CrochetingRenderer(props: { data?: CrochetingData }) {
(event.clientY - viewData.offsetY - rect.y) / viewData.zoom
);

console.log({
offsetX: viewData.offsetX,
clientX: event.clientX,
cellX,
});

return { x: cellX, y: cellY };
}

Expand All @@ -48,7 +42,6 @@ export function CrochetingRenderer(props: { data?: CrochetingData }) {
}

viewData.hoveredCell = getCellFromEvent(event);
console.log(getCellFromEvent(event));

rerender();
};
Expand All @@ -60,19 +53,15 @@ export function CrochetingRenderer(props: { data?: CrochetingData }) {
viewData.hoveredCell = getCellFromEvent(event);
}

console.log(viewData.hoveredCell);

rerender();
};

const handleClick = (event: MouseEvent) => {
const clickedCell = getCellFromEvent(event);

patternData.toggleCell({
x: clickedCell.x,
y: clickedCell.y,
color: "red",
count: 1,
content: "X",
});
patternData.toggleCell(clickedCell.x, clickedCell.y);
rerender();
};

Expand All @@ -89,49 +78,79 @@ export function CrochetingRenderer(props: { data?: CrochetingData }) {
};
}, [svgRef]);

function fitToView() {
const rect = patternData.getBoundingRectangle();
const svg = svgRef.current!;

rect.minX -= 1;
rect.minY -= 1;
rect.maxX += 1;
rect.maxY += 1;

viewData.zoom = Math.min(
svg.clientWidth / (rect.maxX - rect.minX),
svg.clientHeight / (rect.maxY - rect.minY)
);

viewData.offsetX = rect.minX * viewData.zoom;
viewData.offsetY = rect.minY * viewData.zoom;

rerender();
}

return (
<svg
ref={svgRef}
<div
style={{
width: "100%",
height: "100%",
backgroundSize: `${viewData.zoom}px ${viewData.zoom}px`,
backgroundPositionX: `${viewData.offsetX}px`,
backgroundPositionY: `${viewData.offsetY}px`,
backgroundImage: `linear-gradient(to right, grey 1px, transparent 1px),linear-gradient(to bottom, grey 1px, transparent 1px)`,
}}
>
{patternData.getCells().map((cell) => (
<g key={"" + cell.x + cell.y}>
<div style={{ position: "absolute", right: 10, top: 40 }}>
<button onClick={fitToView}>fit to view</button>
</div>
<svg
ref={svgRef}
style={{
width: "100%",
height: "100%",
backgroundSize: `${viewData.zoom}px ${viewData.zoom}px`,
backgroundPositionX: `${viewData.offsetX}px`,
backgroundPositionY: `${viewData.offsetY}px`,
backgroundImage: `linear-gradient(to right, grey 1px, transparent 1px),linear-gradient(to bottom, grey 1px, transparent 1px)`,
}}
>
{patternData.getCells().map((cell) => (
<g key={"" + cell.x + cell.y}>
<rect
x={cell.x * viewData.zoom + viewData.offsetX}
y={cell.y * viewData.zoom + viewData.offsetY}
width={viewData.zoom}
height={viewData.zoom}
fill={cell.color}
></rect>
<text
x={cell.x * viewData.zoom + viewData.offsetX + viewData.zoom / 2}
y={cell.y * viewData.zoom + viewData.offsetY + viewData.zoom / 2}
width={viewData.zoom}
height={viewData.zoom}
fontSize={viewData.zoom}
textAnchor="middle"
alignmentBaseline="middle"
>
{cell.content}
</text>
</g>
))}
{viewData.hoveredCell && (
<rect
x={cell.x * viewData.zoom + viewData.offsetX}
y={cell.y * viewData.zoom + viewData.offsetY}
style={{ opacity: 0.1 }}
x={viewData.hoveredCell.x * viewData.zoom + viewData.offsetX}
y={viewData.hoveredCell.y * viewData.zoom + viewData.offsetY}
width={viewData.zoom}
height={viewData.zoom}
fill={cell.color}
></rect>
<text
x={cell.x * viewData.zoom + viewData.offsetX + viewData.zoom / 2}
y={cell.y * viewData.zoom + viewData.offsetY + viewData.zoom / 2}
width={viewData.zoom}
height={viewData.zoom}
fontSize={viewData.zoom}
text-anchor="middle"
alignment-baseline="middle"
>
{cell.content}
</text>
</g>
))}
{viewData.hoveredCell && (
<rect
style={{ opacity: 0.1 }}
x={viewData.hoveredCell.x * viewData.zoom + viewData.offsetX}
y={viewData.hoveredCell.y * viewData.zoom + viewData.offsetY}
width={viewData.zoom}
height={viewData.zoom}
></rect>
)}
</svg>
)}
</svg>
</div>
);
}

0 comments on commit 40ac78d

Please sign in to comment.