Skip to content

Commit

Permalink
Merge pull request #1328 from nextstrain/legend-overflow-text
Browse files Browse the repository at this point in the history
Apply clipping to first column of legend
  • Loading branch information
jameshadfield authored May 24, 2021
2 parents b58f148 + e370dd6 commit 797090f
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 47 deletions.
5 changes: 3 additions & 2 deletions src/components/tree/legend/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { dataFont, darkGrey } from "../../../globalStyles";
const LegendItem = ({
dispatch,
transform,
clipId,
legendRectSize,
legendSpacing,
legendMaxLength,
rectStroke,
rectFill,
label,
Expand All @@ -33,9 +33,10 @@ const LegendItem = ({
x={legendRectSize + legendSpacing + 5}
y={legendRectSize - legendSpacing}
style={{fontSize: 12, fill: darkGrey, fontFamily: dataFont}}
clipPath={clipId?`url(#${clipId})`:undefined}
>
<title>{label}</title>
{typeof label === 'string' ? label.substring(0, legendMaxLength) : label}
{label}
</text>
</g>
);
Expand Down
74 changes: 32 additions & 42 deletions src/components/tree/legend/legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,14 @@ import { connect } from "react-redux";
import { rgb } from "d3-color";
import LegendItem from "./item";
import { headerFont, darkGrey } from "../../../globalStyles";
import { legendRectSize, legendSpacing, legendMaxLength, fastTransitionDuration, months } from "../../../util/globals";
import { fastTransitionDuration, months } from "../../../util/globals";
import { numericToCalendar } from "../../../util/dateHelpers";
import { isColorByGenotype, decodeColorByGenotype } from "../../../util/getGenotype";
import { TOGGLE_LEGEND } from "../../../actions/types";

const svg = {
position: "absolute",
top: 26,
borderRadius: 4,
zIndex: 1000,
userSelect: "none"
};
const ITEM_RECT_SIZE = 15;
const LEGEND_SPACING = 4;
const COLUMN_WIDTH = 145;

@connect((state) => {
return {
Expand Down Expand Up @@ -47,7 +43,7 @@ class Legend extends React.Component {
const nItems = this.props.colorScale.visibleLegendValues.length;
const titlePadding = 20;
return Math.ceil(nItems / 2) *
(legendRectSize + legendSpacing) + legendSpacing + titlePadding || 100;
(ITEM_RECT_SIZE + LEGEND_SPACING) + LEGEND_SPACING + titlePadding || 100;
}

getSVGWidth() {
Expand All @@ -57,14 +53,12 @@ class Legend extends React.Component {
return this.getTitleWidth() + 20;
}

getTransformationForLegendItem(i) {
const count = this.props.colorScale.visibleLegendValues.length;
const stack = Math.ceil(count / 2);
const fromRight = Math.floor(i / stack);
const fromTop = (i % stack);
const horz = fromRight * 145 + 10;
const vert = fromTop * (legendRectSize + legendSpacing);
return "translate(" + horz + "," + vert + ")";
getTransformationForLegendItem(maxNumPerColumn, itemIdx) {
const colIdx = Math.floor(itemIdx/maxNumPerColumn);
const colPos = colIdx * COLUMN_WIDTH + 10;
const rowIdx = (itemIdx % maxNumPerColumn); // hardcoded for 2 rows
const rowPos = rowIdx * (ITEM_RECT_SIZE + LEGEND_SPACING);
return `translate(${colPos},${rowPos})`;
}
getTitleString() {
if (isColorByGenotype(this.props.colorBy)) {
Expand Down Expand Up @@ -162,22 +156,24 @@ class Legend extends React.Component {
* coordinate system from top,left of parent SVG
*/
legendItems() {
const items = this.props.colorScale.visibleLegendValues
const values = this.props.colorScale.visibleLegendValues;
const maxNumPerColumn = Math.ceil(values.length/2); // hardcoded to 2 columns
const items = values
.filter((d) => d !== undefined)
.map((d, i) => {
return (
<LegendItem
dispatch={this.props.dispatch}
legendRectSize={legendRectSize}
legendSpacing={legendSpacing}
legendMaxLength={legendMaxLength}
legendRectSize={ITEM_RECT_SIZE}
legendSpacing={LEGEND_SPACING}
rectFill={rgb(this.props.colorScale.scale(d)).brighter([0.35]).toString()}
rectStroke={rgb(this.props.colorScale.scale(d)).toString()}
transform={this.getTransformationForLegendItem(i)}
transform={this.getTransformationForLegendItem(maxNumPerColumn, i)}
key={d}
value={d}
label={this.styleLabelText(d)}
index={i}
clipId={i<maxNumPerColumn ? "legendFirstColumnClip" : undefined}
/>
);
});
Expand All @@ -190,32 +186,26 @@ class Legend extends React.Component {
// }}>
return (
<g id="ItemsContainer">
<rect width="290" height={this.getSVGHeight()} fill="rgba(255,255,255,.85)"/>
<rect width={this.getSVGWidth()} height={this.getSVGHeight()} fill="rgba(255,255,255,.85)"/>
<clipPath id="legendFirstColumnClip">
<rect x="0" y="0" width={COLUMN_WIDTH-5} height={this.getSVGHeight()} fill="rgb(150, 154, 223)"/>
</clipPath>
<g id="Items" transform="translate(0,20)">
{items}
</g>
</g>
);
}

getStyles() {
return {
svgLeft: {
...svg,
left: 5
},
svgRight: {
...svg,
right: 5
}
getContainerStyles() {
const styles = {
position: "absolute",
top: 26,
borderRadius: 4,
zIndex: 1000,
userSelect: "none"
};
}

getSVGStyle() {
const styles = this.getStyles();

if (this.props.right) { return styles.svgRight; }
return styles.svgLeft;
styles[this.props.right ? "right" : "left"] = 5;
return styles;
}

getArrowOffset() {
Expand All @@ -240,7 +230,7 @@ class Legend extends React.Component {
id="TreeLegendContainer"
width={this.getSVGWidth()}
height={this.getSVGHeight()}
style={this.getSVGStyle()}
style={this.getContainerStyles()}
>
{this.legendItems()}
<g
Expand Down
3 changes: 0 additions & 3 deletions src/util/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ export const epiColorDomain = genericDomain;
export const nonEpiColorDomain = genericDomain;
export const rbsColorDomain = genericDomain;
export const dateColorDomain = genericDomain;
export const legendRectSize = 15;
export const legendSpacing = 4;
export const legendMaxLength = 18;
export const nonTipNodeRadius = 0;
export const tipRadius = 4;
export const tipRadiusOnLegendMatch = 7;
Expand Down

0 comments on commit 797090f

Please sign in to comment.