Insert cell
Insert cell
Insert cell
theHtml = html`

<div style="min-width:${width}px; min-height:${width * 0.75}px;">
<div id='svg-container' style="${
allowPointerEventsOnSVG ? "" : "pointer-events: none"
}; position:absolute; top: 0; border: 2px dashed blue; z-index: 100000">
${svg}
</div>
<div id='plot' style="position: absolute; top: 0;"/>
</div>
`
Insert cell
viewof allowPointerEventsOnSVG = Inputs.toggle({
label: "svg pointer-events?"
})
Insert cell
viewof yearIntervalFromRangeSliderInput = rangeSlider({
title: "Range of years to show data for",
description: "Filter to a range",
min: 1990,
max: 2020,
step: 1
})
Insert cell
Insert cell
d3_annotation = require("https://cdnjs.cloudflare.com/ajax/libs/d3-annotation/2.5.1/d3-annotation.js")
Insert cell
annotationGroupClassName = "annotation-group"
Insert cell
annotations = [
{
type: d3_annotation.annotationCalloutCircle, // overrides default used when creating annotations
note: {
title: "the first point of the dataset 😮 ",
wrap: 10
},
//settings for the subject, in this case the circle radius
subject: {
radius: 12
},
x: 100,
y: 100,
dy: 137,
dx: 102,
color: "#E8336D"
}
]
Insert cell
svg = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, width * 0.75])
.attr("width", width)
.attr("height", width * 0.75)
.attr("id", "svg-layer")
.classed("shared-zoom", true);

const makeAnnotations = d3_annotation
.annotation()
.type(d3_annotation.annotationLabel)
.annotations(annotations);

svg.append("g").attr("class", annotationGroupClassName).call(makeAnnotations);
return svg.node();
}
Insert cell
Insert cell
{
if (!plot._zoom) return;
console.log(plot._zoom);
const annotationGroup = d3.select(`.${annotationGroupClassName}`);

const updateSvgOnZoom = (props) => {
console.log(props);
console.log("the transform", plot._zoom.transform);

annotationGroup.attr("transform", props.transform);

// plot._zoom.canvas.call(plot._zoom.zoomer);
};

d3.selectAll(`.${annotationGroupClassName}`).call(
plot._zoom.zoomer.on("zoom", updateSvgOnZoom)
);
}
Insert cell
Insert cell
Insert cell
Deepscatter = // This is off Ben's website, but for a real use case you want to use your own build.
(await import("https://benschmidt.org/deepscatter/deepscatter.js")).default
Insert cell
Insert cell
plot = {
let soThisRendersAfterTheHTML = theHtml;
d3.select("#plot").selectAll("div").remove(); // Cells get re-run a lot in Observable, so we clear anything that already exists before starting a new chart

// Observable provides handly width (and length) global variables, which we make use of
const computedHeight = Math.floor(width * 0.75);
const plot = new Deepscatter("#plot", width, computedHeight);
return plot; // we need this for updates, as you'll soon see...
}
Insert cell
Insert cell
{
console.log("Submitting a chart update via plotAPI...");
plot
.plotAPI({
// Data fetched from Ben's website. You could also specify a local file, too.
source_url: "https://benschmidt.org/arxiv",
background_color: "#ffffff",
max_points: 10000,
point_size: 16,
alpha: 5,
// Here's where you set (typically via data) chart appearance. This example is just the tip of the iceberg.
encoding: {
x: {
field: "x"
},
y: {
field: "y"
},
color: {
constant: "#00ff00"
}
}
})
.then(() => {
console.log("... chart update done!");
});
console.log("I am synchronous code, so I fire before the update finishes!");
}
Insert cell
## 4. Let's add some interactivity: filtering the data by year, using the range slider you saw below the chart
Insert cell
import { rangeSlider } from "@mootari/range-slider"
Insert cell
Insert cell
yearIntervalFromRangeSliderInput
Insert cell
Insert cell
{
const lowerBound = yearIntervalFromRangeSliderInput[0];
const upperBound = yearIntervalFromRangeSliderInput[1];
const sizeOfRange = upperBound - lowerBound;
const midpointBetweenTheYears = (upperBound + lowerBound) / 2;
plot.plotAPI({
encoding: {
filter: {
field: "year",
op: "within",
a: sizeOfRange / 2, // how far to extend on either end of the midpoint
b: midpointBetweenTheYears
}
}
});
}
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