Skip to content

Commit

Permalink
🔨 drop vertical color legend observer
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Dec 20, 2024
1 parent c549549 commit 7d2fd51
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 302 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
ConnectedScatterLegendManager,
} from "./ConnectedScatterLegend"
import { VerticalColorLegend } from "../verticalColorLegend/VerticalColorLegend"
import { VerticalColorLegendComponent } from "../verticalColorLegend/VerticalColorLegendComponent"
import { DualAxisComponent } from "../axis/AxisViews"
import { DualAxis, HorizontalAxis, VerticalAxis } from "../axis/Axis"

Expand Down Expand Up @@ -506,15 +507,14 @@ export class ScatterPlotChart
return this.tooltipState.target?.series
}

@computed private get verticalColorLegend(): {
width: number
height: number
} {
return VerticalColorLegend.dimensions({
@computed private get verticalColorLegend(): VerticalColorLegend {
return new VerticalColorLegend({
maxLegendWidth: this.maxLegendWidth,
fontSize: this.fontSize,
legendItems: this.legendItems,
legendTitle: this.legendTitle,
activeColors: this.activeColors,
focusColors: this.focusColors,
})
}

Expand Down Expand Up @@ -832,18 +832,15 @@ export class ScatterPlotChart
/>
))}
{this.points}
<VerticalColorLegend
maxLegendWidth={this.maxLegendWidth}
fontSize={this.fontSize}
legendItems={this.legendItems}
legendTitle={this.legendTitle}
onLegendMouseOver={this.onLegendMouseOver}
onLegendClick={this.onLegendClick}
onLegendMouseLeave={this.onLegendMouseLeave}
legendX={this.legendX}
legendY={this.legendY}
activeColors={this.activeColors}
focusColors={this.focusColors}
<VerticalColorLegendComponent
x={this.legendX}
y={this.legendY}
state={this.verticalColorLegend}
eventListeners={{
onLegendMouseOver: this.onLegendMouseOver,
onLegendMouseLeave: this.onLegendMouseLeave,
onLegendClick: this.onLegendClick,
}}
/>
{sizeLegend && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
VerticalColorLegend,
LegendItem,
} from "../verticalColorLegend/VerticalColorLegend"
import { VerticalColorLegendComponent } from "../verticalColorLegend/VerticalColorLegendComponent"
import { TooltipFooterIcon } from "../tooltip/TooltipProps.js"
import {
Tooltip,
Expand Down Expand Up @@ -313,14 +314,12 @@ export class StackedBarChart
)
}

@computed private get verticalColorLegend(): {
width: number
height: number
} {
return VerticalColorLegend.dimensions({
@computed private get verticalColorLegend(): VerticalColorLegend {
return new VerticalColorLegend({
maxLegendWidth: this.maxLegendWidth,
fontSize: this.fontSize,
legendItems: this.legendItems,
activeColors: this.activeColors,
})
}

Expand Down Expand Up @@ -480,6 +479,13 @@ export class StackedBarChart

if (!showLegend) return

const eventListeners = this.manager.isStatic
? undefined
: {
onLegendMouseOver: this.onLegendMouseOver,
onLegendMouseLeave: this.onLegendMouseLeave,
}

return showHorizontalLegend ? (
<HorizontalCategoricalColorLegend
fontSize={this.fontSize}
Expand All @@ -494,16 +500,11 @@ export class StackedBarChart
isStatic={this.isStatic}
/>
) : (
<VerticalColorLegend
legendItems={this.legendItems}
maxLegendWidth={this.maxLegendWidth}
fontSize={this.fontSize}
onLegendMouseOver={this.onLegendMouseOver}
onLegendMouseLeave={this.onLegendMouseLeave}
legendX={this.legendX}
legendY={this.legendY}
activeColors={this.activeColors}
isStatic={this.isStatic}
<VerticalColorLegendComponent
x={this.legendX}
y={this.legendY}
state={this.verticalColorLegend}
eventListeners={eventListeners}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
VerticalColorLegend,
VerticalColorLegendProps,
} from "./VerticalColorLegend"
import { VerticalColorLegendComponent } from "./VerticalColorLegendComponent"

export default {
title: "VerticalColorLegend",
Expand All @@ -26,9 +27,10 @@ const props: VerticalColorLegendProps = {
}

export const CategoricalBins = (): React.ReactElement => {
const verticalColorLegend = new VerticalColorLegend(props)
return (
<svg width={600} height={400}>
<VerticalColorLegend {...props} />
<VerticalColorLegendComponent state={verticalColorLegend} />
</svg>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { sum, max } from "@ourworldindata/utils"
import { TextWrap } from "@ourworldindata/components"
import { computed } from "mobx"
import {
GRAPHER_FONT_SCALE_11_2,
BASE_FONT_SIZE,
} from "../core/GrapherConstants"
import { Color } from "@ourworldindata/types"

export interface VerticalColorLegendProps {
legendItems: LegendItem[]
maxLegendWidth?: number
fontSize?: number
legendTitle?: string
activeColors?: Color[] // inactive colors are grayed out
focusColors?: Color[] // focused colors are bolded
}

export interface LegendItem {
label?: string
minText?: string
maxText?: string
color: Color
}

interface SizedLegendSeries {
textWrap: TextWrap
color: Color
width: number
height: number
yOffset: number
}

export class VerticalColorLegend {
rectPadding = 5
lineHeight = 5

props: VerticalColorLegendProps
constructor(props: VerticalColorLegendProps) {
this.props = props
}

@computed private get maxLegendWidth(): number {
return this.props.maxLegendWidth ?? 100
}

@computed private get fontSize(): number {
return GRAPHER_FONT_SCALE_11_2 * (this.props.fontSize ?? BASE_FONT_SIZE)
}

@computed get rectSize(): number {
return Math.round(this.fontSize / 1.4)
}

@computed get title(): TextWrap | undefined {
if (!this.props.legendTitle) return undefined
return new TextWrap({
maxWidth: this.maxLegendWidth,
fontSize: this.fontSize,
fontWeight: 700,
lineHeight: 1,
text: this.props.legendTitle,
})
}

@computed private get titleHeight(): number {
if (!this.title) return 0
return this.title.height + 5
}

@computed get series(): SizedLegendSeries[] {
const { fontSize, rectSize, rectPadding, titleHeight, lineHeight } =
this

let runningYOffset = titleHeight
return this.props.legendItems.map((series) => {
let label = series.label
// infer label for numeric bins
if (!label && series.minText && series.maxText) {
label = `${series.minText}${series.maxText}`
}
const textWrap = new TextWrap({
maxWidth: this.maxLegendWidth,
fontSize,
lineHeight: 1,
text: label ?? "",
})
const width = rectSize + rectPadding + textWrap.width
const height = Math.max(textWrap.height, rectSize)
const yOffset = runningYOffset

runningYOffset += height + lineHeight

return {
textWrap,
color: series.color,
width,
height,
yOffset,
}
})
}

@computed get width(): number {
const widths = this.series.map((series) => series.width)
if (this.title) widths.push(this.title.width)
return max(widths) ?? 0
}

@computed get height(): number {
return (
this.titleHeight +
sum(this.series.map((series) => series.height)) +
this.lineHeight * this.series.length
)
}
}
Loading

0 comments on commit 7d2fd51

Please sign in to comment.