I'm looking to simplify this code. Any way to it so? Spring MVC + Apex Charts
var d = /*[[${s0}]]*/ null`; <-- It is sent via the Spring Framework. Basically represents datetime(in millis) at `d[0]`, `d[3]`,... Temperature at `d[1]`, `d[4]`,... and Humidity at `d[2]`, `d[5]`,...
<script type="text/javascript" th:inline="javascript">
var d = /*[[${s0}]]*/ null;
var options = {
chart: {
type: 'area',
height: 300
},
series: [
{
name: 'Temperature',
data: [
[d[0], d[1]],
[d[3], d[4]],
[d[6], d[7]],
[d[9], d[10]],
[d[12], d[13]],
[d[15], d[16]],
[d[18], d[19]],
[d[21], d[22]],
[d[24], d[25]],
[d[27], d[28]],
[d[30], d[31]],
[d[33], d[34]],
[d[36], d[37]],
[d[39], d[40]],
[d[42], d[43]],
[d[45], d[46]],
[d[48], d[49]],
[d[51], d[52]],
[d[54], d[55]],
[d[57], d[58]],
[d[60], d[61]],
[d[63], d[64]],
[d[66], d[67]],
[d[69], d[70]]
]
},
{
name: "Humidity",
data: [
[d[0], d[2]],
[d[3], d[5]],
[d[6], d[8]],
[d[9], d[11]],
[d[12], d[14]],
[d[15], d[17]],
[d[18], d[20]],
[d[21], d[23]],
[d[24], d[26]],
[d[27], d[29]],
[d[30], d[32]],
[d[33], d[35]],
[d[36], d[38]],
[d[39], d[41]],
[d[42], d[44]],
[d[45], d[47]],
[d[48], d[50]],
[d[51], d[53]],
[d[54], d[56]],
[d[57], d[59]],
[d[60], d[62]],
[d[63], d[65]],
[d[66], d[68]],
[d[69], d[71]]
]
}
],
xaxis: {
type: 'datetime'
},
yaxis: [
{
axisTicks: {
show: true
},
axisBorder: {
show: true,
},
title: {
text: "Temperature"
}
}, {
min: 0,
max: 100,
opposite: true,
axisTicks: {
show: true
},
axisBorder: {
show: true,
},
title: {
text: "Humidity"
}
}
],
legend: {
position: 'top',
horizontalAlign: 'center'
},
tooltip: {
x: {
format: 'HH:mm dd/MM/yy'
},
}
}
var chart = new ApexCharts(document.querySelector("#chart0"), options);
chart.render();
</script>
I just need to simplify sending data via d[0], d[1] etc. Is there any kind of loop or anything else I can use?
You could take a function which takes the data and a pattern for the wanted elements and an offset for increment for the next row.
function mapByPattern(data, pattern, offset) {
var result = [], i = 0;
while (i < data.length) {
result.push(pattern.map(j => data[i + j]));
i += offset;
}
return result;
}
var data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
result = { series: [
{ name: 'Temperature', data: mapByPattern(data, [0, 1], 3) },
{ name: "Humidity", data: mapByPattern(data, [0, 2], 3) }
]};
console.log(result);
Thank You, Nina. Code code didn't work exactly as i wanted but was so helpful to fix my own. Thanks alot! Here's some fixed code :)
var data = /*[[${s0}]]*/ null;
function mapByPattern(data, pattern, offset) {
var result = [], i = 0;
while (i < data.length) {
result.push(pattern.map(j => data[i + j]));
i += offset;
}
return result;
}
var options = {
chart: {
type: 'area',
height: 300
},
series: [
{
name: 'Temperature',
data: mapByPattern(data, [0, 1], 3)
},
{
name: "Humidity",
data: mapByPattern(data, [0, 2], 3)
}
],
xaxis: {
type: 'datetime'
},
yaxis: [
{
axisTicks: {
show: true
},
axisBorder: {
show: true,
},
title: {
text: "Temperature"
}
}, {
min: 0,
max: 100,
opposite: true,
axisTicks: {
show: true
},
axisBorder: {
show: true,
},
title: {
text: "Humidity"
}
}
],
legend: {
position: 'top',
horizontalAlign: 'center'
},
tooltip: {
x: {
format: 'HH:mm dd/MM/yy'
},
}
}
var chart = new ApexCharts(document.querySelector("#chart0"), options);
chart.render();
Related
I am trying to make a gradient line chart, The issue is with tooltip legend color and color of data points, they appear in brown gradient which was the default.
I was able to change the tooltip color, anyhow that is not the actual data point color but able to fix it to one color at least. whereas the points on the line do not pick up the color of the line.
Can someone point me in right direction?
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
var option;
var data = [["2020-06-05",116],["2020-06-06",129],["2020-06-07",135],["2020-06-08",86],["2020-06-09",73],["2020-06-10",85],["2020-06-11",73],["2020-06-12",68],["2020-06-13",92],["2020-06-14",130],["2020-06-15",245],["2020-06-16",139],["2020-06-17",115],["2020-06-18",111],["2020-06-19",309],["2020-06-20",206],["2020-06-21",137],["2020-06-22",128],["2020-06-23",85],["2020-06-24",94],["2020-06-25",71],["2020-06-26",106],["2020-06-27",84],["2020-06-28",93],["2020-06-29",85],["2020-06-30",73],["2020-07-01",83],["2020-07-02",125],["2020-07-03",107],["2020-07-04",82],["2020-07-05",44],["2020-07-06",72],["2020-07-07",106],["2020-07-08",107],["2020-07-09",66],["2020-07-10",91],["2020-07-11",92],["2020-07-12",113],["2020-07-13",107],["2020-07-14",131],["2020-07-15",111],["2020-07-16",64],["2020-07-17",69],["2020-07-18",88],["2020-07-19",77],["2020-07-20",83],["2020-07-21",111],["2020-07-22",57],["2020-07-23",55],["2020-07-24",60]];
var dateList = data.map(function (item) {
return item[0];
});
var valueList = data.map(function (item) {
return item[1];
});
option = {
color: {
type: 'linear',
x: 0, y: 1,x2:0,y2:0,
colorStops: [{
offset: 0, color: '#00d4ff' // color at 0% position
}, {
offset: 1, color: '#090979' // color at 100% position
}],
global:true
},
// Make gradient line here
visualMap: [{
show: true,
type: 'continuous',
seriesIndex: 0,
min: 0,
max: 400
}],
title: [{
left: 'center',
text: 'Gradient along the y axis'
}],
xAxis: [{
data: dateList,
axisPointer: {
label:{
color:['#5470c6'],
}
},
axisLabel: {
formatter: function (value) {
return moment(value).format("MMM YY");
// And other formatter tool (e.g. moment) can be used here.
}
}
}],
yAxis: [{
type: 'value',
axisPointer: {
label:{
color:['#5470c6'],
}
}
}],
grid: [{
width:'auto',
height:'auto'
}],
tooltip : {
trigger: 'axis',
axisPointer: {
animation: true,
},
formatter: function (params) {
var colorSpan = color => '<span style="display:inline-block;margin-right:5px;border-radius:10px;width:9px;height:9px;background-color:' + color + '"></span>';
let rez = '<p>' + params[0].axisValue + '</p>';
console.log(params); //quite useful for debug
params.forEach(item => {
// console.log(item); //quite useful for debug
var xx = '<p>' + colorSpan('#00d4ff') + ' ' + item.seriesName + ': ' + item.data + '</p>'
rez += xx;
});
console.log(rez);
return rez;
}
},
series: [{
color:['#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc'],
type: 'line',
showSymbol: false,
data: valueList,
// smooth: true,
label:{
show:true,
position:'top'
},
lineStyle:{
color: {
type: 'linear',
x: 0, y: 1,x2:0,y2:0,
colorStops: [{
offset: 0, color: '#00d4ff' // color at 0% position
}, {
offset: 1, color: '#090979' // color at 100% position
}],
global:false
}
}
}]
};
console.log(myChart);
if (option && typeof option === 'object') {
myChart.setOption(option);
}
You need to add gradientColor array to echarts options. Now echart will take care of changing color of tooltip and data point. You can also remove your custom tooltip formatted function.
gradientColor: ["#00d4ff", "#090979"]
Here the complete options object:
var data = [];
var dateList = data.map(function(item) {
return item[0];
});
var valueList = data.map(function(item) {
return item[1];
});
option = {
gradientColor: ["#00d4ff", "#090979"],
// Make gradient line here
visualMap: [
{
show: true,
type: "continuous",
seriesIndex: 0,
min: 0,
max: 400
}
],
title: [
{
left: "center",
text: "Gradient along the y axis"
}
],
xAxis: [
{
data: dateList,
axisPointer: {
label: {
color: ["#5470c6"]
}
},
axisLabel: {
formatter: function(value) {
return moment(value).format("MMM YY");
// And other formatter tool (e.g. moment) can be used here.
}
}
}
],
yAxis: [
{
type: "value",
axisPointer: {
label: {
color: ["#5470c6"]
}
}
}
],
grid: [
{
width: "auto",
height: "auto"
}
],
tooltip: {
trigger: "axis",
axisPointer: {
animation: true
}
},
series: [
{
type: "line",
showSymbol: false,
data: valueList,
// smooth: true,
label: {
show: true,
position: "top"
}
}
]
};
How to filter echarts line chart per week in angular. Currently it display all records example 2019-10-27 10:15:00, 2019-10-27 10:15:30, 2019-10-27 10:16:00, 2019-10-27 10:19:00. It should be 2019-10-27 if there's 2019-28-10 00:00:15, 2019-28-10 00:10:00 the output should be 2019-10-27, 2019-10-28.
here's the code
list.component.html
<button nz-button nzType="default" (click)="dataFilter('prevWeek')">Previous week</button>
<button nz-button nzType="default" (click)="dataFilter('currWeek')">Current week</button>
<button nz-button nzType="default" (click)="dataFilter('all')">All</button>
<div echarts [options]="trendOption" id="trendChart" [autoResize]="true" style="height: 280px;"></div>
list.component.ts
dataFilter(event: any) {
switch (event) {
case 'prevWeek':
console.log('diplay the previous/last week');
break;
case 'currWeek':
console.log('display current week list')
break;
case 'all':
console.log('display all records');
break;
default: break;
}
}
getRoomTrend() {
const _THIS = this;
const dateTime: any = [];
const tempY: any = [];
const humidY: any = [];
this.global
.getData(`/conditions?length=100&sensor=${this.roomTitle}`)
.pipe(take(1))
.subscribe((res: any) => {
const record = res['data'];
for (let i = record.length - 1; i >= 0; i--) {
const date = format(record[i].date, 'MM/DD/YYYY[\n]HH:mm');
const temperature = parseFloat(record[i].temperature);
const humidity = parseFloat(record[i].humidity);
dateTime.push(date);
tempY.push(temperature);
humidY.push(humidity);
}
if (this.initialLoad.trendStatus) {
this.trendOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
animation: false
}
},
legend: {
top: '10',
data: ['Temperature', 'Humidity']
},
grid: {
left: '3%',
bottom: '15%',
containLabel: true
},
dataZoom: [
{
minValueSpan: 4,
startValue: record.length - 3
},
{
type: 'inside'
}
],
xAxis: {
type: 'category',
boundaryGap: false,
splitLine: {
show: false
},
data: dateTime
},
yAxis: [
{
type: 'value',
boundaryGap: [0, '100%'],
axisLabel: {
formatter: '{value} °'
},
splitLine: {
show: false
}
},
{
type: 'value',
boundaryGap: [0, '100%'],
position: 'right',
axisLabel: {
formatter: '{value} °'
},
splitLine: {
show: false
}
}
],
series: [
{
name: 'Temperature',
type: 'line',
color: '#006ec7',
data: tempY
},
{
name: 'Humidity',
type: 'line',
color: '#8c0000',
data: humidY
}
]
};
}
});
}
example I have 30,000 record and the date is same but different time. the output should be only ```2019-15-10, 2019-18-10, 2019-22-10.
Thanks in advance.
let uniqueDates = new Set();
record.forEach(value => {
let date = new Date(value.date.getFullYear(), value.date.getMonth(), value.date.getDate());
uniqueDates.add(date);
});
Set by definition is a set of unique values. So you get the date without the time from the records and add them into the set. You will end up with a list of unique dates.
I'm having trouble aligning tooltip position on bar chart. Tooltip positioning works fine if all charts are line chart but not with bar/column charts. Could the Highcharts experts please help me with this issue?
http://jsfiddle.net/yhenwtsb/1/
var charts = [],
options1, options2;
function syncTooltip(container, p) {
var i = 0;
for (; i < charts.length; i++) {
if (container.id != charts[i].container.id) {
if (charts[i].tooltip.shared) {
charts[i].tooltip.refresh([charts[i].series[0].data[p]]);
} else {
charts[i].tooltip.refresh(charts[i].series[0].data[p]);
}
}
}
}
options1 = {
chart: {
type: "column",
inverted: true
},
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
syncTooltip(this.series.chart.container, this.x - 1);
}
}
}
}
},
xAxis: {
type: 'datetime'
}
};
options2 = {
plotOptions: {
series: {
point: {
events: {
mouseOver: function() {
syncTooltip(this.series.chart.container, this.x - 1);
}
}
}
}
},
xAxis: {
type: 'datetime'
}
};
charts[0] = new Highcharts.Chart($.extend(true, {}, options1, {
chart: {
renderTo: 'container1',
marginLeft: 40, // Keep all charts left aligned
},
tooltip: {
shared: true,
crosshairs: true,
valueDecimals: 2
},
series: [{
data: [
[1, 29.9],
[2, 71.5],
[3, 106.4]
]
}, {
data: [
[1, 59.9],
[2, 91.5],
[3, 136.4]
]
}]
}));
charts[1] = new Highcharts.Chart($.extend(true, {}, options2, {
chart: {
renderTo: 'container2',
marginLeft: 40, // Keep all charts left aligned
},
tooltip: {
shared: false
},
series: [{
data: [
[1, 29.9],
[2, 71.5],
[3, 106.4]
]
}]
}));
You can set tooltip.followPointer to true and add a small plugin to synchronize the second chart:
(function(H) {
H.wrap(H.Pointer.prototype, 'runPointActions', function(proceed, e, p) {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
var tooltipPos = this.chart.tooltip.now;
Highcharts.charts.forEach(function(chart) {
if (chart !== this.chart) {
chart.tooltip.updatePosition({
plotX: tooltipPos.x - chart.plotLeft,
plotY: tooltipPos.y - chart.plotTop
});
}
}, this);
});
}(Highcharts));
Live demo: http://jsfiddle.net/BlackLabel/2w9683gb/
API Reference: https://api.highcharts.com/highcharts/tooltip.followPointer
Docs: https://www.highcharts.com/docs/extending-highcharts
Can I apply theme without reloading the whole chart. Can I push the themes settings within the chart code? In highcharts site all examples are single theme based. Here is my code
$(function() {
$.getJSON('http://api-sandbox.oanda.com/v1/candles?instrument=EUR_USD&candleFormat=midpoint&granularity=W', function(data) {
// create the chart
var onadata =[];
var yData=[];
var type='line';
var datalen=data.candles.length;
var all_points= [];
var all_str="";
for(var i=0; i<datalen;i++)
{
var each=[Date._parse(data.candles[i].time), data.candles[i].openMid, data.candles[i].highMid, data.candles[i].lowMid, data.candles[i].closeMid]
onadata.push(each);
yData.push(data.candles[i].closeMid);
}
$( "#change_theme" ).on("change", function() {
var optionSelected = $("option:selected", this);
var valueSelected = this.value;
//alert(valueSelected);
if(valueSelected=='default.js')
{
location.reload();
}
else{ $.getScript('js/themes/'+valueSelected, function() {
//alert('Load was performed.');
chart();
});
}
});
chart();
function chart()
{
$('#container').highcharts('StockChart', {
credits: {
enabled : 0
},
rangeSelector : {
buttons: [{
type: 'month',
count: 1,
text: '1M'
}, {
type: 'month',
count: 3,
text: '3M'
},{
type: 'month',
count: 6,
text: '6M'
},{
type: 'all',
text: 'All'
}],
selected:3
},
legend: {
enabled: true,
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
title : {
text : 'Stock Price'
},
xAxis :{
minRange : 3600000
},
yAxis : [{
offset: 0,
ordinal: false,
height:280,
labels: {
format: '{value:.5f}'
}
}],
chart: {
events: {
click: function(event) {
var x1=event.xAxis[0].value;
var x2 =this.xAxis[0].toPixels(x1);
var y1=event.yAxis[0].value;
var y2 =this.yAxis[0].toPixels(y1);
selected_point='['+x1+','+y1+']';
all_points.push(selected_point);
all_str=all_points.toString();
if(all_points.length>1)
{
this.addSeries({
type : 'line',
name : 'Trendline',
id: 'trend',
data: JSON.parse("[" + all_str + "]"),
color:'#'+(Math.random()*0xEEEEEE<<0).toString(16),
marker:{enabled:true}
});
}
if(all_points.length==2)
{
all_points=[];
}
}
}
},
series : [{
//allowPointSelect : true,
type : type,
name : 'Stock Price',
id: 'primary',
data : onadata,
tooltip: {
valueDecimals: 5,
crosshairs: true,
shared: true
},
dataGrouping : {
units : [
[
'hour',
[1, 2, 3, 4, 6, 8, 12]
], [
'day',
[1]
], [
'week',
[1]
], [
'month',
[1, 3, 6]
], [
'year',
[1]
]
]
}
},
]
});
}
});
});
and this is my js fiddle
Please help. Thanks in advance.
This is possible if you're using modern browsers that support CSS variables.
Highcharts.theme = {
colors: [
'var(--color1)',
'var(--color2)',
'var(--color3)',
'var(--color4)',
'var(--color5)',
'var(--color6)',
]
}
Highcharts.setOptions(Highcharts.theme);
function setTheme(themeName) {
// remove theme-* classes from body
removeClasses = Array.from(document.body.classList).filter(s => s.startsWith('theme-'));
document.body.classList.remove(...removeClasses)
if (themeName) {
document.body.classList.add('theme-' + themeName);
}
}
CSS
body {
--color1: #e00;
--color2: #b00;
--color3: #900;
--color4: #600;
--color5: #300;
--color6: #000;
}
body.theme-dark {
--color1: #555;
--color2: #444;
--color3: #333;
--color4: #222;
--color5: #111;
--color6: #000;
}
body.theme-retro {
--color1: #0f0;
--color2: #ff0;
--color3: #0ff;
--color4: #0a0;
--color5: #aa0;
--color6: #00a;
}
Unfortunately it is not possible, so you need to destroy and create new chart.
I use date as a string in my chart.
How can I use my start-date and end-date string variables as a label in my xAxis?
start-date = '10.02.2013'
end-date = '10.05.2013'
The code and the chart image is attached. The only thing I need to do is to add startDateLabel and endDateLabel.
var dateEndLabel, dateStartLabel, i, j, lastDate, seriesData, x, y;
i = 0;
seriesData = new Array();
lastDate = data[i].Values.length - 1;
dateStartLabel = data[i].Values[0].Time;
dateEndLabel = data[i].Values[lastDate].Time;
while (i < data.length) {
seriesData[i] = [];
j = 0;
x = [];
y = [];
while (j < data[i].Values.length) {
x = data[i].Values[j].Time;
y = data[i].Values[j].Value;
seriesData[i].push([x, y]);
j++;
}
i++;
}
return $("#criticalWPtrend").highcharts({
chart: {
type: "line"
},
area: {
height: "100%",
width: "100%",
margin: {
top: 20,
right: 30,
bottom: 30,
left: 50
}
},
title: {
text: ""
},
subtitle: {
text: ""
},
legend: {
layout: "vertical",
verticalAlign: "right",
align: "right",
borderWidth: 0
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: {
day: '%m-%d'
},
tickInterval: 24 * 3600 * 1000
},
yAxis: {
title: {
text: 'Value'
},
lineWidth: 1,
min: 0,
minorGridLineWidth: 0,
gridLineWidth: 0,
alternateGridColor: null
},
tooltip: {
valueSuffix: " "
},
plotOptions: {
series: {
marker: {
enabled: false
},
stickyTracking: {
enabled: false
}
},
line: {
lineWidth: 2,
states: {
hover: {
lineWidth: 3
}
},
marker: {
enabled: false
}
}
},
series: [
{
name: data[0].Name,
data: seriesData[0]
}, {
name: data[1].Name,
data: seriesData[1]
}, {
name: data[2].Name,
data: seriesData[2]
}, {
name: data[3].Name,
data: seriesData[3]
}, {
name: data[4].Name,
data: seriesData[4]
}, {
name: data[5].Name,
data: seriesData[5]
}
],
navigation: {
menuItemStyle: {
fontSize: "10px"
}
}
});
});
Yes, this is possible with the renderer method. See this basic example.
chart.renderer.text('10.02.2013', 0, 300)
.attr({
rotation: 0
})
.css({
color: '#4572A7',
fontSize: '16px'
})
.add();
You are going to need to pay attention to the x/y locations (the 2 other params) to place it correctly. You can also modify the text styling.
I'm not sure, but i think you just need to update your xAxis by update method
this.xAxis[0].update({
title: {
text: "start-date = '10.02.2013' end-date = '10.05.2013'",
style: {
fontSize: '10px'
}
}
});
Here's example: http://jsfiddle.net/FEwKX/
But!
If your mean that the start and end dates need to tie to edges, you must specify xAxis settings in config
xAxis: {
categories: categoriesArray
}
where categoriesArray is array like this:
['10.02.2013', '', '', '', '', '', '', '', '', '', '', '10.05.2013']
It should be the same lenght as your lenght of series data.
Check out here: http://jsfiddle.net/FEwKX/1/
Hope that'll help you.
You can also use labelFormatter and http://api.highcharts.com/highcharts#xAxis.labels.formatter and check if labels isFirst or isLast then use your dates, in other cases return proper value (like number).