export default function() { var x = function(d) { return d.x; }, y = function(d) { return d.y; }, xScale = d3.scale.identity(), yScale = d3.scale.identity(), decorate = noop; var dataJoin = dataJoinUtil() .children(true) .selector('g.crosshair') .element('g') .attr('class', 'crosshair'); var pointSeries = point() .xValue(x) .yValue(y); var horizontalLine = line() .value(y) .label(y); var verticalLine = line() .orient('vertical') .value(x) .label(x); // The line annotations and point series used to render the crosshair are positioned using // screen coordinates. This function constructs an identity scale for these components. var identityXScale = d3.scale.identity(); var identityYScale = d3.scale.identity(); var multi = multiSeries() .series([horizontalLine, verticalLine, pointSeries]) .xScale(identityXScale) .yScale(identityYScale) .mapping(function() { return [this]; }); var crosshair = function(selection) { selection.each(function(data, index) { var container = d3.select(this); var crosshairElement = dataJoin(container, data); crosshairElement.enter() .style('pointer-events', 'none'); // Assign the identity scales an accurate range to allow the line annotations to cover // the full width/height of the chart. identityXScale.range(range(xScale)); identityYScale.range(range(yScale)); crosshairElement.call(multi); decorate(crosshairElement, data, index); }); }; // Don't use the xValue/yValue convention to indicate that these values are in screen // not domain co-ordinates and are therefore not scaled. crosshair.x = function(_x) { if (!arguments.length) { return x; } x = _x; return crosshair; }; crosshair.y = function(_x) { if (!arguments.length) { return y; } y = _x; return crosshair; }; crosshair.xScale = function(_x) { if (!arguments.length) { return xScale; } xScale = _x; return crosshair; }; crosshair.yScale = function(_x) { if (!arguments.length) { return yScale; } yScale = _x; return crosshair; }; crosshair.decorate = function(_x) { if (!arguments.length) { return decorate; } decorate = _x; return crosshair; }; var lineIncludes = include('label'); rebindAll(crosshair, horizontalLine, lineIncludes, prefix('y')); rebindAll(crosshair, verticalLine, lineIncludes, prefix('x')); return crosshair; }
export default function() { let x = (d) => d.x; let y = (d) => d.y; let xScale = scaleIdentity(); let yScale = scaleIdentity(); let decorate = () => {}; const join = dataJoin('g', 'annotation-crosshair'); const point = seriesSvgPoint(); const horizontalLine = annotationLine(); const verticalLine = annotationLine() .orient('vertical'); // The line annotations and point series used to render the crosshair are positioned using // screen coordinates. This function constructs an identity scale for these components. const xIdentity = scaleIdentity(); const yIdentity = scaleIdentity(); const multi = seriesSvgMulti() .series([horizontalLine, verticalLine, point]) .xScale(xIdentity) .yScale(yIdentity) .mapping((data) => [data]); const instance = (selection) => { selection.each((data, index, nodes) => { const g = join(select(nodes[index]), data); // Prevent the crosshair triggering pointer events on itself g.enter() .style('pointer-events', 'none'); // Assign the identity scales an accurate range to allow the line annotations to cover // the full width/height of the chart. xIdentity.range(xScale.range()); yIdentity.range(yScale.range()); point.xValue(x) .yValue(y); horizontalLine.value(y); verticalLine.value(x); g.call(multi); decorate(g, data, index); }); }; // Don't use the xValue/yValue convention to indicate that these values are in screen // not domain co-ordinates and are therefore not scaled. instance.x = (...args) => { if (!args.length) { return x; } x = args[0]; return instance; }; instance.y = (...args) => { if (!args.length) { return y; } y = args[0]; return instance; }; instance.xScale = (...args) => { if (!args.length) { return xScale; } xScale = args[0]; return instance; }; instance.yScale = (...args) => { if (!args.length) { return yScale; } yScale = args[0]; return instance; }; instance.decorate = (...args) => { if (!args.length) { return decorate; } decorate = args[0]; return instance; }; const lineIncludes = include('label'); rebindAll(instance, horizontalLine, lineIncludes, prefix('y')); rebindAll(instance, verticalLine, lineIncludes, prefix('x')); return instance; }
export default function() { // creates an array with four elements, representing the high, low, open and close // values of the given array function highLowOpenClose(data) { var xValueAccessor = sparkline.xValue(), yValueAccessor = sparkline.yValue(); var high = d3.max(data, yValueAccessor); var low = d3.min(data, yValueAccessor); function elementWithYValue(value) { return data.filter(function(d) { return yValueAccessor(d) === value; })[0]; } return [{ x: xValueAccessor(data[0]), y: yValueAccessor(data[0]) }, { x: xValueAccessor(elementWithYValue(high)), y: high }, { x: xValueAccessor(elementWithYValue(low)), y: low }, { x: xValueAccessor(data[data.length - 1]), y: yValueAccessor(data[data.length - 1]) }]; } var xScale = dateTime(); var yScale = d3.scale.linear(); var radius = 2; var line = _line(); // configure the point series to render the data from the // highLowOpenClose function var point = _point() .xValue(function(d) { return d.x; }) .yValue(function(d) { return d.y; }) .decorate(function(sel) { sel.attr('class', function(d, i) { switch (i) { case 0: return 'open'; case 1: return 'high'; case 2: return 'low'; case 3: return 'close'; } }); }); var multi = _multi() .series([line, point]) .mapping(function(series) { switch (series) { case point: return highLowOpenClose(this); default: return this; } }); var sparkline = function(selection) { point.size(radius * radius * Math.PI); selection.each(function(data) { var container = d3.select(this); var dimensions = innerDimensions(this); var margin = radius; xScale.range([margin, dimensions.width - margin]); yScale.range([dimensions.height - margin, margin]); multi.xScale(xScale) .yScale(yScale); container.call(multi); }); }; rebindAll(sparkline, xScale, include('discontinuityProvider', 'domain'), prefix('x')); rebindAll(sparkline, yScale, include('domain'), prefix('y')); rebindAll(sparkline, line, include('xValue', 'yValue')); sparkline.xScale = function() { return xScale; }; sparkline.yScale = function() { return yScale; }; sparkline.radius = function(x) { if (!arguments.length) { return radius; } radius = x; return sparkline; }; return sparkline; }