|
@@ -1,64 +1,34 @@
|
|
|
-const scores = [
|
|
|
- { name: "Alice", score: 96 },
|
|
|
- { name: "Billy", score: 83 },
|
|
|
- { name: "Cindy", score: 81 },
|
|
|
- { name: "David", score: 96 },
|
|
|
- { name: "Emily", score: 88 }
|
|
|
-];
|
|
|
-
|
|
|
-function scaleBar(selection, scale) {
|
|
|
- selection.style('transform', `scaleX(${scale})`);
|
|
|
-}
|
|
|
-
|
|
|
-function fade(selection, opacity) {
|
|
|
- selection.style('fill-opacity', opacity);
|
|
|
-}
|
|
|
-
|
|
|
-function setFill(selection, color) {
|
|
|
- selection.style('fill', color);
|
|
|
-}
|
|
|
-
|
|
|
-const bar = d3.select(".chart")
|
|
|
+/* global d3 */
|
|
|
+
|
|
|
+// D3 convention: define margin as an object called margin with these props:
|
|
|
+let margin = {
|
|
|
+ top: 10,
|
|
|
+ right: 20,
|
|
|
+ bottom: 25,
|
|
|
+ left: 25
|
|
|
+};
|
|
|
+let width = 425 - margin.left - margin.right;
|
|
|
+let height = 625 - margin.top - margin.bottom;
|
|
|
+
|
|
|
+let svg = d3.select('.chart')
|
|
|
.append('svg')
|
|
|
- .attr('width', 225)
|
|
|
- .attr('height', 300) // 5 * 33 = 165 < 300
|
|
|
- .selectAll("g")
|
|
|
- .data(scores)
|
|
|
- .enter()
|
|
|
- // In D3, the SVG <g> is used as a generic container like a HTML <div>.
|
|
|
- .append("g")
|
|
|
- // D3 convention: d for data, i for index.
|
|
|
- // <g> doesn't support x,y, but needs transform.
|
|
|
- // translate take a comma-separated list of x,y coordinates.
|
|
|
- .attr('transform', (d, i) => 'translate(0, ' + i * 33 + ')');
|
|
|
-
|
|
|
-// Notice how we don't pass data again or use a loop: they are included in the selection.
|
|
|
-bar.append('rect')
|
|
|
- .style("width", d => d.score)
|
|
|
- .text(d => d.name)
|
|
|
- .attr("class", "bar")
|
|
|
-
|
|
|
- .on('mouseover', function (d, i, elements) {
|
|
|
- d3.select(this)
|
|
|
- .call(scaleBar, 1.5)
|
|
|
- .call(setFill, 'orange');
|
|
|
-
|
|
|
- d3.selectAll(elements)
|
|
|
- .filter(':not(:hover)')
|
|
|
- .call(fade, 0.2);
|
|
|
- })
|
|
|
- .on('mouseout', function (d, i, elements) {
|
|
|
- d3.select(this)
|
|
|
- .call(scaleBar, 1) // call returns the (modified) selection.
|
|
|
- .call(setFill, 'palegreen'); // ...which allows chaining.
|
|
|
-
|
|
|
- d3.selectAll(elements)
|
|
|
- .call(fade, 1);
|
|
|
- })
|
|
|
-
|
|
|
- .on('click', (who) => console.log(`hi ${who.name}`));
|
|
|
-
|
|
|
-bar.append('text')
|
|
|
- .attr('y', 20)
|
|
|
- .text(d => d.name);
|
|
|
-
|
|
|
+ // Match the size of the chart-containing <div>.
|
|
|
+ .attr('width', width + margin.left + margin.right)
|
|
|
+ .attr('height', height + margin.top + margin.bottom)
|
|
|
+ .append('g')
|
|
|
+ .attr('transform', () => `translate(${margin.left},${margin.top})`);
|
|
|
+// Everything below this line no longer needs to care about margins.
|
|
|
+
|
|
|
+// At this point, the "svg" variable actually contains the <g> selection.
|
|
|
+svg.append('rect')
|
|
|
+ .attr('width', width / 2)
|
|
|
+ .attr('height', height)
|
|
|
+ .style('fill', 'lightblue')
|
|
|
+ .style('stroke', 'green');
|
|
|
+
|
|
|
+svg.append('rect')
|
|
|
+ .attr('x', width / 2)
|
|
|
+ .attr('width', width / 2)
|
|
|
+ .attr('height', height)
|
|
|
+ .style('fill', 'lightblue')
|
|
|
+ .style('stroke', 'green');
|