Adding labels to a pv.Layout.Stack (streamgraph) in Protovis - javascript
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.
Related
How can I remove an axis on click in Plotly for parcoords?
From the documentation, I've found custom buttons and click events. However, I can't figure out how to pair these to make it so when I click on a y axis in my parallel coordinates plot, it deletes that axis. edit: What I tried: It seems that I can choose dots, but not lines. plot_ly(partial, type = 'parcoords', line = list(color = partial$freq, colorscale = 'Jet', showscale = TRUE, reversescale = TRUE, cmin = min_freq, cmax = max_freq), dimensions = interactiveList ) %>% layout(title=name) %>% onRender(" function(el, x) { console.log('entered'); console.log(el); el.on('plotly_click', function(d) { // d.points is an array of objects which, in this case, // is length 1 since the click is tied to 1 point. console.log('lalala'); var pt = d.points[0]; var url = pt.data.text[pt.pointNumber]; // DISCLAIMER: this won't work from RStudio console.log('hello'); window.open(url); }); el.on('plotly_selected', function(d) { console.log('selected'); }); } ")
Creating newline in nvd3.js graph x-axis labels
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);
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!
d3.js Two Dimensional Array Bar Chart
I am trying to make a bar chart containing 3 'groups' of data in d3.js. I have been able to implement the example from "Let's Make a Bar Chart" sample http://bost.ocks.org/mike/bar/2/, but am wondering how you would implement that with a 2 dimensional data set instead. I'm having a bit of a tough time wrapping my head around what I feel should be a fairly straight forward process (select first index of 2d array -> iterate through that array and display the values of each element in bars -> select second index of array -> iterate through that array and display the value of each element in bars etc...), so examples would be hugely appreciated. The code thus far is: var data = [4, 8, 15, 16, 23, 42];*/ var width = Math.max(500, innerWidth), height = Math.max(500, innerHeight), barHeight = 80; var x = d3.scale.linear().domain([0, d3.max(data)]).range([0, width]); var chart = d3.select(".chart").attr("width", width).attr("height", barHeight * data.length * 3); var bar = chart.selectAll("g").data(data).enter().append("g").attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; }); bar.append("rect").attr("width", x).attr("height", barHeight - 1); bar.append("text").attr("x", function(d) { return x(d) - 3; }).attr("y", barHeight / 2).attr("dy", ".35em").text(function(d) { return d; }); however I would like to change the "data" variable to be: var data = [[40,45,5], [50,49,2], [60,62,4], [40,41,6], [42,40,3], [65,67,10], [70,67,17], [66,65,2], [45,44,3], [39,38,7], [38,38,8], [45,40,4], [43,35,3], [50,65,8], [51,50,6]];
How to update a D3 chart dynamically
I am trying to create an easy way to create and update donut charts (And other charts, later) in an application. This is built on top of D3. I've created a drawDonutChart as shown below: var data = [50, 50]; var dataTwo = [75, 25]; var options = { colors: ["#0074D9", "#7FDBFF"], }; function createDonutChart(data, height, width, domElement, options) { var radius = Math.min(width, height); var color = d3.scale.category20(); var donut = d3.layout.pie().sort(null); var arc = d3.svg.arc() .innerRadius(radius/4) .outerRadius(radius/2); var svg = d3.select(domElement).append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var path = svg.selectAll("path") .data(donut(data)) .enter().append("path") .attr("fill", function(d, i) { if (options.colors == null || options.colors == "undefined") { return color(i); } else { return options.colors[i]; } }).attr("d", arc); } var donutChart = createDonutChart(data, 50, 50, ".slices", options); when you have a in the page, this will draw a donut chart there. I would like to write a function updateDonutChart(originalChart, newData), pass it (donutChart, dataTwo) and have it transition this data into the chart instead of the old data. I've been looking at multiple examples on the D3 website but I haven't been able to get something to work this way (where you simply pass the old chart, and new data). It might be simple, I am just new to D3 :) Thanks in advance for the help.
So, it wasn't clear to me from the signature of your update call if you wanted to create a new SVG under a possibly new DOM element every time you updated the chart. Also, I am not sure if you are using the word transition to specify a D3 transition of just a change in the data (although that would be simple enough to add). I any case, a simple adaptation to your code to do what you want is in this FIDDLE. function updateDonutChart(data, options) {...