Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
Rotate Labels: Fix bugs and feedback (#214)
Browse files Browse the repository at this point in the history
* Fix bugs and feedback

* Firefox requires elements with at least 1px width to display them

Co-authored-by: danthe3rd <[email protected]>
  • Loading branch information
danthe3rd and danthe3rd committed Sep 30, 2021
1 parent 7ccd228 commit cf5d3ae
Showing 1 changed file with 35 additions and 31 deletions.
66 changes: 35 additions & 31 deletions src/parallel/parallel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface ParallelPlotDisplayData {
export interface ParallelPlotData extends HiPlotPluginData, ParallelPlotDisplayData {
};

const TOP_MARGIN_PIXELS = 100;
const TOP_MARGIN_PIXELS = 80;
export class ParallelPlot extends React.Component<ParallelPlotData, ParallelPlotState> {
on_resize: () => void = null;
m = [
Expand Down Expand Up @@ -157,6 +157,7 @@ export class ParallelPlot extends React.Component<ParallelPlotData, ParallelPlot
}
g.attr("transform", function(this: ParallelPlot, p) { return "translate(" + this.position(p) + ")"; }.bind(this));
this.update_ticks();
this.updateAxisTitlesAnglesAndFontSize();
}
// Highlight polylines
if (prevProps.rows_highlighted != this.props.rows_highlighted) {
Expand Down Expand Up @@ -397,37 +398,10 @@ export class ParallelPlot extends React.Component<ParallelPlotData, ParallelPlot
.classed("pplot-label", true)
.classed(style.pplotLabel, true);
me.dimensions_dom.selectAll(".label-name").style("font-size", "20px");
// Set optimal rotation angle and scale fonts so that everything fits on screen
const MIN_ROTATION_ANGLE = 20;
const MAX_ROTATION_ANGLE = 70;
const MAX_FONT_SIZE = 24;
const MIN_FONT_SIZE = 8;
const MAX_X = me.dimensions_dom.node().parentElement.parentElement.getBoundingClientRect().right;
const ROTATION_ANGLE_RADS = Math.max(MIN_ROTATION_ANGLE * Math.PI / 180, Math.min(MAX_ROTATION_ANGLE * Math.PI / 180,
Math.atan(24 * me.state.dimensions.length / me.state.width)
));
const maxWidthForTop = TOP_MARGIN_PIXELS / Math.sin(ROTATION_ANGLE_RADS) - MAX_FONT_SIZE;
me.dimensions_dom.selectAll(".label-name").each(function(this: HTMLSpanElement) {
// Scale the font-size up or down depending on the text-length
const beginX = this.getBoundingClientRect().left;
const maxWidth = Math.min(
// Should not go outside of the svg (top)
maxWidthForTop,
// Should not go outside of the svg (right)
(MAX_X - beginX) / Math.cos(ROTATION_ANGLE_RADS)
);
const newFontSize = Math.min(MAX_FONT_SIZE, Math.max(MIN_FONT_SIZE,
maxWidth / this.clientWidth * parseFloat(this.style.fontSize)
));
this.style.fontSize = newFontSize + "px";
this.style.transform = "rotate(" + (360 - ROTATION_ANGLE_RADS * 180 / Math.PI) + "deg)";
const fo = this.parentElement.parentElement as any as SVGForeignObjectElement;
fo.setAttribute("y", -newFontSize + "");
});
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);

}).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)
Expand Down Expand Up @@ -620,7 +594,6 @@ export class ParallelPlot extends React.Component<ParallelPlotData, ParallelPlot
});
}


// scale to window size
this.on_resize = _.debounce(function() {
me.compute_dimensions();
Expand Down Expand Up @@ -683,6 +656,37 @@ export class ParallelPlot extends React.Component<ParallelPlotData, ParallelPlot
return scale;
}


updateAxisTitlesAnglesAndFontSize() {
// Set optimal rotation angle and scale fonts so that everything fits on screen
const MIN_ROTATION_ANGLE = 20;
const MAX_ROTATION_ANGLE = 70;
const MAX_FONT_SIZE = 20;
const MIN_FONT_SIZE = 6;
const MAX_X = this.dimensions_dom.node().parentElement.parentElement.getBoundingClientRect().right;
const ROTATION_ANGLE_RADS = Math.max(MIN_ROTATION_ANGLE * Math.PI / 180, Math.min(MAX_ROTATION_ANGLE * Math.PI / 180,
Math.atan(24 * this.state.dimensions.length / this.state.width)
));
const maxWidthForTop = TOP_MARGIN_PIXELS / Math.sin(ROTATION_ANGLE_RADS) - MAX_FONT_SIZE;
this.dimensions_dom.selectAll(".label-name").each(function(this: HTMLSpanElement) {
// Scale the font-size up or down depending on the text-length
const beginX = this.getBoundingClientRect().left;
const maxWidth = Math.min(
// Should not go outside of the svg (top)
maxWidthForTop,
// Should not go outside of the svg (right)
(MAX_X - beginX) / Math.cos(ROTATION_ANGLE_RADS)
);
const newFontSize = Math.min(MAX_FONT_SIZE, Math.max(MIN_FONT_SIZE,
maxWidth / this.clientWidth * parseFloat(this.style.fontSize)
));
this.style.fontSize = newFontSize + "px";
this.style.transform = "rotate(" + (360 - ROTATION_ANGLE_RADS * 180 / Math.PI) + "deg)";
const fo = this.parentElement.parentElement as any as SVGForeignObjectElement;
fo.setAttribute("y", -newFontSize + "");
});
}

compute_dimensions() {
this.w = this.state.width - this.m[1] - this.m[3];
this.h = this.state.height - this.m[0] - this.m[2];
Expand Down

0 comments on commit cf5d3ae

Please sign in to comment.