Related
I'm trying to add values to nodes of plotly graph but there is an issue.
Code:
<html>
<head>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<style>
.graph-container {
display: flex;
justify-content: center;
align-items: center;
}
.main-panel {
width: 70%;
float: left;
}
.side-panel {
width: 30%;
background-color: lightgray;
min-height: 300px;
overflow: auto;
float: right;
}
</style>
</head>
<body>
<div class="graph-container">
<div id="myDiv" class="main-panel"></div>
<div id="lineGraph" class="side-panel"></div>
</div>
<script>
var nodes = [
{ x: 0, y: 0, z: 0, value: [1, 2, 3] },
{ x: 1, y: 1, z: 1, value: [4, 5, 6] },
{ x: 2, y: 0, z: 2, value: [7, 8, 9] },
{ x: 3, y: 1, z: 3, value: [10, 11, 12] },
{ x: 4, y: 0, z: 4, value: [13, 14, 15] }
];
var edges = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
{ source: 3, target: 4 }
];
var x = [];
var y = [];
var z = [];
for (var i = 0; i < nodes.length; i++) {
x.push(nodes[i].x);
y.push(nodes[i].y);
z.push(nodes[i].z);
}
var xS = [];
var yS = [];
var zS = [];
var xT = [];
var yT = [];
var zT = [];
for (var i = 0; i < edges.length; i++) {
xS.push(nodes[edges[i].source].x);
yS.push(nodes[edges[i].source].y);
zS.push(nodes[edges[i].source].z);
xT.push(nodes[edges[i].target].x);
yT.push(nodes[edges[i].target].y);
zT.push(nodes[edges[i].target].z);
}
var traceNodes = {
x: x, y: y, z: z,
mode: 'markers',
marker: { size: 12, color: 'red' },
type: 'scatter3d',
text: [0, 1, 2, 3, 4],
hoverinfo: 'text',
hoverlabel: {
bgcolor: 'white'
},
customdata: nodes.map(function(node) {
if (node.value !== undefined)
return node.value;
}),
type: 'scatter3d'
};
var layout = {
margin: { l: 0, r: 0, b: 0, t: 0 }
};
Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });
document.getElementById("myDiv").on("plotly_click", function(data){
var nodeIndex = data.points[0].pointIndex;
var values = nodes[nodeIndex].value;
console.log(values);
Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
margin: { t: 0 }
});
});
</script>
</body>
</html>
var values = nodes[nodeIndex].value; is not able to access the node values.
Suggestions on how to fix this will be really helpful.
EDIT0:
<html>
<head>
<script src="https://cdn.plot.ly/plotly-1.58.5.min.js"></script>
<style>
.graph-container {
display: flex;
justify-content: center;
align-items: center;
}
.main-panel {
width: 70%;
float: left;
}
.side-panel {
width: 30%;
background-color: lightgray;
min-height: 300px;
overflow: auto;
float: right;
}
</style>
</head>
<body>
<div class="graph-container">
<div id="myDiv" class="main-panel"></div>
<div id="lineGraph" class="side-panel"></div>
</div>
<script>
var nodes = [
{ x: 0, y: 0, z: 0, value: [1, 2, 3] },
{ x: 1, y: 1, z: 1, value: [4, 5, 6] },
{ x: 2, y: 0, z: 2, value: [7, 8, 9] },
{ x: 3, y: 1, z: 3, value: [10, 11, 12] },
{ x: 4, y: 0, z: 4, value: [13, 14, 15] }
];
var edges = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
{ source: 3, target: 4 }
];
var x = [];
var y = [];
var z = [];
for (var i = 0; i < nodes.length; i++) {
x.push(nodes[i].x);
y.push(nodes[i].y);
z.push(nodes[i].z);
}
var xS = [];
var yS = [];
var zS = [];
var xT = [];
var yT = [];
var zT = [];
for (var i = 0; i < edges.length; i++) {
xS.push(nodes[edges[i].source].x);
yS.push(nodes[edges[i].source].y);
zS.push(nodes[edges[i].source].z);
xT.push(nodes[edges[i].target].x);
yT.push(nodes[edges[i].target].y);
zT.push(nodes[edges[i].target].z);
}
var traceNodes = {
x: x, y: y, z: z,
mode: 'markers',
marker: { size: 12, color: 'red' },
type: 'scatter3d',
text: [0, 1, 2, 3, 4],
hoverinfo: 'text',
hoverlabel: {
bgcolor: 'white'
},
customdata: nodes.map(function(node) {
if (node.value !== undefined)
return node.value;
}),
type: 'scatter3d'
};
var layout = {
margin: { l: 0, r: 0, b: 0, t: 0 }
};
Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });
const ymax = Math.max(...nodes.map(n => n.value).flat());
document.getElementById("myDiv").on("plotly_click", function(data){
var nodeIndex = data.points[0].pointNumber;
var values = nodes[nodeIndex].value;
console.log(values);
Plotly.newPlot('lineGraph', [{ x: [0, 1, 2], y: values, type: 'scatter3d'}], {
margin: { t: 0 },
yaxis: {autorange: false, range: [0, ymax + 1]}
});
});
</script>
</body>
</html>
I made the corrections suggested in the answer below but the I am still not able to see the line graph when nodes in the main panel are clicked.
Use pointNumber instead of pointIndex. You also need to fix the type of the second plot, for which I also suggest to set a fixed axis range (otherwise the axis will reset for each selected point) :
// max y value for the line plot
const ymax = Math.max(...nodes.map(n => n.value).flat());
document.getElementById('myDiv').on('plotly_click', function(data){
var nodeIndex = data.points[0].pointNumber;
var values = nodes[nodeIndex].value;
Plotly.newPlot('lineGraph', [{
type: 'scatter',
mode: 'lines',
x: [0, 1, 2],
y: values
}], {
margin: { t: 0 },
yaxis: {autorange: false, range: [0, ymax + 1]}
});
});
For reference, here is the event data structure for 3d plots :
{
points: [{
curveNumber: 2, // index in data of the trace associated with the selected point
pointNumber: 2, // index of the selected point
x: 5, // x value
y: 600, // y value
z: 12, // z value
data: {/* */}, // ref to the trace as sent to Plotly.newPlot associated with the selected point
fullData: {/* */}, // ref to the trace including all of the default attributes
xaxis: {/* */}, // ref to x-axis object (i.e layout.xaxis) associated with the selected point
yaxis: {/* */} // ref to y-axis object " "
zaxis: {/* */} // ref to z-axis object " "
}, {
/* similarly for other selected points */
}]
}
One last thing, don't use plotly-latest.js or its minified version anymore. While still referenced here and there in the documentation, they are stuck at version 1.58.5.
Please note that as of v2 the "plotly-latest" outputs will no longer be updated on the CDN, and will stay at the last v1 patch v1.58.5. Therefore, to use the CDN with plotly.js v2 and higher, you must specify an exact plotly.js version.
Here is the complete code :
<html>
<head>
<script src="https://cdn.plot.ly/plotly-2.18.1.min.js"></script>
<style>
.graph-container {
display: flex;
justify-content: center;
align-items: center;
}
.main-panel {
width: 70%;
float: left;
}
.side-panel {
width: 30%;
background-color: lightgray;
min-height: 300px;
overflow: auto;
float: right;
}
</style>
</head>
<body>
<div class="graph-container">
<div id="myDiv" class="main-panel"></div>
<div id="lineGraph" class="side-panel"></div>
</div>
<script>
var nodes = [
{ x: 0, y: 0, z: 0, value: [1, 2, 3] },
{ x: 1, y: 1, z: 1, value: [4, 5, 6] },
{ x: 2, y: 0, z: 2, value: [7, 8, 9] },
{ x: 3, y: 1, z: 3, value: [10, 11, 12] },
{ x: 4, y: 0, z: 4, value: [13, 14, 15] }
];
var edges = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
{ source: 3, target: 4 }
];
var x = [];
var y = [];
var z = [];
for (var i = 0; i < nodes.length; i++) {
x.push(nodes[i].x);
y.push(nodes[i].y);
z.push(nodes[i].z);
}
var xS = [];
var yS = [];
var zS = [];
var xT = [];
var yT = [];
var zT = [];
for (var i = 0; i < edges.length; i++) {
xS.push(nodes[edges[i].source].x);
yS.push(nodes[edges[i].source].y);
zS.push(nodes[edges[i].source].z);
xT.push(nodes[edges[i].target].x);
yT.push(nodes[edges[i].target].y);
zT.push(nodes[edges[i].target].z);
}
var traceNodes = {
x: x, y: y, z: z,
mode: 'markers',
marker: { size: 12, color: 'red' },
type: 'scatter3d',
text: [0, 1, 2, 3, 4],
hoverinfo: 'text',
hoverlabel: {
bgcolor: 'white'
},
customdata: nodes.map(function(node) {
if (node.value !== undefined)
return node.value;
}),
type: 'scatter3d'
};
var layout = {
margin: { l: 0, r: 0, b: 0, t: 0 }
};
Plotly.newPlot('myDiv', [traceNodes], layout, { displayModeBar: false });
// max y value for the line plot
const ymax = Math.max(...nodes.map(n => n.value).flat());
document.getElementById('myDiv').on('plotly_click', function(data){
var nodeIndex = data.points[0].pointNumber;
var values = nodes[nodeIndex].value;
Plotly.newPlot('lineGraph', [{
type: 'scatter',
mode: 'lines',
x: [0, 1, 2],
y: values
}], {
margin: { t: 0 },
yaxis: {autorange: false, range: [0, ymax + 1]}
});
});
</script>
</body>
</html>
I tried using the stack and offset but it does not seem to work
This is my code:
import React, {
useEffect
} from 'react';
import {
Bar
} from 'react-chartjs-2';
import useWindowWidth from 'wa-shared/src/hooks/useWindowWidth';
const state = {
count: 0,
data: {
labels: [
['Total Users'],
['Users with', 'Active', 'Session'],
['Created 1', 'or More', 'Videos'],
['Shared 1', 'or More', 'Videos']
],
datasets: [{
backgroundColor: '#26863D',
data: [70, 66, 57, 1],
barThickness: '35',
},
{
backgroundColor: '#F2F2F2',
data: [70, 70, 70, 70],
borderRadius: '5',
barThickness: '35',
}
]
}
}
const App = ({}) => {
const width = useWindowWidth();
useEffect(() => {});
return ( <
div className = 'singlebar-chart'
id = "barchart" >
<Bar> data = {
state.data
}
options = {
{
scales: {
x: {
grid: {
display: false,
},
offset: true,
ticks: {
maxRotation: 0,
minRotation: 0,
font: {
size: 8,
}
},
},
y: {
min: 0,
max: 100,
ticks: {
fontColor: '#8A8A8A',
font: {
size: 8,
},
stepSize: 25,
callback: function(value) {
return value + "%"
},
},
scaleLabel: {
display: true,
labelString: "Percentage",
},
grid: {
display: false,
}
}
},
plugins: {
legend: {
display: false,
},
}
}
</Bar>
</div>
)
}
export default App;
.singlebar-chart{
width: 95%;
}
You can use a second x axis and map the other dataset to that axes:
var options = {
type: 'bar',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: 'pink'
},
{
label: '# of Points',
data: [7, 11, 5, 8, 3, 7],
backgroundColor: 'orange',
xAxisID: 'x2'
}
]
},
options: {
scales: {
x: {},
x2: {
display: false // Dont show the axes since it is just a duplicate
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.js"></script>
</body>
Although this gives the exect same result as setting stacked true on the x axis.
While plotting a chart in chart js with y axes steps like 0 573 675 900. When i plot it the spacing is between adjacent points are. can i bring the points evenly spaced?
Consider the image
chart
In this image i want the number 7 to appear exactly in the middle and the chart to scale between 1 and 7 and also 7 and 10 accordingly.
Following is a sample code iam working on:
////////////////////////////////////////////////////////
document.addEventListener("DOMContentLoaded", function() {
var
example = document.getElementById('example1'),
hot;
var headers = ["Red", "Blue", "Yellow", "Green", "Purple", "Orange", "Pink", 'Brown'];
var myData = [
[5, 10, 3, 5, 2, 3, 5, 1],
[9, 9, 3, 10, 8, 7, 7, 2],
[5, 1, 10, 6, 7, 9, 4, 8]
];
var StepValues = [1,7,10];
var rowheaders = ['Mark', 'Anna', 'Diana']
hot = new Handsontable(example, {
data: myData,
rowHeaders: rowheaders,
colHeaders: headers,
readOnly: true,
colWidths: 88,
licenseKey: 'non-commercial-and-evaluation',
fillHandle: {
autoInsertRow: false,
}
});
var options = {
type: 'bar',
data: {
labels: headers,
datasets: [{
label: rowheaders[0],
data: myData[0],
borderWidth: 1,
backgroundColor: 'rgb(255, 236, 217)'
}, {
label: rowheaders[1],
data: myData[1],
borderWidth: 1,
backgroundColor: 'rgb(235, 224, 255)'
}, {
label: rowheaders[2],
data: myData[2],
borderWidth: 1,
backgroundColor: 'rgb(219, 242, 242)'
}]
},
options: {
scales: {
yAxes: [{
ticks: {
reverse: false,
callback: (label) =>{
if(StepValues.includes(label)){
return label;
}
}
}
}]
}
}
}
var ctx = document.querySelector('.chartJSContainer').getContext('2d');
var myChart = new Chart(ctx, options);
});
//////////////////////////////////////////////////////////////////
I get data set from back end api, it will have multiple data labels for the same x and y-axis.How can i achieve this for 'n' values.
I tried with 1,2, and 4 it was working. But not sure if it is the right approach and how can i achieve for 'n'values adjusting row size and col size.
Highcharts.chart('container', {
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
title: {
text: 'Sales per employee per weekday'
},
xAxis: {
min: 0,
categories: ['Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas', 'Maria', 'Leon', 'Anna', 'Tim', 'Laura']
},
yAxis: {
categories: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
title: null,
min: 0
},
colorAxis: {
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend: {
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
plotOptions: {
series: {
borderWidth: 1,
dataLabels: {
enabled: true,
color: '#000000'
},
states: {
inactive: {
opacity: 1
}
}
}
},
series: [{
name: 'Sales per employee',
data: [
[0, 1, 19],
[0, 2, 8],
[0, 3, 24],
[0, 4, 67],
[1, 0, 92],
[9, 4, 91]
]
}, {
rowsize: 0.5,
colsize: 0.5,
color: Highcharts.getOptions().colors[0],
data: [
[-0.25, 0.25, 70],
[0.25, 0.25, 60],
[-0.25, -0.25, 65],
[0.25, -0.25, 34]
]
}]
});
Above is the sample code
I think that your idea is quite good, but to align points easier, you can create only columns or rows.
I created a function below that creates new series for points with the same x and y values and align them in one row.
function getSeries(data) {
var i = 0,
k,
dataLength,
movement,
index = 0,
colSize,
limitVal,
series = [{
data: []
}],
newSeries;
for (i; i < data.length; i++) {
if (
data[i + 1] &&
data[i][0] === data[i + 1][0] &&
data[i][1] === data[i + 1][1]
) {
if (newSeries) {
newSeries.data.push(data[i]);
} else {
newSeries = {
data: [data[i]]
}
}
} else {
if (newSeries) {
newSeries.data.push(data[i]);
dataLength = newSeries.data.length;
newSeries.colsize = colSize = 1 / newSeries.data.length;
movement = dataLength % 2 ? 0 : colSize / 2;
limitVal = colSize * Math.floor(dataLength / 2) - movement;
for (k = -limitVal; k <= limitVal; k += colSize) {
newSeries.data[index][0] += k;
index++;
}
series.push(newSeries);
index = 0;
newSeries = null;
} else {
series[0].data.push(data[i]);
}
}
}
return series
}
Highcharts.chart('container', {
...,
series: getSeries(data)
});
Live demo: https://jsfiddle.net/BlackLabel/9Ltxcgn6/
As said, X axis label is not showing months as expected. What I doing wrong ?
Here is my example code
HTML:
<div id="placeholder"></div>
CSS:
#placeholder {
height: 300px;
}
Javascript:
var d1 = [
[1388530800, 4],
[1393542000, 8],
[1396216800, 3],
[1398808800, 16],
[1401487200, 2],
[1404079200, 2],
[1406757600, 28],
[1409436000, 24],
[1412028000, 0],
[1414710000, 18],
[1417302000, 0],
[1419980400, 11]
];
var d2 = null;
var d3 = null;
var d4 = null;
var d5 = null;
var d6 = [
[1388530800, 2],
[1396303200, 2],
[1398895200, 1],
[1401573600, 1],
[1406844000, 1],
[1409522400, 1],
[1417388400, 1]
];
var data1 = [{
data: d1,
points: {
fillColor: "#d1e399"
},
color: '#d1e399'
}, {
data: d2,
points: {
fillColor: "#ecc0ce"
},
color: '#ecc0ce'
}, {
data: d3,
points: {
fillColor: "#daeaed"
},
color: '#daeaed'
}, {
data: d4,
points: {
fillColor: "#e6ceea"
},
color: '#e6ceea'
}, {
data: d5,
points: {
fillColor: "#edb9a6"
},
color: '#edb9a6'
}, {
data: d6,
points: {
fillColor: "#92e48a"
},
color: '#92e48a'
}];
$.plot($("#placeholder"), data1, {
xaxis: {
mode: "time",
minTickSize: [1, "month"],
tickLength: 1,
ticks: 12
},
yaxis: {
tickSize: 5
},
grid: {
hoverable: true,
borderWidth: 1
},
series: {
lines: {
show: true,
lineWidth: 1,
fill: true,
fillColor: {
colors: [{
opacity: 0.1
}, {
opacity: 0.13
}]
}
},
points: {
show: true,
lineWidth: 2,
radius: 3
},
shadowSize: 0,
stack: true
},
clickable: true,
hoverable: true
});
Code in JSFiddle -> http://jsfiddle.net/v5M9L/11/
Thanks for your help !
I suspect your problem is that your timestamps are in seconds rather than milliseconds. Multiply all your data by 1000 appears to give the result you want:
{ data: d1.map(function(d) { return [d[0] * 1000, d[1]]; }), points: { fillColor: "#d1e399" }, color: '#d1e399'}
http://jsfiddle.net/v5M9L/12/