react-native-chart-kit
react-native-chart-kit copied to clipboard
Candle Stick chart Request
Feature request
This would be a great feature to add. If no one looks into that I'll try to implement this.
any news about candle charts? @vitorverasm
No news
Sorry, lately I've been so jammed with work. Hopefully someone take a look into that.
up
up
I made my own implementation of CandleStick chart by modifing the BarChart component (since I didn't need it in my project). It's wasn't that hard to implement, just a few lines of code. It aint worth a pull request since its barely customizable, but I can share a patch if anyone would like to try it.
Well, someone liked my comment, so here it is. The patch is meant for version 6.10.0 BarChart would expect an array of objects which contain keys: high, low, open, close, timestamp.
diff --git a/node_modules/react-native-chart-kit/dist/BarChart.js b/node_modules/react-native-chart-kit/dist/BarChart.js
index 429d7d9..85f9519 100644
--- a/node_modules/react-native-chart-kit/dist/BarChart.js
+++ b/node_modules/react-native-chart-kit/dist/BarChart.js
@@ -24,29 +24,110 @@ var __assign = (this && this.__assign) || function () {
};
import React from "react";
import { View } from "react-native";
-import { Defs, G, LinearGradient, Rect, Stop, Svg, Text } from "react-native-svg";
+import { Defs, G, LinearGradient, Rect, Stop, Svg, Text, Line } from "react-native-svg";
import AbstractChart from "./AbstractChart";
var barWidth = 32;
+
+function calcCandle({ data, width, height }) {
+ const count = data.length
+ const maxHighValue = Math.max(...data.map(e => e.high))
+ const minLowValue = Math.min(...data.map(e => e.low))
+ const pixelValue = (height) / (maxHighValue - minLowValue)
+ let singleBarWidth = (width / count)
+ if (singleBarWidth < 0) {
+ singleBarWidth = 1
+ }
+ return ({
+ pixelValue,
+ singleBarWidth,
+ minLowValue,
+ })
+}
+
var BarChart = /** @class */ (function (_super) {
__extends(BarChart, _super);
function BarChart() {
var _this = _super !== null && _super.apply(this, arguments) || this;
+ _this.dotsCoordinates = []
_this.getBarPercentage = function () {
var _a = _this.props.chartConfig.barPercentage, barPercentage = _a === void 0 ? 1 : _a;
return barPercentage;
};
_this.renderBars = function (_a) {
+ _this.dotsCoordinates = []
+ var candleData = _a.candleData || {}
var data = _a.data, width = _a.width, height = _a.height, paddingTop = _a.paddingTop, paddingRight = _a.paddingRight, barRadius = _a.barRadius, withCustomBarColorFromData = _a.withCustomBarColorFromData;
var baseHeight = _this.calcBaseHeight(data, height);
+ var chartYSize = _this.props.chartYSize
+ var candleCalculations = calcCandle({ data: candleData, width, height: chartYSize })
+
+ const {
+ pixelValue,
+ singleBarWidth,
+ minLowValue
+ } = candleCalculations
+
+ function scale(value) {
+ return Math.ceil((value - minLowValue) * pixelValue)
+ }
+
return data.map(function (x, i) {
- var barHeight = _this.calcHeight(x, data, height);
- var barWidth = 32 * _this.getBarPercentage();
- return (<Rect key={Math.random()} x={paddingRight +
- (i * (width - paddingRight)) / data.length +
- barWidth / 2} y={((barHeight > 0 ? baseHeight - barHeight : baseHeight) / 4) * 3 +
- paddingTop} rx={barRadius} width={barWidth} height={(Math.abs(barHeight) / 4) * 3} fill={withCustomBarColorFromData
- ? "url(#customColor_0_" + i + ")"
- : "url(#fillShadowGradient)"}/>);
+ let {
+ close,
+ open,
+ high,
+ low,
+ timestamp,
+ } = candleData[i] || {}
+
+ var barWidth = singleBarWidth;
+ const barSpacing = 1
+ let rectWidth = barWidth - barSpacing * 2
+
+ const lineStartX = i * (width) / data.length + barWidth / 2
+ const lineEndX = lineStartX
+ let rectStartX = (i * width) / data.length + barSpacing
+
+ let rectHeight = scale(Math.max(open, close)) - scale(Math.min(open, close))
+ let lineStartY = chartYSize - scale(high)
+ let lineEndY = chartYSize - scale(low)
+ let rectStartY = chartYSize - scale(Math.max(open, close))
+
+ const color = open < close ? '#34C800' : '#E05353'
+
+ _this.dotsCoordinates.push({
+ x: lineStartX,
+ y: lineStartY,
+ value: data[i]
+ })
+
+ if (rectHeight == 0) {
+ rectHeight = 1
+ rectStartY = lineStartY + 1
+ }
+
+ if (rectWidth <= 2) {
+ rectWidth = 3
+ rectStartX -= 0.5
+ }
+
+ return (
+ <Svg key={`${timestamp}_${i}`}>
+ <Line
+ x1={lineStartX}
+ y1={lineStartY}
+ x2={lineEndX}
+ y2={lineEndY}
+ stroke={color}
+ strokeWidth="1.5"
+ />
+ <Rect
+ x={rectStartX}
+ y={rectStartY}
+ width={rectWidth} height={rectHeight} fill={color}
+ />
+ </Svg>
+ )
});
};
_this.renderBarTops = function (_a) {
@@ -56,8 +137,7 @@ var BarChart = /** @class */ (function (_super) {
var barHeight = _this.calcHeight(x, data, height);
var barWidth = 32 * _this.getBarPercentage();
return (<Rect key={Math.random()} x={paddingRight +
- (i * (width - paddingRight)) / data.length +
- barWidth / 2} y={((baseHeight - barHeight) / 4) * 3 + paddingTop} width={barWidth} height={2} fill={_this.props.chartConfig.color(0.6)}/>);
+ (i * (width - paddingRight)) / data.length + 0} y={((baseHeight - barHeight) / 4) * 3 + paddingTop} width={barWidth} height={2} fill={_this.props.chartConfig.color(0.6)}/>);
});
};
_this.renderColors = function (_a) {
@@ -94,7 +174,7 @@ var BarChart = /** @class */ (function (_super) {
BarChart.prototype.render = function () {
var _a;
var _b = this.props, width = _b.width, height = _b.height, data = _b.data, _c = _b.style, style = _c === void 0 ? {} : _c, _d = _b.withHorizontalLabels, withHorizontalLabels = _d === void 0 ? true : _d, _e = _b.withVerticalLabels, withVerticalLabels = _e === void 0 ? true : _e, _f = _b.verticalLabelRotation, verticalLabelRotation = _f === void 0 ? 0 : _f, _g = _b.horizontalLabelRotation, horizontalLabelRotation = _g === void 0 ? 0 : _g, _h = _b.withInnerLines, withInnerLines = _h === void 0 ? true : _h, _j = _b.showBarTops, showBarTops = _j === void 0 ? true : _j, _k = _b.withCustomBarColorFromData, withCustomBarColorFromData = _k === void 0 ? false : _k, _l = _b.showValuesOnTopOfBars, showValuesOnTopOfBars = _l === void 0 ? false : _l, _m = _b.flatColor, flatColor = _m === void 0 ? false : _m, _o = _b.segments, segments = _o === void 0 ? 4 : _o;
- var _p = style.borderRadius, borderRadius = _p === void 0 ? 0 : _p, _q = style.paddingTop, paddingTop = _q === void 0 ? 16 : _q, _r = style.paddingRight, paddingRight = _r === void 0 ? 64 : _r;
+ var _p = style.borderRadius, borderRadius = _p === void 0 ? 0 : _p, _q = style.paddingTop, paddingTop = _q === void 0 ? 16 : _q, _r = style.paddingRight, paddingRight = 0;
var config = {
width: width,
height: height,
@@ -121,6 +201,9 @@ var BarChart = /** @class */ (function (_super) {
? this.renderHorizontalLines(__assign(__assign({}, config), { count: segments, paddingTop: paddingTop }))
: null}
</G>
+ <G>
+ {this.renderBars(__assign(__assign({}, config), { candleData: data.datasets[0].candleData, data: data.datasets[0].data, paddingTop: paddingTop, paddingRight: paddingRight, withCustomBarColorFromData: withCustomBarColorFromData }))}
+ </G>
<G>
{withHorizontalLabels
? this.renderHorizontalLabels(__assign(__assign({}, config), { count: segments, data: data.datasets[0].data, paddingTop: paddingTop, paddingRight: paddingRight }))
@@ -131,9 +214,6 @@ var BarChart = /** @class */ (function (_super) {
? this.renderVerticalLabels(__assign(__assign({}, config), { labels: data.labels, paddingRight: paddingRight, paddingTop: paddingTop, horizontalOffset: barWidth * this.getBarPercentage() }))
: null}
</G>
- <G>
- {this.renderBars(__assign(__assign({}, config), { data: data.datasets[0].data, paddingTop: paddingTop, paddingRight: paddingRight, withCustomBarColorFromData: withCustomBarColorFromData }))}
- </G>
<G>
{showValuesOnTopOfBars &&
this.renderValuesOnTopOfBars(__assign(__assign({}, config), { data: data.datasets[0].data, paddingTop: paddingTop, paddingRight: paddingRight }))}
It may not install on a latest version, but you can modify the module code directly. I suggest installing an addon for .patch
files syntax highlighting in your IDE so it is easier to read.