Public
Edited
Mar 6
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
encodings = ["x", "y", "size", "fill", "column", "opacity"]
Insert cell
Insert cell
viewof data = dataInput({value: nutrients});
Insert cell
viewof showInPlot = Inputs.toggle({label: "Show using Plot"})
Insert cell
Insert cell
Insert cell
{
if (!showInPlot) return html`<svg><text transform="translate(0, 20)">Enable show in plot to see the chart<text></svg>`;

const encodings = ["x", "y", "r", "fill", "fx", "opacity"];
return animateSVG(
this,

Plot.plot({
fx: { tickFormat: null },
// r: { range: [0, 15] },
color: { legend: true },
width: width,
marks: [
Plot.circle(
data,
Object.fromEntries(
encodings.map((e, i) => [e, selectedAttributes[i]])
)
)
]
}),
{
cssSelector: "circle",
attributesToAnimate: ["cx", "cy", ...encodings],
delay: (_, i) => i / 5
}
);
}
Insert cell
mutable defaultDataset = 0;
Insert cell
{
// Clear the selected attributes when changing the dataset
data;
viewof selectedAttributes.value = [];
viewof selectedAttributes.dispatchEvent(new Event("input"));
mutable defaultDataset += 1;
}
Insert cell
Insert cell
viewof attribsCount = {
selectedAttributes;
function getNewAttr(allAttrs, currentAttribs) {
const remainingAttrs = allAttrs.filter((a) => !currentAttribs.includes(a));
return remainingAttrs.at(Math.floor(Math.random() * remainingAttrs.length));
}

const addAttrib = html`<button>+</button>`;
const removeAttrib = html`<button>-</button>`;
const spanCount = html`<span style="margin: 1px 2px">${
viewof selectedAttributes.value.length
}</span>`;

const target = ReactiveWidget(html`<span id="plusMinus">
<style>
#plusMinus {
display: inline-flex;
align-items: center;
}
#plusMinus button {
font-size: 1.2rem;
margin: 1px 10px
}
</style>
${removeAttrib} <div> ${spanCount} attributes </div> ${addAttrib}
</span>`);

function update(stopAnimation = false) {
spanCount.textContent = viewof selectedAttributes.value.length;
viewof selectedAttributes.dispatchEvent(new Event("input"));
if (stopAnimation) {
viewof animate.value = false;
viewof animate.dispatchEvent(new Event("input"));
}
}

target.incr = (evt) => {
evt && evt.preventDefault();
evt && evt.stopPropagation();
viewof selectedAttributes.value = [
...viewof selectedAttributes.value,
getNewAttr(attrs, viewof selectedAttributes.value)
];

update(!!evt);
};
target.decr = (evt) => {
evt && evt.preventDefault();
evt && evt.stopPropagation();
viewof selectedAttributes.value = viewof selectedAttributes.value.slice(
0,
viewof selectedAttributes.value.length - 1
);

update(!!evt);
};
addAttrib.addEventListener("click", target.incr);
removeAttrib.addEventListener("click", target.decr);

return target;
}
Insert cell
{
// Animation demo code
// const root = viewof selection.value;
// let currentChildrenI = 0,
// newI = 0;

const interval = setInterval(async () => {
if (!animate) {
return;
}
if (selectedAttributes.length >= 5) {
clearInterval(interval);
viewof animate.value = false;
viewof animate.dispatchEvent(new Event("input"));
return;
}

viewof attribsCount.incr();
viewof attribsCount.dispatchEvent(new Event("input"));
}, 2500);

invalidation.then(() => {
clearInterval(interval);
});
}
Insert cell
attrs = Object.keys(data[0]).filter((a) => mutable defaultDataset > 1 || a !== "name")
Insert cell
nutrients = FileAttachment("nutrients.csv").csv({typed: true})
Insert cell
import {conditionalShow} from "@john-guerra/conditional-show"
Insert cell
import {navio} from "@john-guerra/navio"
Insert cell
ReactiveWidget = require("reactive-widget-helper")
Insert cell
import {animateSVG} from "@john-guerra/animate-svg"
Insert cell
import {vl} from "@vega/vega-lite-api-v5"
Insert cell
import {dataInput} from "@john-guerra/data-input"
Insert cell
import {multiAutoSelect} from "@john-guerra/multi-auto-select"
Insert cell
import {PersistInput} from "@john-guerra/persist-input"
Insert cell
import { Scrubber } from "@mbostock/scrubber"
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more