Skip to content

Instantly share code, notes, and snippets.

@HarryStevens
Last active October 26, 2022 18:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HarryStevens/797a8bccbcc6f09a6c13e8c5cb1ecd76 to your computer and use it in GitHub Desktop.
Save HarryStevens/797a8bccbcc6f09a6c13e8c5cb1ecd76 to your computer and use it in GitHub Desktop.
Isometric Grid Slider
license: gpl-3.0
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
}
svg {
display: table;
margin: 0 auto;
}
line {
stroke-width: 4px;
}
path {
fill: none;
}
.cell {
stroke: #eee;
}
.outline {
stroke: #000;
stroke-width: 2px;
}
.input {
display: table;
margin: 0 auto;
}
.input label {
font-family: sans-serif;
margin-right: 8px;
}
</style>
</head>
<body>
<div class="input">
<label>Rotation</label>
<input type="range" min="0" max="30" value="30">
</div>
<div class="grid"></div>
<script type="module">
import { cross, range } from "https://cdn.skypack.dev/d3-array@3";
import { geoEquirectangular, geoPath } from "https://cdn.skypack.dev/d3-geo@3";
import { randomUniform } from "https://cdn.skypack.dev/d3-random@3";
import { interpolateSinebow } from "https://cdn.skypack.dev/d3-scale-chromatic@3";
import { select } from "https://cdn.skypack.dev/d3-selection@3";
import { interval } from "https://cdn.skypack.dev/d3-timer@3";
import { transition } from "https://cdn.skypack.dev/d3-transition@3";
const { cos, PI, round, sin } = Math;
const i = 0.4;
const r = range(-1, 1, i);
const cells = {
type: "FeatureCollection",
features: cross(r, r)
.map(([lon, lat]) => ({
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [
[
[lon, lat],
[lon, lat + i],
[lon + i, lat + i],
[lon + i, lat],
[lon, lat]
]
]
}
}))
};
const x = n => round(cos(n));
const y = n => round(sin(n));
const random = randomUniform(-1, 1);
const data = Array.from({ length: 250 }).map(d => ([random(), random()]));
const square = [ range(1, PI * 2.5, PI * 0.25).map(n => [x(n), y(n)]) ];
const margin = {left: 1, right: 1, top: 50, bottom: 1};
const size = 400;
const projection = geoEquirectangular()
.reflectY(true)
.fitSize([size, size], cells);
const path = geoPath(projection);
const svg = select(".grid").append("svg")
.attr("width", size + margin.left + margin.right)
.attr("height", size + margin.top + margin.bottom);
const g = svg.append("g")
.attr("transform", `translate(${[margin.left, margin.top]})`);
const cell = g.selectAll(".cell")
.data(cells.features)
.join("path")
.attr("class", "cell");
const outline = g.append("path")
.attr("class", "outline")
.datum({
type: "Polygon",
coordinates: square
});
const line = g.selectAll("line")
.data(data)
.join("line")
.attr("stroke", (d, i, e) => interpolateSinebow(i / e.length))
.attr("y2", -margin.top + 15);
draw([30, -60, 0]);
select("input").on("input", function(){
draw([this.value, -this.value * 2, 0]);
});
function draw(rotation){
projection
.rotate(rotation)
.fitSize([size, size], cells);
cell
.attr("d", path);
outline
.attr("d", path);
line
.attr("transform", d => `translate(${projection(d)})`);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment