Public
Edited
Oct 4, 2023
Insert cell
Insert cell
d33d = require("https://unpkg.com/d3-3d/build/d3-3d.min.js")
Insert cell
k = 1/4
Insert cell
height = width * k
Insert cell
d3._3d = d33d._3d
Insert cell
function getTriangles(angle) {
// https://en.wikipedia.org/wiki/Tetrahedron
const p = [[1,0,-1/Math.sqrt(2)],[-1,0,-1/Math.sqrt(2)],[0,1,1/Math.sqrt(2)], [0,-1,1/Math.sqrt(2)]];
const data = [
[p[0], p[2], p[1]],
[p[0], p[3], p[2]],
[p[0], p[1], p[3]],
[p[1], p[3], p[2]]
];

let points = d3._3d()
.scale(100)
.origin([width/2, height/2])
.shape('TRIANGLE')
.rotateY(angle)
(data);
return d3.map(points, d => [...d, d[0]]);
}
Insert cell
Insert cell
{
const margin = {top: 0, right: 0, bottom: 0, left: 0};
const [svg_width, svg_height] = [width + margin.left + margin.right, height + margin.top + margin.bottom];

let mx, mouseX = 0;

const svg = d3.create("svg")
.attr("width", svg_width)
.attr("height", svg_height)
.attr("viewBox", [0, 0, svg_width, svg_height])
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

svg.call(d3.drag()
.on("drag", dragged)
.on("start", dragStart)
.on("end", dragEnd)
);
const chart = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);

const line = d3.line()
.x(d => d.projected.x)
.y(d => d.projected.y);

update(getTriangles(0));

function update(data) {
chart.selectAll('path')
.data(data)
.join("path")
.attr("fill", toggleFill ? "lightblue" : "none")
.attr("fill-opacity", 0.2)
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", d => line(d));
}

// See also: https://gist.github.com/niekes/ff4d3c8497d8436d4d8fdb9f0121d12d
// https://gist.github.com/niekes/5e1254ae778e2854f0079350a0376528
// For drag, see https://observablehq.com/@d3/versor-dragging?intent=fork
// https://d3js.org/d3-drag
function dragStart({x, y}){
mx = x;
}

function dragEnd({x, y}) {
mouseX = x - mx + mouseX;
}

function dragged(event) {
const beta = (event.x - mx + mouseX) * Math.PI / (-360);
update(getTriangles(beta));
}
return svg.node();
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more