const { dia, shapes, util } = joint;
const GRID_SIZE = 20;
const GRID_COUNT = 12;
// Matrix of the isometric transformation and its parameters
const SCALE = 1;
const ISOMETRIC_SCALE = 0.8602;
const ROTATION_DEGREES = 30;
const transformationMatrix = () => {
return V.createSVGMatrix()
.translate(GRID_SIZE * GRID_COUNT, GRID_SIZE)
.rotate(ROTATION_DEGREES)
.skewX(-ROTATION_DEGREES)
.scaleNonUniform(SCALE, SCALE * ISOMETRIC_SCALE);
};
// Paper
const cellNamespace = { ...shapes };
const graph = new dia.Graph({}, { cellNamespace });
const paper = new dia.Paper({
el: document.getElementById("paper-container"),
model: graph,
restrictTranslate: {
x: 0,
y: 0,
width: GRID_SIZE * GRID_COUNT,
height: GRID_SIZE * GRID_COUNT
},
width: "100%",
height: "100%",
gridSize: GRID_SIZE,
async: true,
autoFreeze: true,
sorting: dia.Paper.sorting.APPROX,
cellViewNamespace: cellNamespace
});
// Make the paper isometric by applying the isometric matrix to all
// SVG content it contains.
paper.matrix(transformationMatrix());
const gVEl = V("g", { fill: "#ed2637" });
const rectVEl = V("rect", {
width: GRID_SIZE,
height: GRID_SIZE,
stroke: "#ed2637",
"stroke-width": 1
});
const textVEl = V("text").attr({
"text-anchor": "start",
x: 2 * GRID_SIZE,
"font-size": GRID_SIZE,
"font-family": "sans-serif",
stroke: "white",
"stroke-width": 3,
"paint-order": "stroke"
});
gVEl.append([rectVEl, textVEl]);
paper.el.addEventListener(
"mousemove",
(evt) => {
const { x, y } = paper.clientToLocalPoint(evt.clientX, evt.clientY);
const i = Math.floor(x / GRID_SIZE);
const j = Math.floor(y / GRID_SIZE);
drawCoordinates(paper, i, j);
},
false
);
drawGrid(paper);
drawCoordinates(paper, 0, 0);
// Add switch to toggle the isometric view with 2d for demonstration purposes
document
.getElementById("isometric-switch")
.addEventListener("change", (evt) => {
if (evt.target.checked) {
paper.matrix(transformationMatrix());
} else {
paper.matrix(
V.createSVGMatrix().translate(GRID_SIZE * GRID_COUNT, GRID_SIZE)
);
}
});
// A function to draw the grid.
function drawGrid(paper) {
const gridData = [];
const j = GRID_COUNT;
for (let i = 0; i <= j; i++) {
gridData.push(`M 0,${i * GRID_SIZE} ${j * GRID_SIZE},${i * GRID_SIZE}`);
gridData.push(`M ${i * GRID_SIZE},0 ${i * GRID_SIZE},${j * GRID_SIZE}`);
}
const gridEl = V("path").attr({
d: gridData.join(" "),
fill: "none",
stroke: "lightgray"
}).node;
// When the grid is appended to one of the paper's layer, it gets automatically transformed
// by the isometric matrix
paper.getLayerNode(dia.Paper.Layers.BACK).append(gridEl);
}
// A function to highlight a point in the grid
function drawCoordinates(paper, i, j) {
textVEl.text(`x: ${i} y: ${j}`, { verticalTextAnchor: "middle" });
gVEl.attr("transform", `translate(${i * GRID_SIZE},${j * GRID_SIZE})`);
if (i >= 0 && j >= 0 && i < GRID_COUNT && j < GRID_COUNT) {
if (!gVEl.node.isConnected) {
gVEl.appendTo(paper.getLayerNode(dia.Paper.Layers.BACK));
}
} else {
gVEl.remove();
}
}