in src/parallel/parallel.tsx [312:425]
function redraw_axis() {
// Extract the list of numerical dimensions and create a scale for each.
me.xscale.domain(me.state.dimensions);
// Add a group element for each dimension.
function create_drag_beh() {
return d3.drag().on("start", function(d: string) {
me.setState({
dragging: {
col: d,
pos: me.xscale(d),
origin: me.xscale(d),
dragging: false
}
});
d3.select(me.foreground_ref.current).style("opacity", "0.35");
})
.on("drag", function(d: string) {
const eventdx = d3.event.dx;
const brushEl = d3.select(this).select("." + style.brush);
me.setState(function(prevState, _) { return {
dragging: {
col: d,
pos: Math.min(me.w, Math.max(0, prevState.dragging.pos + eventdx)),
origin: prevState.dragging.origin,
dragging: true
}
};}, function() {
// Feedback for axis deletion if dropped
if (me.state.dragging.pos < 12 || me.state.dragging.pos > me.w-12) {
brushEl.style('fill', 'red');
} else {
brushEl.style('fill', null);
}
});
var new_dimensions = Array.from(me.state.dimensions);
new_dimensions.sort(function(a, b) { return me.position(a) - me.position(b); });
if (!new_dimensions.every(function(val, idx) { return val == me.state.dimensions[idx]; })) {
me.setState({dimensions: new_dimensions});
}
me.dimensions_dom.attr("transform", function(d) { return "translate(" + me.position(d) + ")"; });
redrawAllForeignObjectsIfSafari();
})
.on("end", function(d: string) {
if (!me.state.dragging.dragging) {
// no movement, invert axis
var extent = invert_axis(d);
} else {
// reorder axes
var drag: any = d3.select(this);
if (!IS_SAFARI) {
drag = drag.transition();
}
drag.attr("transform", "translate(" + me.xscale(d) + ")");
var extents = brush_extends();
extent = extents[d];
}
// remove axis if dragged all the way left
if (me.state.dragging.pos < 12 || me.state.dragging.pos > me.w-12) {
me.remove_axis(d);
} else {
me.setState({order: Array.from(me.state.dimensions)});
}
me.update_ticks(d, extent);
// rerender
d3.select(me.foreground_ref.current).style("opacity", null);
me.setState({dragging: null});
});
}
if (me.dimensions_dom) {
me.dimensions_dom.remove();
}
me.dimensions_dom = d3.select(me.svgg_ref.current).selectAll<SVGGElement, string>(".dimension")
// reverse the order so that the tooltips appear on top of the axis ticks
.data(me.state.dimensions.reverse())
.enter().append<SVGGElement>("svg:g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + me.xscale(d) + ")"; })
//@ts-ignore
.call(create_drag_beh());
// Add an axis and title.
me.dimensions_dom.append("svg:g")
.attr("class", style.axis)
.attr("transform", "translate(0,0)")
.each(function(d) { console.assert(me.yscale[d], d, me.yscale, this); d3.select(this).call(me.axis.scale(me.yscale[d])); })
.append(function(dim) { return foCreateAxisLabel(me.props.params_def[dim], me.props.context_menu_ref, "Drag to move, right click for options"); })
.attr("y", -20)
.attr("text-anchor", "left")
.classed("pplot-label", true)
.classed(style.pplotLabel, true);
me.dimensions_dom.selectAll(".label-name").style("font-size", "20px");
me.dimensions_dom.selectAll(".pplot-label").each(function(this: SVGForeignObjectElement, d: string) {
foDynamicSizeFitContent(this, [-me.xscale(d) + 5, -me.xscale(d) + me.state.width - 5]);
}).attr("x", 0).style("width", "1px");
me.updateAxisTitlesAnglesAndFontSize();
// Add and store a brush for each axis.
me.dimensions_dom.append("svg:g")
.classed(style.brush, true)
.classed("pplot-brush", true)
.each(function(d) { d3.select(this).call(me.d3brush); })
.selectAll("rect")
.style("visibility", null)
.append("title")
.text("Drag up or down to brush along this axis");
me.dimensions_dom.selectAll(".extent")
.append("title")
.text("Drag or resize this filter");
};