@coinspot-official/react-stockcharts
Version:
Highly customizable stock charts with ReactJS and d3
487 lines (403 loc) • 16.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
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 _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _propTypes = require("prop-types");
var _propTypes2 = _interopRequireDefault(_propTypes);
var _d3Force = require("d3-force");
var _d3Array = require("d3-array");
var _GenericChartComponent = require("../GenericChartComponent");
var _GenericChartComponent2 = _interopRequireDefault(_GenericChartComponent);
var _GenericComponent = require("../GenericComponent");
var _AxisZoomCapture = require("./AxisZoomCapture");
var _AxisZoomCapture2 = _interopRequireDefault(_AxisZoomCapture);
var _utils = require("../utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return 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 Axis = function (_Component) {
_inherits(Axis, _Component);
function Axis(props) {
_classCallCheck(this, Axis);
var _this = _possibleConstructorReturn(this, (Axis.__proto__ || Object.getPrototypeOf(Axis)).call(this, props));
_this.drawOnCanvas = _this.drawOnCanvas.bind(_this);
_this.saveNode = _this.saveNode.bind(_this);
_this.getMoreProps = _this.getMoreProps.bind(_this);
return _this;
}
_createClass(Axis, [{
key: "saveNode",
value: function saveNode(node) {
this.node = node;
}
}, {
key: "getMoreProps",
value: function getMoreProps() {
return this.node.getMoreProps();
}
}, {
key: "getCachedSizesKey",
value: function getCachedSizesKey() {
var _this2 = this;
var keyProps = ["tickPadding", "tickLabelFill", "tickStroke", "tickStrokeOpacity", "tickStrokeWidth", "orient", "showTickLabel", "fontSize", "fontFamily", "fontWeight", "showTicks", "flexTicks"];
return keyProps.map(function (prop) {
return _this2.props[prop];
}).join("-");
}
}, {
key: "getCachedSizes",
value: function getCachedSizes() {
var onGetTickLabelDimensions = this.props.onGetTickLabelDimensions;
if (onGetTickLabelDimensions) {
var cachedSizesKey = this.getCachedSizesKey();
if (this.cachedSizesKey !== cachedSizesKey) {
this.cachedSizesKey = cachedSizesKey;
this.cachedSizes = {};
}
}
return this.cachedSizes;
}
}, {
key: "drawOnCanvas",
value: function drawOnCanvas(ctx, moreProps) {
var _this3 = this;
var _props = this.props,
showDomain = _props.showDomain,
showTicks = _props.showTicks,
transform = _props.transform,
range = _props.range,
getScale = _props.getScale,
onGetTickLabelDimensions = _props.onGetTickLabelDimensions;
ctx.save();
ctx.translate(transform[0], transform[1]);
if (showDomain) drawAxisLine(ctx, this.props, range);
if (showTicks) {
var tickProps = tickHelper(this.props, getScale(moreProps));
var measureLabels = Boolean(onGetTickLabelDimensions);
this.cachedSizes = drawTicks(ctx, tickProps, this.getCachedSizes(), measureLabels);
ctx.restore();
if (measureLabels) {
var tickDimensions = Object.keys(this.cachedSizes).reduce(function (result, key) {
var size = _this3.cachedSizes[key];
return {
width: Math.max(result.width, size.width),
height: Math.max(result.height, size.height)
};
}, {
width: 0,
height: 0
});
onGetTickLabelDimensions(tickDimensions);
}
} else {
ctx.restore();
}
}
}, {
key: "render",
value: function render() {
var _props2 = this.props,
bg = _props2.bg,
axisZoomCallback = _props2.axisZoomCallback,
className = _props2.className,
zoomCursorClassName = _props2.zoomCursorClassName,
zoomEnabled = _props2.zoomEnabled,
getScale = _props2.getScale,
inverted = _props2.inverted;
var _props3 = this.props,
transform = _props3.transform,
getMouseDelta = _props3.getMouseDelta,
edgeClip = _props3.edgeClip;
var _props4 = this.props,
onContextMenu = _props4.onContextMenu,
onDoubleClick = _props4.onDoubleClick;
var zoomCapture = zoomEnabled ? _react2.default.createElement(_AxisZoomCapture2.default, {
bg: bg,
getScale: getScale,
getMoreProps: this.getMoreProps,
getMouseDelta: getMouseDelta,
axisZoomCallback: axisZoomCallback,
className: className,
zoomCursorClassName: zoomCursorClassName,
inverted: inverted,
onContextMenu: onContextMenu,
onDoubleClick: onDoubleClick
}) : null;
return _react2.default.createElement(
"g",
{ transform: "translate(" + transform[0] + ", " + transform[1] + ")" },
zoomCapture,
_react2.default.createElement(_GenericChartComponent2.default, { ref: this.saveNode,
canvasToDraw: _GenericComponent.getAxisCanvas,
clip: false,
edgeClip: edgeClip,
canvasDraw: this.drawOnCanvas,
drawOn: ["pan"]
})
);
}
}]);
return Axis;
}(_react.Component);
Axis.propTypes = {
innerTickSize: _propTypes2.default.number,
outerTickSize: _propTypes2.default.number,
tickFormat: _propTypes2.default.func,
tickPadding: _propTypes2.default.number,
tickSize: _propTypes2.default.number,
ticks: _propTypes2.default.number,
tickLabelFill: _propTypes2.default.string,
tickStroke: _propTypes2.default.string,
tickStrokeOpacity: _propTypes2.default.number,
tickStrokeWidth: _propTypes2.default.number,
tickStrokeDasharray: _propTypes2.default.oneOf(_utils.strokeDashTypes),
tickValues: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.func]),
tickInterval: _propTypes2.default.number,
tickIntervalFunction: _propTypes2.default.func,
showDomain: _propTypes2.default.bool,
showTicks: _propTypes2.default.bool,
className: _propTypes2.default.string,
axisZoomCallback: _propTypes2.default.func,
zoomEnabled: _propTypes2.default.bool,
inverted: _propTypes2.default.bool,
zoomCursorClassName: _propTypes2.default.string,
transform: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired,
range: _propTypes2.default.arrayOf(_propTypes2.default.number).isRequired,
getMouseDelta: _propTypes2.default.func.isRequired,
getScale: _propTypes2.default.func.isRequired,
bg: _propTypes2.default.object.isRequired,
edgeClip: _propTypes2.default.bool.isRequired,
onContextMenu: _propTypes2.default.func,
onDoubleClick: _propTypes2.default.func,
onGetTickLabelDimensions: _propTypes2.default.func
};
Axis.defaultProps = {
zoomEnabled: false,
zoomCursorClassName: "",
edgeClip: false
};
function tickHelper(props, scale) {
var orient = props.orient,
innerTickSize = props.innerTickSize,
tickFormat = props.tickFormat,
tickPadding = props.tickPadding,
tickLabelFill = props.tickLabelFill,
tickStrokeWidth = props.tickStrokeWidth,
tickStrokeDasharray = props.tickStrokeDasharray,
fontSize = props.fontSize,
fontFamily = props.fontFamily,
fontWeight = props.fontWeight,
showTicks = props.showTicks,
flexTicks = props.flexTicks,
showTickLabel = props.showTickLabel;
var tickArguments = props.ticks,
tickValuesProp = props.tickValues,
tickStroke = props.tickStroke,
tickStrokeOpacity = props.tickStrokeOpacity,
tickInterval = props.tickInterval,
tickIntervalFunction = props.tickIntervalFunction;
// if (tickArguments) tickArguments = [tickArguments];
var tickValues = void 0;
if ((0, _utils.isDefined)(tickValuesProp)) {
if (typeof tickValuesProp === "function") {
tickValues = tickValuesProp(scale.domain());
} else {
tickValues = tickValuesProp;
}
} else if ((0, _utils.isDefined)(tickInterval)) {
var _scale$domain = scale.domain(),
_scale$domain2 = _slicedToArray(_scale$domain, 2),
min = _scale$domain2[0],
max = _scale$domain2[1];
var baseTickValues = (0, _d3Array.range)(min, max, (max - min) / tickInterval);
tickValues = tickIntervalFunction ? tickIntervalFunction(min, max, tickInterval) : baseTickValues;
} else if ((0, _utils.isDefined)(scale.ticks)) {
tickValues = scale.ticks(tickArguments, flexTicks);
} else {
tickValues = scale.domain();
}
var baseFormat = scale.tickFormat ? scale.tickFormat(tickArguments) : _utils.identity;
var format = (0, _utils.isNotDefined)(tickFormat) ? baseFormat : function (d) {
return tickFormat(d) || "";
};
var sign = orient === "top" || orient === "left" ? -1 : 1;
var tickSpacing = Math.max(innerTickSize, 0) + tickPadding;
var ticks = void 0,
dy = void 0,
canvas_dy = void 0,
textAnchor = void 0;
if (orient === "bottom" || orient === "top") {
dy = sign < 0 ? "0em" : ".71em";
canvas_dy = sign < 0 ? 0 : fontSize * .71;
textAnchor = "middle";
ticks = tickValues.map(function (d) {
var x = Math.round(scale(d));
return {
value: d,
x1: x,
y1: 0,
x2: x,
y2: sign * innerTickSize,
labelX: x,
labelY: sign * tickSpacing
};
});
if (showTicks && flexTicks) {
// console.log(ticks, showTicks);
var nodes = ticks.map(function (d) {
return { id: d.value, value: d.value, fy: d.y2, origX: d.x1 };
});
var simulation = (0, _d3Force.forceSimulation)(nodes).force("x", (0, _d3Force.forceX)(function (d) {
return d.origX;
}).strength(1)).force("collide", (0, _d3Force.forceCollide)(22))
// .force("center", forceCenter())
.stop();
for (var i = 0; i < 100; ++i) {
simulation.tick();
} // console.log(nodes);
var zip = (0, _utils.zipper)().combine(function (a, b) {
if (Math.abs(b.x - b.origX) > 0.01) {
return _extends({}, a, {
x2: b.x,
labelX: b.x
});
}
return a;
});
ticks = zip(ticks, nodes);
}
} else {
ticks = tickValues.map(function (d) {
var y = Math.round(scale(d));
return {
value: d,
x1: 0,
y1: y,
x2: sign * innerTickSize,
y2: y,
labelX: sign * tickSpacing,
labelY: y
};
});
dy = ".32em";
canvas_dy = fontSize * .32;
textAnchor = sign < 0 ? "end" : "start";
}
return {
ticks: ticks, scale: scale, tickStroke: tickStroke,
tickLabelFill: tickLabelFill || tickStroke,
tickStrokeOpacity: tickStrokeOpacity,
tickStrokeWidth: tickStrokeWidth,
tickStrokeDasharray: tickStrokeDasharray,
dy: dy,
canvas_dy: canvas_dy,
textAnchor: textAnchor,
fontSize: fontSize,
fontFamily: fontFamily,
fontWeight: fontWeight,
format: format,
showTickLabel: showTickLabel,
tickSpacing: tickSpacing
};
}
function drawAxisLine(ctx, props, range) {
// props = { ...AxisLine.defaultProps, ...props };
var orient = props.orient,
outerTickSize = props.outerTickSize,
stroke = props.stroke,
strokeWidth = props.strokeWidth,
opacity = props.opacity;
var sign = orient === "top" || orient === "left" ? -1 : 1;
var xAxis = orient === "bottom" || orient === "top";
// var range = d3_scaleRange(xAxis ? xScale : yScale);
ctx.lineWidth = strokeWidth;
ctx.strokeStyle = (0, _utils.hexToRGBA)(stroke, opacity);
ctx.beginPath();
if (xAxis) {
ctx.moveTo((0, _utils.first)(range), sign * outerTickSize);
ctx.lineTo((0, _utils.first)(range), 0);
ctx.lineTo((0, _utils.last)(range), 0);
ctx.lineTo((0, _utils.last)(range), sign * outerTickSize);
} else {
ctx.moveTo(sign * outerTickSize, (0, _utils.first)(range));
ctx.lineTo(0, (0, _utils.first)(range));
ctx.lineTo(0, (0, _utils.last)(range));
ctx.lineTo(sign * outerTickSize, (0, _utils.last)(range));
}
ctx.stroke();
}
function drawTicks(ctx, result, cachedSizes, measureLabels) {
var tickStroke = result.tickStroke,
tickStrokeOpacity = result.tickStrokeOpacity,
tickLabelFill = result.tickLabelFill;
var textAnchor = result.textAnchor,
fontSize = result.fontSize,
fontFamily = result.fontFamily,
fontWeight = result.fontWeight,
ticks = result.ticks,
showTickLabel = result.showTickLabel;
ctx.strokeStyle = (0, _utils.hexToRGBA)(tickStroke, tickStrokeOpacity);
ctx.fillStyle = tickStroke;
// ctx.textBaseline = 'middle';
ticks.forEach(function (tick) {
drawEachTick(ctx, tick, result);
});
ctx.font = fontWeight + " " + fontSize + "px " + fontFamily;
ctx.fillStyle = tickLabelFill;
ctx.textAlign = textAnchor === "middle" ? "center" : textAnchor;
if (showTickLabel) {
return ticks.reduce(function (newCachedSizes, tick) {
var newSize = drawEachTickLabel(ctx, tick, result, cachedSizes, measureLabels);
return _extends({}, newCachedSizes, newSize);
}, {});
}
return cachedSizes;
}
function drawEachTick(ctx, tick, result) {
var tickStrokeWidth = result.tickStrokeWidth,
tickStrokeDasharray = result.tickStrokeDasharray;
ctx.beginPath();
ctx.moveTo(tick.x1, tick.y1);
ctx.lineTo(tick.x2, tick.y2);
ctx.lineWidth = tickStrokeWidth;
ctx.setLineDash((0, _utils.getStrokeDasharray)(tickStrokeDasharray).split(","));
ctx.stroke();
}
function drawEachTickLabel(ctx, tick, result, cachedSizes, measureLabels) {
var orient = result.orient,
canvas_dy = result.canvas_dy,
format = result.format,
fontSize = result.fontSize,
tickSpacing = result.tickSpacing;
var xAxis = orient === "bottom" || orient === "top";
var text = format(tick.value);
ctx.beginPath();
ctx.fillText(text, tick.labelX, tick.labelY + canvas_dy);
if (measureLabels) {
if (cachedSizes[text]) {
return {
text: cachedSizes[text]
};
} else {
var _ctx$measureText = ctx.measureText(text),
width = _ctx$measureText.width;
var widthSpacing = xAxis ? 0 : tickSpacing;
var heightSpacing = xAxis ? tickSpacing : 0;
return _defineProperty({}, text, {
width: widthSpacing + width,
height: heightSpacing + fontSize
});
}
} else {
return {};
}
}
exports.default = Axis;
//# sourceMappingURL=Axis.js.map