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

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>

Related

(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>

Using ChartJS to create a multiple grouped bar chart - see picture below

I am testing out HighCharts and ChartJS to see which to use. For Highcharts, I was able to find a hack to create a bar chart that had double grouping on the x-axis.
This is what I want to look like:
I am new to both charting JS options and wonder if there is a way to do this in ChartJS.
I have the datasets something like this:
xAxis: {
categories: [{
name: "Total",
categories: ["2004", "2008", "2012"]
}, {
name: "Lower than 2.50",
categories: ["2004", "2008", "2012"]
}]
},
yAxis: {
min: 0,
title: {
text: 'Percent (%)'
}
},
series: [{
name: 'Male',
data: [42.4, 43.0, 43.0, 50.3, 49.4, 48.4]
}, {
name: 'Female',
data: [57.6, 57.0, 57.0, 49.7, 50.6, 51.6]
}]
Essentially I need a nest series on the x-axis and I am open to plugins or code from Github to do this.
You can make use of the Plugin Core API. It offers different hooks that may be used for executing custom code. In below code, I use the afterDraw hook to draw the category labels and the delimiter lines.
new Chart('myChart', {
type: 'bar',
plugins: [{
afterDraw: chart => {
let ctx = chart.chart.ctx;
ctx.save();
let xAxis = chart.scales['x-axis-0'];
let xCenter = (xAxis.left + xAxis.right) / 2;
let yBottom = chart.scales['y-axis-0'].bottom;
ctx.textAlign = 'center';
ctx.font = '12px Arial';
ctx.fillText(chart.data.categories[0], (xAxis.left + xCenter) / 2, yBottom + 40);
ctx.fillText(chart.data.categories[1], (xCenter + xAxis.right) / 2, yBottom + 40);
ctx.strokeStyle = 'lightgray';
[xAxis.left, xCenter, xAxis.right].forEach(x => {
ctx.beginPath();
ctx.moveTo(x, yBottom);
ctx.lineTo(x, yBottom + 40);
ctx.stroke();
});
ctx.restore();
}
}],
data: {
labels: ['2004', '2008', '2012', '2016', '2004', '2008', '2012', '2016'],
categories: ['Total', 'Lower than 2.50'],
datasets: [{
label: 'Male',
data: [42.4, 43.0, 43.0, 50.3, 49.4, 48.4, 51.2, 51.8],
backgroundColor: 'rgba(124, 181, 236, 0.9)',
borderColor: 'rgb(124, 181, 236)',
borderWidth: 1
},
{
label: 'Female',
data: [57.6, 57.0, 57.0, 49.7, 50.6, 51.6, 53.7, 54.6],
backgroundColor: 'rgba(67, 67, 72, 0.9)',
borderColor: 'rgb(67, 67, 72)',
borderWidth: 1
}
]
},
options: {
legend: {
position: 'bottom',
labels: {
padding: 30,
usePointStyle: true
}
},
scales: {
yAxes: [{
ticks: {
min: 0,
max: 80,
stepSize: 20
},
scaleLabel: {
display: true,
labelString: 'Percent (%)'
}
}],
xAxes: [{
gridLines: {
drawOnChartArea: false
}
}]
}
}
});
canvas {
max-width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="myChart" height="200"></canvas>
You have to define a second x-axis and play around with the many ticks and gridLines options.
Please take a look at below runnable code and see how it could be done. This is obviously only a draft and needs to optimized and made more generic.
new Chart(document.getElementById('myChart'), {
type: 'bar',
data: {
labels: ['2004', '2008', '2012', '2004', '2008', '2012'],
datasets: [{
label: 'Male',
data: [42.4, 43.0, 43.0, 50.3, 49.4, 48.4],
backgroundColor: 'rgba(124, 181, 236, 0.9)',
borderColor: 'rgb(124, 181, 236)',
borderWidth: 1
},
{
label: 'Female',
data: [57.6, 57.0, 57.0, 49.7, 50.6, 51.6],
backgroundColor: 'rgba(67, 67, 72, 0.9)',
borderColor: 'rgb(67, 67, 72)',
borderWidth: 1
}
]
},
options: {
legend: {
position: 'bottom',
labels: {
usePointStyle: true
}
},
scales: {
yAxes: [{
ticks: {
min: 0,
max: 80,
stepSize: 20
},
scaleLabel: {
display: true,
labelString: 'Percent (%)'
}
}],
xAxes: [{
gridLines: {
drawOnChartArea: false
}
},
{
offset: true,
ticks: {
autoSkip: false,
maxRotation: 0,
padding: -15,
callback: (v, i) => {
if (i == 1) {
return 'Total';
} else if (i == 4) {
return 'Lower than 2.50';
} else {
return '';
}
}
},
gridLines: {
drawOnChartArea: false,
offsetGridLines: true,
tickMarkLength: 20,
color: ['white', 'white', 'white', 'lightgray', 'white', 'white', 'lightgray']
}
}
]
}
}
});
canvas {
max-width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<canvas id="myChart" height="200"></canvas>

Apache ECharts: Rotated labels get cropped

I'm trying to use rotated labels in my graph. However, the labels are getting cropped. How can I make more space in the bottom so that the labels can fit?
options = {
xAxis: {
type: "category",
data: axis,
axisLabel: {
show: true,
interval: 0,
rotate: 45,
},
axisTick: {
show: true,
interval: 0
}
},
yAxis: {
type: "value",
data: axis,
min: 1,
minInterval: 1,
maxInterval: 1,
max: 15,
axisTick: {
interval: 1
}
},
series: [
{
type: "bar",
stack: "minmax",
itemStyle: {
normal: {
color: "rgba(0,0,0,0)"
}
},
data: maxs
},
{
type: "bar",
stack: "minmax",
data: mins,
itemStyle: { color: "#63869e" }
},
{
symbolSize: 20,
data: scatter,
type: "scatter",
itemStyle: { color: "black" },
},
]
};
To contain the label you can use:
options = {
grid: {
containLabel: true,
}
}
Space can be added with grid option bottom:
options = {
grid: {
bottom: 100,
}
}

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

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).

Google barchart tooltip no tail

Im using google barchart and I added tooltips with html in it. The problem is that the tooltip does not have the tail arrow thing. I saw that some charts has the arrow while others dont?
function drawFrequencyCharts(response) {
var data2 = new google.visualization.DataTable();
data2.addColumn('number', 'Value');
data2.addColumn('number', 'Value');
data2.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
.... some code
var view = new google.visualization.DataView(data2);
var chart2 = new google.visualization.ComboChart(document.getElementById('barChart'));
var options2 = {
height: 300,
width: 500,
series: {
0: {
type: 'bars'
},
1: {
type: 'line',
color: 'grey',
lineWidth: 0,
pointSize: 0,
visibleInLegend: false
}
},
colors: ['#3394D1'],
backgroundColor: {
fill: 'transparent'
},
legend: 'none',
vAxis: {
maxValue: 100,
minValue: 0,
ticks: [{
v: 0,
f: '0%'
}, {
v: 25,
f: '25%'
}, {
v: 50,
f: '50%'
}, {
v: 75,
f: '75%'
}, {
v: 100,
f: '100%'
}, ]
},
hAxis: {
format: '#',
viewWindowMode: 'explicit',
viewWindow: {
min: 0.1
},
title: 'Drops per day',
gridlines: {
color: 'transparent'
},
ticks: ticksValues
},
animation: {
duration: 750,
easing: 'linear',
startup: chartAnimate
}
};
chart2.draw(view, options2);
The problem with the "tail" is that you're using tooltip:{isHtml:true}. They are not shown with the tip, just an ordinary "box" floating above your chart.
If you revoke to "normal" tooltip, then you'll see the 'tail'.
JSFiddle where you can see the difference.