var rnd = new Random();
var a = Enumerable.Range(1,rnd.Next(4,12)).Select( t => rnd.Next(t, t*10)).ToArray();
Using RequireJS we import d3.js. We setup the rendering code, some SVG filter inspiredy by Visual Cinnamon article on gooey effect.
Using interactive.csharp.getVariable
we fetch the variable a
value.
#!javascript
if (typeof (notebookScope.interval) !== 'undefined') {
clearInterval(notebookScope.interval);
}
notebookScope.plot = (sgvSelector, variableName) => {
let dtreeLoader = interactive.configureRequire({
paths: {
d3: "https://d3js.org/d3.v6.min"
}
});
dtreeLoader(["d3"], function (d3) {
let svg = d3.
select(sgvSelector);
svg.selectAll("defs").remove();
svg.selectAll("g").remove();
let defs = svg.append("defs");
let filter = defs.append("filter").attr("id", "gooeyCodeFilter");
filter.append("feGaussianBlur")
.attr("in", "SourceGraphic")
.attr("stdDeviation", "10")
.attr("color-interpolation-filters", "sRGB")
.attr("result", "blur");
filter.append("feColorMatrix")
.attr("in", "blur")
.attr("mode", "matrix")
.attr("values", "1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9")
.attr("result", "gooey");
let container = d3
.select(sgvSelector)
.append("g")
.style("filter", "url(#gooeyCodeFilter)");
console.log(container);
let updateD3Rendering = () => interactive.csharp.getVariable(variableName)
.then(data => {
var i = 0;
var p = container
.selectAll(".points")
.data(data, (d, i) => i);
p.transition()
.duration(2000)
.style("fill", d => d3.interpolateTurbo(d / 80))
.attr("r", d => Math.max(0, d));
p.enter()
.append("circle")
.attr("class", "points")
.attr("cy", 80)
.attr("cx", (d,i) => ((i) + 1) * 60)
.transition()
.duration(2000)
.style("fill", d => d3.interpolateTurbo(d / 80))
.ease(d3.easeElasticOut.period(1.00))
.attr("r", d => Math.max(0, d)),
p.exit()
.transition()
.duration(1000)
.attr("r", 0)
.remove();
});
notebookScope.interval = setInterval(() => updateD3Rendering(), 3000);
});
}
Notice the setInterval
call near the end of the previous cell. This rechecks the data in the kernel and updates the plot.
Back on the kernel, we can now update the data so that the kernel can see it.
Yes, this is a contrived example, and we're planning to support true streaming data, but it's a start.
#!html
<svg id="dataPlot1" width="100%" height=200></svg>
#!js
notebookScope.plot("svg#dataPlot1", "a");
#!csharp
for(var i = 0; i < 10; i++){
await Task.Delay(1000);
var limit = rnd.Next(4,12);
a = Enumerable.Range(1,limit).Select( t => rnd.Next(30, 80)).ToArray();
}