Vertical d3.svg.area? - javascript

I'm trying to make a vertical area chart, with a line in it's right borders. Line is being drawn perfectly ( top to bottom ), but the area is being drawn on right side of the path, it should be on the left.
I started with a horizontal chart, it worked then. See jsfiddle. I've also tried rotating the path but cannot get desired result.
var xScale = d3.scale.linear().range([0, sm_width]),
yScale = d3.time.scale().range([0, sm_height]);
var area = d3.svg.area().x(function(d) {
return xScale(xValue(d));
})
.y0(sm_height).y1(function(d) {
return yScale(yValue(d));
});
var line = d3.svg.line().x(function(d) {
return xScale(xValue(d));
})
.y(function(d) {
return yScale(yValue(d));
});

It might not help you though, what about using css like below
.area{
fill:white;
}
svg{
background:#ccc;
}

Solution was to rotate the chart itself as Cool Blue mentioned in the comment.

Related

How to avoid overlapping and stack long text legends in D3 graph?

I have D3 graph base on Multi-line graph 3 with v7: Legend, this sample contains few and shorts legends for the graph. In my sample I want to increase the length for legends and stack the data if is necessary, I want to avoid overlapping in the legends,
https://bl.ocks.org/d3noob/d4a9e3e45094e89808095a47da19808d
dataNest.forEach(function(d,i) {
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key); })
.attr("d", priceline(d.value));
// Add the Legend
svg.append("text")
.attr("x", (legendSpace/2)+i*legendSpace) // space legend
.attr("y", height + (margin.bottom/2)+ 5)
.attr("class", "legend") // style the legend
.style("fill", function() { // Add the colours dynamically
return d.color = color(d.key); })
.text(d.key);
});
There are two possible solutions I can think of, shown in this JSFiddle.
First, if it is acceptable that the legend is not part of the svg, then realize the legend with a simple unordered list in a container next to the svg. This is probably the best when there is a varying number of legend entries and there are no restrictions considering the styling via css. The browser takes care of varying lengths and does an automatic line break.
Second, if the legend has to be a part of the svg, one can use the getBBox()-method that determines the coordinates of the smallest rectangle around an object inside an svg.
In a first step select all the legend entries that have been rendered and get the bounding boxes:
const bbox = svg.selectAll(".legend")
.nodes()
.map(legend_entry => legend_entry.getBBox());
With this array and the width of the svg, we can calculate the positions for each legend entry:
bbox.reduce((pos, box) => {
let left, right, line;
if (pos.length === 0) {
left = 0;
line = 1;
} else {
/* The legend entry starts where the last one ended. */
left = pos[pos.length - 1].right;
line = pos[pos.length - 1].line;
}
/* Cumulative width of legend entries. */
right = left + box.width;
/* If right end of legend entry is outside of svg, make a line break. */
if (right > svg_width) {
line = line + 1;
left = 0;
right = box.width;
}
pos.push({
left: left,
right: right,
line: line,
});
return pos;
}, []);
Margins and paddings have to be included manually in the calculation of the positions. Of course, one could obtain the maximum width of all legend entries and make them all the same width with center alignment as in the d3noob example.
In the JSFiddle, I realized this repositioning by first rendering a hidden legend and then an additional one that is visible. It is of course possible to use only one legend, but I would not to take any chances that the process of repositioning is visible in the rendered document.

nvd3 charts - changing text color in hover boxes

All of my charts, regardless of type, have the popover/hover box with a dark grey (almost black) background with black text - making it almost impossible to read. The color segment of the chart appears in the hover box, but the text and labels are all in black.
How can I change the text color in the hover boxes? Is this a tooltip item or is it chart specific?
Here is a sample of one of my charts JS, can the hover box text color be set in options or do I need to find the setting in the CSS file - and if so, which setting is it? :
/**
* Widget 5
*/
var widget5Option = '3M';
// Main Chart
nv.addGraph(function ()
{
var chart = nv.models.multiBarChart()
.options(
{
color : ['#03a9f4', '#b3e5fc'],
margin : {
top : 48,
right : 16,
bottom: 16,
left : 32
},
clipEdge : true,
groupSpacing: 0.3,
reduceXTicks: false,
stacked : false,
duration : 250,
x : function (d)
{
return d.x;
},
y : function (d)
{
return d.y;
},
yTickFormat : function (d)
{
return d;
}
}
);
var chartd3 = d3.select('#widget5-main-chart svg')
var chartData;
initChart();
nv.utils.windowResize(chart.update);
$(window).bind('update:widget5', function ()
{
initChart();
})
function initChart()
{
chartData = data.widget5.mainChart[widget5Option];
chartd3.datum(chartData).call(chart);
}
return chart;
});
Ok...I finally found the CSS value to change the color of the text in the popover on various chart graphs.
In nv.d3.min.css, there is the value .nvtooltip - there are various .nvtooltip sub definitions but the very first one is defined as:
.nvtooltip{position:absolute;color:rgba(0,0,0,1);padding:1px;z-index:10000;display:block;font-family:Arial,sans-serif;font-size:13px;text-align:left;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}
I changed color:rbga(0,0,0,1) to color:white
Took me a day to find it because its only appears in the hover over popup table, which you can't put your mouse into because the popup moves with your mouse and is always about 1/2" away from mouse pointer - thus I could click on the popup over using Dev Tools Inspector to see what CSS values are assigned to the popup. Very annoying.

dc.js Stretch GeoChoroplethChart to Full Screen

I'm trying to create a world map using d3.geoChoroplethChart. My problem is that I can't stretch it to the full screen. I'm setting the width of the chart, and svg is picking up the setting, but the underlying g element does not. I assume it uses the projection together with the set width to calculate its size.
The projection I'm using
var projection = d3.geo.mercator()
.center([0, 55])
.scale(180);
Here is chart code
mapChart.width(2000)
.height(1000)
.dimension(countryDim)
.group(countryDimGroup)
.colors(d3.scale.quantize().range(["#E2F2FF", "#C4E4FF", "#9ED2FF", "#81C5FF", "#6BBAFF", "#51AEFF", "#36A2FF", "#1E96FF", "#0089FF", "#0061B5"]))
.projection(projection)
.valueAccessor(function(d) { return d.value; })
.overlayGeoJson(africaJson.features, "Countries", function(d) {
return d.properties.admin.toUpperCase();
});
I use geoJSON from here http://geojson-maps.kyd.com.au/
Am I missing something?

formatting nvd3.js colors and interactiveGuideLine

I've gotten lost amongst the d3.js weeds. I'm putting together a chart using nvd3.js (http://i.stack.imgur.com/ghueS.png).
But, while the colors appear correct in the legend, they do not in the chart. Additionally, there is significant white space in the hovering tooltip.
Looking into the object structure, I get what looks like one layer of keys too many, which makes me think the color issue and white space have to do with my actual keys being too far buried in the object (http://i.stack.imgur.com/k46CO.png).
I've looked into nest() and rollup(), but can't comprehend how they might help.
My javascript is as follows:
d3.csv("http://fwllc.wpstagecoach.com/wp-content/themes/frameworkcr/markers.csv",function(err,data){
var noDates = d3.keys(data[0]).filter(function(k){return k!="date"});
var dataToPlot = noDates.map(function(k){
return {"key":k,
"values":data.map(function(d){
return {
"x":d3.time.format("%m/%d/%y").parse(d.date),
"y":+d[k]
}
})}
})
console.log(d3.entries(dataToPlot));
nv.addGraph(function() {
var chart = nv.models.lineChart()
.margin({left: 100}) //Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
// .transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true) //Show the x-axis
;
chart.xAxis //Chart x-axis settings
.tickFormat(function(d) { return d3.time.format("%m/%d/%y")(new Date(d)); });
chart.yAxis //Chart y-axis settings
.axisLabel('Total Return Percent')
.tickFormat(d3.format('%'));
d3.select('#chart').append("svg")
.datum(dataToPlot)
.call(chart);
nv.utils.windowResize(function() { chart.update() });
return chart;
});
})
And a portion of my .csv file:
date,ESG,global100,outperformance
12/22/08,0,0,0
3/23/09,-0.059812891,-0.094081914,0.034269023
6/22/09,0.137426291,0.033160892,0.104265399
9/21/09,0.418041893,0.249191458,0.168850435
12/21/09,0.460914373,0.294278644,0.166635729
3/22/10,0.504442354,0.306489826,0.197952528
I copied you code to a plnkr, it seems correct...
<div id="chart" style="width:300px; height:300px"></div>
plnkr

Adding Object with Transition in D3.js after Zooming

In the d3.js example, the goal is to change the X & Y scales to reveal a newly added circle which is added offscreen.
Currently, if you were to change the zoom scale, then click on the button to add a new circle, the zoom level suddenly resets to 1. Now dragging the view will cause the zoom scale to become correct again, which is the same zoom scale right before adding the circle.
However this problem goes away if you change redrawWithTransition() on line 123 to redraw() which removes the transitions.
Everything works fine if you add the circle without first zooming.
Why do we have to drag the view again to get the correct zoom scale back? How can we avoid having to do this additional drag and still use transitions in redrawWithTransition()? Thank you!!
Jsfiddle: http://jsfiddle.net/NgWmU/
Because panning again after adding the circle solves the problem, I tried calling redraw() at the end but theres no difference! Is the panning/zooming triggering something else in addition to redraw()?
Jsfiddle: http://jsfiddle.net/NgWmU/2/
First the user zooms/pans around and ends up with a view like in figure A. Next the new circle is added and we should get figure C, but instead we get figure B where the user's current translate/zoom is changed significantly.
Another case
If the user pan/zoom to a view similar to the top figure, adding the new circle should reposition the existing circles slightly, but instead the entire view is reset.
Was thinking about something like:
// Copy existing domains
var xMinOld = xMin,
xMaxOld = xMax,
yMinOld = yMin,
yMaxOld = yMax;
// Update domains
var yMin = d3.min(data.map( function(d) { return d; } )),
yMax = d3.max(data.map( function(d) { return d; } )),
xMin = d3.min(data.map( function(d) { return d; } )),
xMax = d3.max(data.map( function(d) { return d; } ));
if(x.domain()[0] > newData[0] || x.domain()[1] < newData[0]) {
if(x.domain()[0] > newData[0]) {
x.domain([xMin, xMaxOld]);
} else {
x.domain([xMinOld, xMax]);
}
zoom.x(x);
}
if(y.domain()[0] > newData[0] || y.domain()[1] < newData[0]) {
if(y.domain()[0] > newData[0]) {
y.domain([yMin, yMaxOld]);
} else {
y.domain([yMinOld, yMax]);
}
zoom.y(y);
}
But eventually the view will still be reset because we pass the updated scales x and y into zoom...

Categories

Resources