Creating newline in nvd3.js graph x-axis labels - javascript
so I've been trying to find a way to create new lines in the x-axis labels of my nvd3 graph but nothing seems to work so far. I have referred to these two questions: Newline in labels in d3 charts and nvd3 chart axis label but didn't find a sufficient answer because these are both relating to d3.js graphs. They both have answers relating to using tspan to create the new-line but doesn't seem to work for me no matter how much I play around with it. This is what I have now but it doesn't seem to be correct at all...any help would be appreciated!
nv.addGraph(function () {
var chart = nv.models.multiBarChart().stacked(false).showControls(false);
chart.x(function (d) { return d.x; });
chart.y(function (d) { return d.y; });
chart.yAxis
.axisLabel('Jobs')
//Too many bars and not enough room? Try staggering labels.
chart.staggerLabels(true);
chart.margin().left = 70;
//chart.showValues(true);
var tech_data = technicianReport();
console.log(tech_data[1] + " " + tech_data[2])
$("#date_range").text(tech_data[1] + " - " + tech_data[2]);
$("#tech_title").text("Technician-Advisor Actions");
d3.select('#tech_chart svg')
.datum(tech_data[0])
.transition().duration(500).call(chart);
var insertLinebreaks = function (d) {
var el = d3.select(this).text();
var words = d.description.split('\n');
el.text('');
for (var i = 0; i < words.length; i++) {
var tspan = el.append('tspan').text(words[i]);
if (i > 0)
tspan.attr('x', 0).attr('dy', '15');
}
};
svg = d3.select("tech_chart svg");
svg.selectAll('g.x.axis g text').each(insertLinebreaks);
nv.utils.windowResize(function () { chart.update() });
return chart;
});
Use .wrapLabels parameter from the latest nvd3 source (1.8.1-dev) The parameter wraps long x axis labels. Compare the two screenshots
So you'll come up with
chart.wrapLabels(true);
Related
Coloring hexbin series with d3js
I have a problem with coloring hexbin mesh using d3js. I'm plotting the hexbin series without a problem. But I want for each series a different color gradient. I don't know how to do that. jsbin https://jsbin.com/zogohap/edit?js,output
Take a look at this block var body = d3.select("body"), length = 100, color = d3.scale.linear().domain([1,length]) .interpolate(d3.interpolateHcl) .range([d3.rgb("#007AFF"), d3.rgb('#FFF500')]); for (var i = 0; i < length; i++) { body.append('div').attr('style', function (d) { return 'background-color: ' + color(i); }); }
Unable to get zoom by dragging a rectangle over a d3 series chart to work properly
I am trying to get zoom to work by dragging a rectangle over my series plot to identify the interval of zooming. Here is my plunkr http://plnkr.co/edit/isaHzvCO6fTNlXpE18Yt?p=preview You can see the issue by drawing a rectangle with the mouse over the chart - The new chart overshoots the boundary of the X and Y axes. I thought my group under the svg would take care of the bounds of the series (path) but I am clearly mistaken. After staring at it for a long time, I could not figure it out. Please ignore the angular aspect of the plunkr. I think the issue is somewhere in the //Build series group var series = svgGroup.selectAll(".series") .data(data) .enter().append("g") .attr("class", "series"); //Build each series using the line function series.append("path") .attr("class", "line") .attr("d", function (d) { return line(d.series); }) .attr("id", function (d) { //While generating the id for each series, map series name to the path element. //This is useful later on for dealing with legend clicks to enable/disable plots legendMap[d.name] = this; //Build series id return buildPathId(d.name); }) .style("stroke", function (d) { //Use series name to get the color for plotting return colorFcn(d.name); }) .style("stroke-width", "1px") .style("fill", "none"); Any help with this is appreciated. Thank you very much.
I think the method renderChartWithinSpecifiedInterval(minX, maxX, minY, maxY, pixelCoordinates) maybe has some problem there. It seems the parameter like max_x passed in line 130 are a very big value like time seconds var svg = renderChartWithinSpecifiedInterval(min_X, max_X, min_Y, max_Y, false); max_X,min_X are value like 1415171404335 min_Y = 0, max_Y = 100 But in dragDrop call in line 192 function gEnd(d,i){ svg.selectAll(".zoom-rect").remove(); var svgGp = svg.select("g"); var groupTransform = d3.transform(svgGp.attr("transform")); var xOffset = groupTransform.translate[0]; var yOffset = groupTransform.translate[1]; var xBegin = Math.min(xStart,xDyn) - xOffset; var xEnd = Math.max(xStart,xDyn) - xOffset; var yBegin = Math.min(yStart,yDyn) - yOffset; var yEnd = Math.max(yStart,yDyn) - yOffset; renderChartWithinSpecifiedInterval(xBegin, xEnd, yBegin, yEnd, true); //It seems here the parameters values are all pixels like xBegin = 100, xEnd = 200 } hope it helps!
How do I change XTick format in NVD3?
I would like to change the XTick format of the small chart to also be a date. I have the following which is lifted from this example: function chart(div) { var testdata = loadData(); nv.addGraph(function() { var chart = nv.models.lineWithFocusChart(); chart.xAxis.tickFormat(function(d) { var dx = testdata[0].values[d] && testdata[0].values[d].x || 0; return d3.time.format('%x')(new Date(dx)) }); chart.yAxis .tickFormat(d3.format(',.2f')); chart.y2Axis .tickFormat(d3.format(',.2f')); d3.select(div + ' svg') .datum(loadData()) .transition().duration(500) .call(chart); nv.utils.windowResize(chart.update); return chart; }); } But only the large chart's format changes to date.
There are two ways of fixing the ticks for the second x-axis. The first way is by setting the tickFormat explicitly for the second axis as well. This design follows the traditional paradigm of setting one attribute at a time. var xFormat = function(d) { var dx = testdata[0].values[d] && testdata[0].values[d].x || 0; return d3.time.format('%x')(new Date(dx)); }; chart.xAxis.tickFormat(xFormat); chart.xAxis2.tickFormat(xFormat); The second way, which would avoid code duplication, is setting both the axis together using a special function exposed by the chart API: // This would set both the axis simultaneously chart.xTickFormat(xFormat); This function is present in the code (introduced here) for exactly this purpose. However, as the API is not very stable, it might be removed later.
NVD3 not dealing with large values
I have a graph implemented in NVD3, and I'm having serious trouble with it. NVD3 seems unable to handle datasets which contain large values. The graph is located here: http://brad.kizer.com.ng/. The code for the graph is as so: nv.addGraph(function() { // Get maximum and minimum Y values var minY = 2 >> 30, maxY = 0; data.forEach(function (d) { d.values.forEach(function (s) { minY = Math.min(minY, s.y); maxY = Math.max(maxY, s.y); }); }); var chart = nv.models.stackedArea() .forceY([0, 20]) .height($(container).closest('.chart').height()) .width($(container).closest('.chart').width()); (Object.prototype.toString.call(data) === '[object Array]') || (data = [data]); d3.select(container) .attr('width', $(container).closest('.chart').width()) .attr('height', 250) .datum(data) .transition().duration(500) .call(chart); nv.utils.windowResize(chart.update); return chart; }); I will appreciate any help so much, as this has kept me scratching my head for days.
Solved my problem. The issue was that the data provided for the Y-axis was strings, which made supposedly number addition become string concatenation: "123" + "902" + "384" + "382" == "123902384382"; // (instead of 1791) What I did was walk through the data and convert the strings to numbers.
Adding labels to a pv.Layout.Stack (streamgraph) in Protovis
I'm working with the Protovis library to do a streamgraph of data. I want to label the different layers with the "words" array. I can't seem to get the words to line up how I'd like. I want them to be inserted where the graph is the largest for that particular layer, similar to this site: http://mbostock.github.com/protovis/ex/jobs.html var words = [ "tasty","delicious","yum","scrumpious","dry"]; var data = [ [23,52,6,3,16,35,24,12,35,119,2,5,65,33,81,61,55,122,3,19,2,5,65,33,81,61,55,122,3,19,54,72,85,119,23,52,6,3,16,35], [43,2,46,78,46,25,54,72,85,119,23,52,6,3,16,35,24,12,35,119,23,52,6,3,16,35,24,12,35,119,2,5,65,33,81,61,55,122,3,19], [2,5,65,33,81,61,55,122,3,19,54,72,85,119,23,52,6,3,16,35,2,5,65,33,81,1,5,12,95,14,12,8,84,115,15,27,6,31,6,35], [2,5,6,3,1,6,5,12,32,191,142,22,75,139,27,32,26,13,161,35,21,52,64,35,21,61,55,123,5,142,54,58,8,11,53,2,64,3,16,35], [2,5,65,33,81,61,55,122,3,19,54,72,85,119,23,52,6,3,16,35,2,5,65,33,81,61,55,123,5,142,54,58,8,11,53,2,64,3,16,35]]; var w = 800, h = 300, x = pv.Scale.linear(0, 40).range(0, w), y = pv.Scale.linear(0, 600).range(0, h); var vis = new pv.Panel() .canvas('streamgraph') .width(w) .height(h); vis.add(pv.Layout.Stack) .layers(data) .order("inside-out") .offset("wiggle") .x(x.by(pv.index)) .y(y) .layer.add(pv.Area) .fillStyle(pv.ramp("#aad", "#556").by(Math.random)) .strokeStyle(function () { this.fillStyle().alpha(.5) }); vis.render();
Try this: vis.add(pv.Layout.Stack) .layers(data) .order("inside-out") .offset("wiggle") .x(x.by(pv.index)) .y(y) .layer.add(pv.Area) .fillStyle(pv.ramp("#aad", "#556").by(Math.random)) .strokeStyle(function () { this.fillStyle().alpha(.5) }) // this is new code: .anchor("center").add(pv.Label) .def("max", function(d) {return pv.max.index(d)}) .visible(function() {return this.index == this.max() }) .text(function(d, p) {return words[this.parent.index]}); Basically this adds a whole bunch of labels to your areas, But then only makes them visible at the index where the value is the maximum, by defining a function max on the series. I adapted this code from the code in the link you sent.