Change graph color above and below plot-line in Column chart in Highcharts - charts

I have a graph with two plot-lines.I need to color the column portion with different color after crossing each plot-lines. But zones makes different column different color not the portion above plot-lone. I have tried Zones & Thresholds but haven't got any solution for column chart.
There are solutions for line chart but they don't work for column chart.
Highcharts.chart('container', {
chart: {
zoomType: 'xy',
events: {
load: function () {
this.myTooltip = new Highcharts.Tooltip(this, this.options.tooltip);
}
}
},
title: {
text: ''
},
credits: {
enabled: false
},
subtitle: {
text: ''
},
useUTC: false,
xAxis: [{
type: 'datetime',
dateTimeLabelFormats: {
day: '%e %b',
hour: '%I:%M %P'
}
}],
yAxis: [{ // Primary yAxis
labels: {
format: '{value:,.0f}',
style: {
color: Highcharts.getOptions().colors[1]
}
},
plotLines: [peakPlotLineOption, averagePlotLineOption],
title: {
text: 'Consumption (kWh)',
style: {
color: Highcharts.getOptions().colors[1]
}
}}
, { // Secondary yAxis
title: {
text: '',
style: {
color: Highcharts.getOptions().colors[0]
}
},
labels: {
format: '{value} kWh',
style: {
color: Highcharts.getOptions().colors[0]
}
},
visible: false
}],
tooltip: {
crosshairs: true,
shared: true,
valueSuffix: '°C'
},
series: [{
name: 'ABC',
type: 'column',
data:
[
{ x: Date.UTC(2017, 6, 2, 0), y: 49.9, bId: 1 },
{ x: Date.UTC(2017, 6, 2, 1), y: 71.5, bId: 2 },
{ x: Date.UTC(2017, 6, 2, 2), y: 106.4, bId: 3 },
{ x: Date.UTC(2017, 6, 2, 3), y: 129.2, bId: 4 },
{ x: Date.UTC(2017, 6, 2, 4), y: 144.0, bId: 5 },
{ x: Date.UTC(2017, 6, 2, 5), y: 176.0, bId: 6 },
{ x: Date.UTC(2017, 6, 2, 6), y: 135.6, bId: 7 },
{ x: Date.UTC(2017, 6, 2, 7), y: 148.5, bId: 8 },
{ x: Date.UTC(2017, 6, 2, 8), y: 216.4, bId: 9 },
{ x: Date.UTC(2017, 6, 2, 9), y: 194.1, bId: 10 },
{ x: Date.UTC(2017, 6, 2, 10), y: 95.6, bId: 11 },
{ x: Date.UTC(2017, 6, 2, 11), y: 54.4, bId: 12 },
{ x: Date.UTC(2017, 6, 2, 12), y: 45, bId: 13 },
{ x: Date.UTC(2017, 6, 2, 13), y: 62, bId: 14 },
{ x: Date.UTC(2017, 6, 2, 14), y: 35, bId: 15 }
],
tooltip: {
valueSuffix: ' kWh'
},
yAxis: 0,
zones: [{
value: 50,
color: '#90ed7d'
}, {
value: 100,
color: '#FFDE00'
},{
color: '#CE0000'
}]
}
, {
// Series that mimics the plot line
color: '#ee8176',
name: 'contract capacity',
dashStyle: 'Solid',
marker: {
enabled: false
},
events: {
legendItemClick: function (e) {
if (this.visible) {
this.chart.yAxis[0].removePlotLine(averagePlotLine);
}
else {
this.chart.yAxis[0].addPlotLine(averagePlotLineOption);
}
}
},
yAxis: 0
}, {
// Series that mimics the plot line
color: '#9fa7b1',
name: 'max demand',
dashStyle: 'Solid',
marker: {
enabled: false
},
events: {
legendItemClick: function (e) {
if (this.visible) {
this.chart.yAxis[0].removePlotLine(peakPlotLine);
}
else {
this.chart.yAxis[0].addPlotLine(peakPlotLineOption);
}
}
},
yAxis: 0
}
]
});
JsFiddle Colulmn chart

By default Highcharts doesn't support that kind of coloring.
The workaround here is to mimic zones using stacking mechanism and dividing a point into multiple ones that reflect zones. Every series contains points from one zone:
var zones = [{
color: 'green',
start: 0
}, {
color: 'yellow',
start: 30
}, {
color: 'red',
start: 80
}];
//(...)
function prepareSeries(series) {
var newSeries = [],
data = series.data;
series.data = [];
// create separate series for each zone
zones.forEach(function(z, i) {
newSeries.push({
data: []
}); // copy series properties
});
// create new points and add them to new series array
data.forEach(function(p) {
for (var i = 0; i < zones.length; i++) {
var currentZone = zones[i],
nextZone = zones[i + 1],
zoneSeries = newSeries[i];
zoneSeries.color = currentZone.color;
if (nextZone && p.y > nextZone.start) {
zoneSeries.data.push({
x: p.x,
y: nextZone.start - currentZone.start
});
} else if (p.y > currentZone.start) {
zoneSeries.data.push({
x: p.x,
y: p.y - currentZone.start
});
}
}
});
newSeries.reverse();
// one legend for all created series
for (var i = 1; i < newSeries.length; i++) {
newSeries[i].linkedTo = ':previous';
}
return newSeries;
}
Live demo: http://jsfiddle.net/kkulig/g77od3wr/
linkedTo causes that all series are connected (there's only one legend item). tooltip.shared: true and tooltipFormater are used for restoring the previous formatting of the tooltip (total value instead of all series listed).

Related

Apache ECharts Gauge Gradient Style

I am trying to get something like this, where the style of the chart goes from a color on the min value to a color on the max value, and the progress value is in between.
I have this code:
option = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%'
},
series: [{
name: 'Pressure',
type: 'gauge',
max: 40,
min: -10,
startAngle: 180,
endAngle: 0,
progress: {
show: true,
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 1,
x2: 1,
y2: 1,
colorStops: [{
offset: 0,
color: "blue"
}, {
offset: 0.25,
color: "blue"
}, {
offset: 0.5,
color: "green"
}, {
offset: 0.75,
color: "orange"
}, {
offset: 1,
color: "red"
}],
global: false // default is false
}
}
},
pointer: {
show: false
},
detail: {
valueAnimation: true,
formatter: '{value}'
},
data: [{
// name of date item
name: 'data1',
// value of date item is 8
value: 10,
},
// {
// name: 'data2',
// value: 40,
// // user-defined label format that only useful for this data item
// label: {},
// // user-defined special itemStyle that only useful for this data item
// itemStyle:{},
// anchor: {
// show: false
// },
// progress: {
// itemStyle: {
// color: 'black'
// }
// },
// title: {
// show: false
// },
// detail: {
// show: false
// },
// }
]
}]
};
Which gives the close to what I want but not really as you can see the range of colors apply up to the current value. To test this paste the code in here:
https://echarts.apache.org/examples/en/editor.html?c=gauge-simple
The result:
Another solution is to draw the entire axis line with this gradient color and cover the right side after the progress value but not sure how to do this.

(Chart.js 3.7.0) change position of x-axis ticks to alternate between each tick?

I have a chart which effectively renders a timeline, but sometimes the tick positions are too close together
Current graph (padding: 25)
I can change the padding to be negative which puts them above the x-axis:
Ticks above x-axis (padding: -60)
But I'd prefer them to alternate to above and below eg 1st tick below, 2nd tick above, 3rd tick below etc.
Can I access the individual ticks padding to do this? See below my current code:
ticks: {
source: 'data',
maxRotation: 90,
minRotation: 90,
font: {
size: 12,
},
autoskip: true,
padding: -60,
},
TIA for any help! :-)
You can define two identical datasets together with two x-axes. One of the x-axes with position: 'top', the other one with default position ('bottom').
A slightly different ticks.callback function on both x-axes makes sure that only every second tick is displayed.
ticks: {
source: 'data',
...
callback: (v, i) => i % 2 ? v : ''
},
Please take a look at the following runnable code and see how it works.
const data = [
{ x: "2022-03-22", y: 0 },
{ x: "2022-04-01", y: 0 },
{ x: "2022-04-02", y: 0 },
{ x: "2022-04-03", y: 0 },
{ x: "2022-04-08", y: 0 },
{ x: "2022-04-12", y: 0 },
{ x: "2022-04-15", y: 0 }
];
new Chart('chart', {
type: 'line',
data: {
datasets: [{
data: data,
backgroundColor: 'black',
pointRadius: 5,
pointHoverRadius: 5,
borderWidth: 2,
xAxisID: 'x'
},
{
data: data,
backgroundColor: 'black',
pointRadius: 5,
pointHoverRadius: 5,
borderWidth: 2,
xAxisID: 'x2'
}]
},
options: {
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: context => undefined
}
}
},
scales: {
y: {
ticks: {
display: false,
},
grid: {
display: false,
drawBorder: false
}
},
x: {
position: 'top',
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
},
ticks: {
source: 'data',
minRotation: 90,
callback: (v, i) => i % 2 ? v : ''
},
grid: {
display:false,
drawBorder: false
}
},
x2: {
type: 'time',
time: {
unit: 'day',
tooltipFormat: 'MMM DD'
},
ticks: {
source: 'data',
minRotation: 90,
callback: (v, i) => i % 2 ? '' : v
},
grid: {
display:false,
drawBorder: false
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment-with-locales.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment#1.0.0"></script>
<canvas id="chart" height="50"></canvas>

Echarts:how to set markLine lable above the line and at the end of the line?

In echarts-3.6.2, when I set position:'end' for markLine, the lable will display at the end of line
markLine: {
data: [{
symbol:"none",
name: 'GOAL',
yAxis: 3.12 ,
label:{
normal:{
show:true,
position:'end'
}
},
lineStyle: {
normal: {
color: '#5C57FF',
width: 2
}
},
}]
},
However, I want to dislay it above the line at the end of the line? How to make it?
Change position value to insideEndTop(see in docs):
markLine: {
data: [{
symbol: "none",
name: 'GOAL',
yAxis: 3.12,
label: {
normal: {
show: true,
position: 'insideEndTop'
}
},
lineStyle: {
normal: {
color: '#5C57FF',
width: 2
}
},
}]
},
hello,do you have any ideas for not using position: 'insideEndTop', I could not upgrade the echarts plugin
I can't help without a crutch/workaround because it's very old version. You need to update the Echarts immediately, it's only right way. Or you can try to simulate markLine with the graphic component, something like below but it's highway to hell.
var myChart = echarts.init(document.getElementById('main'));
var option = {
color: ['rgba(92, 87, 255, 0.3)'],
grid: {
left: 50,
bottom: 50,
},
graphic: [{
type: 'group',
id: 'markLine',
bounding: 'raw',
children: [{
id: 'lineShape',
$action: 'replace',
type: 'line',
invisible: true,
shape: {
x1: 50,
y1: 300,
x2: 120,
y2: 300,
},
style: {
stroke: '#5C57FF',
lineWidth: 2,
},
zlevel: 10,
}, {
type: 'polygon',
$action: 'replace',
id: 'arrowShape',
invisible: true,
scale: [0.5, 0.3],
position: [90, 292.5],
shape: {
points: [
[16, 5],
[16, 47],
[38, 26]
]
},
style: {
fill: '#5C57FF',
}
}, {
type: 'text',
$action: 'replace',
id: 'labelShape',
invisible: true,
style: {
text: 'GOAL: 3.12',
x: -100,
y: 290,
fill: '#5C57FF',
font: 'bolder 12px sans-serif',
},
zlevel: 10,
}],
}],
xAxis: {
data: ["1", "2", "3", "4", "5", "6"]
},
yAxis: {
type: 'value',
max: 50
},
series: [{
name: 'Series',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
}]
};
myChart.setOption(option);
function renderMarkLine({ instance, yAxisValue, text, speed }){
var currentStep = 0;
var arrowShape = (val) => {
return {
stopCoord: 710, // 525
opts: {
invisible: false,
id: 'arrowShape',
position: [5 + val, yAxisValue - 7.5] // yAxisValue + 7.5
}
}
};
var lineShape = (val) => {
return {
stopCoord: 680, //540
opts: {
id: 'lineShape',
invisible: false,
shape: {
x1: 50,
y1: yAxisValue, // +0
x2: 50 + val,
y2: yAxisValue
}
}
}
};
var labelShape = (val) => {
return {
stopCoord: 660, // 460
opts: {
id: 'labelShape',
invisible: false,
style: {
x: -10 + val,
y: yAxisValue - 10, // 10
fill: '#5C57FF',
font: 'bolder 12px sans-serif'
}
}
}
};
var interval = setInterval(function(){
var graphicData = [];
[arrowShape, lineShape, labelShape].forEach(el => {
if (el(null).stopCoord > currentStep){
graphicData.push(el(currentStep).opts);
}
});
if (graphicData.length === 0) clearInterval(interval);
instance.setOption({ graphic: graphicData });
currentStep += 10;
}, speed);
};
renderMarkLine({ instance: myChart, yAxisValue: 500, speed: 0 });
<script src="https://cdn.jsdelivr.net/npm/echarts#3.6.2/dist/echarts.min.js"></script>
<div id="main" style="width:800px;height:600px;"></div>

APEX Chart not showing anything when using timestamp

var options = {
chart: {
height: 150,
type: 'rangeBar',
},
plotOptions: {
bar: {
horizontal: true,
endingShape: 'flat',
columnWidth: '70%',
barHeight: '70%',
distributed: false,
colors: {
ranges: [{
from: 0,
to: 0,
color: undefined
}],
backgroundBarColors: [],
backgroundBarOpacity: 1,
},
dataLabels: {
position: 'top',
maxItems: 100,
hideOverflowingLabels: true,
}
}
},
dataLabels: {
enabled: true
},
tooltip: {
y: {
formatter: function(value) {
return moment(new Date(value)).format("HH : mm : ss :")
}
}
},
series: [{
data: [{
x: 'TEAM A',
y: [1358447400000, 1358620200000]
}]
}],
xaxis: {
labels: {
formatter: function (value, timestamp) {
return timestamp//moment(new Date(value)).format("HH : mm : ss :")
},
}
}
// [{
// data: [{
// x: 'Team A',
// y: [1, 5]
// }, {
// x: 'Team B',
// y: [4, 6]
// }, {
// x: 'Team C',
// y: [5, 8]
// }, {
// x: 'Team D',
// y: [3, 11]
// }]
// }, {
// data: [{
// x: 'Team A',
// y: [2, 6]
// }, {
// x: 'Team B',
// y: [1, 3]
// }, {
// x: 'Team C',
// y: [7, 8]
// }, {
// x: 'Team D',
// y: [5, 9]
// }]
// }],
}
var chart = new ApexCharts(
document.querySelector(el),
options
);
Using Apex Chart I want to plot time stamp. Above code is from documentation. But when I run it its not working when i change to number only it works. What is missing in my code

Grouped Scatter or Bars Chart

Is there a way to make a grouped bars/scatter chart with date intervals?
I've tried 2 different ways to achieve the desired result.
1 - Used a grouped bars charts and trie to apply intervals (with no success).
http://jsfiddle.net/W6pgu/
$(function () {
Highcharts.getOptions().colors = Highcharts.map(Highcharts.getOptions().colors, function (color) {
return Highcharts.Color(color)
.setOpacity(0.5)
.get('rgba');
});
$('#container').highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Basic Info',
},
xAxis: {
categories: [
'Basic Info', ]
},
yAxis: {
min: 0,
title: {
text: 'Rainfall (mm)'
}
},
tooltip: {
shared: true,
valueSuffix: ' mm'
},
plotOptions: {
bar: {
grouping: false,
shadow: false
}
},
series: [{
name: 'Basic Info 1',
data: [49.9],
pointPadding: 0
}, {
name: 'Basic Info 1',
data: [83.6],
pointPadding: 0.1
}, {
name: 'Basic Info 3',
data: [48.9],
pointPadding: 0.2
}, {
name: 'Basic Info 4',
data: [42.4],
pointPadding: 0.3
}]
});
});
2 - Used a scatter chart to reproduce something similar to a Gantt chart, but I can't group this.
http://jsfiddle.net/r6emu/1814/
var tasks = [{
name: 'Sleep',
intervals: [{ // From-To pairs
from: Date.UTC(0, 0, 0, 0),
to: Date.UTC(0, 0, 0, 6),
}, {
from: Date.UTC(0, 0, 0, 22),
to: Date.UTC(0, 0, 0, 24),
}]
}, {
name: 'Family time',
intervals: [{ // From-To pairs
from: Date.UTC(0, 0, 0, 6),
to: Date.UTC(0, 0, 0, 8),
}, {
from: Date.UTC(0, 0, 0, 16),
to: Date.UTC(0, 0, 0, 22)
}]
}, {
name: 'Eat',
intervals: [{ // From-To pairs
from: Date.UTC(0, 0, 0, 7),
to: Date.UTC(0, 0, 0, 8),
}, {
from: Date.UTC(0, 0, 0, 12),
to: Date.UTC(0, 0, 0, 12, 30)
}, {
from: Date.UTC(0, 0, 0, 16),
to: Date.UTC(0, 0, 0, 17),
}, {
from: Date.UTC(0, 0, 0, 20, 30),
to: Date.UTC(0, 0, 0, 21)
}]
}, {
name: 'Work',
intervals: [{ // From-To pairs
from: Date.UTC(0, 0, 0, 8),
to: Date.UTC(0, 0, 0, 16)
}]
}];
var series = [];
$.each(tasks.reverse(), function (i, task) {
var item = {
name: task.name,
data: []
};
$.each(task.intervals, function (j, interval) {
item.data.push({
x: interval.from,
y: i,
label: interval.label,
from: interval.from,
to: interval.to,
}, {
x: interval.to,
y: i,
from: interval.from,
to: interval.to
});
if (task.intervals[j + 1]) {
item.data.push(
[(interval.to + task.intervals[j + 1].from) / 2, null]);
}
});
series.push(item);
});
Highcharts.getOptions().colors = Highcharts.map(Highcharts.getOptions().colors, function (color) {
return Highcharts.Color(color)
.setOpacity(0.5)
.get('rgba');
});
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container'
},
title: {
text: 'Daily activities'
},
xAxis: {
type: 'datetime'
},
yAxis: {
tickInterval: 1,
labels: false,
startOnTick: false,
endOnTick: false,
},
legend: {
enabled: false
},
tooltip: {
shared: true,
},
plotOptions: {
line: {
lineWidth: 9,
grouping: false,
shadow: false,
marker: {
enabled: false
},
dataLabels: {
enabled: true,
align: 'left',
formatter: function () {
return this.point.options && this.point.options.label;
}
}
}
},
series: series
});
I need a mixing of both. Any suggestion?
Use columnrange series instead of bars, see: http://jsfiddle.net/W6pgu/1/
$('#container').highcharts({
chart: {
type: 'columnrange',
inverted: true
},
title: {
text: 'Basic Info',
},
xAxis: {
categories: [
'Basic Info',
]
},
yAxis: {
min: 0,
title: {
text: 'Rainfall (mm)'
}
},
tooltip: {
shared: true,
valueSuffix: ' mm'
},
plotOptions: {
columnrange: {
grouping: false,
shadow: false
}
},
series: [{
name: 'Basic Info 1',
data: [[0,15,49.9]],
pointPadding: 0
}, {
name: 'Basic Info 1',
data: [[3,30,83.6]],
pointPadding: 0.1
}, {
name: 'Basic Info 3',
data: [[1,15,48.9]],
pointPadding: 0.2
}, {
name: 'Basic Info 4',
data: [[0,15,42.4]],
pointPadding: 0.3
}]
});
});