Repeated animations with eCharts - javascript

I'm using eCharts to plot some scatterplots. I have several data series, and what I want is for each one to sequentially appear following an animation of my choice. What's happening instead is that the first series animates by my choice, but the subsequent ones revert to the default animation, even though (as far as I can see) I'm still defining the animation for them.
Following is the shortest complete example I can make ...
var chartOptions = function(seriesData) {
let option = {
xAxis: {
min: 0,
max: 11
},
yAxis: {
min: 0,
max: 11
},
series: [{
name: "Series 1",
type: 'scatter',
data: seriesData,
color: "red",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return option;
};
var nextSeries = function(seriesData) {
let series = {
series: [{
name: "Next series",
type: 'scatter',
data: seriesData,
color: "blue",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return series;
};
var series1 = [
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
];
var series2 = [
[10, 10],
[9, 9],
[8, 8],
[7, 7],
[6, 6]
];
var series3 = [
[10, 10],
[1, 1],
[8, 8],
[2, 2],
[6, 6]
];
var seriesAll = [series1, series2, series3]
var options = chartOptions(series1);
var chart1 = echarts.init(document.getElementById("ChartView"));
chart1.setOption(options);
var i = 0;
var timer = setInterval(function() {
i++;
if (i >= seriesAll.length) {
clearInterval(timer)
} else {
var nextOptions = nextSeries(seriesAll[i])
chart1.setOption(nextOptions);
};
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts-en.js"></script>
<div id="ChartView" style="height:300px;max-width:300px;">
</div>

Well, you can clear all scatterplots first then plot next series like below:
chart1.setOption(nextSeries([]));
chart1.setOption(nextOptions);
var chartOptions = function(seriesData) {
let option = {
xAxis: {
min: 0,
max: 11
},
yAxis: {
min: 0,
max: 11
},
series: [{
name: "Series 1",
type: 'scatter',
data: seriesData,
color: "red",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return option;
};
var nextSeries = function(seriesData) {
let series = {
series: [{
name: "Next series",
type: 'scatter',
data: seriesData,
color: "blue",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return series;
};
var series1 = [
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
];
var series2 = [
[10, 10],
[9, 9],
[8, 8],
[7, 7],
[6, 6]
];
var series3 = [
[10, 10],
[1, 1],
[8, 8],
[2, 2],
[6, 6]
];
var seriesAll = [series1, series2, series3]
var options = chartOptions(series1);
var chart1 = echarts.init(document.getElementById("ChartView"));
chart1.setOption(options);
var i = 0;
var timer = setInterval(function() {
i++;
if (i >= seriesAll.length) {
clearInterval(timer)
} else {
var nextOptions = nextSeries(seriesAll[i])
chart1.setOption(nextSeries([]));
chart1.setOption(nextOptions);
};
}, 2000);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" > </script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts-en.js"> </script>
<div id = "ChartView" style = "height:300px;max-width:300px;" >
</div>

Related

flotcharts - yaxis tick names not aligned to bars

I'm using this code to get my chart working
var d1 = [
[0, 3],
[1, 8],
[2, 5]
];
var d2 = [
[0, 3],
[1, 8],
[2, 5]
];
var d3 = [
[0, 3],
[1, 8],
[2, 5]
];
var d4 = [
[0, 3],
[1, 8],
[2, 5]
];
function plotWithOptions() {
$.plot("#placeholder", [
{ label: "novo", data: d1 },
{ label: "revisao", data: d2 },
{ label: "bla1", data: d3 },
{ label: "bla2", data: d4 },
], {
series: {
stack: 0,
bars: {
show:true,
horizontal:true,
}
},
yaxis: {
tickLength: 1,
gridLines: false,
ticks: [
[0, 'Bob'],
[1, 'Chris'],
[2, 'Joe'],
]
}
});
}
$(document).ready(function(){
plotWithOptions();
});
The problem is that the tick names are not aligned to bars.
Am I doing something wrong?

Data map to suitable Highcharts series

In my aplication I am using Highcharts and I have and data like from API
var data=[
{Part1:6,Part2:3,Test2:7,Part4:4,Part5:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2,Test:3}
]
and I need to convert it to
[
{ name:"Test", data: [null, null, 3] },
{ name:"Part6", data: [null, 2, 2] },
{ name:"Part5", data: [2, 7, 7] },
{ name:"Part4", data: [4, 6, 6] },
{ name:"Test2", data: [7, 8, 8] },
{ name:"Part2", data: [3, 5, 5] },
{ name:"Part1", data: [6, 8, 8] }
];
this is my example app snipped
var data=[
{Part1:6,Part2:3,Test2:7,Part4:4,Part5:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2,Test:3}
]
var expected_result=
[
{name: 'Test', data: [null, null, 3] },
{name: 'Part6', data: [null, 2,2] },
{name: 'Part5', data: [2, 7, 7] },
{name: 'Part4', data: [4, 6, 6] },
{name: 'Test2', data: [7, 8, 8] },
{name: 'Part2', data: [3, 5, 5] },
{name: 'Part1', data: [6, 8, 8] }
];
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Net', 'Brut', 'Others']
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series: expected_result
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<figure class="highcharts-figure">
<div id="container"></div>
</figure>
How can I convert my base data to expected. Thanks in advance
const data = [
{ Part1: 6, Part2: 3, Part3: 7, Part4: 4, Part5: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2, Part7: 3 },
];
const maxNumberPart = Math.max.apply(
null,
data.map(d => Object.keys(d).length),
);
const result = new Array(maxNumberPart).fill(null).map((p, i) => ({ name: `Part${maxNumberPart - i}`, data: [] }));
data.forEach(obj => {
result.forEach(part => {
part.data.push(obj[part.name] ? obj[part.name] : null);
});
});
console.log(result);
UPD dynamic key names:
const data = [
{ Part1: 6, Part2: 3, Test2: 7, Part4: 4, Part5: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Test: 6, Part5: 7, Part6: 2, Part7: 3 },
];
const keys = data.reduce((set, val) => {
Object.keys(val).forEach(key => set.add(key));
return set;
}, new Set());
const result = [...keys].map(key => ({
name: key,
data: [],
}));
data.forEach(obj => {
result.forEach(part => {
part.data.push(obj[part.name] ? obj[part.name] : null);
});
});
console.log(result);
You can group numbers first using a foreach and then fill the null value after
you can try this it is key agnostic
var data=[
{Part1:6,part2:3,part3:7,part4:4,part5:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2,part7:3}
]
p={}
res=[]
for(let o of data ){
Object.entries(o).forEach(k=>{
if(!p[k[0]]) res.push({name:k[0],data:p[k[0]]=[]})
p[k[0]].push(k[1])
})
}
i=0
while(i<res.length){
while(res[i].data.length<3){
res[i].data.unshift(null)}
i++
}
console.log(res.reverse())
if your keys are not the same and each time they can be different you can
try this
var data=[
{Test:6,part2:3,part3:7,part4:4,part5:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2,part7:3}
]
p={}
res=[]
for(let o of data ){
obarr= Object.entries(o)
obarr.forEach((k)=>{
if(!p[obarr.indexOf(k)]) res.push({name:k[0],data:p[obarr.indexOf(k)]=[]})
p[obarr.indexOf(k)].push(k[1])
})
}
i=0
while(i<res.length){
while(res[i].data.length<3){
res[i].data.unshift(null)}
i++
}
console.log(res.reverse())

ApexCharts Data not Rendering Properly

as far as I can tell I've mirrored the Series format as shown in ApexCharts' examples but the chart looks really wrong.
I've made a codepen with my test data and the chart rendering awkwardly.
I've tried it with different date formats but they all render the same.
https://codepen.io/yaehjs/pen/wvBdMWB
series: [
{
name: "Damage",
data: [
[1572912000000, 1],
[1573516800000, 2],
[1574640000000, 3],
[1575331200000, 4],
[1575417600000, 5],
[1575763200000, 6],
[1576540800000, 7],
[1576627200000, 8],
[1576713600000, 14],
[1576800000000, 15]
]
},
{
name: "Injury",
data: [[1576627200000, 1], [1576713600000, 4]]
},
{
name: "Slip/Fall",
data: [
[1572739200000, 1],
[1576022400000, 2],
[1576108800000, 3],
[1576540800000, 5]
]
},
{
name: "Spill",
data: [[1576627200000, 1], [1576713600000, 7], [1576800000000, 8]]
},
{
name: "Personnel",
data: [
[1572912000000, 1],
[1573516800000, 2],
[1574640000000, 3],
[1575331200000, 4],
[1575417600000, 5],
[1575763200000, 6],
[1576540800000, 7],
[1576627200000, 9],
[1576713600000, 12]
]
},
{
name: "Equipment",
data: []
}
],
Can anyone see where I went wrong with my data?
For anyone looking at this in the future the weirdness stems from one core issue. For timeline charts all series need to have the same date data-points otherwise the chart won't get rendered properly.
Here is a sample of the correct data:
[{
"totalCount": 15,
"name": "Damage",
"data": [
[ "2019-11-03", 0],
[ "2019-11-05", 1],
[ "2019-11-12", 2],
[ "2019-11-25", 3],
[ "2019-12-01", 3],
[ "2019-12-03", 4],
[ "2019-12-04", 5],
[ "2019-12-08", 6],
[ "2019-12-11", 6],
[ "2019-12-12", 6],
[ "2019-12-17", 7],
[ "2019-12-18", 8],
[ "2019-12-19", 14],
[ "2019-12-20", 15],
[ "2019-12-21", 15]
]
},
{
"totalCount": 4,
"name": "Injury",
"data": [
[ "2019-11-03", 0],
[ "2019-11-05", 0],
[ "2019-11-12", 0],
[ "2019-11-25", 0],
[ "2019-12-01", 0],
[ "2019-12-03", 0],
[ "2019-12-04", 0],
[ "2019-12-08", 0],
[ "2019-12-11", 0],
[ "2019-12-12", 0],
[ "2019-12-17", 0],
[ "2019-12-18", 1],
[ "2019-12-19", 4],
[ "2019-12-20", 4],
[ "2019-12-21", 4]
]
}
//...,
]
Code Pen: https://codepen.io/yaehjs/pen/wvBdMWB
var options = {
chart: {
height: 350,
type: "area",
stacked: true,
events: {
selection: function(chart, e) {
console.log(new Date(e.xaxis.min));
}
}
},
colors: ["#008FFB", "#00E396", "#CED4DC"],
dataLabels: {
enabled: false
},
stroke: {
curve: "smooth"
},
series: [
{
name: "Damage",
data: [
[1572912000000, 1],
[1573516800000, 2],
[1574640000000, 3],
[1575331200000, 4],
[1575417600000, 5],
[1575763200000, 6],
[1576540800000, 7],
[1576627200000, 8],
[1576713600000, 14],
[1576800000000, 15]
]
},
{
name: "Injury",
data: [[1576627200000, 1], [1576713600000, 4]]
},
{
name: "Slip/Fall",
data: [
[1572739200000, 1],
[1576022400000, 2],
[1576108800000, 3],
[1576540800000, 5]
]
},
{
name: "Spill",
data: [[1576627200000, 1], [1576713600000, 7], [1576800000000, 8]]
},
{
name: "Personnel",
data: [
[1572912000000, 1],
[1573516800000, 2],
[1574640000000, 3],
[1575331200000, 4],
[1575417600000, 5],
[1575763200000, 6],
[1576540800000, 7],
[1576627200000, 9],
[1576713600000, 12]
]
},
{
name: "Equipment",
data: []
}
],
fill: {
type: "gradient",
gradient: {
opacityFrom: 0.6,
opacityTo: 0.8
}
},
legend: {
position: "top",
horizontalAlign: "left"
},
xaxis: {
type: "datetime"
}
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
/*
// this function will generate output in this format
// data = [
[timestamp, 23],
[timestamp, 33],
[timestamp, 12]
...
]
*/
function generateDayWiseTimeSeries(baseval, count, yrange) {
var i = 0;
var series = [];
while (i < count) {
var x = baseval;
var y =
Math.floor(Math.random() * (yrange.max - yrange.min + 1)) + yrange.min;
series.push([x, y]);
baseval += 86400000;
i++;
}
return series;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/apexcharts/3.8.6/apexcharts.min.js"></script>
<div id="chart"></div>

How to use an array inside a multidimensional array?

If I have an array like so:
var phpintojsArray = [["1","20"]];
and... I also have a multid-array:
var data = [[1,20], [4, 20], [7, 55], [9, 10], [9, 10]];
how to add the phpintojsArray into the data array? I want:
var data = [[phpintojsArray], [1,20], [4, 20], [7, 55], [9, 10], [9, 10]];
What is one way to accomplish this?
Clarification -- Trying to manipulate the data in a chart
This works:
/* Bar Chart */
var data = [[1, 10],[3, 60], [5, 20], [7, 50], [9, 10]];
// Initialize Bars Chart
$.plot(BarChart, [
{ data: data, bars: { show: true, fillColor: { colors: [{ opacity: 1 }, { opacity: 1 }] } }, label: 'Example label' } ],
{
legend: {
backgroundColor: '#f6f6f6',
backgroundOpacity: 0.8
},
colors: ['#39d5db'],
grid: {
borderColor: '#cccccc',
color: '#999999',
labelMargin: 10
},
yaxis: {
ticks: 5
},
xaxis: {
tickSize: 1
}
}
);
This does Not work:
var phpintojsArray = <?= json_encode($sales); ?>;
var two = [3, 60];
var three = [5, 20];
var four = [7, 50];
var five = [9, 10];
/* Bars Chart */
var data = [[phpintojsArray], [two], [three], [four], [five]];
// Initialize Bars Chart
$.plot(BarChart, [
{ data: data, bars: { show: true, fillColor: { colors: [{ opacity: 1 }, { opacity: 1 }] } }, label: 'Example label' } ],
{
legend: {
backgroundColor: '#f6f6f6',
backgroundOpacity: 0.8
},
colors: ['#39d5db'],
grid: {
borderColor: '#cccccc',
color: '#999999',
labelMargin: 10
},
yaxis: {
ticks: 5
},
xaxis: {
tickSize: 1
}
}
);
Why?
You can use splice to insert the elements:
data.splice(0, 0, phpintojsArray);
This works:
/* Bar Chart */
var data = [[1, 10],[3, 60], [5, 20], [7, 50], [9, 10]];
This does Not work:
/* Bars Chart */
var data = [[phpintojsArray], [two], [three], [four], [five]];
Why?
Because the two expressions yield different structures. In the first one you have two levels of nested arrays (small arrays inside a big one). In the second you have three levels of nested arrays.
A simple console.log will show you the difference.
Make sure that your data is in the correct structure. Change it to:
var data = [two, three, four, five];
(In case it's still not clear, the brackets [] define a new array)
Regarding your question on how to prepend phpintojsArray, you could do:
Array.prototype.unshift.apply(data, phpintojsArray);
You could use eval in javascript.
For Example:
var data = [[eval("phpintojsArray")], [eval("two")], [eval("three")], [eval("four")], [eval("five")]];

Why doesn't this script print out any graphs? Flot Jquery

This script below is printing out the checkboxes but isn't plotting anything in the graph window.
if (key && allDataSets[key])
data.push(allDataSets[key]);
<link href="layout.css" rel="stylesheet" type="text/css">
<!--[if lte IE 8]><script language="javascript" type="text/javascript" src="root/include/excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="root/include/jquery.js"></script>
<script language="javascript" type="text/javascript" src="root/include/jquery.flot.js"></script>
</head>
<body>
<h1>Flot Examples</h1>
<div id="placeholder" style="width:600px;height:300px;"></div>
<p>Here is an example with real data: military budgets for
various countries in constant (2005) million US dollars (source: SIPRI).</p>
<p>Since all data is available client-side, it's pretty easy to
make the plot interactive. Try turning countries on/off with the
checkboxes below.</p>
<p id="choices">Show:</p>
<script type="text/javascript">
$(function () {
var Test1 = {
"date": {
label: "Date",
data: [[1, 20110122], [2, 20110123], [3, 20110124], [4, 20110125]]
},
"time": {
label: "Time",
data: [[1, 22.12], [2, 22.12], [3, 22.12], [4, 22.12]]
},
"modules": {
label: "Modules",
data: [[1, 22], [2, 22], [3, 22], [4, 22]]
},
"cases": {
label: "Cases",
data: [[1, 1312], [2, 1312], [3, 1312], [4, 1312]]
},
"failed": {
label: "Failed",
data: [[1, 75], [2, 77], [3, 64], [4, 55]]
},
"cover": {
label: "Cover",
data: [[1, 13.55 ], [2, 23.55], [3, 33.55], [4, 43.55]]
}};
var Test2 = {
"date": {
label: "Date",
data: [[1, 20110122], [2, 20110123], [3, 20110124], [4, 20110125]]
},
"time": {
label: "Time",
data: [[1, 22.12], [2, 22.12], [3, 22.12], [4, 22.12]]
},
"modules": {
label: "Modules",
data: [[1, 22], [2, 22], [3, 22], [4, 22]]
},
"cases": {
label: "Cases",
data: [[1, 1312], [2, 1312], [3, 1312], [4, 1312]]
},
"failed": {
label: "Failed",
data: [[1, 75], [2, 77], [3, 64], [4, 55]]
},
"cover": {
label: "Cover",
data: [[1, 13.55 ], [2, 23.55], [3, 33.55], [4, 43.55]]
}};
var Test3 = {
"date": {
label: "Date",
data: [[1, 20110122], [2, 20110123], [3, 20110124], [4, 20110125]]
},
"time": {
label: "Time",
data: [[1, 22.12], [2, 22.12], [3, 22.12], [4, 22.12]]
},
"modules": {
label: "Modules",
data: [[1, 22], [2, 22], [3, 22], [4, 22]]
},
"cases": {
label: "Cases",
data: [[1, 1312], [2, 1312], [3, 1312], [4, 1312]]
},
"failed": {
label: "Failed",
data: [[1, 75], [2, 77], [3, 64], [4, 55]]
},
"cover": {
label: "errover",
data: [[1, 13.55 ], [2, 23.55], [3, 33.55], [4, 43.55]]
}};
var allDataSets = [Test1,Test2,Test3];
// hard-code color indices to prevent them from shifting as
// countries are turned on/off
for(j=0; j<allDataSets.length; j++){//Going through all datasets, are there any other more simple way to do this???
var i = 0;
$.each(allDataSets[j], function(key, val) {
val.color = i;
++i;
});
// insert checkboxes
var choiceContainer = $("#choices");
$.each(allDataSets[j], function(key, val) {
choiceContainer.append('<br/><input type="checkbox" name="' + key +
'" checked="checked" id="id' + key + '">' +
'<label for="id' + key + '">'
+ val.label + '</label>');
});
/**************************Here the script stops working???**********************/
choiceContainer.find("input").click(plotAccordingToChoices);
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && allDataSets[j][key])
data.push(allDataSets[j][key]);
});
if (data.length > 0)
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 }
});
}
plotAccordingToChoices();
}
});
</script>
</body>
</html>
/***********EDIT****************/
OK so I solved the first issue with was simply replacing allDataSets[key] with allDataSets[j][key]
But as i now uncheck a checkbox I get the following error line 134 allDataSets[...] is null or not an object. Why do I get this error? In other words its this line that is incorrect when I uncheck a checkbox if (key && allDataSets[j][key])
Three things you need to do:
Declare that loop variable "j" with the var keyword.
for(var j=0; j<allDataSets.length; j++) {
All that code after your comment line - the click handler etc - needs to move out of that loop.
Inside the click handler, the code needs to iterate over "allDataSets" and then look for the key in each one:
choiceContainer.find("input:checked").each(function() {
var key = $(this).attr("name");
$.each(allDataSets, function(_, set) {
if (set[key]) data.push(set[key]);
});
});
Here is the jsfiddle demonstrating the changes. You'll note that it looks terrible. That's because your "allDataSets" re-uses the same keys for each clump. I have no idea what you're trying to achieve, but those changes will at least make something show up.

Categories