Skip to content

Commit 63ec204

Browse files
committed
Make annotation a new type of datum
Annotations can be set in two locations: - in the object sent to functionPlot (legacy) - as a new type of datum Example usage: ```javascript functionPlot({ target: '#playground', y: { domain: [-1, 9] }, data: [ { fn: 'x^2' }, functionPlot.annotation({ x: -1 }), functionPlot.annotation({ x: 1, label: 'x = 1' }), functionPlot.annotation({ y: 2, label: 'y = 2' }) ], }) ```
1 parent 3998952 commit 63ec204

File tree

8 files changed

+78
-29
lines changed

8 files changed

+78
-29
lines changed

site/js/vendor/jquery-1.11.2.min.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

site/js/vendor/modernizr-2.8.3.min.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

site/playground.html

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,27 @@
2828
functionPlot.withWebWorkers(8)
2929
functionPlot({
3030
target: '#playground',
31+
y: { domain: [-1, 9] },
3132
data: [
32-
functionPlot.interval({ fn: 'x^2' }),
33-
functionPlot.scatter({ fn: 'sin(x)', nSamples: 50 }),
34-
functionPlot.polyline({ fn: 'x^3' }),
35-
functionPlot.text({ text: 'foo', location: [1, 2] })
36-
]
33+
{
34+
fn: 'x^2'
35+
},
36+
functionPlot.annotation({ x: -1 }),
37+
functionPlot.annotation({ x: 1, label: 'x = 1' }),
38+
functionPlot.annotation({ y: 2, label: 'y = 2' })
39+
],
3740
})
41+
42+
// functionPlot({
43+
// target: '#playground',
44+
// data: [
45+
// functionPlot.interval({ fn: 'x^2' }),
46+
// functionPlot.scatter({ fn: 'sin(x)', nSamples: 50 }),
47+
// functionPlot.polyline({ fn: 'x^3' }),
48+
// functionPlot.text({ text: 'foo', location: [1, 2] })
49+
// ]
50+
// })
51+
3852
// functionPlot({
3953
// target: '#playground',
4054
// data: [

src/chart.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,18 @@ export class Chart extends EventEmitter.EventEmitter {
542542
}
543543

544544
// annotations
545-
content.merge(contentEnter).each(function (d: Mark | FunctionPlotDatum) {
545+
const annotations = content
546+
.merge(contentEnter)
547+
.selectAll('g.annotations')
548+
.data(function (d: FunctionPlotOptions) {
549+
return d.annotations || []
550+
})
551+
// exit
552+
annotations.exit().remove()
553+
// enter
554+
const annotationsEnter = annotations.enter().append('g').attr('class', 'annotations')
555+
// enter + update
556+
annotations.merge(annotationsEnter).each(function (d: Mark | FunctionPlotDatum, index: number) {
546557
const selection = d3Select(this)
547558
const ann = annotation(d)
548559
ann.chart = self

src/graph-types/annotation.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,32 @@
11
import { line as d3Line } from 'd3-shape'
22
import type { Selection } from 'd3-selection'
33

4-
import type { FunctionPlotOptions } from '../types.js'
5-
import { Mark } from '../graph-types/mark.js'
4+
import type { FunctionPlotAnnotation } from '../types.js'
65

7-
const line = d3Line()
8-
.x((d) => d[0])
9-
.y((d) => d[1])
6+
import { Mark } from '../graph-types/mark.js'
107

118
export class Annotation extends Mark {
9+
x?: number
10+
y?: number
11+
label?: string
12+
1213
constructor(options: any) {
1314
super(options)
15+
this.x = options.x
16+
this.y = options.y
17+
this.label = options.label
1418
}
1519

16-
render(parentSelection: Selection<any, FunctionPlotOptions, any, any>) {
20+
render(parentSelection: Selection<any, FunctionPlotAnnotation, any, any>) {
21+
const self = this
22+
1723
// join
18-
const selection = parentSelection.selectAll('g.annotations').data(function (d: FunctionPlotOptions) {
19-
return d.annotations || []
24+
const selection = parentSelection.selectAll('g.annotation').data(function () {
25+
return [self]
2026
})
2127

2228
// enter
23-
const enter = selection.enter().append('g').attr('class', 'annotations')
29+
const enter = selection.enter().append('g').attr('class', 'annotation')
2430

2531
const xScale = this.chart.meta.xScale
2632
const yScale = this.chart.meta.yScale
@@ -33,14 +39,21 @@ export class Annotation extends Mark {
3339
// prettier-ignore
3440
const path = selection.merge(enter).selectAll('path')
3541
.data(function (d) {
36-
if ('x' in d) {
42+
if (typeof d.x !== "undefined") {
3743
return [[[0, yRange[0]], [0, yRange[1]]]]
38-
} else {
44+
} else if (typeof d.y !== "undefined") {
3945
return [[[xRange[0], 0], [xRange[1], 0]]]
46+
} else {
47+
throw new Error(`Property x or y wasn't set in the annotation`)
4048
}
4149
})
4250
// enter
4351
const pathEnter = path.enter().append('path')
52+
53+
const line = d3Line()
54+
.x((d) => d[0])
55+
.y((d) => d[1])
56+
4457
// enter + update
4558
path
4659
.merge(pathEnter)
@@ -56,7 +69,7 @@ export class Annotation extends Mark {
5669
{
5770
label: d.label || '',
5871
// used to determine if x or y is set.
59-
xIsSet: 'x' in d
72+
xIsSet: typeof d.x !== 'undefined'
6073
}
6174
])
6275
// enter
@@ -85,7 +98,7 @@ export class Annotation extends Mark {
8598
// enter + update
8699
// move group
87100
selection.merge(enter).attr('transform', function (d) {
88-
if ('x' in d) {
101+
if (typeof d.x !== 'undefined') {
89102
return 'translate(' + xScale(d.x) + ', 0)'
90103
} else {
91104
return 'translate(0, ' + yScale(d.y) + ')'

0 commit comments

Comments
 (0)