Skip to content

Commit f025af7

Browse files
committed
feat: new graph type text
1 parent be655e1 commit f025af7

File tree

7 files changed

+86
-5
lines changed

7 files changed

+86
-5
lines changed

src/graph-types/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import polyline from './polyline'
22
import interval from './interval'
33
import scatter from './scatter'
4+
import text from './text'
45

5-
export { polyline, interval, scatter }
6+
export { polyline, interval, scatter, text }

src/graph-types/scatter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default function Scatter(chart: Chart) {
3434

3535
const selection = innerSelection
3636
.merge(innerSelectionEnter)
37-
.attr('fill', d3Hsl(color.toString()).brighter(1.5).hex())
37+
.attr('fill', d3Hsl(color.toString()).brighter(1.5).formatHex())
3838
.attr('stroke', color)
3939
.attr('opacity', 0.7)
4040
.attr('r', 1)

src/graph-types/text.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { select as d3Select, Selection } from 'd3-selection'
2+
import { hsl as d3Hsl } from 'd3-color'
3+
4+
import utils from '../utils'
5+
6+
import { Chart } from '../index'
7+
import { FunctionPlotDatum } from '../types'
8+
9+
export default function Text(chart: Chart) {
10+
const xScale = chart.meta.xScale
11+
const yScale = chart.meta.yScale
12+
13+
function text(selection: Selection<any, FunctionPlotDatum, any, any>) {
14+
selection.each(function (d) {
15+
// Force some parameters to make it look like a vector.
16+
d.sampler = 'builtIn'
17+
d.fnType = 'vector'
18+
19+
const innerSelection = d3Select(this).selectAll(':scope > text.fn-text').data([d.location])
20+
const innerSelectionEnter = innerSelection.enter().append('text').attr('class', `fn-text fn-text-${d.index}`)
21+
22+
const color = utils.color(d, d.index)
23+
24+
// enter + update
25+
const selection = innerSelection
26+
.merge(innerSelectionEnter)
27+
.attr('fill', d3Hsl(color.toString()).brighter(1.5).formatHex())
28+
.attr('x', (d) => xScale(d[0]))
29+
.attr('y', (d) => yScale(d[1]))
30+
.text(() => d.text)
31+
32+
if (d.attr) {
33+
for (const k in d.attr) {
34+
selection.attr(k, d.attr[k])
35+
}
36+
}
37+
38+
// exit
39+
innerSelection.exit().remove()
40+
})
41+
}
42+
43+
return text
44+
}

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import { FunctionPlotOptions } from './types'
44
import { Chart } from './chart'
55

66
import globals, { registerGraphType } from './globals'
7-
import { polyline, interval, scatter } from './graph-types'
7+
import { polyline, interval, scatter, text } from './graph-types'
88
import * as $eval from './helpers/eval'
99

1010
// register common graphTypes on library load.
1111
registerGraphType('polyline', polyline)
1212
registerGraphType('interval', interval)
1313
registerGraphType('scatter', scatter)
14+
registerGraphType('text', text)
1415

1516
/**
1617
* functionPlot is a function plotter of 2d functions.

src/types.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export interface FunctionPlotDatum {
154154
/**
155155
* The type of function to render
156156
*/
157-
fnType?: 'linear' | 'parametric' | 'implicit' | 'polar' | 'points' | 'vector'
157+
fnType?: 'linear' | 'parametric' | 'implicit' | 'polar' | 'points' | 'vector' | string
158158

159159
/**
160160
* The sampler to take samples from `range`, available values are `interval|builtIn`
@@ -224,13 +224,23 @@ export interface FunctionPlotDatum {
224224
/**
225225
* An array of 2-number array which hold the coordinates of the points to render when `fnType: 'vector'`
226226
*/
227-
vector?: number[]
227+
vector?: [number, number]
228228

229229
/**
230230
* Vector offset when `fnType: 'vector'`
231231
*/
232232
offset?: number[]
233233

234+
/**
235+
* An array of 2-number array for the position of the text when `fnType: 'text'`
236+
*/
237+
location?: [number, number]
238+
239+
/**
240+
* Used as text if `graphType: 'text'`
241+
*/
242+
text?: string
243+
234244
// helper data
235245
/**
236246
* @private
35.2 KB
Loading

test/e2e/graphs.test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,31 @@ functionPlot({
188188
fn: 'x^2',
189189
graphType: 'interval'
190190
}]
191+
})
192+
`)
193+
const image = await page.screenshot()
194+
expect(image).toMatchImageSnapshot(matchSnapshotConfig)
195+
})
196+
197+
it('should render text', async () => {
198+
await page.evaluate(`
199+
functionPlot({
200+
target: '#playground',
201+
data: [
202+
{
203+
graphType: "text",
204+
location: [1, 1],
205+
text: "hello world"
206+
},
207+
{
208+
graphType: "text",
209+
location: [-1, -1],
210+
text: "foo bar",
211+
attr: {
212+
'text-anchor': 'end'
213+
}
214+
},
215+
]
191216
})
192217
`)
193218
const image = await page.screenshot()

0 commit comments

Comments
 (0)