Published
Edited
Oct 12, 2018
1 fork
12 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
html`
<div class="parent-DOM-element">
<svg class="my-canvas" width="100" height="100">
<rect x="0" y="0" height="20" width="20" fill="red" />
<rect x="80" y="0" height="20" width="20" fill="blue" />
<circle cx="50" cy="50" r="25" fill="blanchedalmond" />
</svg>
</div>

<style>
.parent-DOM-element {
border: 1px solid black;
display: inline-block;
}
</style
`
Insert cell
Insert cell
Insert cell
html`
<div class="parent-DOM-element-for-enter-and-append-example">
</div>

<style>
.parent-DOM-element-for-enter-and-append-example {
border: 1px solid black;
display: inline-block;
}
</style
`
Insert cell
{
d3.selectAll('svg').remove() // See what happens if you delete this line and repeatedly re-run this block
// returns a d3 selection of parent-DOM-element-for-d3 (which continues down the method chain...)
const d3SelectionOfSVGCanvas = d3.select('.parent-DOM-element-for-enter-and-append-example')
// adds an svg element as a child of parent-DOM-element, returns a d3 selection of that new svg child:
.append('svg')
// These 3 chained method calls assign attributes to that newly created svg child DOM element
.attr('class', 'my-canvas') // Sets class attribute to d3 selected svg, returns said svg
.attr('width', 100) // Sets class attribute to d3 selected svg, returns said svg
.attr('height', 100) // Sets class attribute to d3 selected svg, returns said svg which is (finally) stored in the variable d3SelectionOfSVGCanvas
d3SelectionOfSVGCanvas.append('circle')
.attr('cx', 10)
.attr('cy', 10)
.attr('r', 10)
.attr('fill', 'red')
// I use d3's transition() here to slow down and illuminate to sequence of selecting and changing DOM elements
d3SelectionOfSVGCanvas.selectAll('circle')
.transition()
// D3 will take 2000 ms to transition the selected circles from their current attributes to the new ones
.duration(2000)
.attr('fill', 'mediumorchid')
.attr('r', '50')
}
Insert cell
Insert cell
Insert cell
html`
<div class="parent-DOM-element-for-d3">
</div>

<style>
.parent-DOM-element-for-d3 {
background-color: black;
display: inline-block;
}
</style
`
Insert cell
{
d3.selectAll('svg').remove() // Without this, D3 just keeps appending new svgs each time.

// returns a d3 selection of parent-DOM-element-for-d3 (which continues down the method chain...)
const d3SelectionOfSVGCanvas = d3.select('.parent-DOM-element-for-d3')
.append('svg')
.attr('class', 'my-canvas')
.attr('width', 100)
.attr('height', 100)


// RECTANGLE (using method-chaining, just like with the above SVG creation)
d3SelectionOfSVGCanvas
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', 20)
.attr('height', 20)
.attr('fill', 'red')
// ADDED RECTANGLE
d3SelectionOfSVGCanvas
.append('rect')
.attr('x', 80)
.attr('y', 0)
.attr('width', 20)
.attr('height', 20)
.attr('fill', 'blue')


// CIRCLE (NOT using method-chaining. This code is more explicit, but more verbose. Which do you prefer?)
const d3SelectionOfSVGCircle = d3SelectionOfSVGCanvas.append('circle')
d3SelectionOfSVGCircle.attr('cx', 50)
d3SelectionOfSVGCircle.attr('cy', 50)
d3SelectionOfSVGCircle.attr('r', 25)
d3SelectionOfSVGCircle.attr('fill', 'blanchedalmond')


// CIRCLE (using method chaining, for reference)
// d3SelectionOfSVGCanvas.append('circle')
// .attr('cx', 60)
// .attr('cy', 60)
// .attr('r', 25)
// .attr('fill', 'blanchedalmond')
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const width = 100
const height = 100
// DOM.svg() is a Observables specific convenience method which creates an SVG DOM element.
const svg = d3.select(DOM.svg(width, height))
const arrayOfNumbers = [10, 70, 100]

svg.selectAll('circle') // Select all the circles that are children of svg (in this case, an empty selection)
.data(arrayOfNumbers) // Joins arrayOfNumbers with DOM <rect/> elements, producing .enter(),.exit() selections
.enter()// Returns the portion of the data which is new ("entering") and not yet bound to DOM elements
.append('circle') // For each, append a <circle /> to selected svg
.attr('cx', (d, i) => i * 30) // Set each cirlces x position using its index in the array
.attr('cy', 10) // Set each circles y position (cy is short for 'y coordinate of the circle's center')
.attr('r', 10) // Set each circles radius
// Once we append the vis elments to it, we return the DOM element for Observable to display above.
return svg.node()
}
Insert cell
Insert cell
{
const width = 200
const height = 200
// DOM.svg is a Observables specific convenience method which creates an SVG DOM element.
const svg = d3.select(DOM.svg(width, height))
const arrayOfNumbers = [10, 70, 100, 40]
const colorScale = d3.scaleLinear().domain([d3.min(arrayOfNumbers), d3.max(arrayOfNumbers)]).range(['blue', 'red'])

svg.selectAll('rect')
.data(arrayOfNumbers) // Joins arrayOfNumbers with DOM <rect/> elements, producing .enter(),.exit() selections
.enter()// Returns the portion of the data which is new ("entering") and not yet bound to DOM elements
.append('rect') // For each, append a <rect/> to selected svg
.attr('x', (d, itemsIndexInArray) => itemsIndexInArray * 10)// For each, set x attr
.attr('y', d => height - d) // For each, set y attr. D3 convention: a datum joined to a DOM element is 'd'
.attr('width', 8) // For each, set width attribute
// Below is an example of using an "anonymous" arrow function to return a custom value for each datum.
// In this case, each array item is just an integer, so we can use that value directly.
.attr('height', arrayItemTypicallyNamed_d => arrayItemTypicallyNamed_d)
// Below is an example of passing in a function which comptutes a custom value for each data point.
.attr('fill', colorScale)
// Once we append the vis elments to it, we return the DOM element for Observable to display above.
return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
// This is a Observables specific convenience method which creates an SVG in the DOM.
const svg = d3.select(DOM.svg(width, height))
const bars = svg.selectAll('rect')
.data(barChartData).enter().append('rect')
.attr('x', d => d.x)
.attr('y', d => d.y)
.attr('width', 2)
.attr('height', d => d.height)
.attr('fill', d => d.fill)
// Once we append the vis elments to it, we return the DOM node for Observable to display above.
return svg.node()
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3 = require('d3')
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