I have a bar charts with 3 categories in Dc.Js
I simply want to display the percentage of each row:
/ Construct the charts
xdata = crossfilter(data);
runDimension = ndx.dimension(function(d) {return "run-"+d.Run;})
speedSumGroup = runDimension.group().reduceSum(function(d) {return d.Speed * d.Run;});
var all = xdata.groupAll();
dataCount.dimension(xdata)
.group(all);
// Define the crossfilter dimensions
cities = xdata.dimension(function (d) { return d.City; });
locations = xdata.dimension(function (d) { return d.all; });
var districttype = xdata.dimension(function (d) { return d.zip; });
var wardTypes = xdata.dimension(function (d) { return d.ward; });
var coordinates = xdata.dimension(function(d) { return d.geo; });
var type = xdata.dimension(function(d) { return d.type; });
// Marker Chart
typeChart.width($('#type-chart').innerWidth()-30)
.height(250)
.colors(commonChartBarColor)
.margins({top: 10, left: 20, right: 10, bottom: 20})
.group(type.group())
.dimension(type)
.elasticX(true)
.on("filtered", onFilt)
.label(function (d) {
return d.data.key + "(" + Math.floor(d.data.value / all.value() * 100) + "%)";
});
I've tried the label function but its not working.
Error: Unable to get property 'key' of undefined or null reference
How do i do that?
Solution:
typeChart.width($('#type-chart').innerWidth()-30)
.height(250)
.colors(commonChartBarColor)
.margins({top: 10, left: 20, right: 10, bottom: 20})
.group(type.group())
.dimension(type)
.elasticX(true)
.ordering(function(d) {
return -d.value
})
.label(function (d) {
if (typeChart.hasFilter() && !typeChart.hasFilter(d.key))
return d.key + " (0%)";
var label = d.key;
if(all.value())
label += " (" + Math.floor(d.value / all.value() * 100) + "%)";
return label;
})
.xAxis().ticks(5);
I´ve implemented the code of a Plotly onclick-method mentioned on Plotly.js create a point on click, but on my PCs the clickmethod don´t works perfectly. The problem is, that if I click on the graph, e.layerX and e.layerY return 0.
The code in the movemethod works perfect, even though it´s pretty much the same as in the clickmethod.
Here is my Code:
var maxXGraph = 24;
var maxYGraph = 36;
var touchobj;
var lastTouchDownXY = [0, 0];
var xValueArray = ['0.25', '12.25', '22.23'];
var yValueArray = [1, 3, 35];
var data = [ {
x: xValueArray,
y: yValueArray,
type: 'scatter'
}];
var layout = {
hovermode: 'closest',
xaxis: {
autorange: true,
range: [0, maxXGraph],
type: 'linear'
},
yaxis: {
autorange: true,
range: [0, maxYGraph],
type: 'linear'
}
};
Plotly.newPlot('myChart', data, layout);
var graph = document.getElementById('myChart');
Number.prototype.between = function(min, max) {
return this >= min && this <= max;
};
Plotly.d3.select(".plotly").on('click', function(d, i) {
var e = Plotly.d3.event;
var bg = document.getElementsByClassName('bg')[0];
alert(e.layerX); //returns 0 on graph
alert(e.layerY); //returns 0 on graph
var x = ((e.layerX - bg.attributes['x'].value + 4)/
(bg.attributes['width'].value)) * (graph.layout.xaxis.range[1] -
graph.layout.xaxis.range[0]) + graph.layout.xaxis.range[0];
var y = ((e.layerY - bg.attributes['y'].value + 4) /
(bg.attributes['height'].value)) * (graph.layout.yaxis.range[0] -
graph.layout.yaxis.range[1]) + graph.layout.yaxis.range[1];
if (x.between(graph.layout.xaxis.range[0],
graph.layout.xaxis.range[1]) &&
y.between(graph.layout.yaxis.range[0],
graph.layout.yaxis.range[1])) {
xValueArray.push(x);
yValueArray.push(y);
}
data = [ {
x: xValueArray,
y: yValueArray,
type: 'scatter'
}];
Plotly.newPlot('myChart', data, layout);
});
Plotly.d3.select(".plotly").on('mousemove', function(d, i) {
var e = Plotly.d3.event;
var bg = document.getElementsByClassName('bg')[0];
var x = ((e.layerX - bg.attributes['x'].value + 4) /
(bg.attributes['width'].value)) * (graph.layout.xaxis.range[1] -
graph.layout.xaxis.range[0]) + graph.layout.xaxis.range[0];
var y = ((e.layerY - bg.attributes['y'].value + 4) /
(bg.attributes['height'].value)) * (graph.layout.yaxis.range[0] -
graph.layout.yaxis.range[1]) + graph.layout.yaxis.range[1];
if (x.between(graph.layout.xaxis.range[0], graph.layout.xaxis.range[1])
&& y.between(graph.layout.yaxis.range[0], graph.layout.yaxis.range[1]))
{
console.log("Location X:"+x+" Y"+y)
document.getElementById("xvalue").value = x;
document.getElementById("yvalue").value = y;
}
});
Have anybody the same problem or event better, a solution.
Thank you in advance
I tried to erase negative ticks from my NVD3 line chart (with data includes 0 only)
but It seems impossible what I wanted to do...
I want to set the line bottom when I throw data what includes 0 only.
Is there another way? or just I had a mistake?
code:
nv.addGraph(function() {
//DATA.B includes only 0 data, the value must be "data>0"
data = DATA.A,DATA.B;
var chart = nv.models.linePlusBarChart()
.margin({top: 30, right: 60, bottom: 50, left: 70})
.x(function(d,i) { return i })
.y(function(d,i) { return d[1] });
chart.xAxis.tickFormat(function(d) {
var dx = data[0].values[d] && data[0].values[d][0] || 0;
return d3.time.format('%Y-%m-%d')(new Date(dx))
});
chart.y1Axis
.tickFormat(d3.format(',f'))
.tickSize(0,6);
chart.y2Axis
.tickFormat(function(d) { return d3.format(',f')(d) + '%' });
chart.bars.forceY([0]);
d3.select($node).datum(data).transition().duration(0).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
thanks
I have two row charts and need to show the 2nd chart after i clicked (selectetd one) on the first row chart. how can i make it?
I can't add a js fiddle, because i'm getting my data from a database.
var TestCaseRow = dc.rowChart("#TestCaserowchart");
var TestCaseDim = perfData.dimension(function (d) {
return d.TestCase;
});
var clickGroup = TestCaseDim.group().reduceCount(function (d) {
return d.x;
});
var filtered_groupTestCase = remove_empty_bins(clickGroup);
TestCaseRow
.width(1100)
.height(filtered_groupTestCase.all().length*18)
.margins({ top: 5, left: 10, right: 10, bottom: 20 })
.dimension(TestCaseDim)
.group(filtered_groupTestCase)
.elasticX(true);
//my other row chart
var testscriptRow = dc.rowChart("#testscriptrowchart");
var testscriptDim = perfData.dimension(function (d) {
return d.TestScript;
});
var ClickTestscriptGroup = testscriptDim.group().reduceCount(function (d) {
return d.x;
});
var filtered_groupTestScript = remove_empty_bins(ClickTestscriptGroup);
testscriptRow
.width(1100)
.height(filtered_groupTestScript.all().length*40)
.margins({ top: 5, left: 10, right: 10, bottom: 20 })
.dimension(testscriptDim)
.group(filtered_groupTestScript)
.elasticX(true);
Register an event-handler on the first chart with .on('filtered', function(chart, filter){...}). Within that function, check if the 2nd chart is displayed and if it is not, do whatever you need to do to display it.
I am trying to insert a x3d object via ajax callback but the object doesn't appear. I copied the source code of the page then placed it on a new page then the x3d object showed. Am I missing something here? Is there a work around for this? thanks.
html:
<div id="divPlot" style="border: 1px solid black"></div>
<button onclick="add_x3d()">Click</button>
<script>
d3.select('html').style('height','100%').style('width','100%');
d3.select('body').style('height','100%').style('width','100%');
d3.select('#divPlot').style('width', "450px").style('height', "450px");
function add_x3d() {
scatterPlot3d(d3.select('#divPlot'));
}
</script>
javascript:
function scatterPlot3d(parent){
var rows = [
{"SITE":"1","SIGNAME":"A","X":10,"Y":10,"Z":111},
{"SITE":"1","SIGNAME":"B","X":200,"Y":10,"Z":222},
{"SITE":"2","SIGNAME":"A","X":10,"Y":40,"Z":333},
{"SITE":"2","SIGNAME":"B","X":200,"Y":40,"Z":444},
{"SITE":"3","SIGNAME":"A","X":10,"Y":70,"Z":555},
{"SITE":"3","SIGNAME":"B","X":200,"Y":70,"Z":666},
{"SITE":"4","SIGNAME":"A","X":10,"Y":100,"Z":777},
{"SITE":"4","SIGNAME":"B","X":200,"Y":100,"Z":888}
];
var x3d = parent
.append("x3d")
.style("width", parseInt(parent.style("width")) + "px")
.style("height", parseInt(parent.style("height")) + "px")
.style("border", "none");
var scene = x3d.append("scene");
scene.append("orthoviewpoint")
.attr("centerOfRotation", [5, 5, 5])
.attr("fieldOfView", [-5, -5, 15, 15])
.attr("orientation", [-0.5, 1, 0.2, 1.12 * Math.PI / 4])
.attr("position", [8, 4, 15]);
// Used to make 2d elements visible
function makeSolid(selection, color) {
selection.append("appearance")
.append("material")
.attr("diffuseColor", color || "black");
return selection;
}
function constVecWithAxisValue(otherValue, axisValue, axisIndex) {
var result = [otherValue, otherValue, otherValue];
result[axisIndex] = axisValue;
return result;
}
var XAxisMin = d3.min(rows, function(d){return d.X;});
var XAxisMax = d3.max(rows, function(d){return d.X;});
var XAxisDel = XAxisMax-XAxisMin;
var YAxisMin = d3.min(rows, function(d){return d.Y;});
var YAxisMax = d3.max(rows, function(d){return d.Y;});
var YAxisDel = YAxisMax-YAxisMin;
var ZAxisMin = d3.min(rows, function(d){return d.Z;});
var ZAxisMax = d3.max(rows, function(d){return d.Z;});
var ZAxisDel = ZAxisMax-ZAxisMin;
function AxisMin(axisIndex) {
return [XAxisMin, ZAxisMin, YAxisMin][axisIndex];
}
function AxisMax(axisIndex) {
return [XAxisMax, ZAxisMax, YAxisMax][axisIndex];
}
function AxisDel(axisIndex) {
return [XAxisDel, ZAxisDel, YAxisDel][axisIndex];
}
function axisName(name, axisIndex) {
return AxisKeys[axisIndex] + name;
}
function get2DVal(){
if (XAxisDel >= YAxisDel){
return XAxisDel;
} else {
return YAxisDel;
}
}
function ConvAxisRange(inputVal, axisIndex) {
var val;
if (axisIndex === 0 || axisIndex === 2) {
val = d3.scale.linear()
.domain([0, delta2D])
.range(AxisRange);
} else {
val = d3.scale.linear()
.domain([0, ZAxisDel])
.range(AxisRange);
}
return val(inputVal);
}
function ConvAxisRange2D(inputVal) {
var val = d3.scale.linear()
.domain([0, delta2D])
.range(AxisRange);
return val(inputVal);
}
var AxisKeys = ["X", "HEIGHT", "Y"];
var AxisRange = [0, 10];
var scales = [];
var AxisLen;
var duration = 300;
var delta2D = get2DVal();
var ArrayOfColors = ["#0000FF", "#00FFFF", "#00FF00", "#FFFF00", "#FF0000"];
var colorScale = d3.scale.linear()
.domain([0, ZAxisDel*0.25, ZAxisDel*0.50, ZAxisDel*0.75, ZAxisDel])
.range(ArrayOfColors);
function initializeAxis(axisIndex) {
var key = AxisKeys[axisIndex];
drawAxis(axisIndex, key, duration);
var scaleDel = AxisDel(axisIndex);
var rotation = [[0, 0, 0, 0], [0, 0, 1, Math.PI / 2], [0, 1, 0, -Math.PI / 2]];
var newAxisLine = scene.append("transform")
.attr("class", axisName("Axis", axisIndex))
.attr("rotation", (rotation[axisIndex]))
.append("shape");
newAxisLine
.append("appearance")
.append("material")
.attr("emissiveColor", "lightgray");
newAxisLine
.append("polyline2d")
// Line drawn along y axis does not render in Firefox, so draw one
// along the x axis instead and rotate it (above).
.attr("lineSegments", "[" + ConvAxisRange(scaleDel, axisIndex) + " 0, 0 0]");
// axis labels
var newAxisLabel = scene.append("transform")
.attr("class", axisName("AxisLabel", axisIndex))
.attr("translation", constVecWithAxisValue(0, ConvAxisRange(scaleDel*1.15, axisIndex), axisIndex));
var newAxisLabelShape = newAxisLabel
.append("billboard")
.attr("axisOfRotation", "0 0 0") // face viewer
.append("shape")
.call(makeSolid);
var labelFontSize = 0.6;
newAxisLabelShape
.append("text")
.attr("class", axisName("AxisLabelText", axisIndex))
.attr("solid", "true")
.attr("string", key)
.append("fontstyle")
.attr("size", labelFontSize)
.attr("family", "SANS")
.attr("justify", "END MIDDLE");
}
// Assign key to axis, creating or updating its ticks, grid lines, and labels.
function drawAxis(axisIndex, key, duration) {
var scale;
if (axisIndex === 0 || axisIndex === 2) {
scale = d3.scale.linear()
.domain([AxisMin(axisIndex), AxisMax(axisIndex)]) // demo data range
.range([0, ConvAxisRange2D(AxisDel(axisIndex))]);
} else {
scale = d3.scale.linear()
.domain([AxisMin(axisIndex), AxisMax(axisIndex)]) // demo data range
.range(AxisRange);
}
scales[axisIndex] = scale;
var numTicks = 5;
var tickSize = 0.1;
var tickFontSize = 0.5;
// ticks along each axis
var ticks = scene.selectAll("." + axisName("Tick", axisIndex))
.data(scale.ticks(numTicks));
var newTicks = ticks.enter()
.append("transform")
.attr("class", axisName("Tick", axisIndex));
newTicks.append("shape").call(makeSolid)
.append("box")
.attr("size", tickSize + " " + tickSize + " " + tickSize);
// enter + update
ticks.transition().duration(duration)
.attr("translation", function(tick) {
return constVecWithAxisValue(0, scale(tick), axisIndex);
});
ticks.exit().remove();
// tick labels
var tickLabels = ticks.selectAll("billboard shape text")
.data(function(d) {
return [d];
});
var newTickLabels = tickLabels.enter()
.append("billboard")
.attr("axisOfRotation", "0 0 0")
.append("shape")
.call(makeSolid);
newTickLabels.append("text")
.attr("string", scale.tickFormat(10))
.attr("solid", "true")
.append("fontstyle")
.attr("size", tickFontSize)
.attr("family", "SANS")
.attr("justify", "END MIDDLE");
tickLabels // enter + update
.attr("string", scale.tickFormat(10));
tickLabels.exit().remove();
}
function plotData() {
if (!rows) {
console.log("no rows to plot.");
return;
}
var x = scales[0], z = scales[1], y = scales[2];
var sphereRadius = 0.2;
// Draw a sphere at each x,y,z coordinate.
var datapoints = scene.selectAll(".datapoint").data(rows);
datapoints.exit().remove();
var newDatapoints = datapoints.enter()
.append("transform")
.attr("class", "datapoint")
.attr("scale", [sphereRadius, sphereRadius, sphereRadius])
.append("shape");
newDatapoints
.append("appearance")
.append("material");
newDatapoints
.append("sphere");
// Does not work on Chrome; use transform instead
//.attr("radius", sphereRadius)
datapoints.selectAll("shape appearance material")
.attr("diffuseColor", function(row){
return colorScale(row.Z-ZAxisMin);
});
datapoints.attr("translation", function(row) {
return x(row.X) + " " + z(row.Z) + " " + y(row.Y);
});
}
function initializePlot() {
initializeAxis(0);
initializeAxis(1);
initializeAxis(2);
}
initializePlot();
}
You cannot add the whole x3d element and a scene dynamically per se since x3dom is initialized with an window.onload event. This should be part of your HTML document beforehand. Then you can add the elements (views, shapes etc) to the scene.
But I heard sometime ago something about a reload function (https://github.com/x3dom/x3dom/blob/1.7.1/src/Main.js#L327) in the mailing list, sadly this is not well documented:
/** Initializes an <x3d> root element that was added after document load. */
x3dom.reload = function() {
onload();
};
This should be doing what you want.