julia_svg = {
let w = total_width / 2;
const xScale = d3.scaleLinear().domain([-2, 2]).range([0, w]);
const yScale = d3.scaleLinear().domain([-2, 2]).range([w, 0]);
const rScale = d3.scaleLinear().domain([0, 4]).range([0, w]);
const pts_to_path = d3
.line()
.x(function (d) {
return xScale(d[0]);
})
.y(function (d) {
return yScale(d[1]);
});
let svg = d3.create("svg").attr("width", w).attr("height", w);
if (!svg.attr("c")) {
svg.attr("c", "-1,0");
}
const mapbg = DOM.uid("mapbg");
svg
.append("defs")
.append("pattern")
.attr("id", mapbg.id)
.attr("patternUnits", "userSpaceOnUse")
.attr("width", w)
.attr("height", w)
.append("image")
.attr("xlink:href", generate_julia_im_url({ re: -1, im: 0 }))
.attr("width", w)
.attr("height", w);
svg
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", w)
.attr("height", w)
.attr("fill", mapbg);
svg
.on("mousemove", function () {
svg.selectAll(".orbit").remove();
let c = svg.attr("c").split(",").map(parseFloat);
let xy = ij_to_xy(d3.mouse(this), -2, 2, -2, 2, w);
let orbit = compute_orbit(c, xy);
for (let i = 0; i < orbit.length; i++) {
svg
.append("path")
.attr("class", "orbit")
.attr("d", pts_to_path(orbit.slice(i, i + 2)))
.attr("stroke", "#8888FF")
.attr("stroke-width", 2)
.attr("fill", "none")
.style("opacity", 0.5);
svg
.append("circle")
.attr("class", "orbit")
.attr("cx", xScale(orbit[i][0]))
.attr("cy", yScale(orbit[i][1]))
.attr("r", 4)
.attr("fill", "red")
.attr("stroke", "none")
.attr("fill-opacity", 0.03);
}
svg
.append("circle")
.attr("class", "orbit")
.attr("cx", xScale(orbit[0][0]))
.attr("cy", yScale(orbit[0][1]))
.attr("r", 4)
.attr("fill", "green")
.attr("stroke", "black")
.attr("stroke-width", 1);
})
.on("mouseleave", function () {
svg.selectAll(".orbit").remove();
});
return svg.node();
}