@react-financial-charts/interactive
Version:
Interactive features for react-financial-charts
104 lines • 4.19 kB
JavaScript
import { deviation, sum, zip } from "d3-array";
import * as React from "react";
import { getClosestItemIndexes, getMouseCanvas, GenericChartComponent } from "@react-financial-charts/core";
import { isHovering2 } from "./InteractiveStraightLine";
export class LinearRegressionChannelWithArea extends React.Component {
constructor() {
super(...arguments);
this.drawOnCanvas = (ctx, moreProps) => {
const { strokeStyle, strokeWidth, fillStyle } = this.props;
const { x1, y1, x2, y2, dy } = helper(this.props, moreProps);
ctx.lineWidth = strokeWidth;
ctx.strokeStyle = strokeStyle;
ctx.fillStyle = fillStyle;
ctx.beginPath();
ctx.moveTo(x1, y1 - dy);
ctx.lineTo(x2, y2 - dy);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2 + dy);
ctx.lineTo(x1, y1 + dy);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x1, y1 - dy);
ctx.lineTo(x2, y2 - dy);
ctx.lineTo(x2, y2 + dy);
ctx.lineTo(x1, y1 + dy);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(x1, y1);
ctx.stroke();
};
this.isHover = (moreProps) => {
const { tolerance, onHover } = this.props;
if (onHover !== undefined) {
const { mouseXY } = moreProps;
const { x1, y1, x2, y2, dy } = helper(this.props, moreProps);
const yDiffs = [-dy, 0, dy];
const hovering = yDiffs.reduce((result, diff) => result || isHovering2([x1, y1 + diff], [x2, y2 + diff], mouseXY, tolerance), false);
return hovering;
}
return false;
};
}
render() {
const { selected, interactiveCursorClass } = this.props;
const { onDragStart, onDrag, onDragComplete, onHover, onUnHover } = this.props;
return (React.createElement(GenericChartComponent, { isHover: this.isHover, canvasToDraw: getMouseCanvas, canvasDraw: this.drawOnCanvas, interactiveCursorClass: interactiveCursorClass, selected: selected, onDragStart: onDragStart, onDrag: onDrag, onDragComplete: onDragComplete, onHover: onHover, onUnHover: onUnHover, drawOn: ["mousemove", "mouseleave", "pan", "drag"] }));
}
}
LinearRegressionChannelWithArea.defaultProps = {
type: "SD",
strokeWidth: 1,
tolerance: 4,
selected: false,
};
export function edge1Provider(props) {
return function (moreProps) {
const { x1, y1 } = helper(props, moreProps);
return [x1, y1];
};
}
export function edge2Provider(props) {
return function (moreProps) {
const { x2, y2 } = helper(props, moreProps);
return [x2, y2];
};
}
function helper(props, moreProps) {
const { x1Value, x2Value, type } = props;
const { xScale, chartConfig: { yScale }, fullData, } = moreProps;
const { xAccessor } = moreProps;
const { left } = getClosestItemIndexes(fullData, x1Value, xAccessor);
const { right } = getClosestItemIndexes(fullData, x2Value, xAccessor);
const startIndex = Math.min(left, right);
const endIndex = Math.max(left, right) + 1;
const array = fullData.slice(startIndex, endIndex);
const xs = array.map((d) => xAccessor(d).valueOf());
const ys = array.map((d) => d.close);
const n = array.length;
const xys = zip(xs, ys).map((d) => {
return d[0] * d[1];
});
const xSquareds = xs.map((x) => Math.pow(x, 2));
const b = (n * sum(xys) - sum(xs) * sum(ys)) / (n * sum(xSquareds) - Math.pow(sum(xs), 2));
const a = (sum(ys) - b * sum(xs)) / n;
const newy1 = a + b * x1Value;
const newy2 = a + b * x2Value;
const x1 = xScale(x1Value);
const y1 = yScale(newy1);
const x2 = xScale(x2Value);
const y2 = yScale(newy2);
const stdDev = type === "SD" ? deviation(array, (d) => d.close) : 0;
const dy = yScale(newy1 - stdDev) - y1;
return {
x1,
y1,
x2,
y2,
dy,
};
}
//# sourceMappingURL=LinearRegressionChannelWithArea.js.map