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/
Related
I need the value of chart show after name of data for example ([colour of data] Car 50, [colour of data] Motorcycle 200). I've tried change the value of legend title but it doesn't work at all
Here is it my code:
var ctx = document.getElementById('top-five').getContext('2d');
var myChartpie = new Chart(ctx, {
type: 'pie',
data: {
labels: {!! $top->pluck('name') !!},
datasets: [{
label: 'Statistics',
data: {!! $top->pluck('m_count') !!},
backgroundColor: {!! $top->pluck('colour') !!},
borderColor: {!! $top->pluck('colour') !!},
}]
},
options: {
plugins: {
legend: {
display: true,
title: {
text: function(context) {//I've tried to override this but doesn't work
var value = context.dataset.data[context.dataIndex];
var label = context.label[context.dataIndex];
return label + ' ' + value;
},
}
},
},
responsive: true,
}
});
You can use a custom generateLabels function for this:
var options = {
type: 'doughnut',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
}]
},
options: {
plugins: {
legend: {
labels: {
generateLabels: (chart) => {
const datasets = chart.data.datasets;
return datasets[0].data.map((data, i) => ({
text: `${chart.data.labels[i]} ${data}`,
fillStyle: datasets[0].backgroundColor[i],
index: i
}))
}
}
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>
The below is a direct over ride of the default label generation found in the controller here. I have made one change on the text property within the generateLabels function in order to append the data value. It preserves the data toggling and strikethrough styling when a label is toggled.
plugins: {
legend: {
labels: {
generateLabels(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
const {labels: {pointStyle}} = chart.legend.options;
return data.labels.map((label, i) => {
const meta = chart.getDatasetMeta(0);
const style = meta.controller.getStyle(i);
return {
text: `${label}: ${data['datasets'][0].data[i]}`,
fillStyle: style.backgroundColor,
strokeStyle: style.borderColor,
lineWidth: style.borderWidth,
pointStyle: pointStyle,
hidden: !chart.getDataVisibility(i),
// Extra data used for toggling the correct item
index: i
};
});
}
return [];
}
},
onClick(e, legendItem, legend) {
legend.chart.toggleDataVisibility(legendItem.index);
legend.chart.update();
}
}
//...
}
[1]: https://github.com/chartjs/Chart.js/blob/master/docs/samples/legend/html.md
You can also use the base implementation to reduce the amount of copied code. Note that some chart types (like donut) already overrides the default label generation.
plugins: {
legend: {
labels: {
generateLabels: function (chart) {
return Chart.defaults.plugins.legend.labels.generateLabels(chart).map(function (label) {
var dataset = chart.data.datasets[label.datasetIndex];
var total = 0;
for (var j = 0; j < dataset.data.length; j++)
total += dataset.data[j].y;
label.text = dataset.label + ': ' + total;
return label;
});
}
}
}
}
I am working on the latest version of Chart.js, i.e., v3.7.1. However, I notice that most of the configurations have been changed from those of version 2.x. My problem is that I would like to draw a vertical line everytime there is a mouseover the chart, but not necessary having the mouse on the data points, but can be above or below, as long as the mouse point is in line with a data point, a verical line is drawn. This is clearly illustrated by this code on JSFiddle. I tried this Solution on this platform but it fails to work since it is based on ChartJS v2.6.0. Anyone with an idea of doing this? Here are my codes:
LineChart.js
import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';
const newOptions = {
responsive: true,
plugins: {
responsive: true,
title: {
display: true,
text: 'Weekly Logs'
},
},
scales: {
x: {
type: "time",
time: {
displayFormats: {
'day': 'dddd'
}
}
}
},
interaction: {
mode: "index",
axis: 'y'
}
};
const LineChart = ({ dataChart }) => {
return <Line
data={dataChart} options={newOptions}
/>;
};
export default LineChart;
You can use a custom plugin for this:
const plugin = {
id: 'corsair',
afterInit: (chart) => {
chart.corsair = {
x: 0,
y: 0
}
},
afterEvent: (chart, evt) => {
const {
chartArea: {
top,
bottom,
left,
right
}
} = chart;
const {
x,
y
} = evt.event;
if (x < left || x > right || y < top || y > bottom) {
chart.corsair = {
x,
y,
draw: false
}
chart.draw();
return;
}
chart.corsair = {
x,
y,
draw: true
}
chart.draw();
},
afterDatasetsDraw: (chart, _, opts) => {
const {
ctx,
chartArea: {
top,
bottom,
left,
right
}
} = chart;
const {
x,
y,
draw
} = chart.corsair;
if (!draw) {
return;
}
ctx.lineWidth = opts.width || 0;
ctx.setLineDash(opts.dash || []);
ctx.strokeStyle = opts.color || 'black'
ctx.save();
ctx.beginPath();
if (opts.vertical) {
ctx.moveTo(x, bottom);
ctx.lineTo(x, top);
}
if (opts.horizontal) {
ctx.moveTo(left, y);
ctx.lineTo(right, y);
}
ctx.stroke();
ctx.restore();
}
}
Chart.register(plugin)
const options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
borderColor: 'orange'
}
]
},
options: {
plugins: {
corsair: {
horizontal: false,
vertical: true,
color: 'red',
dash: [],
width: 2
}
}
},
}
const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>
For you to use this in react, you only need the Chart.register line like so:
import React from "react";
import Chart from 'chart.js/auto';
import { Line } from "react-chartjs-2";
import 'chartjs-adapter-moment';
const plugin = {
// Plugin code, see stack snipet above
}
Chart.register(plugin)
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 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,
})
I am trying to integrate spark line high chart in Angularjs nested UI grid. I have implemented Highcharts.SparkLine function within row expand event in UI grid. Is there any function like rowExpandComplete in Angular UiGrid?
gridApi.expandable.on.rowExpandedStateChanged($scope, function (row) {
if (row.isExpanded) {
var str = "10,12,45,34";
$scope.template = "<table id='table-sparkline'><tbody id='tbody-sparkline'><tr><td data-sparkline=" + str + "> </td> </tr> </tbody></table>";
row.entity.subGridOptions = {
columnDefs: [
{ name: 'name' },
{ name: 'gender', cellTemplate: $scope.template },
{ name: 'company' }
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json')
.success(function (data) {
row.entity.subGridOptions.data = data;
/**
* Create a constructor for sparklines that takes some sensible defaults and merges in the individual
* chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine').
*/
Highcharts.SparkLine = function (a, b, c) {
var hasRenderToArg = typeof a === 'string' || a.nodeName,
options = arguments[hasRenderToArg ? 1 : 0],
defaultOptions = {
chart: {
renderTo: (options.chart && options.chart.renderTo) || this,
backgroundColor: null,
borderWidth: 0,
type: 'area',
margin: [2, 0, 2, 0],
width: 120,
height: 20,
style: {
overflow: 'visible'
},
// small optimalization, saves 1-2 ms each sparkline
skipClone: true
},
title: {
text: ''
},
credits: {
enabled: false
},
xAxis: {
labels: {
enabled: false
},
title: {
text: null
},
startOnTick: false,
endOnTick: false,
tickPositions: []
},
yAxis: {
endOnTick: false,
startOnTick: false,
labels: {
enabled: false
},
title: {
text: null
},
tickPositions: [0]
},
legend: {
enabled: false
},
tooltip: {
backgroundColor: null,
borderWidth: 0,
shadow: false,
useHTML: true,
hideDelay: 0,
shared: true,
padding: 0,
positioner: function (w, h, point) {
return { x: point.plotX - w / 2, y: point.plotY - h };
}
},
plotOptions: {
series: {
animation: false,
lineWidth: 1,
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
marker: {
radius: 1,
states: {
hover: {
radius: 2
}
}
},
fillOpacity: 0.25
},
column: {
negativeColor: '#910000',
borderColor: 'silver'
}
}
};
options = Highcharts.merge(defaultOptions, options);
return hasRenderToArg ?
new Highcharts.Chart(a, options, c) :
new Highcharts.Chart(options, b);
};
var start = +new Date(),
$tds = $('td[data-sparkline]'),
fullLen = $tds.length,
n = 0;
// Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile
// can take some seconds, so we split the input into chunks and apply them in timeouts
// in order avoid locking up the browser process and allow interaction.
function doChunk() {
var time = +new Date(),
i,
len = $tds.length,
$td,
stringdata,
arr,
data,
chart;
for (i = 0; i < len; i += 1) {
$td = $($tds[i]);
stringdata = $td.data('sparkline');
arr = stringdata.split('; ');
data = $.map(arr[0].split(', '), parseFloat);
chart = {};
if (arr[1]) {
chart.type = arr[1];
}
$td.highcharts('SparkLine', {
series: [{
data: data,
pointStart: 1
}],
tooltip: {
headerFormat: '<span style="font-size: 10px">' + $td.parent().find('th').html() + ', Q{point.x}:</span><br/>',
pointFormat: '<b>{point.y}.000</b> USD'
},
chart: chart
});
n += 1;
// If the process takes too much time, run a timeout to allow interaction with the browser
if (new Date() - time > 500) {
$tds.splice(0, i + 1);
setTimeout(doChunk, 0);
break;
}
// Print a feedback on the performance
if (n === fullLen) {
$('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms');
}
}
}
doChunk();
});
}
});
But it is triggering only for second time when we expand the row. Can any one tell me where I am going wrong. I have created the plunker for the same.