D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
cmmyers
Full window
Github gist
snowflake
Built with
blockbuilder.org
<!DOCTYPE html> <meta charset="utf-8"> <style> body { background-color: #f0f0f0; } circle { fill: none; stroke: #999999; stroke-width: 1px; } line { stroke: #999999; stroke-width: 1px; } .arc { fill-opacity: 0.7; } </style> <svg width="1600" height="500"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> //load in both files d3.queue() .defer(d3.json, "data.json") .await(make_snowflake_chart); // make another function function make_snowflake_chart(error, data) { if (error) { console.log(error); } Snowflake.draw("#test", data); } const Snowflake = { draw: function(id, userInfo) { // drawing board const svg = d3.select("svg") const margin = { top: 20, right: 20, bottom: 30, left: 40 } const width = +svg.attr("width") - margin.left - margin.right const height = +svg.attr("height") - margin.top - margin.bottom const snowflakeRadius = 100 const radians = Math.PI * 2 const xCenter = 350 const yCenter = 150 const levels = 5 const userOffset = 2 * snowflakeRadius + margin.left const legendX = 50 const legendY = 50 const legendW = 100 const legendH = 40 // piece of paper const g = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); const colors = { "one": '#9A57C1', "two": '#79A54F', "three": '#C1A957', "four": '#5783C1', "five": "#008BB9" } const set = new Set() for (const user of userInfo) { for (const key of Object.keys(user.proportions_by_topic)) { set.add(key) } } const topicNames = [...set] const numTopics = topicNames.length const theta = radians / numTopics const levelWidth = snowflakeRadius / levels const legend = () => { g.selectAll(".legendBox") .data(topicNames) .enter().append("rect") .attr("x", legendX) .attr("y", (d, i) => legendY + i * legendH) .attr("width", legendW) .attr("height", legendH) .attr("fill", (d) => colors[d]) .on("mouseover", (d) => toggleHighlight(d)) .on("mouseout", (d) => toggleHighlightOff(d)) const textMarginX = 10 const textMarginY = 20 g.selectAll(".legendBox") .data(topicNames) .enter().append("text") .attr('x', legendX + textMarginX) .attr('y', (d, i) => legendY + i * legendH + textMarginY) .attr('fill', '#CCCCCC') .attr('font-family', 'sans-serif') .text((d) => d) } legend() // draw the Axes the wedges will live on const snowflakeAxes = (userIx) => { const thisXCenter = xCenter + userIx * userOffset //make the circles for (var i = 0; i < levels; i++) { g.selectAll(".circle") .data([1]) .enter().append("circle") .attr("r", d => (i + 1) * levelWidth) .attr('transform', "translate(" + thisXCenter + "," + yCenter + ")") } //make the radiating lines for (var j = 0; j < numTopics; j++) { g.selectAll(".radials") .data([1]) .enter().append("line") .attr("x1", thisXCenter) .attr("y1", yCenter) .attr("x2", thisXCenter + Math.sin(j * theta) * snowflakeRadius) .attr("y2", yCenter + Math.cos(j * theta) * snowflakeRadius) } } //make the wedges const makeArc = (topixIx, topic, topicValue, userIx) => { const thisXCenter = xCenter + userIx * userOffset const startAngle = theta * topixIx + radians / 2 const endAngle = startAngle + theta const trueRadius = topicValue * 100 / snowflakeRadius const myArc = d3.arc() .innerRadius(0) .outerRadius(trueRadius) .startAngle(startAngle) .endAngle(endAngle) g.append("path") .attr("d", myArc) .attr("class", "arc arc-" + topic) .attr("fill", colors[topic]) .attr('transform', "translate(" + thisXCenter + "," + yCenter + ")") } //for each user for (const [userIx, user] of userInfo.entries()) { //draw the axes snowflakeAxes(userIx) const topicsInfo = user.proportions_by_topic //draw a wedge for each topic for (const [ix, topic] of topicNames.entries()) { console.log(topic) const topicData = topicsInfo[topic] if (topicData) { makeArc(ix, topic, topicData, userIx) } else { makeArc(ix, topic, 0, userIx) } } } const toggleHighlight = (topic) => { const newOpacityHighlight = 0.9 const newOpacityLowlight = 0.2 d3.selectAll('.arc-' + topic) .transition(500) .style("fill-opacity", newOpacityHighlight) d3.selectAll('.arc:not(.arc-' + topic + ')') .transition(500) .style("fill-opacity", newOpacityLowlight) } const toggleHighlightOff = (topic) => { const defaultOpacity = 0.7 d3.selectAll('.arc') .transition(500) .style("fill-opacity", defaultOpacity) } } } </script>
https://d3js.org/d3.v4.min.js