Rickshaw - need help designing line + bar toggle chart - charts

I just started using Ricksaw for animated graphs and I'm trying to set up my x-axes to list months. Not in a particular time series (yet), but just to correspond with specific data points. I have a fairly simple coding program to try and do this but I can't seem to modify the x-axes labels. Is there an easy way to do this? Also, how would I do something similar for the y-axis? Thanks!
< script >
var myGraph = new Rickshaw.Graph({
element: document.querySelector("#mychart"),
renderer: 'multi',
width: 500,
height: 250,
min: 0,
max: 18,
series: [{
name: "Population1",
color: "steelblue",
renderer: 'lineplot',
data: [{
x: 0,
y: 10,
}, {
x: 1,
y: 3,
}, {
x: 2,
y: 8,
}, {
x: 3,
y: 15,
}, {
x: 4,
y: 12,
}, {
x: 5,
y: 8,
}, {
x: 6,
y: 3,
}, {
x: 7,
y: 5,
}, {
x: 8,
y: 2,
}, {
x: 9,
y: 1,
}, {
x: 10,
y: 4,
}, ]
}, {
name: "Population2",
color: "green",
renderer: 'bar',
data: [{
x: 0,
y: 5,
}, {
x: 1,
y: 3,
}, {
x: 2,
y: 8,
}, {
x: 3,
y: 6,
}, {
x: 4,
y: 3,
}, {
x: 5,
y: 12,
}, {
x: 6,
y: 13,
}, {
x: 7,
y: 14,
}, {
x: 8,
y: 12,
}, {
x: 9,
y: 8,
}, {
x: 10,
y: 9,
}, ]
}]
});
var xTicks = new Rickshaw.Graph.Axis.X({
graph: myGraph,
orientation: "bottom",
element: document.querySelector("#xaxis")
});
var yTicks = new Rickshaw.Graph.Axis.Y({
graph: myGraph,
orientation: "left",
element: document.querySelector("#yaxis")
});
var graphHover = new Rickshaw.Graph.HoverDetail({
graph: myGraph
});
var myLegend = new Rickshaw.Graph.Legend({
graph: myGraph,
element: document.querySelector("#mylegend")
});
var toggling = new Rickshaw.Graph.Behavior.Series.Toggle({
graph: myGraph,
legend: myLegend
});
myGraph.render(); < /script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.5.1/rickshaw.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.5.1/rickshaw.min.js"></script>
<body>
<div style="margin-bottom:10px; margin-left:20px" id="mylegend"></div>
<div style="display:block; float:left; width:20px; height:280px; padding-bottom:10px;" id="yaxis"></div>
<div>
<div style="margin-left:20px;" id="mychart"></div>
<div style="margin-left:20px" id="xaxis"></div>
</div>
</body>

try something like this
var xAxis = new Rickshaw.Graph.Axis.Time({
graph: graph,
tickFormat: function(x){
return new Date(x).toLocaleString();
},
ticks: 4
});
xAxis.render();

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>

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>

How to add text at end of each line in charts.js

How can i add text at each line end like 97th, 95th etc using charts.js. Any help would be great. I tried documentation and did googling.
You can extend line controller drawing serie labels at the end of each line:
var chartData = {
datasets: [{
label: 'serie1',
backgroundColor: 'rgba(255, 255, 255, 0.0)',
borderColor: 'rgba(0, 119, 290, 0.6)',
data: [{x: 1, y: 10}, {x: 2, y: 12}, {x: 3, y: 18}, {x: 4, y: 5}, {x: 5, y: 25}, {x: 6, y: 30}]
},
{
label: 'serie2',
backgroundColor: 'rgba(255, 255, 255, 0.0)',
borderColor: 'rgba(120, 0, 190, 0.6)',
data: [{x: 1, y: 8}, {x: 2, y: 9}, {x: 3, y: 16}, {x: 4, y: 8}, {x: 5, y: 12}, {x: 6, y: 20}]
},
{
label: 'serie3',
backgroundColor: 'rgba(255, 255, 255, 0.0)',
borderColor: 'rgba(0, 200, 10, 0.6)',
data: [{x: 1, y: 10}, {x: 2, y: 5}, {x: 3, y: 26}, {x: 4, y: 18}, {x: 5, y: 19}, {x: 6, y: 10}]
}]
};
var originalController = Chart.controllers.line;
Chart.controllers.line = Chart.controllers.line.extend({
draw: function() {
originalController.prototype.draw.call(this, arguments);
drawLabels(this);
}
});
function drawLabels(t) {
ctx.save();
ctx.font = Chart.helpers.fontString(12, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.fillStyle = 'red';
ctx.textBaseline = 'bottom';
var chartInstance = t.chart;
var datasets = chartInstance.config.data.datasets;
datasets.forEach(function(ds, index) {
var label = ds.label;
var meta = chartInstance.controller.getDatasetMeta(index);
var len = meta.data.length-1;
//console.log(ds, meta.data[len]._model);
var xOffset = meta.data[len]._model.x+10;
var yOffset = meta.data[len]._model.y;
ctx.fillText(label, xOffset, yOffset);
});
ctx.restore();
}
var ctx = document.getElementById("myChart").getContext("2d");
var myBar = new Chart(ctx, {
type: 'line',
data: chartData,
options: {
legend: { display: false },
scales: {
xAxes: [{
type: 'linear',
scaleLabel: { display: true, labelString: 'x' }
}],
yAxes: [{
ticks: { min: 0 },
scaleLabel: { display: true, labelString: 'y' }
}]
},
layout: {
padding: {
left: 0,
right: 60,
top: 20,
bottom: 0
}
}
}
});
#myChart {
border: solid 1px rgba(255, 0, 0, 0.5);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="myChart" height="300" width="500"></canvas>
Here is a jsfiddle: http://jsfiddle.net/beaver71/q62yv516/
plugins = [
{
id: 'customPlugin',
beforeDraw: chart => {
const datasets = chart.config.data.datasets;
if (datasets) {
const { ctx } = chart.chart;
ctx.save();
ctx.fillStyle = 'black';
ctx.font = '400 12px Open Sans, sans-serif';
for (let i = 0; i < datasets.length - 1; i++) {
const ds = datasets[i];
const label = ds.label;
const meta = chart.getDatasetMeta(i);
const len = meta.data.length - 1;
const xOffset = chart.canvas.width - 26;
const yOffset = meta.data[len]._model.y;
ctx.fillText(label, xOffset, yOffset);
}
ctx.restore();
}
}
}
];
Same as above, but as a plugin

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

Error when rendering nvd3 bar graph

I keep getting this error:
Uncaught TypeError: Cannot call method 'map' of undefined
When running this code:
var testdata = [
{
label: "One",
x: 5,
y: 10
},
{
label: "2",
x: 6,
y: 15
},
{
label: "3",
x: 5,
y: 25
},
{
label: "4",
x: 10,
y: 0
}
];
nv.addGraph(function () {
var width = nv.utils.windowSize().width - 40,
height = nv.utils.windowSize().height / 2 - 40;
var chart = nv.models.multiBar()
.stacked(true)
.width(width)
.height(height);
d3.select("#lschart svg")
.datum(testdata)
.transition().duration(1200)
.attr('width', width)
.attr('height', height)
.call(chart);
return chart;
});
Problem is test_data is formatted incorrectly. It should be wrapped in an array containing an object which defines the fields "keys" and "values"
var testdata = [
{
keys: "returns",
values: [
{
label: "One",
x: 5,
y: 10
},
{
label: "2",
x: 6,
y: 15
},
{
label: "3",
x: 5,
y: 25
},
{
label: "4",
x: 10,
y: 0
},
]
}
];