|
<!DOCTYPE html> |
|
<!-- include polyfills for custom event, Symbol and Custom Elements --> |
|
<script src="//unpkg.com/babel-polyfill@6.26.0/dist/polyfill.js"></script> |
|
<script src="//unpkg.com/custom-event-polyfill@0.3.0/custom-event-polyfill.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/document-register-element/1.8.0/document-register-element.js"></script> |
|
|
|
<!-- use babel so that we can use arrow functions and other goodness in this block! --> |
|
<script src="//unpkg.com/babel-standalone@6/babel.min.js"></script> |
|
|
|
<script src="//unpkg.com/d3@5.5.0"></script> |
|
<script src="//unpkg.com/d3fc@14.0.41"></script> |
|
|
|
<style> |
|
body { |
|
font: 16px sans-serif; |
|
} |
|
.chart { |
|
height: 480px; |
|
} |
|
.plot-area { |
|
overflow: visible !important; |
|
} |
|
#container { |
|
position: relative; |
|
} |
|
.tooltip { |
|
position: absolute; |
|
top: 10px; |
|
left: 10px; |
|
} |
|
</style> |
|
|
|
<div id='simple-chart' class='chart'></div> |
|
|
|
<script type='text/babel'> |
|
// create some test data |
|
var sinewave = d3.range(50).map((d) => ({ |
|
x: d / 4, |
|
y: Math.sin(d / 4) |
|
})) |
|
|
|
// combine the sine wave with an empty array which will hold the |
|
// current crosshair value |
|
var data = { |
|
series: sinewave, |
|
crosshair: [] |
|
}; |
|
|
|
// use the extent component to compute the x / y domain |
|
var yExtent = fc.extentLinear() |
|
.accessors([d => d.y]) |
|
.pad([0.4, 0.4]) |
|
.padUnit('domain'); |
|
var xExtent = fc.extentLinear() |
|
.accessors([d => d.x]); |
|
|
|
// create a chart |
|
var chart = fc.chartCartesian( |
|
d3.scaleLinear(), |
|
d3.scaleLinear()) |
|
.yDomain(yExtent(sinewave)) |
|
.yLabel('Sine') |
|
.xDomain(xExtent(sinewave)) |
|
.xLabel('Value') |
|
.decorate(function(sel) { |
|
// decorate the cartesian chart to add the tooltip element on |
|
// the enter selection |
|
sel.enter() |
|
.append('div') |
|
.classed('tooltip', true); |
|
|
|
// on the update selection, update the text |
|
sel.select('.tooltip') |
|
.text(d => |
|
d.crosshair.length > 0 |
|
? 'x: ' + d.crosshair[0].x.toFixed(0) + ', y: ' + d.crosshair[0].y.toFixed(0) |
|
: '' |
|
); |
|
}) |
|
|
|
var sinLine = fc.seriesSvgLine() |
|
.crossValue(d => d.x) |
|
.mainValue(d => d.y); |
|
|
|
var crosshair = fc.annotationSvgCrosshair() |
|
.xLabel('') |
|
.yLabel(''); |
|
|
|
// Add the line and crosshair via a multi-series. Use the mapping function |
|
// to provide the correct data to each |
|
var multi = fc.seriesSvgMulti() |
|
.series([sinLine, crosshair]) |
|
.mapping((data, index, series) => { |
|
switch(series[index]) { |
|
case sinLine: |
|
return data.series; |
|
case crosshair: |
|
return data.crosshair; |
|
} |
|
}); |
|
|
|
chart.svgPlotArea(multi); |
|
|
|
function render(){ |
|
// render |
|
d3.select('#simple-chart') |
|
.datum(data) |
|
.call(chart); |
|
|
|
// add the pointer component to the plot-area, re-rendering |
|
// each time the event fires. |
|
var pointer = fc.pointer() |
|
.on('point', (event) => { |
|
data.crosshair = event; |
|
render(); |
|
}); |
|
|
|
d3.select('#simple-chart .plot-area') |
|
.call(pointer); |
|
} |
|
|
|
render(); |
|
</script> |