React chartsJS streaming live data - javascript

I am trying to build a React ChartsJS live data streaming using Chartjs i managed to render the canvas on the page but for some reason, I still can't make move like a live line chart data I am not sure if I need to embed anything to the HTML page. i install those packages: chart.js "chartjs-adapter-luxon": "^1.1.0 "chartjs-plugin-streaming": "^2.0.0"
I hope someone could help me!
import React from "react";
import { Line } from "react-chartjs-2";
import Chart from "chart.js/auto";
import { StreamingPlugin, RealTimeScale } from "chartjs-plugin-streaming";
Chart.register(StreamingPlugin, RealTimeScale);
export const IotChart = () => {
const data = {
datasets: [
{
label: "Dataset 1",
fill: false,
lineTension: 0.4,
backgroundColor: "#f44336",
borderColor: "#f44336",
borderJoinStyle: "miter",
pointRadius: 0,
showLine: true,
data: [] as any,
},
],
};
const options = {
scales: {
xAxes: [
{
type: "realtime",
realtime: {
onRefresh: function () {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100,
});
},
delay: 300,
refresh: 300,
},
},
],
yAxes: [
{
scaleLabel: {
display: true,
fontFamily: "Arial",
labelString: "Moment",
fontSize: 20,
fontColor: "#6c757d",
},
ticks: {
max: 100,
min: 0,
},
},
],
},
} as any;
return (
<div>
<div>
<Line data={data} options={options} width={400} height={200} />
</div>
</div>
);
};

This is because you define your scales as arrays instead of objects. This is changed in V3, for all the changes please read the migration guide because there are a lot more breaking changes, for example your Y axis scale label font declaration.
If you check the streaming documentation/examples you would also see that its defined as objects.
So changing to this will fix your issue:
scales: {
x: {
type: "realtime",
realtime: {
onRefresh: function() {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100,
});
},
delay: 300,
refresh: 300,
},
},
}

Related

How to use Real time chart in react?

I'm currently building a realtime chart to test it out. I wrote something to receive data as an example, but it doesn't work. Below is my code.
import { StreamingPlugin, ChartStreaming } from 'chartjs-plugin-streaming'
import {
Chart as ChartJS,
LinearScale,
CategoryScale,
RadialLinearScale,
BarElement,
PointElement,
LineElement,
ArcElement,
Legend,
Tooltip
} from 'chart.js'
import {
Chart,
Line,
Pie,
Doughnut,
Radar,
getDatasetAtEvent,
getElementAtEvent,
getElementsAtEvent,
} from 'react-chartjs-2'
ChartJS.register(
LinearScale,
RadialLinearScale,
CategoryScale,
BarElement,
PointElement,
LineElement,
ArcElement,
StreamingPlugin,
Legend,
Tooltip
)
const data =
{
datasets :
[
{
label : "real",
backgroundColor : "rgb(255, 99, 132)",
borderColor: "rgb(255, 99, 132)",
fill : false,
lineTension : 0,
borderDash: [8,4],
data : [],
showLine: true,
}
]
}
console.log(data.datasets[0].data)
const RealTime_ChartTest_options =
{
elements :
{
line :
{
tesion: 0.5
}
},
scales :
{
xAxes: [
{
type: "realtime",
realtime: {
onRefresh: function () {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100
}
);
},
delay: 300,
refresh: 300
}
}
],
yAxes: [
{
scaleLabel: {
display: true,
fontFamily: "Arial",
labelString: "Moment",
fontSize: 20,
fontColor: "#6c757d"
},
ticks: {
max: 100,
min: 0
}
}
]
}
}
const App = ()=>
{
retrun(
<Line data={data} options={RealTime_ChartTest_options} />
)
}
As a result, the Y-axis and labels are displayed correctly, but the values are not stored in the data in real time and the graph is not drawn.
What am I doing wrong in the code?
This is because your scale config is wrong, you are using V2 syntax while using V3, changing it to this should resolve the issue:
scales: {
x: {
type: "realtime",
realtime: {
onRefresh: function() {
data.datasets[0].data.push({
x: Date.now(),
y: Math.random() * 100
});
},
delay: 300,
refresh: 300
}
},
y: {
max: 100,
min: 0
}
}
For all changes please read the migration guide

Apache Echarts & Vue-ECharts - Pie charts animation not working on load

I have a simple doughnut/pie chart that is working fine, but I can not get the default animation, or any animation to work.
I'm using laravel 8, vuejs 2, and echarts / vue-echarts.
This is my vue component in /resopurces/js/components/popular-brands-chart.vue
<template>
<v-chart class="chart" :option="option" autoresize />
</template>
<script>
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { PieChart } from "echarts/charts";
import { TitleComponent, TooltipComponent, LegendComponent } from "echarts/components";
import VChart from "vue-echarts";
use([CanvasRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent]);
export default {
name: "mostpopularbrands",
components: {
VChart,
},
data() {
return {
option: {
animation: true,
backgroundColor: "#fefefe",
color: ["#AD5BA3", "#4EC0B1", "#F4A620", "#EE5969", "#528DCA"],
textStyle: {
fontFamily: "museo-sans",
fontWeight: "bold",
},
label: {
show: true,
color: "#fff",
},
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b} : {c} ({d}%)",
},
legend: {
orient: "vertical",
right: "15%",
top: "13%",
data: ["Titleist", "TaylorMade", "Callaway", "Ping", "Nike"],
icon: "circle",
padding: [5, 5],
itemGap: 15,
textStyle: {
fontFamily: "museo-sans",
fontWeight: "normal",
color: "#4C4C4C",
fontSize: "15",
},
},
series: [
{
name: "Most popular brands",
type: "pie",
animationType: "expansion",
animationDuration: 5000,
animationDurationUpdate: 500,
startAngle: 0,
endAngle: 360,
radius: [30, 95],
center: ["25%", "36%"],
label: {
formatter: function (d = "{d}") {
let rounderPercent = Math.round(d.percent);
return rounderPercent + "%";
},
position: "inside",
show: true,
},
data: [
{ value: 170, name: "Titleist" },
{ value: 100, name: "TaylorMade" },
{ value: 75, name: "Callaway" },
{ value: 50, name: "Ping" },
{ value: 37, name: "Nike" },
],
itemStyle: {
borderColor: "#fff",
borderWidth: 2,
},
},
],
},
};
},
};
</script>
<style scoped>
.chart {
margin-top: 2rem;
height: 300px;
width: 100%;
}
</style>
In the bootstrap.js file I have added this also but pretty sure it's not doing anything at the moment, and even when I did import it using the vue 3 examples nothing worked.
/* VueCompositionAPI */
import VueCompositionAPI from '#vue/composition-api'
Vue.use(VueCompositionAPI)
Technically, I should not have to do anything to get this to animate, no console errors. Here is a reference of what it should do :
https://echarts.apache.org/examples/en/editor.html?c=pie-doughnut
I can actually get this working via the CDN and codepen here, why it works, I have no clue :
https://codepen.io/marcgaumont/pen/OJWyZwe
This is the package used for vue:
https://github.com/ecomfe/vue-echarts
Everything works fine, but after 10 + hours trying to get this to animate, trying every example there is. I'm totally out of luck.
Any ideas ?

Two different x-axes using charts.js and react

I'm trying to create a chart component for weather in React using chart.js. I want two different x-axes with the temp above the chart, and the times below the chart. The data is correct in how I want it, I just want to use two different labels along the top and the bottom of the x-axes. How would I do this?
import React from "react";
import { Line } from "react-chartjs-2";
class WeatherOverview extends React.Component {
constructor(props) {
super(props);
this.state = {
chartData: {
labels: [
"15:00",
"18:00",
"21:00",
"00:00",
"03:00",
"06:00",
"09:00",
"12:00",
], //time
datasets: [
{
data: [18, 19, 18, 16, 15, 15, 16, 17, 18], //temp
},
],
},
};
}
render() {
return (
<div className="chart">
<Line
data={this.state.chartData}
options={{
scales: {
yAxes: [
{
gridLines: {
drawOnChartArea: false,
},
ticks: {
suggestedMin: 13, // lowest from data minus 2/3
display: false,
},
},
],
xAxes: [
{
gridLines: {
drawOnChartArea: false,
},
},
{ position: "top" },
],
},
}}
/>
</div>
);
}
}
export default WeatherOverview;
I want something like the google weather widget -
To match the Google Weather example with values floating over data points, what you really need is a plugin like chartjs-plugin-datalabels.
Install it via npm:
npm install chartjs-plugin-datalabels --save
Import:
import 'chartjs-plugin-datalabels';
And include it in your options object:
plugins: {
datalabels: {
display: true
}
}
This will add data labels on top of your data points. See the documentation for further information on how to customize the data labels.
I've made your chart look like the Google Weather chart with a couple other changes. Here's a full example using your data:
Some of the changes I made include:
Added datalabels plugin
Set colors accordingly
Set pointRadius to 0 on your dataset
Removed your extra X axis
On each axis, set drawBorder: false and tickMarkLength: 0
{
type: 'line',
data: {
labels: ['15:00', '18:00', '21:00', '00:00', '03:00', '06:00', '09:00', '12:00'], //time
datasets: [{
data: [18, 19, 18, 16, 15, 15, 16, 17, 18], //temp
backgroundColor: '#fff5cc',
borderColor: '#fc0',
pointRadius: 0,
}],
},
options: {
scales: {
yAxes: [{
gridLines: {
drawOnChartArea: false,
drawBorder: false,
tickMarkLength: 0,
},
ticks: {
suggestedMin: 13, // lowest from data minus 2/3
display: false
}
}],
xAxes: [{
gridLines: {
drawOnChartArea: false,
drawBorder: false,
tickMarkLength: 0,
},
ticks: {
fontColor: '#bababa',
}
}]
},
legend: {
display: false
},
layout: {
padding: {
top: 20
}
},
plugins: {
datalabels: {
align: 'top',
color: '#bababa',
font: {
weight: 'bold'
},
display: true,
},
},
}
}
This is my approach:
var chartData = {
labels: ['15:00', '18:00', '21:00', '00:00', '03:00', '06:00', '09:00', '12:00'],
datasets: [
{
fillColor: "#FFF5D7",
strokeColor: "#FFCC01",
data: [18, 19, 18, 16, 15, 15, 16, 17, 18]
}
]
};
var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
scaleOverride : true,
scaleSteps : 10,
scaleStepWidth : 3,
scaleStartValue : 0,
showTooltips: false,
onAnimationComplete: function () {
var ctx = this.chart.ctx;
ctx.font = this.scale.font;
ctx.fillStyle = this.scale.textColor
ctx.textAlign = "center";
ctx.textBaseline = "bottom";
this.datasets.forEach(function (dataset) {
dataset.points.forEach(function (points) {
ctx.fillText(points.value, points.x, 20);
});
})
}
});
https://jsfiddle.net/MartinGK/u4Lr8gzw/31/
Maybe it will help you get started.
I recommend to continue reading the documentation.

Chart.js Mouse Over Show Old Chart Data

I was having some problem when trying to redraw chart on canvas using chart.js in Angular. Here is my HTML component:
<div class="form-group">
<select [(ngModel)]="timeMode" id="timeModeInput" class="browser-default custom-select" (change)="onTimeModeChange($event)">
<option value="all" selected>Yearly</option>
<option value="monthly">Monthly</option>
</select>
</div>
<canvas id="expenseTimelineCanvas"></canvas>
Upon dropdown select, I repopulate the chart:
if (chart != null) { chart.destroy(); chart.clear(); }
chart = new Chart(chartName, {
type: "line",
data: {
labels: labels,
datasets: [
{
data: chartData,
borderColor: lineColor,
fill: false,
borderWidth: 1,
borderDash: [10, 10],
pointBackgroundColor: "white",
pointBorderColor: lineColor,
pointRadius: 5
}
]
}
}
});
However, when I mouse over at certain part of the canvas, the old chart will be displayed. Any ideas on how to totally destroy the canvas before replotting on the same DOM element?
Thanks!
this happens because chartjs uses canvas and for redrawing you just have to destroy old drawing from the canvas.
when you make a new chart then you have to destroy the old chart.
but in angular you can also just reload the component to destroy the chart
your method
//this method
initChart(){
//this will generate chart you need
//before generating just destroy the old chart
}
second method
//in html file
<thisIsHTMLTagOfChartComponent *ngIf="showChart">
</thisIsHTMLTagOfChartComponent>
//in typescript
public showChart = false;
//this function will be called everytime you fetch the data from server
getChartData(){
this.showChart = false; //this will remove the component from the page
fetchData(uri)
.then(result => {
//do your stuff here
this.showChart = true // this will load the component in the page again
}
)
i prefer to not destroy your chart just change the value of it for e.g: in your change function just load a new chart definition in your same chart with new config, we have 2 different configs:
config = {
type: 'bar',
data: {
labels: dringlichkeiten.map(x => x.id),
datasets: [
{
label: 'My Bar Chart',
data: dringlichkeiten.map(x => x.value),
backgroundColor: ['red', 'green', 'yellow', 'blue', 'orange']
}
]
},
}
config2 = {
type: 'line',
data: {
datasets: [{
label: 'Höhenlinie',
backgroundColor: "rgba(255, 99, 132,0.4)",
borderColor: "rgb(255, 99, 132)",
fill: true,
data: [
{ x: 1, y: 2 },
{ x: 2500, y: 2.5 },
{ x: 3000, y: 5 },
{ x: 3400, y: 4.75 },
{ x: 3600, y: 4.75 },
{ x: 5200, y: 6 },
{ x: 6000, y: 9 },
{ x: 7100, y: 6 },
],
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Höhenlinie'
},
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
ticks: {
userCallback: function (tick) {
if (tick >= 1000) {
return (tick / 1000).toString() + 'km';
}
return tick.toString() + 'm';
}
},
scaleLabel: {
labelString: 'Länge',
display: true,
}
}],
yAxes: [{
type: 'linear',
ticks: {
userCallback: function (tick) {
return tick.toString() + 'm';
}
},
scaleLabel: {
labelString: 'Höhe',
display: true
}
}]
}
}
}
chart: Chart ;
in your change function just load a new config:
change(){
this.chart = new Chart('canvas', this.config2)
}
DEMO.

Why ReactHighcharts SolidGauge's rounded is not working in react

I use react-highcharts to create a SolidGauge in my Dashboard Page.
and draw rounded edges.
So , I setting the plotOptions.rounded to true.
code:
import ReactHighcharts from 'react-highcharts';
import HighchartsMore from 'highcharts-more';
import SolidGauge from 'highcharts-solid-gauge';
HighchartsMore(ReactHighcharts.Highcharts);
SolidGauge(ReactHighcharts.Highcharts);
...
<ReactHighcharts config={ config }/>
config = {
...
plotOptions: {
solidgauge: {
dataLabels: {
enabled: false
},
linecap: 'round',
rounded: true,
stickyTracking: false
}
}
}
It is working in official jsfiddle with same config setting.
but ReactHighcharts is not working.
Does anyone have a suggestion or can help ?
Thank you for any help you can provide.
07/14 update
code:
import React, { Component } from 'react';
import ReactHighcharts from 'react-highcharts';
import HighchartsMore from 'highcharts-more';
import SolidGauge from 'highcharts-solid-gauge';
class Demo extends Component {
constructor (props) {
super(props);
HighchartsMore(ReactHighcharts.Highcharts);
SolidGauge(ReactHighcharts.Highcharts);
}
render () {
return (
<ReactHighcharts config={
multiChartsConfig(460,60,40,10,'Total','Sent')}></ReactHighcharts>
);
}
}
const multiChartsConfig = (value, open, click, placement, str1, str2) => {
return {
chart: {
type: 'solidgauge',
height: 180,
width: 185,
marginTop: 10,
marginBottom: 0,
style: { margin: 'auto' }
},
title: null,
pane: {
startAngle: 0,
endAngle: 360,
background: [
{
backgroundColor: '#D8D8D8',
outerRadius: '110%',
innerRadius: '100%',
borderWidth: 0
},{
backgroundColor: '#D8D8D8',
outerRadius: '93%',
innerRadius: '83%',
borderWidth: 0
},{
backgroundColor: '#D8D8D8',
outerRadius: '76%',
innerRadius: '66%',
borderWidth: 0
}
]
},
tooltip: {
enabled: false
},
// the value axis
yAxis: {
min: 0,
max: 100,
lineWidth: 0,
tickPositions: []
},
plotOptions: {
solidgauge: {
borderWidth: '34px',
dataLabels: {
enabled: true,
borderWidth: 0,
y: -30,
useHTML: true,
formatter: () => {
return (`
<div style="text-align: center;font-size:15px;color: #777777;">
<div style="color: #009fc5;font-size: 17px;">${value.toLocaleString()}</div><div>${str1}</div><div>${str2}</div>
</div>
`);
}
},
linecap: 'round',
rounded: true,
stickyTracking: false
}
},
credits: {
enabled: false
},
series: [
{
name: 'open',
rounded: true,
data: [{
color: '#009fc5',
radius: '110%',
innerRadius: '100%',
y: Math.round(open * 100)
}]
},
{
name: 'click',
data: [{
color: 'green',
radius: '93%',
innerRadius: '83%',
y: Math.round(click * 100)
}]
},
{
name: 'placement',
data: [{
color: 'red',
radius: '76%',
innerRadius: '66%',
y: Math.round(placement * 100)
}]
}
]
};
}
The problem is where you're getting the solid gauge extension from. The highcharts-solid-gauge package is massively out of date.
Use this instead
import SolidGauge from 'highcharts/modules/solid-gauge';
Version you're using (see https://npmcdn.com/highcharts-solid-gauge#latest) is v4.2.3
Where as the current version is v5.0.12 - https://code.highcharts.com/modules/solid-gauge.js
If you go to the official JSFiddle example you referenced, and change the solid-gauge script src to https://npmcdn.com/highcharts-solid-gauge#latest you'll see the same problem you're having.

Categories

Resources