Skip to content

Commit

Permalink
🔨 (slope) cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Nov 22, 2024
1 parent b568312 commit fc0655c
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ export class RemoveColorDimensionFromSlopeCharts1732195571407
implements MigrationInterface
{
public async up(queryRunner: QueryRunner): Promise<void> {
// update dimensions field in chart configs
// remove color dimension for all slope charts
// the y-dimension always comes first and the color dimension second,
// so it's safe to keep the first dimension only
await queryRunner.query(`
-- sql
UPDATE chart_configs
Expand All @@ -15,7 +17,7 @@ export class RemoveColorDimensionFromSlopeCharts1732195571407
chartType = 'SlopeChart'
`)

// remove from chart_dimensions table
// remove the color dimension for slope charts from the chart_dimensions table
await queryRunner.query(`
-- sql
DELETE cd FROM chart_dimensions cd
Expand Down
4 changes: 2 additions & 2 deletions packages/@ourworldindata/core-table/src/OwidTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ export class OwidTable extends CoreTable<OwidRow, OwidColumnDef> {
return min(this.allTimes) as Time
}

@imemo get maxTime(): Time {
return max(this.allTimes) as Time
@imemo get maxTime(): number | undefined {
return max(this.allTimes)
}

@imemo private get allTimes(): Time[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,14 @@ export class DiscreteBarChart
<g id={makeIdForHumanConsumption("entity-labels")}>
{this.placedSeries.map((series) => {
return (
series.label &&
series.label.render(
series.entityLabelX,
series.barY - series.label.height / 2,
{ textProps: style }
series.label && (
<React.Fragment key={series.seriesName}>
{series.label.render(
series.entityLabelX,
series.barY - series.label.height / 2,
{ textProps: style }
)}
</React.Fragment>
)
)
})}
Expand Down Expand Up @@ -990,6 +993,7 @@ function makeProjectedDataPattern(color: string): React.ReactElement {
const size = 7
return (
<pattern
key={color}
id={makeProjectedDataPatternId(color)}
patternUnits="userSpaceOnUse"
width={size}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
AxisAlign,
Color,
HorizontalAlign,
PrimitiveType,
makeIdForHumanConsumption,
} from "@ourworldindata/utils"
import { computed, action, observable } from "mobx"
Expand Down
48 changes: 21 additions & 27 deletions packages/@ourworldindata/grapher/src/slopeCharts/SlopeChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
import { observable, computed, action } from "mobx"
import { observer } from "mobx-react"
import { NoDataModal } from "../noDataModal/NoDataModal"
import { ColorScaleManager } from "../color/ColorScale"
import {
BASE_FONT_SIZE,
GRAPHER_DARK_TEXT,
Expand All @@ -33,7 +32,6 @@ import {
Time,
SeriesStrategy,
EntityName,
PrimitiveType,
RenderMode,
} from "@ourworldindata/types"
import { ChartInterface } from "../chart/ChartInterface"
Expand Down Expand Up @@ -75,9 +73,11 @@ import {
getSeriesName,
} from "../lineCharts/lineChartHelpers"

type SVGMouseOrTouchEvent =
| React.MouseEvent<SVGGElement>
| React.TouchEvent<SVGGElement>

export interface SlopeChartManager extends ChartManager {
isModalOpen?: boolean
canChangeEntity?: boolean
canSelectMultipleEntities?: boolean
}

Expand All @@ -92,9 +92,9 @@ export class SlopeChart
bounds?: Bounds
manager: SlopeChartManager
}>
implements ChartInterface, ColorScaleManager
implements ChartInterface
{
base: React.RefObject<SVGGElement> = React.createRef()
slopeAreaRef: React.RefObject<SVGGElement> = React.createRef()
defaultBaseColorScheme = ColorSchemeName.OwidDistinctLines

@observable hoveredSeriesName?: string
Expand Down Expand Up @@ -166,7 +166,7 @@ export class SlopeChart
}

@computed private get isLogScale(): boolean {
return this.props.manager.yAxisConfig?.scaleType === ScaleType.log
return this.yScaleType === ScaleType.log
}

@computed private get missingDataStrategy(): MissingDataStrategy {
Expand Down Expand Up @@ -204,26 +204,22 @@ export class SlopeChart
return this.xScale(this.endTime)
}

private updateTooltipPosition(
event: React.MouseEvent<SVGGElement> | React.TouchEvent<SVGGElement>
) {
private updateTooltipPosition(event: SVGMouseOrTouchEvent) {
const ref = this.manager.base?.current
if (ref) this.tooltipState.position = getRelativeMouse(ref, event)
}

private detectHoveredSlope(
event: React.MouseEvent<SVGGElement> | React.TouchEvent<SVGGElement>
) {
const ref = this.base.current
private detectHoveredSlope(event: SVGMouseOrTouchEvent) {
const ref = this.slopeAreaRef.current
if (!ref) return

const mouse = getRelativeMouse(ref, event)
this.mouseFrame = requestAnimationFrame(() => {
if (this.placedSeries.length === 0) return

const distToSlope = new Map<PlacedSlopeChartSeries, number>()
const distanceMap = new Map<PlacedSlopeChartSeries, number>()
for (const series of this.placedSeries) {
distToSlope.set(
distanceMap.set(
series,
PointVector.distanceFromPointToLineSegmentSq(
mouse,
Expand All @@ -234,9 +230,9 @@ export class SlopeChart
}

const closestSlope = minBy(this.placedSeries, (s) =>
distToSlope.get(s)
)
const distanceSq = distToSlope.get(closestSlope!)!
distanceMap.get(s)
)!
const distanceSq = distanceMap.get(closestSlope)!
const tolerance = 10
const toleranceSq = tolerance * tolerance

Expand Down Expand Up @@ -506,7 +502,7 @@ export class SlopeChart
@computed get xRange(): [number, number] {
const lineLegendWidth = this.maxLineLegendWidth + LINE_LEGEND_PADDING

// pick a reasonable width based on an ideal aspect ratio
// pick a reasonable max width based on an ideal aspect ratio
const idealAspectRatio = 0.6
const chartAreaWidth = this.bounds.width - this.sidebarWidth
const availableWidth =
Expand Down Expand Up @@ -553,7 +549,7 @@ export class SlopeChart

private playIntroAnimation() {
// Nice little intro animation
select(this.base.current)
select(this.slopeAreaRef.current)
.select(".slopes")
.attr("stroke-dasharray", "100%")
.attr("stroke-dashoffset", "100%")
Expand Down Expand Up @@ -594,11 +590,9 @@ export class SlopeChart
}

mouseFrame?: number
@action.bound onMouseMove(
ev: React.MouseEvent<SVGGElement> | React.TouchEvent<SVGGElement>
) {
this.updateTooltipPosition(ev)
this.detectHoveredSlope(ev)
@action.bound onMouseMove(event: SVGMouseOrTouchEvent) {
this.updateTooltipPosition(event)
this.detectHoveredSlope(event)
}

@action.bound onMouseLeave() {
Expand Down Expand Up @@ -771,7 +765,7 @@ export class SlopeChart
/>
<g
id={makeIdForHumanConsumption("slopes")}
ref={this.base}
ref={this.slopeAreaRef}
onMouseMove={this.onMouseMove}
onTouchMove={this.onMouseMove}
onTouchStart={this.onMouseMove}
Expand Down

0 comments on commit fc0655c

Please sign in to comment.