I have been trying to utilize the tickvals/ticktext on plotlyjs to be able to show duplicate values on a graph for the xaxis. It works in the aspect of separating the data (having multiple duplicate values be on the xaxis, but a 1:1 data point) -- the issue that I am having is that no xaxis tick marks or xaxis labels show up for the ticks.
Here is a code pen of my problem:
https://codepen.io/hiquetj/pen/yLeBNjJ
Here is the code for easier reading:
var trace1 = {
y: [1323,1070,849,1312,1214,1264,680,2006,1625,0,1199,1770,1880,708,603,649,1384,732,2312,92,1377,1125,1219,1757,1207,2397,1190,1818,2846,1200,1685,1563,1203,1059,820,4303,812,3640,1924,4185,1269,2263,1140,1210,1638,1362,4915,1594,683,1222],
mode: 'markers'
};
var trace2 = {
y: [5870,1574,1372,2093,1361,1388,615,1927,947,,1040,,,638,546,542,1051,637,4161,289,1103,0,1308,1658,1340,2198,1245,1568,2392,1297,1583,1281,1282,697,482,3633,653,3233,2096,3815,1401,2116,867,1232,1420,1010,4091,478,208,1262],
mode: 'lines'
};
var trace3 = {
y: [1141,1324,424,668,414,407,494,1763,1100,,522,360,108,474,145,621,689,234,154,40,303,364,407,1133,347,1527,358,1745,1223,345,1131,1024,365,754,614,1894,287,5332,363,568,335,1545,1294,383,1255,1107,2090,612,66,390],
mode: 'lines+markers'
};
var data = [ trace1, trace2, trace3 ];
var layout = {
xaxis: {
ticktext: [24346247,24346247,24346247,24346247,24332892,24332892,24332892,24332670,24332670,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24316962,24316962,24316962,24290013,24290013,24290013,24290013,24290013,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933],
tickvals: [24346247,24346247,24346247,24346247,24332892,24332892,24332892,24332670,24332670,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24330025,24316962,24316962,24316962,24290013,24290013,24290013,24290013,24290013,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933,23738933],
},
};
Plotly.newPlot('myDiv', data, layout, {showSendToCloud: true});
Example of x axis labels not showing up through codepen.
If you do not set x values for your traces, they are automatically assigned x values from 0 to n. Your ticktexts will therefore only be visible if your tickval array is [0, 1, 2, 3, ..., n], see this jsFiddle: https://jsfiddle.net/9okdx4b2/
I have 3 different values for each grouped bar. I want to sum those 3 values and display the sum on top of each column - Σ59 and Σ89.
I'm testing code below which is not working correctly. Instead of column values, number 59 is displayed above every single column.
formatter: function(value, ctx) {
console.log(ctx.chart.data.datasets)
let sum = 0;
for (var i = 0; i < ctx.chart.data.datasets.length; i++) {
sum += parseInt(ctx.chart.data.datasets[i].data[0]);
}
return sum;
}
you can try something like this fiddle, but i did not format and position the labels as of now, you can do it as you wish.
"onComplete": function() {
var chartInstance = this.chart,
ctx = chartInstance.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
var sums = [0, 0, 0];
this.data.datasets.forEach(function(dataset, i) {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach(function(bar, index) {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y);
sums[index] += data;
});
});
sums.forEach(function(v, i) {
ctx.fillText(v, 150*(i+1)+(i*50), 40);
});
}
The formatter is called for each datalabel, meaning for every bar. That's the reason why you get the same value on top of every bar.
Possible solutions would be either to plot an "invisible" bar for the combined value or check inside the formatter function if it is called for the centered bar. Then you could use mulitline labels to create a label which has the value for the current bar and the combined value as well.
Edit:
After thinking about it the easiest way would be to use mixed charts. You can just calculate your combined values for each group and add a chart for these values. For example you add a line chart with showLines: false.
new Chart('myMixedCharts', {
type: 'bar',
data: {
labels: ['foo', 'bar'],
datasets: [
{
label: "Value 1",
data: [12, 5]
},
{
label: "Value 2",
data: [7, 8]
},
{
label: "Group value",
data: [19, 13],
type: "line",
showLines: false
}
]
}
});
Or as jsFiddle
Language: JavaScript
Framework: Plotly
I have a requirement where i want x-Axis values to be colored individually instead of coloring all the values in x-Axis.
I tried below code, but it does the same thing to all the values on axis.
Here the color 'red' gets applied to all the values on x-Axis. I need each value to be colored based on the colors mentioned in the array 'col' in below code.
var data = [{
x: ['giraffes', 'orangutans', 'monkeys'],
y: [20, 14, 23],
type: 'bar'
}];
var col = ['red','black','yellow'];
var layout = {
xaxis : {
tickangle : -45,
tickfont : {
size : 16,
color : 'red'
}
}
};
Plotly.newPlot('myDiv', data,layout);
If you want to color the bars individually you would need to assign the colors to the color attribute of the marker object inside your data.
If you want to color the axis' ticks individually there is no way of doing it directly in plotly. tickfont color only takes a single color but this should not stop us. The tick text is inside a SVG element with the class name xtick. We can select it and override its fill aka color with our colors.
var col = ['red','black','yellow'];
var data = [{
x: ['giraffes', 'orangutans', 'monkeys'],
y: [20, 14, 23],
type: 'bar',
marker: {color: col}
}];
var layout = {
xaxis : {
tickangle : -45,
tickfont : {
size : 16,
color : 'red'
}
}
};
Plotly.newPlot('myDiv', data,layout);
var ticks = document.getElementsByClassName('xtick');
for (var i = 0; i < ticks.length; i += 1) {
ticks[i].getElementsByTagName('text')[0].style.fill = col[i % col.length];
}
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='myDiv'></div>
I have a area chart which is having a dynamic point that will be added to chart.I got this http://jsfiddle.net/rjpjwve0/
but it looks like the point gets displayed first and then after a delay the chart draws back. Now i want to display the last point which will be a animated point and it should travel with chart without delay in rendering.
Could any one help me to achieve this.
I put together a test, and it seems to work well.
I updated the load event to add a second series, using the same series.data[len -1] values; then in the setInterval portion, we update that new point at each iteration.
That way, by updating the existing marker rather than destroying one marker and creating another, the animation works as desired.
Code:
events: {
load: function () {
var series = this.series[0],
len = series.data.length;
//-------------------------------------
//added this part ->
this.addSeries({
id: 'end point',
type: 'scatter',
marker: {
enabled:true,
symbol:'circle',
radius:5,
fillColor:'white',
lineColor: 'black',
lineWidth:2
},
data: [[
series.data[len - 1].x,
series.data[len - 1].y
]]
});
var series2 = this.get('end point');
//-------------------------------------
setInterval(function () {
var x = (new Date()).getTime(),
y = Math.random();
len = series.data.length;
series.addPoint([x,y], true, true);
//and added this line -->
series2.data[0].update([x,y]);
}, 1000);
}
}
Fiddle:
http://jsfiddle.net/jlbriggs/a6pshutt/
You can try this :
series: [{
name: 'Random data',
marker : {
enabled : false,
lineWidth: 0,
radius: 0
},
data: (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(),
i;
for (i = -19; i <= 0; i += 1) {
data.push({
x: time + i * 1000,
y: Math.random()
});
}
return data;
}())
}]
Its works.
Greg.
Currently, I have a plot that supports "lockable" points. I register a plotclick event, highlight the point, and display a tooltip that I give the id of "lockedPoint" + item.dataindex. I also have a zoom feature that uses jquery.flot.selection.js. By using this, I modify my x and y axis maximums and minimums, and I replot my data (essentially throwing away the old data). I am trying to preserve the "locked points" when zooming.
One solution I have thought of is when gathering my data, I can specifically push the point into the correct place in the series that it needs to be if it is within range of the zoom and then highlight the point. However, this does not seem to be working correctly.
I store the data about "locked points" in an associative array initialized like this.
for (var i = 1; i < 5; i++){
lockedPoints["Series " + i] = [];
}
Then I allow a maximum of three items to be pushed onto each array (max of three lockable points per series). I would replace the point in the array with the new highlighted point (I believe the only thing that would change would be the dataindex). Is it possible that I could make points survive zooming by pushing them into the data series when gathering data?
function gatherData(kElement, a0Element){
//PRE: kElement is the id of the element containing the rate constant, and a0Element is the id of the element
// containing the molarity
//POST: FCTVAL is a data series in the format of {data: data, lines: {show: true}, color: "color", label: "label"}
var xData = []; //x-coordinates
var yData = []; //y-coordinates
var data = []; //array of coordinate pairs
var startingPoint; //least x-value to graph
var finishingPoint; //greatest x-value to graph
var range; //range of x-values
var interval; //value to evenly space x-values for calculations
var current; //current value of x-coordinate for which we are
// calculating a y-value
var labelParent; //parent node of x-axis labels
var k; //rate constant value
var molarValue; //molarity value
var result; //result of the rate equation
numXPoints = 1001;
if (document.getElementById("logCheck").value == "On"){ //graph logarithmically
logarithmic = true;
}
else{ //graph decay
logarithmic = false;
}
if (document.getElementById("blackWhite").value == "On"){
blackWhite = true;
}
else{
blackWhite = false;
}
k = document.getElementById(kElement).value;
molarValue = document.getElementById(a0Element).value;
startingPoint = minX; //we will say time starts at 0 always for this plot
finishingPoint = maxX;
range = finishingPoint - startingPoint; //calculated range for determining points to plot
interval = range / numXPoints; //we will graph numXPoints points
current = startingPoint;
result = molarValue * Math.pow(Math.E, (-k * current));
if (logarithmic){ //for logarithmic calculations
result = Math.log(result);
}
if (result > maxValue){ //store largest y-value
maxValue = result;
}
for (var i = 0; i < numXPoints; i++){ //store x-values and calculated y-values
// and find max y-value
xData[i] = current;
yData[i] = result;
current += interval;
result = molarValue * Math.pow(Math.E, (-k * current));
if (logarithmic){ //for logarithmic calculations
result = Math.log(result);
}
if (yData[i] > maxValue){ //store largest y-value
maxValue = yData[i];
}
if (yData[i] < minValue && minValue > -400){ //store smallest y-value
minValue = yData[i];
}
}
for (var i = 0; i < numXPoints; i++){ //combine coordinates into one series
data[i] = [xData[i], yData[i]];
}
//modified jquery.flot.js to support dashed line hover.
//values modified were pointRadius and radius in the drawPointHighlight method.
if (blackWhite == true){
switch(kElement){
case "kValue1":
return {points:{show: true, radius: 0}, data: data, lines:{show: true}, color: "black", label: "Series 1", shadowSize: 0};
break;
case "kValue2":
return {points:{show: true, radius: 0}, data: data, dashes:{show: true, dashLength: 2}, color: "black", label: "Series 2", shadowSize: 0};
break;
case "kValue3":
return {points:{show: true, radius: 0}, data: data, dashes:{show: true, dashLength: 10}, color: "black", label: "Series 3", shadowSize: 0};
break;
case "kValue4":
return {points:{show: true, radius: 0}, data: data, dashes:{show: true, dashLength: 20}, color: "black", label: "Series 4", shadowSize: 0};
break;
}
}
else{
switch (kElement){ //return proper object to match flot graph description
case "kValue1":
return {points:{show: false, radius: 0}, data: data, lines:{show: true}, color: "red", label: "Series 1"};
break;
case "kValue2":
return {points:{show: false, radius: 0}, data: data, lines:{show: true}, color: "blue", label: "Series 2"};
break;
case "kValue3":
return {points:{show: false, radius: 0}, data: data, lines:{show: true}, color: "green", label: "Series 3"};
break;
case "kValue4":
return {points:{show: false, radius: 0}, data: data, lines:{show: true}, color: "gold", label: "Series 4"};
break;
}
}
}
I can find a way to deal with the tooltip removal, but highlighting the same point is the most trivial part.
If you use a combination of setupGrid and draw, the highlights will persist between redraws and you won't need to manually reapply (like you would if you re-init).
Also, to manipulate the data between re-draws (say on the zoom selection), use a combination of getData and setData:
$("#flot_chart").bind("plotselected", function (event, ranges) {
var fr = ranges.xaxis.from;
var to = ranges.xaxis.to;
$.each(plot.getXAxes(), function(_, axis) {
var opts = axis.options;
opts.min = fr;
opts.max = to
});
//pad data points, so the hover effect doesn't look spotty
var series = plot.getData(); // get series
series[0].data = []; // clear it out
for (var i = fr; i < to; i+=(to-fr)/100){
series[0].data.push([i,Math.sin(i)]); // push in data with a suitable increment to i
}
plot.setData(series); // set the new data
plot.setupGrid(); // redo the grid
plot.draw(); // redraw the plot
plot.clearSelection();
});
Here's a fiddle example.