diff_pic = {
let w = entry_width;
let h = 0.6 * w;
let svg = d3.create("svg").attr("width", w).attr("height", h);
svg
.append("rect")
.attr("width", w)
.attr("height", h)
.attr("fill", "white")
.attr("opacity", 0.9);
let xmin = -2;
let xmax = 2;
let x_scale = d3.scaleLinear().domain([xmin, xmax]).range([0, w]);
let ymin = -0.5;
let ymax = 2;
let y_scale = d3.scaleLinear().domain([ymin, ymax]).range([h, 0]);
let pts_to_path = d3
.line()
.x((d) => x_scale(d[0]))
.y((d) => y_scale(d[1]));
let x0 = -1;
let f = (x) => (x ** 3 - x) / 2 + 1;
let fp = (x) => (3 * x ** 2 - 1) / 2;
let L = (x) => f(x0) + fp(x0) * (x - x0);
let LL = (x, h) => f(x0) + ((f(x0 + h) - f(x0)) * (x - x0)) / h;
let pts = d3.range(xmin, xmax, 0.01).map((x) => [x, f(x)]);
svg
.append("line")
.attr("x1", x_scale(0))
.attr("x2", x_scale(0))
.attr("y1", y_scale(ymin))
.attr("y2", y_scale(ymax - 0.2))
.attr("stroke", "black");
svg
.append("line")
.attr("x1", x_scale(xmin + 0.2))
.attr("x2", x_scale(xmax))
.attr("y1", y_scale(0))
.attr("y2", y_scale(0))
.attr("stroke", "black");
svg
.append("path")
.attr("d", pts_to_path(pts))
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", "3px");
let lines = svg.append("g");
lines
.append("line")
.attr("x1", x_scale(xmin))
.attr("x2", x_scale(xmax))
.attr("y1", y_scale(L(xmin)))
.attr("y2", y_scale(L(xmax)))
.attr("stroke", "black");
let circles = svg.append("g");
circles
.append("circle")
.attr("cx", x_scale(-1))
.attr("cy", y_scale(f(-1)))
.attr("r", 4)
.attr("fill", "green")
.attr("stroke", "darkgreen");
let secant_line, secant_pt;
let dx = 0.4;
let interval_id;
//interval_ids = [];
svg
.on("mouseenter", async function () {
svg
.attr("transform", "scale(1)")
.transition()
.duration(1000)
.attr("transform", "scale(2)");
svg.selectAll(".temp").remove();
secant_line = lines
.append("line")
.attr("class", "temp")
.attr("x1", x_scale(xmin))
.attr("x2", x_scale(xmax))
.attr("y1", y_scale(LL(xmin, dx)))
.attr("y2", y_scale(LL(xmax, dx)))
.attr("stroke", "black");
secant_pt = circles
.append("circle")
.attr("class", "temp")
.attr("cx", x_scale(x0 + dx))
.attr("cy", y_scale(f(x0 + dx)))
.attr("r", 4)
.attr("fill", "red")
.attr("stroke", "darkred");
await Promises.delay(1000);
interval_id = setInterval(function () {
dx = 0.95 * dx;
svg.selectAll(".temp").remove();
secant_line = lines
.append("line")
.attr("class", "temp")
.attr("x1", x_scale(xmin))
.attr("x2", x_scale(xmax))
.attr("y1", y_scale(LL(xmin, dx)))
.attr("y2", y_scale(LL(xmax, dx)))
.attr("stroke", "black");
secant_pt = circles
.append("circle")
.attr("class", "temp")
.attr("cx", x_scale(x0 + dx))
.attr("cy", y_scale(f(x0 + dx)))
.attr("r", 4)
.attr("fill", "red")
.attr("stroke", "darkred");
}, 50);
// interval_ids.push(interval_id);
})
.on("mouseleave", function () {
clearInterval(interval_id);
secant_line.remove();
secant_pt.remove();
dx = 0.4;
svg
.attr("transform", "scale(2)")
.transition()
.duration(500)
.attr("transform", "scale(1)");
})
.on("click", function () {
clearInterval(interval_id);
});
svg.selectAll("*").style("pointer-events", "none");
return svg.node();
}