Published
Edited
Mar 12, 2020
3 stars
Insert cell
md`# D3.js merge() demo`
Insert cell
md`This is a simple demo I set up to accompany my [Codementor article](https://www.codementor.io/@milesbryony/d3-js-merge-in-depth-jm1pwhurw) on d3.js merge.`
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const color_key = {"star":"yellow","boo":"blue","toad":"red"};
const x_scale = d3.scaleBand().range([0,width - (margin*2)]);
const y_scale = d3.scaleLinear().range([0,height/2]);
let position = 0;
new_chart(my_data);
var my_interval = setInterval(function(){
new_chart(my_data);
}, 3000);

function new_chart() {
//loop through data, reset scales and call update, then position.
if(position <= my_data.length){
var current_data = my_data[position];
//find unique ids and max and reset scale domains
var ids = d3.set(current_data,d => d.id).values();
var max = d3.max(current_data,d => d.value);
y_scale.domain([0,max]);
x_scale.domain(ids);
//sort data ascending by value
current_data = current_data.sort((a,b) => d3.ascending(a.value,b.value));
//call update group and then position elements
var my_group = update_group(current_data);
position_elements(my_group);
position += 1;
if(position == my_data.length){
position = 0;
}
}
}
function update_group(data){

//join
var my_group = svg.selectAll('.chart_group')
.data(data, d => d.id);
//exit and remove
my_group.exit().remove();
//enter new groups
var enter = my_group.enter()
.append("g")
.attr("class","chart_group");

//append elements to new group
enter.append("rect").attr("class","group_rect");
enter.append("text").attr("class","group_text");
enter.append("image").attr("class","group_image");

//merge
my_group = my_group.merge(enter);
return my_group;
}
function position_elements(my_group){

//position rectangle
my_group.select(".group_rect")
.attr("x", d => x_scale(d.id))
.attr("y", d => (height/1.5) - y_scale(d.value))
.attr("fill",d => color_key[d.id])
.attr("width",x_scale.bandwidth()-10)
.attr("height",d => y_scale(d.value));
//then position text
my_group.select(".group_text")
.attr("x", d => x_scale(d.id) + ((x_scale.bandwidth()-10)/2) + 40)
.attr("y", d => (height/1.55) - y_scale(d.value))
.attr("text-anchor","end")
.text(d => d.value);
//then position images
my_group.select(".group_image")
.attr("xlink:href", d => "https://bl.ocks.org/BMPMS/raw/f1acde6c8d8d8339d6b638c9e47bc01a/" + d.image)
.attr("x", d => x_scale(d.id) + ((x_scale.bandwidth()-10)/2) - 40)
.attr("y", d => (height/1.55) - y_scale(d.value) - 30)
.attr("width",40)
.attr("height",40);
};

return svg.node();
}
Insert cell
Insert cell
height = 800
Insert cell
margin = 20;
Insert cell
my_data = [
[{id:"star",value:54,image:"star.png"},{id:"toad",value:104,image:"toad.png"},{id:"boo",value:24,image:"boo.png"}],
[{id:"star",value:124,image:"star.png"},{id:"toad",value:74,image:"toad.png"}],
[{id:"star",value:24,image:"star.png"},{id:"toad",value:194,image:"toad.png"},{id:"boo",value:124,image:"boo.png"}],
[{id:"toad",value:34,image:"toad.png"},{id:"boo",value:150,image:"boo.png"}]
]
Insert cell
d3 = require("d3@5")
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