ct-react-stockcharts
Version:
Highly customizable stock charts with ReactJS and d3
369 lines (307 loc) • 11.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _d3Collection = require("d3-collection");
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
var _GenericChartComponent = require("../GenericChartComponent");
var _GenericChartComponent2 = _interopRequireDefault(_GenericChartComponent);
var _GenericComponent = require("../GenericComponent");
var _utils = require("../utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var CandlestickSeries = function (_Component) {
_inherits(CandlestickSeries, _Component);
function CandlestickSeries(props) {
_classCallCheck(this, CandlestickSeries);
var _this = _possibleConstructorReturn(this, (CandlestickSeries.__proto__ || Object.getPrototypeOf(CandlestickSeries)).call(this, props));
_this.renderSVG = _this.renderSVG.bind(_this);
_this.drawOnCanvas = _this.drawOnCanvas.bind(_this);
return _this;
}
_createClass(CandlestickSeries, [{
key: "drawOnCanvas",
value: function drawOnCanvas(ctx, moreProps) {
_drawOnCanvas(ctx, this.props, moreProps);
}
}, {
key: "renderSVG",
value: function renderSVG(moreProps) {
var _props = this.props,
className = _props.className,
wickClassName = _props.wickClassName,
candleClassName = _props.candleClassName;
var xScale = moreProps.xScale,
yScale = moreProps.chartConfig.yScale,
plotData = moreProps.plotData,
xAccessor = moreProps.xAccessor;
var candleData = getCandleData(this.props, xAccessor, xScale, yScale, plotData);
return _react2.default.createElement(
"g",
{ className: className },
_react2.default.createElement(
"g",
{ className: wickClassName, key: "wicks" },
getWicksSVG(candleData)
),
_react2.default.createElement(
"g",
{ className: candleClassName, key: "candles" },
getCandlesSVG(this.props, candleData)
)
);
}
}, {
key: "render",
value: function render() {
var clip = this.props.clip;
return _react2.default.createElement(_GenericChartComponent2.default, {
clip: clip,
svgDraw: this.renderSVG,
canvasDraw: this.drawOnCanvas,
canvasToDraw: _GenericComponent.getAxisCanvas,
drawOn: ["pan"]
});
}
}]);
return CandlestickSeries;
}(_react.Component);
CandlestickSeries.propTypes = {
className: _propTypes2.default.string,
wickClassName: _propTypes2.default.string,
candleClassName: _propTypes2.default.string,
widthRatio: _propTypes2.default.number,
width: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.func]),
classNames: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string]),
fill: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string]),
stroke: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string]),
wickStroke: _propTypes2.default.oneOfType([_propTypes2.default.func, _propTypes2.default.string]),
yAccessor: _propTypes2.default.func,
clip: _propTypes2.default.bool
};
CandlestickSeries.defaultProps = {
className: "react-stockcharts-candlestick",
wickClassName: "react-stockcharts-candlestick-wick",
candleClassName: "react-stockcharts-candlestick-candle",
yAccessor: function yAccessor(d) {
return { open: d.open, high: d.high, low: d.low, close: d.close };
},
classNames: function classNames(d) {
return d.close > d.open ? "up" : "down";
},
width: _utils.plotDataLengthBarWidth,
wickStroke: "#000000",
// wickStroke: d => d.close > d.open ? "#6BA583" : "#FF0000",
fill: function fill(d) {
return d.close > d.open ? "#6BA583" : "#FF0000";
},
// stroke: d => d.close > d.open ? "#6BA583" : "#FF0000",
stroke: "#000000",
candleStrokeWidth: 0.5,
// stroke: "none",
widthRatio: 0.8,
opacity: 0.5,
clip: true
};
function getWicksSVG(candleData) {
var wicks = candleData.map(function (each, idx) {
var d = each.wick;
return _react2.default.createElement("path", { key: idx,
className: each.className,
stroke: d.stroke,
d: "M" + d.x + "," + d.y1 + " L" + d.x + "," + d.y2 + " M" + d.x + "," + d.y3 + " L" + d.x + "," + d.y4 });
});
return wicks;
}
function getCandlesSVG(props, candleData) {
/* eslint-disable react/prop-types */
var opacity = props.opacity,
candleStrokeWidth = props.candleStrokeWidth;
/* eslint-enable react/prop-types */
var candles = candleData.map(function (d, idx) {
if (d.width <= 1) return _react2.default.createElement("line", { className: d.className, key: idx,
x1: d.x, y1: d.y, x2: d.x, y2: d.y + d.height,
stroke: d.fill });else if (d.height === 0) return _react2.default.createElement("line", { key: idx,
x1: d.x, y1: d.y, x2: d.x + d.width, y2: d.y + d.height,
stroke: d.fill });
return _react2.default.createElement("rect", { key: idx, className: d.className,
fillOpacity: opacity,
x: d.x, y: d.y, width: d.width, height: d.height,
fill: d.fill, stroke: d.stroke, strokeWidth: candleStrokeWidth });
});
return candles;
}
function _drawOnCanvas(ctx, props, moreProps) {
var opacity = props.opacity,
candleStrokeWidth = props.candleStrokeWidth;
var xScale = moreProps.xScale,
yScale = moreProps.chartConfig.yScale,
plotData = moreProps.plotData,
xAccessor = moreProps.xAccessor;
// const wickData = getWickData(props, xAccessor, xScale, yScale, plotData);
var candleData = getCandleData(props, xAccessor, xScale, yScale, plotData);
var wickNest = (0, _d3Collection.nest)().key(function (d) {
return d.wick.stroke;
}).entries(candleData);
wickNest.forEach(function (outer) {
var key = outer.key,
values = outer.values;
ctx.strokeStyle = key;
ctx.fillStyle = key;
values.forEach(function (each) {
/*
ctx.moveTo(d.x, d.y1);
ctx.lineTo(d.x, d.y2);
ctx.beginPath();
ctx.moveTo(d.x, d.y3);
ctx.lineTo(d.x, d.y4);
ctx.stroke(); */
var d = each.wick;
ctx.fillRect(d.x - 0.5, d.y1, 1, d.y2 - d.y1);
ctx.fillRect(d.x - 0.5, d.y3, 1, d.y4 - d.y3);
});
});
// const candleData = getCandleData(props, xAccessor, xScale, yScale, plotData);
var candleNest = (0, _d3Collection.nest)().key(function (d) {
return d.stroke;
}).key(function (d) {
return d.fill;
}).entries(candleData);
candleNest.forEach(function (outer) {
var strokeKey = outer.key,
strokeValues = outer.values;
if (strokeKey !== "none") {
ctx.strokeStyle = strokeKey;
ctx.lineWidth = candleStrokeWidth;
}
strokeValues.forEach(function (inner) {
var key = inner.key,
values = inner.values;
var fillStyle = (0, _utils.head)(values).width <= 1 ? key : (0, _utils.hexToRGBA)(key, opacity);
ctx.fillStyle = fillStyle;
values.forEach(function (d) {
if (d.width <= 1) {
// <line className={d.className} key={idx} x1={d.x} y1={d.y} x2={d.x} y2={d.y + d.height}/>
/*
ctx.beginPath();
ctx.moveTo(d.x, d.y);
ctx.lineTo(d.x, d.y + d.height);
ctx.stroke();
*/
ctx.fillRect(d.x - 0.5, d.y, 1, d.height);
} else if (d.height === 0) {
// <line key={idx} x1={d.x} y1={d.y} x2={d.x + d.width} y2={d.y + d.height} />
/*
ctx.beginPath();
ctx.moveTo(d.x, d.y);
ctx.lineTo(d.x + d.width, d.y + d.height);
ctx.stroke();
*/
ctx.fillRect(d.x, d.y - 0.5, d.width, 1);
} else {
/*
ctx.beginPath();
ctx.rect(d.x, d.y, d.width, d.height);
ctx.closePath();
ctx.fill();
if (strokeKey !== "none") ctx.stroke();
*/
ctx.fillRect(d.x, d.y, d.width, d.height);
if (strokeKey !== "none") ctx.strokeRect(d.x, d.y, d.width, d.height);
}
});
});
});
}
/*
function getWickData(props, xAccessor, xScale, yScale, plotData) {
const { classNames: classNameProp, wickStroke: wickStrokeProp, yAccessor } = props;
const wickStroke = functor(wickStrokeProp);
const className = functor(classNameProp);
const wickData = plotData
.filter(d => isDefined(yAccessor(d).close))
.map(d => {
// console.log(yAccessor);
const ohlc = yAccessor(d);
const x = Math.round(xScale(xAccessor(d))),
y1 = yScale(ohlc.high),
y2 = yScale(Math.max(ohlc.open, ohlc.close)),
y3 = yScale(Math.min(ohlc.open, ohlc.close)),
y4 = yScale(ohlc.low);
return {
x,
y1,
y2,
y3,
y4,
className: className(ohlc),
direction: (ohlc.close - ohlc.open),
stroke: wickStroke(ohlc),
};
});
return wickData;
}
*/
function getCandleData(props, xAccessor, xScale, yScale, plotData) {
var wickStrokeProp = props.wickStroke;
var wickStroke = (0, _utils.functor)(wickStrokeProp);
var classNames = props.classNames,
fillProp = props.fill,
strokeProp = props.stroke,
yAccessor = props.yAccessor;
var className = (0, _utils.functor)(classNames);
var fill = (0, _utils.functor)(fillProp);
var stroke = (0, _utils.functor)(strokeProp);
var widthFunctor = (0, _utils.functor)(props.width);
var width = widthFunctor(props, {
xScale: xScale,
xAccessor: xAccessor,
plotData: plotData
});
/*
const candleWidth = Math.round(width);
const offset = Math.round(candleWidth === 1 ? 0 : 0.5 * width);
*/
var trueOffset = 0.5 * width;
var offset = trueOffset > 0.7 ? Math.round(trueOffset) : Math.floor(trueOffset);
// eslint-disable-next-line prefer-const
var candles = [];
for (var i = 0; i < plotData.length; i++) {
var d = plotData[i];
if ((0, _utils.isDefined)(yAccessor(d).close)) {
var x = Math.round(xScale(xAccessor(d)));
// const x = Math.round(xScale(xAccessor(d)) - offset);
var ohlc = yAccessor(d);
var y = Math.round(yScale(Math.max(ohlc.open, ohlc.close)));
var height = Math.round(Math.abs(yScale(ohlc.open) - yScale(ohlc.close)));
candles.push({
// type: "line"
x: x - offset,
y: y,
wick: {
stroke: wickStroke(ohlc),
x: x,
y1: Math.round(yScale(ohlc.high)),
y2: y,
y3: y + height, // Math.round(yScale(Math.min(ohlc.open, ohlc.close))),
y4: Math.round(yScale(ohlc.low))
},
height: height,
width: offset * 2,
className: className(ohlc),
fill: fill(ohlc),
stroke: stroke(ohlc),
direction: ohlc.close - ohlc.open
});
}
}
return candles;
}
exports.default = CandlestickSeries;
//# sourceMappingURL=CandlestickSeries.js.map