i'm doing my first React Native app,
i'm using react-native-charts-wrapper to show graphs.
i have a listener for buttons (see code below comment // CHANGE ZOOM HERE) in my screen to set a predefined zoom in the graph that i'm showing.
How would i do that ?
Does anyone has any experience using that library ?
here is my screen:
import React, {Component} from 'react';
import {View, Text, StyleSheet, processColor} from 'react-native';
import { Button} from "native-base";
import {CombinedChart} from 'react-native-charts-wrapper';
import moment from 'moment';
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'stretch',
backgroundColor: 'transparent',
paddingTop:20
}
});
var InsulinShort = [];
var InsulinLong = [];
var glocuseTests = [];
const injectionsCount = 1000;
for (var i = 1; i < injectionsCount; i++) {
var random = Math.random();
if (random <= 0.7) {
var gloguseValue = Math.floor(Math.random() * 40) + 75;
var gloguseposition =Math.random();
glocuseTests.push({x:i+gloguseposition,y: gloguseValue, marker: "level: "+gloguseValue});
}
}
for (var i = 1; i < injectionsCount; i++) {
var random = Math.random();
if (random <= 0.15) {
var shortvalue = Math.floor(Math.random() * 16) + 1 ;
var shortPosition = Math.round(Math.random() * 100) / 100;
InsulinShort.push({x:i+shortPosition,y: shortvalue*20, marker: shortvalue+ " units of short insulin"});
}else if (random <= 0.3) {
var longePosition = Math.round(Math.random() * 10) / 10;
var longvalue = Math.floor(Math.random() * 16) + 1;
InsulinLong.push({x:i+longePosition,y: longvalue*20, marker: longvalue+ " units of long insulin"});
}else{
}
}
export default class LogGraph extends Component {
constructor() {
super();
// var valueFormatter = new Array(3515599953920);
this.state = {
loading: true,
days:1000,
legend: {
enabled: true,
textSize: 18,
form: 'SQUARE',
formSize: 18,
xEntrySpace: 10,
yEntrySpace: 5,
formToTextSpace: 5,
wordWrapEnabled: true,
maxSizePercent: 0.5
},
xAxis: {
valueFormatter: [
'01/04/18',
'02/04/18',
'03/04/18',
'04/04/18',
'05/04/18',
'06/04/18',
'07/04/18',
'08/04/18',
'09/04/18',
'10/04/18',
'11/04/18',
'12/04/18',
'13/04/18',
'14/04/18',
'15/04/18',
'16/04/18',
'17/04/18',
'18/04/18',
'19/04/18',
'20/04/18',
],
// valueFormatterPattern:'ssss',
// limitLines:100,
// drawLimitLinesBehindData:false,
// avoidFirstLastClipping: false,
textColor: processColor('#000'),
gridColor: processColor('#000'),
axisLineColor: processColor('#000'),
drawGridLines:true,
drawAxisLine:false,
drawLabels:true,
granularityEnabled: true,
// granularity:1515599953920,
granularity: 1,
// granularity: 131096 ,
position:'TOP',
textSize: 10,
labelRotationAngle:45,
gridLineWidth: 1,
axisLineWidth: 2,
gridDashedLine: {
lineLength: 10,
spaceLength: 10
},
centerAxisLabels:false,
},
yAxis: {
left: {
axisMinimum: 0,
axisMaximum: 400,
labelCount: 6,
labelCountForce: true,
granularityEnabled: true,
granularity: 5,
},
right: {
axisMinimum: 0,
axisMaximum: 20,
labelCount: 6, // 0 5 10 15 20 25 30
labelCountForce: true,
granularityEnabled: true,
granularity: 5,
}
},
marker: {
enabled: true,
markerColor: processColor('#F0C0FF8C'),
textColor: processColor('white'),
markerFontSize: 18,
},
data: {
barData: {
config: {
barWidth: 1 / 24 ,
},
dataSets: [{
values:InsulinLong,
label: 'Long Insulin',
config: {
drawValues: false,
colors: [processColor('#a2a4b2')],
}
},{
values:InsulinShort,
label: 'Short Insulin',
config: {
barShadowColor: processColor('red'),
highlightAlpha: 200,
drawValues: false,
colors: [processColor('#d0d5de')],
}
}]
},
lineData: {
dataSets: [{
values: glocuseTests,
label: 'Glucose Level',
config: {
drawValues: false,
colors: [processColor('#81d0fa')],
// mode: "CUBIC_BEZIER",
drawCircles: true,
lineWidth: 3,
}
}],
},
}
};
}
creatList(logs){
// var startTime = moment().millisecond();
var list = [];
var time = false;
if (logs) {
// console.log('firstLogDay',moment(firstLogDay).format('L'));
let gloguseItems = [];
let shortItems = [];
let longItems = [];
let firstValidFlag = false;
let firstLogTime;
let lastLogTime;
let days;
let firstLogDate;
let firstLogDayTime;
lastLogTime = logs[0].time;
for (var i = logs.length-1; i >= 0; i--) {
let item = logs[i];
if ( !firstValidFlag && ['glucose', 'long', 'short'].indexOf(item.type) >= 0 ) {
// debugger;
firstValidFlag = true;
firstLogTime = logs[i].time;
days = Math.round((lastLogTime-firstLogTime)/(1000*60*60*24));
firstLogDate = moment(firstLogTime).format('YYYY-MM-DD');
// console.log('firstLogDate',firstLogDate);
firstLogDayTime = new Date(firstLogDate);
firstLogDayTime = firstLogDayTime.getTime() - (2*60*60*1000);
// console.log('firstLogDayTime',firstLogDayTime);
}
if (firstValidFlag) {
let logX = ( item.time - firstLogDayTime ) / 1000 / 60 / 60 /24;
// logX = Math.round(logX * 10) / 10
if (logX) {
// logX = item.time;
// console.log(logX);
let logY = item.amount;
if (item.type !== 'glucose') {
if (item.type === 'short') {
shortItems.push({
x: logX,
y: logY*20,
marker: logY+ " units of short insulin" + moment(item.time).format('LLL')
})
}
if (item.type === 'long') {
longItems.push({
x: logX,
y: logY*20,
marker: logY+ " units of long insulin" + moment(item.time).format('LLL')
})
}
}else{
if(item.type === 'glucose'){
gloguseItems.push({
x: logX,
y: parseInt(logY),
marker: "level: "+ logY + moment(item.time).format('LLL')
})
}
}
}
}
}
let oldData = this.state.data;
oldData.lineData.dataSets[0].values = gloguseItems;
oldData.barData.dataSets[1].values = shortItems;
oldData.barData.dataSets[0].values = longItems;
let DayFlag = firstLogDate;
let valueFormatter = [];
valueFormatter.push(moment(DayFlag).format('DD/MM/YYYY'));
for (let i = 0; i < days; i++) {
DayFlag = moment(DayFlag).add(1, 'days');
valueFormatter.push(DayFlag.format('DD/MM/YYYY'));
}
let xAxis = this.state.xAxis;
xAxis.valueFormatter = valueFormatter;
this.setState({
data:oldData,
days:days,
xAxis:xAxis,
loading:false
});
}else{
this.setState({loading:false});
}
}
componentDidMount() {
this.creatList(this.props.logs);
}
zoomTwentyPressed() {
console.log ("pressed 25");
}
zoomFiftyPressed() {
console.log ("pressed 50");
}
zoomHundredPressed() {
console.log ("pressed 100");
// CHANGE ZOOM HERE
}
static displayName = 'Combined';
handleSelect(event) {
let entry = event.nativeEvent
if (entry == null) {
this.setState({...this.state, selectedEntry: null})
} else {
this.setState({...this.state, selectedEntry: JSON.stringify(entry)})
}
// console.log(event.nativeEvent)
}
render() {
return (
<View style={styles.container}>
{
(this.state.loading) ? <Text>Loading</Text>:
<CombinedChart
data={this.state.data}
xAxis={this.state.xAxis}
yAxis={this.state.yAxis}
legend={this.state.legend}
onSelect={this.handleSelect.bind(this)}
onChange={(event) => console.log(event.nativeEvent)}
marker={this.state.marker}
animation={{durationY: 1000,durationX: 1000}}
maxVisibleValueCount={16}
autoScaleMinMaxEnabled={true}
zoom={{scaleX: Math.floor(this.state.days/12), scaleY: 1, xValue: 4, yValue: 4, axisDependency: 'LEFT'}}
style={styles.container}/>
}
<View style={styles.buttonWrap}>
<Button block light onPress={this.zoomTwentyPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x100</Text>
</Button>
<Button block light onPress={this.zoomFiftyPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x50</Text>
</Button>
<Button block light onPress={this.zoomHundredPressed()} style={(this.state.view === 'graph')?styles.buttonStyleCurrent:styles.buttonStyle}>
<Text>x25</Text>
</Button>
</View>
</View>
);
}
}
I just put in the json format of options the prop dataZoom look this is my example
{
grafica: true,
option: {
title: {
text: ''
},
width: WIDTH - 100,
tooltip: {
trigger: 'axis'
},
xAxis: {
data: energiaV2.map(function (item) {
console.log(item.date, moment(item.date).format('hh:mm:ss'))
return moment(item.date).utc().calendar()//moment(item.date).utc().format('LL');//moment(item.date).utc().format('hh:mm:ss a');
}),
name: "dias",
nameLocation: 'middle',
nameGap: 30,
splitLine: {
show: false
}
},
yAxis: {
splitLine: {
show: false
},
name: "kWh",
nameLocation: 'middle',
},
/* toolbox: {
left: 'center',
feature: {
dataZoom: {
yAxisIndex: 'none'
},
restore: {},
}
}, */
dataZoom: [{
type: 'inside',
}, {
start: 5,
end: 10,
handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
handleWidth:30,
handleStyle: {
color: '#fff',
shadowBlur: 3,
shadowColor: 'rgba(0, 0, 0, 0.6)',
shadowOffsetX: 2,
shadowOffsetY: 2,
}
}],
series: [{
name: 'Activa kWh',
type: 'line',
data: energiaV2.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
{
name: 'Inductiva kVAr',
type: 'line',
data: energiaV2reactive.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
{
name: 'Capacitiva kVArhR',
type: 'line',
data: energiaV2inductive.map(function (item) {
return Math.floor(item.value * 100) / 100;
}),
},
],
color: ['rgb(253, 180, 59)', 'rgb(240, 94, 54)', 'rgb(0, 128, 35)']
},
grafica: true,
})
Related
I am using highcharts in React.
I want to implement a zoom-in/zoom-out function when displaying a lot of data, but I don't know how to implement mouse wheel zoom-in/zoom-out in React.
help.
import React, { useEffect, useRef, useState } from 'react';
import HighChartsReact from 'highcharts-react-official';
import HighCharts from 'highcharts';
const option = {
title: {
text: 'Monthly Average Temperature',
x: -20, // center
},
subtitle: {
text: 'Source: WorldClimate.com',
x: -20,
},
xAxis: {
/*
categories: ['Jan']
*/
},
yAxis: {
title: {
text: 'Temperature (°C)',
},
plotLines: [{
value: 0,
width: 1,
color: '#808080',
}],
},
tooltip: {
valueSuffix: '°C',
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0,
},
series: [{
name: 'Tokyo',
data: [],
}, {
name: 'New York',
data: [],
}, {
name: 'Berlin',
data: [],
}, {
name: 'London',
data: [],
}],
zoomType: 'x',
};
const HighChartTest = () => {
const chartComponentRef = useRef<HighChartsReact.RefObject>(null);
const [options, setoptions] = useState(option);
let now = new Date(1997, 9, 3);
let value = Math.random() * 1000;
const oneDay = 24 * 3600 * 1000;
const chartData: any = [1, 2, 3, 4, 5];
const chartData1: any = [1, 2, 3, 4, 5];
const chartData2: any = [1, 2, 3, 4, 5];
const chartData3: any = [1, 2, 3, 4, 5];
for (let i = 0; i < 10000; i++) {
chartData.push(randomRange(1, 100));
chartData1.push(randomRange(100, 1000));
chartData2.push(randomRange(1000, 2000));
chartData3.push(randomRange(2000, 5000));
}
function randomData(key: number) {
now = new Date(+now + oneDay);
value = Math.round(Math.random() * key);
return [ Math.round(value)];
}
function randomRange(n1:number, n2:number) {
return [Math.floor((Math.random() * (n2 - n1 + 1)) + n1)];
}
useEffect(() => {
chartComponentRef.current?.chart.series[0].setData(chartData);
chartComponentRef.current?.chart.series[1].setData(chartData1);
chartComponentRef.current?.chart.series[2].setData(chartData2);
chartComponentRef.current?.chart.series[3].setData(chartData3);
}, []);
return (
<div style={{ width: '100%', height: 500 }}>
<HighChartsReact
ref={chartComponentRef}
highcharts={HighCharts}
options={options}
/>
</div>
);
};
export default HighChartTest;
I don't know how to implement the mouse wheel zoom-in/zoom-out function. In js, you can use the code below, but in tsx, a callback error appears. Any solution?
(function(H) {
HighCharts.Chart.prototype.callbacks.push(function(chart) {
H.addEvent(chart.container, 'wheel', function(e) {
const xAxis = chart.xAxis[0],
extremes = xAxis.getExtremes(),
newMin = extremes.min;
console.log(extremes);
console.log(newMin);
if (e.deltaY < 0) {
xAxis.setExtremes(extremes.min - (extremes.min * 0.001), extremes.max, true);
} else {
xAxis.setExtremes(extremes.min + (extremes.min * 0.001), extremes.max, true);
}
});
});
}(HighCharts));
You can add the wheel Highcharts event on chart load and correctly type the function arguments. For example:
chart: {
events: {
load: function(this: Highcharts.Chart){
const chart = this;
Highcharts.addEvent(chart.container, 'wheel', function(e: WheelEvent) {
const xAxis = chart.xAxis[0],
extremes = xAxis.getExtremes(),
newMin = extremes.min;
console.log(extremes);
console.log(newMin);
if (e.deltaY < 0) {
xAxis.setExtremes(extremes.min - (extremes.min * 0.001), extremes.max, true);
} else {
xAxis.setExtremes(extremes.min + (extremes.min * 0.001), extremes.max, true);
}
});
}
}
}
Live demo: https://codesandbox.io/s/react-typescript-79dg6m?file=/src/App.tsx
API Reference: https://api.highcharts.com/highcharts/chart.events.load
I wanna show tooltips over the line not only on data points.
I also tried the chartjs-plugin-crosshair but it doesn't work in V3 of chartjs.
You can write a custom implementation for V3 for it:
// Options for the indicators
const indicatorOptions = {
radius: 4,
borderWidth: 1,
borderColor: 'red',
backgroundColor: 'transparent'
};
// Override getLabelAndValue to return the interpolated value
const getLabelAndValue = Chart.controllers.line.prototype.getLabelAndValue;
Chart.controllers.line.prototype.getLabelAndValue = function(index) {
if (index === -1) {
const meta = this.getMeta();
const pt = meta._pt;
const vScale = meta.vScale;
return {
label: 'interpolated',
value: vScale.getValueForPixel(pt.y)
};
}
return getLabelAndValue.call(this, index);
}
// The interaction mode
Chart.Interaction.modes.interpolate = function(chart, e, option) {
const x = e.x;
const items = [];
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
const meta = metas[i];
const pt = meta.dataset.interpolate({
x
}, "x");
if (pt) {
const element = new Chart.elements.PointElement({ ...pt,
options: { ...indicatorOptions
}
});
meta._pt = element;
items.push({
element,
index: -1,
datasetIndex: meta.index
});
} else {
meta._pt = null;
}
}
return items;
};
// Plugin to draw the indicators
Chart.register({
id: 'indicators',
afterDraw(chart) {
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
const meta = metas[i];
if (meta._pt) {
meta._pt.draw(chart.ctx);
}
}
},
afterEvent(chart, args) {
if (args.event.type === 'mouseout') {
const metas = chart.getSortedVisibleDatasetMetas();
for (let i = 0; i < metas.length; i++) {
metas[i]._pt = null;
}
args.changed = true;
}
}
})
var ctx = document.getElementById("myChart").getContext("2d");
var chart = new Chart(ctx, {
type: "line",
data: {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
fill: true,
label: "My First dataset",
backgroundColor: "rgba(132, 0, 0, 1)",
borderColor: "rgb(255, 99, 132)",
data: [0, 10, 5, 2, 20, 30, 45]
},
{
data: [30, 40, 50],
label: 'My Second Dataset',
fill: true,
backgroundColor: "lightgreen",
borderColor: "green"
}
]
},
options: {
interaction: {
mode: "interpolate",
intersect: false,
axis: "x"
},
plugins: {
tooltip: {
displayColors: false,
}
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
<h1>Interpolating line values</h1>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
The following combination of chartjs-plugin-crosshair and chart.js seems to be working fine for me.
"chart.js": "^3.4.0",
"chartjs-plugin-crosshair": "^1.2.0"
I am initiating the Chart object like below:
Chart.register(CrosshairPlugin);
Which can be used properly in an useEffect block:
useEffect(() =>
Chart.register(CrosshairPlugin);
return () => {
Chart.unregister(CrosshairPlugin);
};
}, []);
And then you can pass the options of the chart like below:
{
...,
options: {
plugins: {
crosshair: {
line: {
color: "#d1d1d1",
width: 1,
},
sync: {
enabled: true,
group: 1,
suppressTooltips: false,
},
zoom: {
enabled: false,
},
}
}
}
}
Note that the configurations above, will keep the crosshair pointer synced over all your charts rendered on the same component. You may need to change the behavior here.
you can use chartjs-plugin-crosshair
function generateDataset(shift, label, color) {
var data = [];
var x = 0;
while (x < 30) {
data.push({
x: x,
y: Math.sin(shift + x / 3)
});
x += Math.random();
}
var dataset = {
backgroundColor: color,
borderColor: color,
showLine: true,
fill: false,
pointRadius: 2,
label: label,
data: data,
lineTension: 0,
interpolate: true
};
return dataset;
}
var chart1 = new Chart(document.getElementById("chart").getContext("2d"), {
type: "scatter",
options: {
plugins: {
crosshair: {
sync: {
enabled: false
},
},
tooltip: {
animation: false,
mode: "interpolate",
intersect: false,
callbacks: {
title: function(a, d) {
return a[0].element.x.toFixed(2);
},
label: function(d) {
return (
d.chart.data.datasets[d.datasetIndex].label + ": " + d.element.y.toFixed(2)
);
}
}
}
},
scales: {
x: {
min: 2,
max: 28
}
}
},
data: {
datasets: [
generateDataset(0, "A", "red")
]
}
});
<script src="https://cdn.jsdelivr.net/npm/moment#2.27.0/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.4.0/dist/chart.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#0.1.1"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair#1.2.0/dist/chartjs-plugin-crosshair.min.js"></script>
<canvas id="chart" height="100"></canvas>
https://jsfiddle.net/Lb0k2sqx/1/
I am trying to alignment nodes, But I cant see any options how to do it,
Currently my code is
Highcharts.chart('container', {
chart: {
type: 'networkgraph',
plotBorderWidth: 1
},
title: {
text: 'Trans-Siberian Railway'
},
subtitle: {
text: 'Barnes-Hut approximation'
},
plotOptions: {
networkgraph: {
layoutAlgorithm: {
enableSimulation: false,
linkLength: 100,
integration: 'verlet',
approximation: 'barnes-hut',
gravitationalConstant: 4,
// Elastic like forces:
attractiveForce: function (d, k) {
return (k - d) / d;
},
/* repulsiveForce: function (d, k) {
return Math.min((k * k) / (d), 100);
} */
}
}
},
series: [{
marker: {
radius: 3,
lineWidth: 1
},
dataLabels: {
enabled: true,
linkFormatter: function () {
return '';
}
},
nodes: [
{
id: 'test',
marker: {
radius: 10
}
},
{
id: 'Moscow',
marker: {
radius: 10
}
}, {
id: 'Beijing',
marker: {
radius: 10
}
},
{
id: 'Brussels',
marker: {
radius: 10
}
},
{
id: 'Bangkok',
marker: {
radius: 10
}
}],
data: [
{ from: 'Bangkok', to: 'Beijing', color: 'blue' },
{ from: 'Moscow', to: 'Beijing', color: 'blue' },
{ from: 'test', to: 'Moscow', color: 'blue' },
{ from: 'Beijing', to: 'Brussels', color: 'blue' },
]
}]
});
the result of code is:
and its still not alignment the wanted results is
You should be able to set fixed positions in the networkgraph chart by using the initialPositions callback. To work it well you need also to set maxIterations to some small value, like 1.
See demo
initialPositions: function() {
var chart = this.series[0].chart,
width = chart.plotWidth,
height = chart.plotHeight;
this.nodes.forEach(function(node, i) {
if(i === 0){
node.plotX = 600;
node.plotY = 100;
}
if(i === 1) {
node.plotX = 350;
node.plotY = 100;
}
if(i === 2){
node.plotX = 200;
node.plotY = 0;
}
if(i === 3) {
node.plotX = 0;
node.plotY = 0;
}
if(i === 4) {
node.plotX = 200;
node.plotY = 200;
}
});
}
API: https://api.highcharts.com/highcharts/series.networkgraph.layoutAlgorithm.maxIterations
API: https://api.highcharts.com/highcharts/series.networkgraph.layoutAlgorithm.initialPositions
If you want to have those points not draggable, maybe an easier solution will be to render regular line chart?
Demo: https://jsfiddle.net/BlackLabel/06Lkgwbz/
So, I have been trying to use drill down to multiple levels, problem I am facing is that I couldn't drill down to the third level because the data will be fetched by ajax upon second drilldown's selection.
for example, refer to this link:
https://codepen.io/ajaymalhotra15/pen/aZpxXq
drilldown example
Here, the third level is possible because he has the data already, but mine will be depended on seconds selection.
So, how to make this happen, where am I supposed to call the ajax request and set the drill down series data dynamically?
EDIT:
Highcharts.chart("energy_chart", {
chart: {
type: "column",
spacingBottom: 15,
spacingTop: 10,
spacingLeft: 10,
spacingRight: 10,
backgroundColor: "#f2f2f2",
events: {
load: function() {
var fin = new Date();
var finDate = fin.getDate();
var finMonth = fin.getMonth();
var finYear = fin.getFullYear();
var ini = new Date();
ini.setFullYear(ini.getFullYear() - 1);
var iniDate = ini.getDate();
var iniMonth = ini.getMonth();
var iniYear = ini.getFullYear();
if (this.yAxis[0].dataMax == 0) {
this.yAxis[0].setExtremes(null, 1);
}
//this.yAxis.set
this.xAxis[0].setExtremes(
Date.UTC(iniYear, iniMonth, iniDate),
Date.UTC(finYear, finMonth, finDate)
);
},
drilldown: function(e) {
var charts_this = this;
var inidrillDate = new Date(e.point.x);
setTimeout(function() {
inidrillDate.setDate(0);
inidrillDate.setMonth(inidrillDate.getMonth());
var DateinidrillDate = inidrillDate.getDate();
var MonthinidrillDate = inidrillDate.getMonth();
var YearinidrillDate = inidrillDate.getFullYear();
var findrillDate = inidrillDate;
findrillDate.setMonth(findrillDate.getMonth() + 1);
findrillDate.setDate(findrillDate.getDate() - 1);
var DatefindrillDate = findrillDate.getDate();
var MonthfindrillDate = findrillDate.getMonth();
var YearfindrillDate = findrillDate.getFullYear();
charts_this.xAxis[0].setExtremes(
Date.UTC(
YearinidrillDate,
MonthinidrillDate,
DateinidrillDate
),
Date.UTC(
YearfindrillDate,
MonthfindrillDate,
DatefindrillDate
)
);
if (charts_this.yAxis[0].dataMax === 0) {
charts_this.yAxis[0].setExtremes(null, 1);
}
}, 0);
}
}
},
title: {
text: '<p className="energy_gen">Energy Generated</p>'
},
exporting: { enabled: false },
xAxis: {
type: "datetime",
labels: {
step: 1
},
dateTimeLabelFormats: {
day: "%e"
}
},
yAxis: {
title: {
text: "kWh"
}
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: "pointer",
dataLabels: {
enabled: true,
format: "{point.y}"
},
color: "#fcd562",
point:{
events:{
click:function(event){
if(this.options!=null){
var dayOfYear=new Date(this.x).getFullYear() +"-"+(new Date(this.x).getMonth()+1)+"-"+new Date(this.x).getDate();
var formatted_date = new Date(this.x).getDate() + " " + months[(new Date(this.x).getMonth())] +" "+ new Date(this.x).getFullYear();
// document.getElementById('chart_date_id').innerHTML = formatted_date; //setting modal title with current date
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
var sync_charts = $('.chart');
for (i = 0; i < sync_charts.length; i = i + 1) {
var chart_1 = sync_charts[i];
var chart_2 = chart_1.getAttribute('data-highcharts-chart');
chart=Highcharts.charts[chart_2];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
if (point) {
point.highlight(e);
}
}
});
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
Highcharts.Point.prototype.highlight = function (event) {
event = this.series.chart.pointer.normalize(event);
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(
e.min,
e.max,
undefined,
false,
{ trigger: 'syncExtremes' }
);
}
}
});
}
}
axios({
url: config.fvcstat,
method: "POST",
data: {
"customerId":self.props.location.state.detail.customerId,"rmsVendorId":self.props.location.state.detail.rmsVendorId,
"date":dayOfYear,
"powerType":self.props.location.state.detail.powerType
},
headers: {
"Content-Type": "application/json"
}
}).then((res)=>{
let activity = fvc.data;
if($('.chart')){
$('.chart').remove();
}
$.each(activity.datasets, function (i, dataset) {
console.log(1)
var chartDiv = document.createElement('div');
chartDiv.className = 'chart';
document.getElementById('container').appendChild(chartDiv);
Highcharts.chart(chartDiv,{
chart: {
},
plotOptions: {
series: {
marker:{
enabled:false
}
}
},
exporting: { enabled: false },
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair:{ width: 3},
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value}'
},categories: activity.xData
},
yAxis: {
title: {
text: null
}
},
series: [{
data: dataset
}],
tooltip: {
positioner: function () {
return {
x: this.chart.chartWidth - this.label.width,
y: 10 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
})
}
}
}
}
}
},
tooltip: {
formatter: function() {
if (this.point.options.drilldown) {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%b %Y", new Date(this.x))
);
} else {
return (
"Energy generated: <b> " +
this.y +
"</b> kWh " +
"<br>" +
Highcharts.dateFormat("%e %b %Y", new Date(this.x))
);
}
}
},
series: [{'data':obj.data,'name':obj.name,"color":"#4848d3"}],
drilldown: {
series: obj.data
}
});
So, here if you notice in plotoptions i am trying to create a whole new chart which is a synced line charts showing frquency, voltage and current.
But, i am guessing my approach is not correct as i am plotting a new highchart.
So, how do i make this synced line chart part of my drilldown.
let me know if you require any help in understanding.
I will suggest first minimize the plotoption. Then expand for further fuck up :P
Thanks.
You can put all your logic to get the third level data and to create a drilldown series in drilldown event:
chart: {
type: 'column',
events: {
drilldown: function(e) {
if (!thirdLevel.length) {
// get data
}
if (!e.seriesOptions) {
var chart = this,
drilldowns = {
'Animals': {
name: 'Animals',
data: [
['Cows', 2],
['Sheep', 3]
]
},
'Fruits': {
name: 'Fruits',
data: [
['Apples', 5],
['Oranges', 7],
['Bananas', 2]
]
},
'Cars': {
name: 'Cars',
data: [
['Toyota', 1],
['Volkswagen', 2],
['Opel', 5]
]
}
},
series = drilldowns[e.point.name];
chart.addSingleSeriesAsDrilldown(e.point, series);
chart.applyDrilldown();
}
}
}
}
Live demo : http://jsfiddle.net/BlackLabel/86v3L4ft/
API Reference: https://api.highcharts.com/highcharts/chart.events.drilldown
I'm implementing this example http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/samples/highcharts/boost/line-series-heavy-dynamic/ but with React.
import React from 'react'
import Highcharts from 'highcharts'
import HighchartsBoost from 'highcharts/modules/boost'
HighchartsBoost(Highcharts)
Highcharts.setOptions({
global: {
useUTC: false
}
});
class Plot extends React.Component {
constructor(props) {
super(props)
this.n = 20
this.s = 600
this.addPoint = this.addPoint.bind(this)
}
componentDidMount() {
var series = getSeries(this.n, this.s)
console.time('line');
this.chart = Highcharts.chart('hc-container', {
boost: {
enabled: true,
seriesThreshold: 1
},
chart: {
animation: false,
zoomType: 'x'
},
title: {
text: 'Highcharts drawing ' + (this.n * this.s) + ' points across ' + this.s + ' series'
},
navigator: {
xAxis: {
ordinal: false//,
},
yAxis: {
},
series: {
color: null
}
},
legend: {
enabled: false
},
xAxis: {
ordinal: false
},
yAxis: {
},
subtitle: {
text: 'Using the Boost module'
},
tooltip: {
valueDecimals: 2,
shared: false
},
series: series
});
console.timeEnd('line');
setInterval(this.addPoint, 1000);
}
addPoint() {
++this.n;
if (!this.chart.series) return
this.chart.series.forEach(se => {
var x = this.n
var y = 2 * Math.sin(x / 100) + Math.random()
//Yeah...
if (se.options.className === "highcharts-navigator-series") {
return;
}
se.addPoint([x, y], false, true, false);
// se.options.data.push([x, y]);
// se.options.data.shift();
// se.isDirty = true;
// se.isDirtyData = true;
});
this.chart.redraw();
}
render() {
return <div id='hc-container' />
}
}
export default Plot
function getData(n) {
var arr = [],
i;
for (i = 0; i < n; i = i + 1) {
arr.push([
i,
2 * Math.sin(i / 100) + Math.random()
]);
}
return arr;
}
function getSeries(n, s) {
var i = 0,
r = [];
for (; i < s; i++) {
r.push({
data: getData(n),
animation: false,
lineWidth: 2,
boostThreshold: 1,
turboThreshold: 1,
showInNavigator: true,
requireSorting: false
});
}
return r;
}
I don't think boost module is working this way because CPU goes very very high.
I their example (running in chrome) CPU is around 0.x
But in my implementation it goes to 120 most of the time.