Public
Edited
Sep 12, 2023
Insert cell
Insert cell
Insert cell
<svg width=${width} height="800" viewBox="0 0 ${width} 800" id='mySVG'></svg>
Insert cell
// Tree
main = {

const svg = d3.select('#mySVG');
const height = 800 // document.body.clientHeight;
//const width = document.body.clientWidth;

const treeLayout = d3.tree().nodeSize([160, 260]);

const zoomG = svg
.attr('width', width)
.attr('height', height)
.append('g');

svg.call(d3.zoom().on('zoom', () => { zoomG.attr('transform', d3.event.transform); }));

const root = d3.hierarchy(jsonData);
const links = treeLayout(root).links();

const treeHeight = d3.max(root.descendants(), d => d.y)
const treeWidth = d3.max(root.descendants(), d => d.x)
const translations = getTranslations(height, width, treeHeight, treeWidth)

const g = zoomG.append('g').attr('transform', `translate(${translations[0]},${translations[1]}) scale(${getScale(height, treeHeight)})`);

makeLines(g, links);
makeCircle(g, root.descendants());
makeText(g, root.descendants());
makeIcons(g, root.descendants());

}
Insert cell
Insert cell
function getTranslations(boxHeight, boxWidth, treeHeight, treeWidth) {
if (treeHeight == 0) {
return [boxWidth / 2, (boxHeight / 2)]
}
else if (boxHeight + 100 >= treeHeight) {
return [boxWidth / 2, (boxHeight - (treeHeight * 0.8)) / 2];
}
return [boxWidth / 2, 50];
}

Insert cell
function getScale(boxHeight, treeHeight) {
if (boxHeight + 100 >= treeHeight) {
return 0.8;
}
return (boxHeight - 100) / treeHeight;
}
Insert cell
function makeLines(g, l) {
g.selectAll('path').data(l)
.enter().append('path')
.attr("fill", "orange")
.attr("stroke-width", 3)
.attr('d', customCurve);
}
Insert cell
function customCurve(d) {
return "M" + d.source.x + "," + d.source.y // move to
+ "C" + d.source.x + "," + (d.source.y + d.target.y) / 2 // curve start C instructs CVG to draw a cubic Bézier curve
+ " " + d.target.x + "," + (d.source.y + d.target.y) / 2 // curve mid point
+ " " + d.target.x + "," + d.target.y; // curve end
}
Insert cell
Insert cell
function makeCircle(g, r) {
g.selectAll('circle').data(r)
.enter().append('circle')
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.attr('r', 60)
.attr('stroke', d => d.data.data.isFocused ? blue : surface2)
.attr('stroke-width', 4)
.attr('fill', crust);
}

Insert cell
function makeText(g, r) {
g.selectAll('text').data(r)
.enter().append('text')
.attr('x', d => d.x)
.attr('y', d => d.y - 15)
.attr('dy', '0.32em')
.attr('fill', d => d.data.data.isFocused ? blue : textt)
.attr('text-anchor', 'middle')
.attr('font-size', 30)
.text(d => d.data.data.wff);
}
Insert cell
function makeIcons(g, r) {
r.forEach(node => {
const icons = getIcons(node.data);

switch (icons.length) {
case 4:
makeIcon(g, icons[0][0], icons[0][1], node.x - 50, node.y + 7);
makeIcon(g, icons[1][0], icons[1][1], node.x - 23, node.y + 7);
makeIcon(g, icons[2][0], icons[2][1], node.x, node.y + 7);
makeIcon(g, icons[3][0], icons[3][1], node.x + 24, node.y + 7);
break;
case 3:
makeIcon(g, icons[0][0], icons[0][1], node.x - 35, node.y + 7);
makeIcon(g, icons[1][0], icons[1][1], node.x - 13, node.y + 7);
makeIcon(g, icons[2][0], icons[2][1], node.x + 12, node.y + 7);
break;
case 2:
makeIcon(g, icons[0][0], icons[0][1], node.x - 23, node.y + 7);
makeIcon(g, icons[1][0], icons[1][1], node.x, node.y + 7);
break;
case 1:
makeIcon(g, icons[0][0], icons[0][1], node.x - 10, node.y + 7);
break;
default:
break;
}
});
}
Insert cell
function makeIcon(g, icon, color, x, y) {
g.append('g')
.append('path')
.attr('d', icon)
.attr('transform', `translate(${x},${y}) scale(.04)`)
.style('fill', color)
.style('stroke', color);
}
Insert cell
function getIcons(n) {
const icons = [];

if (n.data.isFocused) {
icons.push([eye, blue]);
}

if (n.data.isYours) {
icons.push([user, green]);
} else {
icons.push([user, red]);
}

switch (n.data.doxasticState) {
case "agnosticism":
icons.push([brain, peach]);
break;
case "belief":
icons.push([brain, green]);
break;
case "disbelief":
icons.push([brain, red]);
break;
default:
break;
}

switch (n.data.doxasticStateSupport) {
case "agnosticism":
icons.push([nodes, peach]);
break;
case "belief":
icons.push([nodes, green]);
break;
case "disbelief":
icons.push([nodes, red]);
break;
default:
break;
}

return icons;
}
Insert cell
rosewater = '#f5e0dc';
Insert cell
flamingo = '#f2cdcd';
Insert cell
pink = '#f5c2e7';
Insert cell
mauve = '#cba6f7';
Insert cell
red = '#f38ba8';
Insert cell
maroon = '#eba0ac';
Insert cell
peach = '#fab387';
Insert cell
yellow = '#f9e2af';
Insert cell
green = '#a6e3a1';
Insert cell
teal = '#94e2d5';
Insert cell
sky = '#89dceb';
Insert cell
sapphire = '#74c7ec';
Insert cell
blue = '#89b4fa';
Insert cell
lavender = '#b4befe';
Insert cell
textt = '#cdd6f4';
Insert cell
subtext1 = '#bac2de';
Insert cell
subtext0 = '#a6adc8';
Insert cell
overlay2 = '#9399b2';
Insert cell
overlay1 = '#7f849c';
Insert cell
overlay0 = '#6c7086';
Insert cell
surface2 = '#585b70';
Insert cell
surface1 = '#45475a';
Insert cell
surface0 = '#313244';
Insert cell
base = '#1e1e2e';
Insert cell
mantle = '#181825';
Insert cell
crust = '#11111b';
Insert cell
brain = 'M184 0c30.9 0 56 25.1 56 56V456c0 30.9-25.1 56-56 56c-28.9 0-52.7-21.9-55.7-50.1c-5.2 1.4-10.7 2.1-16.3 2.1c-35.3 0-64-28.7-64-64c0-7.4 1.3-14.6 3.6-21.2C21.4 367.4 0 338.2 0 304c0-31.9 18.7-59.5 45.8-72.3C37.1 220.8 32 207 32 192c0-30.7 21.6-56.3 50.4-62.6C80.8 123.9 80 118 80 112c0-29.9 20.6-55.1 48.3-62.1C131.3 21.9 155.1 0 184 0zM328 0c28.9 0 52.6 21.9 55.7 49.9c27.8 7 48.3 32.1 48.3 62.1c0 6-.8 11.9-2.4 17.4c28.8 6.2 50.4 31.9 50.4 62.6c0 15-5.1 28.8-13.8 39.7C493.3 244.5 512 272.1 512 304c0 34.2-21.4 63.4-51.6 74.8c2.3 6.6 3.6 13.8 3.6 21.2c0 35.3-28.7 64-64 64c-5.6 0-11.1-.7-16.3-2.1c-3 28.2-26.8 50.1-55.7 50.1c-30.9 0-56-25.1-56-56V56c0-30.9 25.1-56 56-56z';
Insert cell
eye = 'M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z';

Insert cell
nodes = 'M208 80c0-26.5 21.5-48 48-48h64c26.5 0 48 21.5 48 48v64c0 26.5-21.5 48-48 48h-8v40H464c30.9 0 56 25.1 56 56v32h8c26.5 0 48 21.5 48 48v64c0 26.5-21.5 48-48 48H464c-26.5 0-48-21.5-48-48V368c0-26.5 21.5-48 48-48h8V288c0-4.4-3.6-8-8-8H312v40h8c26.5 0 48 21.5 48 48v64c0 26.5-21.5 48-48 48H256c-26.5 0-48-21.5-48-48V368c0-26.5 21.5-48 48-48h8V280H112c-4.4 0-8 3.6-8 8v32h8c26.5 0 48 21.5 48 48v64c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V368c0-26.5 21.5-48 48-48h8V288c0-30.9 25.1-56 56-56H264V192h-8c-26.5 0-48-21.5-48-48V80z';

Insert cell
user = 'M224 256A128 128 0 1 0 224 0a128 128 0 1 0 0 256zm-45.7 48C79.8 304 0 383.8 0 482.3C0 498.7 13.3 512 29.7 512H418.3c16.4 0 29.7-13.3 29.7-29.7C448 383.8 368.2 304 269.7 304H178.3z';

Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more