Published
Edited
Apr 9, 2021
5 forks
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require("d3@6")
Insert cell
Insert cell
data = d3.csvParse(await FileAttachment("alphabet.csv").text(), ({letter, frequency}) => ({name: letter, value: +frequency})).sort((a, b) => b.value - a.value)
Insert cell
Insert cell
Insert cell
margin = ({top: 20, right: 0, bottom: 30, left: 40})
Insert cell
height = 500
Insert cell
Insert cell
x = d3.scaleBand()
.domain(data.map(d => d.name))
//Here the domain is the letters in the our data and that's what will be written on the Axis
.range([margin.left, width - margin.right])
// margin.left and width-margin.right are respectively the minimum and maximum extents of the bands and that's where the axis will be placed.
.padding(0.1)
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)]).nice()
//Here the domain of y will vary between 0 and the maximum frequency of the letters and that's what will be written on the Axis
.range([height - margin.bottom, margin.top])
//The extents of the bands will vary from height-margin to margin.top and that's where the axis will be placed.
Insert cell
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`) // This controls the vertical position of the Axis
.call(d3.axisBottom(x).tickSizeOuter(0)) //Creates bottom horizontal axis with an outer tick size equal to 0
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`) // This controls the horizontal position of the Axis
.call(d3.axisLeft(y)) //Creates left vertical axis
.call(g => g.select(".domain").remove()) //This removes the domain from the DOM API.
Insert cell
Insert cell
JustAxis = {
// creating of the svg object in the body of the page
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]) //This is the viewBox that we will be seeing (size of our svg)
;
//Add the x-Axis
svg.append("g")
.attr("class", "x-axis")
.call(xAxis);
//Add the y-Axis
svg.append("g")
.attr("class", "y-axis")
.call(yAxis);

return svg.node();
}
Insert cell
Insert cell
Insert cell
d4 = {
const d4 = require("d3-dsv@1", "d3@5","d3-scale@3","d3-scale-chromatic@1", "d3-shape@1", "d3-array@2")
return d4
}
Insert cell
tooltip = {
Animation2,Animation1, BarChart,ZoomableBarChart;

const tooltip = d4
.select("body")
.append("div")
.attr("class", "svg1-tooltip")
.style("position", "absolute")
.style("visibility", "hidden");

// select all rect
d4.selectAll("rect")
.on("mouseover", function(d) {
// change the selection style: width and color of the stroke which allows up to control of the shape of the ends of lines
d4.select(this)
.attr('stroke-width', '2')
.attr("stroke", "black");
// make the tooltip visible and update its text
tooltip
.style("visibility", "visible")
.text(`frequency: ${d.value*100}%\nletter: ${d.name}`); // the formating of the output text
})
.on("mousemove", function() {
tooltip
.style("top", d4.event.pageY - 90 + "px")
.style("left", d4.event.pageX + 90 + "px");
})
.on("mouseout", function() {
// change the selection style
d4.select(this).attr('stroke-width', '0');

tooltip.style("visibility", "hidden");
});
}
Insert cell
Insert cell
styles = html`
<style>

.svg1-tooltip {
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background: rgba(69,77,93,.9);
border-radius: .1rem;
color: #fff;
box-shadow: 0 0 5px #999999;
display: block;
font-size: 14px;
max-width: 320px;
padding: .2rem .4rem;
position: absolute;
text-overflow: ellipsis;
white-space: pre;
z-index: 300;
visibility: hidden;
}
rect:hover {
fill: bisque;
}
</style>`
Insert cell
Insert cell
Insert cell
BarChart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])

svg.append("g")
.attr("class", "bars") // Adds the bars
.attr("fill", "steelblue") //fills the bars with a steelblue color
.selectAll("rect") //selects all the “rect” elements in the document.
.data(data) // loops through each svg element and sets __data_ attribute
.join("rect")
.attr("x", d => x(d.name)) //joins the x variable and use them to construct the bars
.attr("y", d => y(d.value)) // joins the y variable and use them to construct the bars
.attr("height", d => y(0) - y(d.value)) //sets the height of each bar following the value of each letter's frequency
.attr("width", x.bandwidth());//sets the width of each bar following the bandwidth of the variable x

svg.append("g")
.attr("class", "x-axis")
.call(xAxis);

svg.append("g")
.attr("class", "y-axis")
.call(yAxis);

return svg.node();
}
Insert cell
Insert cell
Insert cell
function zoom(svg) {
const extent = [[margin.left, margin.top], [width - margin.right, height - margin.top]];

svg.call(d3.zoom()
.scaleExtent([1, 8])
.translateExtent(extent) //If extent is specified, sets the translate extent to the specified array of points in extent
.extent(extent) //If extent is specified, sets the viewport extent to the specified array of points (sets the zooming behaviour)
.on("zoom", zoomed)); //Applies this zoom behavior to the specified event
// in this function we will specify our zooming targets
function zoomed(event) {
x.range([margin.left, width - margin.right].map(d => event.transform.applyX(d)));
svg.selectAll(".bars rect").attr("x", d => x(d.name)).attr("width", x.bandwidth());
svg.selectAll(".x-axis").call(xAxis);
// in our case these targets are the x axis and the bar rectangles that's why when you zoom you won't see the y axis zooming too.
}
}
Insert cell
Insert cell
ZoomableBarChart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.call(zoom); //calls the zoom function

svg.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(d.name))
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.attr("width", x.bandwidth());

svg.append("g")
.attr("class", "x-axis")
.call(xAxis);

svg.append("g")
.attr("class", "y-axis")
.call(yAxis);

return svg.node();
}
Insert cell
Insert cell
Insert cell
Animation1 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.call(zoom);

svg.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(d.name))
// no bar at the beginning thus:
.attr("y", d => 0)
.attr("height", d => 0)
.attr("width", x.bandwidth());
svg.selectAll("rect")
.transition() //assures the transition of the bars
.duration(800) //the transition lasts 800 ms
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.delay(750) //The transitions starts after 750ms

svg.append("g")
.attr("class", "x-axis")
.call(xAxis);

svg.append("g")
.attr("class", "y-axis")
.call(yAxis);

return svg.node();
}
Insert cell
Insert cell
Animation2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.call(zoom);

svg.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => x(d.name))
.attr("y", d => 0)
.attr("height", d => 0)
.attr("width", x.bandwidth());
svg.selectAll("rect")
.transition()
.duration(800)
.attr("y", d => y(d.value))
.attr("height", d => y(0) - y(d.value))
.delay(function(d,i){console.log(i) ; return(i*100)}) //generates a variable delay so each bar will have its own delay

svg.append("g")
.attr("class", "x-axis")
.call(xAxis);

svg.append("g")
.attr("class", "y-axis")
.call(yAxis);

return svg.node();
}
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