Public
Edited
May 31, 2022
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vertices = [
[width/2,padding],
[padding,height-padding],
[width-padding,height/2]
]
Insert cell
meanX = vertices.reduce( (sum,v) => sum + v[0], 0 ) / vertices.length
Insert cell
{
const { ternaryPlot, barycentric } = d3ternary
const { Delaunay } = d3delaunay

const sampleData = [
{E:1,S:1,G:1,color:'#dfdfdf'}, // center
{E:1,S:0,G:0,color:'#20ad57'}, // E
{E:0,S:1,G:0,color:'#2a40c7'}, // S
{E:0,S:0,G:1,color:'#e45317'}, // G
{E:1,S:1,G:0,color:'#25bfc4'}, // E/S
{E:1,S:0,G:1,color:'#d2d514'}, // E/G
{E:0,S:1,G:1,color:'#a586e8'}, // G/S
]

const bary = barycentric().a(d=>d.E).b(d=>d.S).c(d=>d.G).vertices(vertices)
const tp = ternaryPlot(bary).radius(1)

// get triangle point coordinates
sampleData.forEach( d => [d.x,d.y] = bary(d) )
// get voronoi polygon coordinates
let tesselation = Delaunay.from(sampleData.map(d=>[d.x,d.y])).voronoi()
sampleData.forEach( (d,i) => d.pathData = tesselation.renderCell(i) )

const svg = d3.create("svg")
.attr("viewBox", [width/2, height/2, width, height]);
const g = svg.append('g')
.attr('transform',`translate(${width/2} ${height/2})`)

g.selectAll('path')
.data(sampleData)
.join('path')
.attr('d',d=>d.pathData)
.attr('fill',d=>d.color)

g.selectAll('circle')
.data(sampleData)
.join('circle')
.attr('cx',d=>d.x)
.attr('cy',d=>d.y)
.attr('r',3)
.attr('fill','black')
g.append('path')
.attr('class','triangle')
.attr('d',tp.triangle())
.attr('stroke','black')
.attr('fill','none')
return Object.assign( svg.node(), {} )
}
Insert cell
Insert cell
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