I am trying to draw a chart fetching data from a Web Api. I can see some data is getting through but I still can not get the chart drawn. Pls let me know if I am doing something wrong.
import React, { Component } from 'react';
import './main.styles.scss';
import { createChart } from 'lightweight-charts';
async function getData() {
const response = await fetch(`http://localhost:3500/stock/app/RY`);
const data = await response.json();
return data.webApiData;
}
class Main extends Component {
ref = React.createRef();
componentDidMount() {
const chart = createChart(this.ref.current, {
width: 1400,
height: 550,
timeScale: {
timeVisible: true,
secondsVisible: false,
},
});
const candleSeries = chart.addCandlestickSeries();
const chartData = getData().then((data) => {
console.log(data);
candleSeries.setData(data);
});
}
render() {
return (
<div className="main">
<div className="trading">
<div className="box one">1</div>
<div className="box two" ref={this.ref}></div>
</div>
</div>
);
}
}
export default Main;
Here is the data on the console.log
Here is the error I am getting
It's because the format of the time attribute is not in the correct style.
It should be in YYYY-MM-DD style.
For example, you can try
const chartData = getData().then((data) => {
console.log(data);
candleSeries.setData(data.map((sD) => {
return {time: `${sD.time.year}-${sD.month > 9 ? sD.month : `0${sD.time.month}`}-${sD.day > 9 ? sD.day : `0${sD.day}`}`, ...sD}
}));
});
It is because time format is incorrect. It should be a date string.
From the candlestick chart docs:
Each item of the candlestick series is either an OHLC or a whitespace item.
So time must be in the following format.
const ohlcItem = {
time: '2018-06-25',
open: 10,
high: 12,
low: 9,
close: 11,
};
OR
// note it might be any type of series here
const series = chart.addHistogramSeries();
series.setData([
{ time: '2018-12-01', value: 32.51 },
{ time: '2018-12-02', value: 31.11 },
{ time: '2018-12-03', value: 27.02 },
{ time: '2018-12-04' }, // whitespace
{ time: '2018-12-05' }, // whitespace
{ time: '2018-12-06' }, // whitespace
{ time: '2018-12-07' }, // whitespace
{ time: '2018-12-08', value: 23.92 },
{ time: '2018-12-09', value: 22.68 },
{ time: '2018-12-10', value: 22.67 },
{ time: '2018-12-11', value: 27.57 },
{ time: '2018-12-12', value: 24.11 },
{ time: '2018-12-13', value: 30.74 },
]);
Related
I am working in Vue. My goal is create dynamic stepsize for timeline chart. Here my
TimelineChart.vue:
<template>
<div class="chart chart-timeline">
<ChartLegend
:items="legend"
:allowFilterCreation="allowFilterCreation"
#highlight="highlighted = $event"
#toggle="toggleDatasetVisibility($event)"
#apply-filter="$emit('apply-filter', $event)"
v-if="legend"/>
<div class="chart-container" v-show="hasData">
<canvas ref="chart"></canvas>
<hr> <hr> <hr> Stepsize Y
<input type="number" id ="ySteps">
<hr> Stepsize X
<input type="number" id ="xSteps">
</div>
<h2 class="subtitle is-5" v-if="!hasData">
No data
</h2>
</div>
</template>
<script>
import _ from "lodash";
import Chart from "chart.js";
import Moment from "moment";
import ChartLegend from "#/components/charts/ChartLegend";
import ChartMixin from "#/components/charts/ChartMixin";
import Deferred from "#/Deferred";
export default {
props: ["data", "multiMode", "labelConverter", "valueConverter", "allowFilterCreation"],
components: { ChartLegend },
mixins: [ChartMixin],
data() {
return {
chart: Deferred.create(),
highlighted: null
};
},
computed: {
timeline() {
return this.data ? _.map(this.data.parameter, it => new Moment(it)) : [];
},
keys() {
return this.data ? _.map(this.data.datasets, it => it.name) : [];
},
labels() {
const converter = this.labelConverter || _.identity;
return _.map(this.keys, converter);
},
datasets() {
return this.data ? _.map(this.data.datasets, it => it.data) : [];
},
datasetCount() {
return this.datasets.length;
},
legend() {
if (!this.multiMode) {
return null;
}
return _.zipWith(this.keys, this.labels, this.palette, (key, text, color) => ({
id: key,
text,
color: color.normal,
hidden: _.includes(this.hiddenDatasets, key)
}));
},
chartColors() {
const highlightIndex = this.highlighted !== null && !_.includes(this.hiddenDatasets, this.highlighted)
? _.indexOf(this.keys, this.highlighted)
: null;
const colors = [];
for (const index of _.keys(this.datasets)) {
const color = this.palette[index];
if (highlightIndex !== null) {
if (index == highlightIndex) {
colors.push({ backgroundColor: color.strongMuted, borderColor: color.strong });
} else {
colors.push({ backgroundColor: color.weakMuted, borderColor: color.weak });
}
} else {
colors.push({ backgroundColor: color.normalMuted, borderColor: color.normal });
}
}
return colors;
}
},
mounted() {
this.chart.resolve(new Chart(this.$refs.chart, {
type: "line",
data: {
datasets: [],
labels: []
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
xAxes: [{
type: "time",
time: {
isoWeekday: true,
displayFormats: {
hour: "HH:mm",
day: "DD-MM",
week: "DD-MM",
month: "MM-YYYY"
}
},
tooltips: {
},
ticks: { source: "labels",
// stepSize: 2
}
}],
yAxes: [{
ticks: { min: 0, precision: 0,
stepSize: 1
}
}]
},
spanGaps: false,
tooltips: {
callbacks: {
label: item => {
const converter = this.valueConverter || _.identity;
const label = this.multiMode ? (this.labels[item.datasetIndex] + ": ") : "";
return label + converter(this.datasets[item.datasetIndex][item.index]);
}
}
}
}
}));
// method that change stepsize
const ySteps = document.getElementById('ySteps');
ySteps.addEventListener('input', (e) => {
// eslint-disable-next-line no-undef
stepSize(this.$refs.chart, e)
});
function stepSize(chart) {
this.chart.resolve.scales.yAxes.stepSize = ySteps.value;
this.$refs.chart.update()
}
watch: {
data() {
this.resetDatasetVisibility();
}
}
}
</script>
When I alter stepsize nothing happen. In debug mode I have noticed the following pattern:
When I create chart 'this.chart' is not undefined. But when I use function stepSize I have an error, that this.chart is undefined. I have read a documentation about it, but I still do not understand how to connect to instance and change the property in the chart.
this.chart inside stepSize function will not be referring to the chart object inside your data node, because stepSize is not a vue compoenent method, its a javascript function. So this wont be refering to your vue scope.
Since you are already passing your chart object as a parameter to stepSize function as stepSize(this.$refs.chart, e), you can make use of the same inside your stepSize function like
function stepSize(chart) {
chart.resolve.scales.yAxes.stepSize = ySteps.value;
chart.update();
}
uplot is used to dislay timeseries data from VictoriaMetrics database.
For the backend Node-Red is used to forward and recieve the query with node-red-contrib-uibuilder.
It works basically and is very fast.
The problem is, when I try to zoom into the uplot graph, my browser (Chrome, Firefox, Edge) freezes. It seems to run out of memory.
Here are parts of my code, using svelte.
<script>
import { onMount } from "svelte";
import { query } from "../lib/uibStore";
import { transformToUplot } from "../lib/helper";
// import uPlot from "uplot";
import Browsebar from "../components/Browsebar.svelte";
import TimerangeSelect from "../components/TimerangeSelect.svelte";
let uplotdiv; //
let opts = {
title: "Temperaturen1",
id: "chart1",
class: "my-chart",
width: 1000,
height: 600,
series: [
{},
{
show: true, // initial toggled state (optional)
spanGaps: true,
label: "RT",
stroke: "red", // series style
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
{
show: true,
spanGaps: true,
label: "KT",
stroke: "green",
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
{
show: true,
spanGaps: true,
label: "VT",
stroke: "blue",
scale: "Temperature",
value: (self, rawValue) => rawValue.toFixed(1) + "°C",
},
],
scales: {
x: { time: true },
Temperature: {
auto: true,
// range: [-10, 20],
side: 3,
},
},
axes: [
{},
{
scale: "Temperature",
values: (self, ticks) => ticks.map((rawValue) => rawValue.toFixed(1) + "°C"),
},
],
cursor: { drag: { x: true, y: true } },
};
let plot; // = new uPlot(opts);
let uPlot;
let d = [[0], [0], [0], [0]];
let resolved = false;
$: uisend($query); //use uibilder.send, if query changes which occurs when timerange or nav index changes
//send a victoriametrics query to the backend, _q is part of query
function uisend(_q) {
// Example 'uvr_prozess_celsius{ort="1"}&start=-3d&step=60s'
uibuilder.send({ topic: "getVMetrics", payload: _q });
}
onMount(async () => {
uisend($query);
const uplotModule = await import("https://unpkg.com/uplot#1.6.22/dist/uPlot.esm.js");
uPlot = uplotModule.default;
plot = new uPlot(opts, [[0], [0], [0], [0]], uplotdiv);
});
uibuilder.onChange("msg", function (msg) {
// load Metrics via Node-Red's uibuilder, serverside
if (msg.topic === "getVMetrics") {
resolved = true;
if (msg.payload.data.result.length > 0) {
d = transformToUplot(msg.payload.data);
plot.setData(d);
}
}
});
</script>
<svelte:head>
<link rel="stylesheet" href="https://unpkg.com/uplot#1.6.22/dist/uPlot.min.css" />
</svelte:head>
<Browsebar>
<TimerangeSelect />
</Browsebar>
<hr />
<div bind:this={uplotdiv} />
{#if resolved}
<code>{$query}</code>
{:else}
<h4>lade Metriken... {$query}</h4>
{/if}
<hr />
Has anyone experienced freezing with uplot? What did you do?
Lucky me, I found the problem. It had to do with the way I transformed the victoriametrics data. On every timestamp I did Number(timestamp).toFixed(0). Without toFixed(0) it is working now. :)
//transform raw data from metrics query to the uplot format
export function transformToUplot(dt) {
let udata = []; //2d data array, conforming uPlot
let tsd = []; //timestamp array
//from first result take only the timestamps
for (let t of dt.result[0].values) {
// tsd.push(Number(t[0]).toFixed(0)); //this was bad!!!!, it lead to freezing
tsd.push(Number(t[0]));
}
udata.push(tsd);
//then the values
for (let r of dt.result) {
let sd = [];
for (let d of r.values) {
let val = Number(d[1]);
sd.push(val);
}
udata.push(sd);
}
return udata;
}
Thanks for your interest!
hi i want charting stock data in web page.
i found sample project in github
https://github.com/tvjsx/tvjs-xp
i change code and connect the binance and receive and charting real time data.
i have some problem after add online receive data chart lagend bouttun not work and i cant add layer.
please help me.
thanks
<trading-vue :data="dc" :width="this.width" :height="this.height"
title-txt="TVJS XP" :key="resetkey"
:chart-config="{DEFAULT_LEN:70}"
ref="tvjs"
:legend-buttons="['display', 'settings', 'up', 'down', 'add', 'remove']"
:toolbar="true"
:index-based="index_based"
:color-back="colors.colorBack"
:color-grid="colors.colorGrid"
:color-text="colors.colorText"
:extensions="ext"
:overlays="ovs"
:x-settings="xsett">
</trading-vue>
<span class="gc-mode">
<input type="checkbox" v-model="index_based">
<label>Index Based</label>
</span>
export default {
name: 'DataHelper',
icon: '⚡',
description: 'Real-time updates. Play with DataCube in the console',
props: ['night', 'ext', 'resetkey'],
components: {
TradingVue
},
mounted() {
window.addEventListener('resize', this.onResize)
this.onResize()
// Load the last data chunk & init DataCube:
let now = Utils.now()
this.load_chunk([now - Const.HOUR4, now]).then(data => {
this.dc = new DataCube({
ohlcv: data['dc.data'],
// onchart: [{
// type: 'EMAx6',
// name: 'Multiple EMA',
// data: []
// }],
offchart: [
// {
// type: 'BuySellBalance',
// name: 'Buy/Sell Balance, $lookback',
// data: [],
// settings: {}
// },
{
name: "RSI, 20",
type: "Range",
data: [],
settings: {
"upper": 70,
"lower": 30,
"backColor": "#9b9ba316",
"bandColor": "#666"
}
},
],
datasets: [{
type: 'Trades',
id: 'binance-btcusdt',
data: []
}]
}, { aggregation: 100 })
// Register onrange callback & And a stream of trades
this.dc.onrange(this.load_chunk)
this.$refs.tvjs.resetChart()
this.stream = new Stream(WSS)
this.stream.ontrades = this.on_trades
window.dc = this.dc // Debug
window.tv = this.$refs.tvjs // Debug
})
},
methods: {
onResize(event) {
this.width = window.innerWidth
this.height = window.innerHeight - 50
},
// New data handler. Should return Promise, or
// use callback: load_chunk(range, tf, callback)
async load_chunk(range) {
let [t1, t2] = range
let x = 'BTCUSDT'
let q = `${x}&interval=1m&startTime=${t1}&endTime=${t2}`
let r = await fetch(URL + q).then(r => r.json())
return this.format(this.parse_binance(r))
},
// Parse a specific exchange format
parse_binance(data) {
if (!Array.isArray(data)) return []
return data.map(x => {
for (var i = 0; i < x.length; i++) {
x[i] = parseFloat(x[i])
}
return x.slice(0,6)
})
},
format(data) {
// Each query sets data to a corresponding overlay
return {
'dc.data': data
// other onchart/offchart overlays can be added here,
// but we are using Script Engine to calculate some:
// see EMAx6 & BuySellBalance
}
},
on_trades(trade) {
this.dc.update({
t: trade.T, // Exchange time (optional)
price: parseFloat(trade.p), // Trade price
volume: parseFloat(trade.q), // Trade amount
'datasets.binance-btcusdt': [ // Update dataset
trade.T,
trade.m ? 0 : 1, // Sell or Buy
parseFloat(trade.q),
parseFloat(trade.p)
],
// ... other onchart/offchart updates
})
}
},
beforeDestroy() {
window.removeEventListener('resize', this.onResize)
if (this.stream) this.stream.off()
},
computed: {
colors() {
return this.$props.night ? {} : {
colorBack: '#fff',
colorGrid: '#eee',
colorText: '#333'
}
},
},
data() {
return {
dc: {},
width: window.innerWidth,
height: window.innerHeight,
index_based: false,
xsett: {
'grid-resize': { min_height: 30 }
},
ovs: Object.values(Overlays),
}
}
}
So I have ChartData Component. I am taking the data from an API, the data is being displayed through Chart. I have determine Format Logic, which it's the main thing is to determine the time of the data, I have 3 buttons, the thing that I am struggling to achieve is when let's say I wanna see the data of 7days when I press the button. I can see data is changing in the yAxes but I can't see time being changed on thexAxes, it's still set to hours, it should display the days.
ChartData
import React, { useRef, useEffect, useState } from "react";
import 'chartjs-adapter-moment';
import annotationPlugin from 'chartjs-plugin-annotation';
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables);
Chart.register(annotationPlugin);
const determineTimeFormat = (
timeFormat: string,
day: any,
week: any,
year: any
) => {
switch (timeFormat) {
case "24h":
return day;
case "7d":
return week;
case "1y":
return year;
default:
return day;
}
};
interface Props {
data: any
}
const ChartData: React.FC<Props> = ({ data }) => {
const chartCanvasRef = useRef<HTMLCanvasElement | null>(null);
const { day, week, year, detail } = data;
const [timeFormat, setTimeFormat] = useState("24h");
const [isRebuildingCanvas, setIsRebuildingCanvas] = useState(false);
useEffect(() => {
setIsRebuildingCanvas(true);
}, [timeFormat]);
useEffect(() => {
if (isRebuildingCanvas) {
setIsRebuildingCanvas(false);
}
}, [isRebuildingCanvas]);
useEffect(() => {
if (chartCanvasRef && chartCanvasRef.current && detail) {
const chartCanvas = chartCanvasRef.current
if (isRebuildingCanvas || !chartCanvas) {
return;
}
const chartInstance = new Chart(chartCanvasRef.current, {
type: "line",
data: {
datasets: [
{
label: `${detail.name} price`,
data: determineTimeFormat(timeFormat, day, week, year),
backgroundColor: "rgba(134,159,152, 1)",
borderColor: "rgba(174, 305, 194, 0.4",
},
],
},
Options
options: {
plugins: {
annotation: {
annotations: {
}
}
},
animations: {
tension: {
duration: 1000,
easing: 'linear',
from: 1,
to: 0,
loop: true
}
},
maintainAspectRatio: false,
responsive: true,
scales: {
x:
{
type: 'time',
},
},
}
});
return () => {
chartInstance.destroy();
}
}}, [day, isRebuildingCanvas,timeFormat, week, year, detail]);
Rest of the Component
return (
<div className='chart__container'>
{renderPrice()}
{isRebuildingCanvas ? undefined : (
<canvas ref={chartCanvasRef} width={250} height={250} id='myChart'></canvas>
)}
<button className='time__format' onClick={() => setTimeFormat("24h")}>24h</button>
<button className='time__format' onClick={() => setTimeFormat("7d")}>7d</button>
<button className='time__format' onClick={() => setTimeFormat("1y")}>1y</button>
</div>
);
};
export default ChartData;
I have created a similar working example without reactjs. This can be useful for you to understand. You can refer the fiddle as well. A limitation that am currently facing is if there is data more than 100 then am getting errors while updating the data, performed slicing of data upto 100 to make it working.
var coinData = {};
var fetchData = async() => {
api = "https://api.coingecko.com/api/v3";
id = "bitcoin";
var [day1, week1, year1, detail1] = await Promise.all([
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=1`).then(data => {
return data.json()
}),
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=7`).then(data => {
return data.json()
}),
fetch(api + `/coins/${id}/market_chart/?vs_currency=usd&days=365`).then(data => {
return data.json()
}),
fetch(api + `/coins/markets/?vs_currency=usd&ids=${id}`).then(data => {
return data.json()
})
]);
coinData = {
day: formatData(day1.prices).slice(0, 100),
week: formatData(week1.prices).slice(0, 100),
year: formatData(year1.prices).slice(0, 100),
detail: detail1[0]
}
}
const formatData = (data) => {
return data.map((el) => {
return {
t: el[0],
y: el[1].toFixed(2)
};
});
};
const determineTimeFormat = (timeFormat) => {
switch (timeFormat) {
case "24h":
return coinData.day;
case "7d":
return coinData.week;
case "1y":
return coinData.year;
default:
return coinData.day;
}
};
var chartInstance;
fetchData().then(() => {
/* console.log(coinData); */
var ctx = document.getElementById('chartJSContainer');
chartInstance = new Chart(ctx, {
type: "line",
labels: false,
data: {
datasets: [{
label: `${coinData.detail.name} price`,
data: determineTimeFormat('1d'),
parsing: {
yAxisKey: 'y',
xAxisKey: 't',
},
backgroundColor: "rgba(134,159,152, 1)",
borderColor: "rgba(174, 305, 194, 0.4)"
}],
},
options: {
scales: {
x: {
ticks: {
source: "data"
},
type: 'time',
time: {
unit: "day"
}
}
},
}
});
});
function setTimeFormat(format) {
Chart.instances[0].data.datasets[0].data = determineTimeFormat(format);
Chart.instances[0].update();
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.3.1/dist/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#1.0.0/dist/chartjs-adapter-moment.min.js"></script>
<body>
<button className='time__format' onclick="setTimeFormat( '24h')">24h</button>
<button className='time__format' onclick="setTimeFormat( '7d')">7d</button>
<button className='time__format' onclick="setTimeFormat( '1y')">1y</button><br><br>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
</body>
Introduction:
I have a ApexCharts chart with data from an API. I'm using an API called finnhub to get the stock market data which is displayed on the chart. The data returned has an array of prices and a corresponding array of times, which are not at an equal interval (stock market is closed at certain times) (prices on the y-axis and time on the x-axis). The data I'm getting is quite high resolution, which means there are a LOT of labels on the x-axis, making it look really cluttered and unreadable. I'm using React Hooks.
The problem I'm getting:
X-axis labels are too close together (image)
As you can see, the labels on the on the x-axis which are displaying the time, are really close together. It looks too cluttered. I want to make it so that there are only about 4-5 labels on the chart which are spaced out evenly across.
Code:
import React, { useState, useEffect } from "react";
import Chart from "react-apexcharts";
import axios from "axios";
import dayjs from "dayjs";
function StockChart() {
const [options, setOptions] = useState({
chart: {
type: "area",
height: 350,
zoom: {
enabled: false
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: "straight"
},
xaxis: {
categories: [],
labels: {
formatter: function (val) {
return dayjs(val).format("DD. HH:mm");
},
hideOverlappingLabels: Boolean,
rotate: 0,
trim: false
},
axisTicks: {
autoskip: true,
maxTicksLimit: 4,
interval: 3
}
},
tooltip: {
x: {
format: "dd MMM yyyy"
}
},
fill: {
type: "gradient",
gradient: {
shadeIntensity: 1,
opacityFrom: 0.7,
opacityTo: 0.9,
stops: [0, 100]
}
}
});
const [series, setSeries] = useState([
{
name: "Closing Price",
data: []
}
]);
useEffect(() => {
axios
.get(
"https://finnhub.io/api/v1/stock/candle?symbol=AAPL&resolution=60&from=1572100000&to=1572910590"
)
.then(res => {
setSeries(prev => {
prev[0].data = res.data.c.map(val => val);
return prev;
});
setOptions(prev => {
prev.xaxis.categories = res.data.t.map(time => time * 1000);
return prev;
});
})
.catch(err => console.log(err));
});
// Ignore the below function and state, it's just for testing
const [disableChart, setDisableChart] = useState(false);
function toggleChart() {
setDisableChart(prev => !prev);
}
return (
<div className="chart-container">
<h1 onClick={toggleChart}>my chart</h1>
{disableChart ? null : (
<Chart options={options} series={series} type="area" width="50%" />
)}
</div>
);
}
export default StockChart;
What I've tried:
I've tried messing around with the ticks property. There was no effect. I've tried setting it to a type: "numeric" and type: "datetime" chart but that caused the following effect:
Irregular data intervals(image)
The x-axis labels are now spaced perfectly, but the problem now is that the data on the chart isn't evenly spaced. As you can see, the data interval between 5:50 and 5:55 is very large, unlike the data interval right above 5:55. I want the data interval of the chart to be equal in all places, like in the first image.
Code:
import React, { useState, useEffect } from "react";
import Chart from "react-apexcharts";
import axios from "axios";
import dayjs from "dayjs";
function StockChart() {
const [options, setOptions] = useState({
chart: {
type: "area",
height: 350,
zoom: {
enabled: false
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: "straight"
},
xaxis: {
type: "numeric",
labels: {
formatter: function (val) {
return dayjs(val).format("DD. HH:mm");
},
hideOverlappingLabels: Boolean,
rotate: 0,
trim: false
},
axisTicks: {
show: true
}
},
tooltip: {
x: {
format: "dd MMM yyyy"
}
},
fill: {
type: "gradient",
gradient: {
shadeIntensity: 1,
opacityFrom: 0.7,
opacityTo: 0.9,
stops: [0, 100]
}
}
});
const [series, setSeries] = useState([
{
name: "Closing Price",
data: []
}
]);
useEffect(() => {
axios
.get(
"https://finnhub.io/api/v1/stock/candle?symbol=AAPL&resolution=60&from=1572100000&to=1572910590"
)
.then(res => {
setSeries(prev => {
for (let i = 0; i < res.data.c.length; i++) {
console.log(res.data.t[i]);
prev[0].data[i] = [res.data.t[i], res.data.c[i]];
}
console.log(prev);
return prev;
});
})
.catch(err => console.log(err));
});
// Ignore the below function and state, it's just for testing
const [disableChart, setDisableChart] = useState(false);
function toggleChart() {
setDisableChart(prev => !prev);
}
return (
<div className="chart-container">
<h1 onClick={toggleChart}>my chart</h1>
{disableChart ? null : (
<Chart options={options} series={series} type="area" width="50%" />
)}
</div>
);
}
export default StockChart;
What I want to achieve:
I want to have the data labels on the x-axis be similar to the ones like in the second picture (not too cluttered, only about 4-5 labels per chart), while having the chart itself look like the second picture (distance between data changes is equal). Any help would be greatly appreaciated.
PS: This is my first StackOverflow question, sorry if I did something incorrectly.
Well, I faced the same problem but in vue-project. So this helped to me:
methods: {
onChartResize(event) {
this.$refs.oilProductionProfile.updateOptions({
xaxis: { tickAmount: Math.ceil(event.srcElement.innerWidth / 140) },
});
},
},
created() {
window.addEventListener("resize", this.onChartResize);
},
destroyed() {
window.removeEventListener("resize", this.onChartResize);
},
We subscribing on window event, recalculating tickAmount according to current window's innerwidth, and then calling "updateOptions" to refresh axis.