Here a link with fantastic description of sparklines implementation using d3.js
I'm doing something similar but I need to define a normal range for each sparkline, like here on mockup :
This grey bar is hard coded now. The meaning of this bar is to represent "green" range of data. For example from 0 to 1. Everything that is less or more then this range should be not in that bar.
I have such domain in my js file:
y.domain(
d3.extent(data, function (d) {
return d.y;
})
and this is how i`m drawing my greybar:
var baseline = graph.append("rect")
.attr("x", 0)
.attr("y", y(2))
.attr("width", 100)
.attr("height", y(3))
.attr("class", "rect_");
But when I'll give for this block of code my normal range [0,1]
var baseline = graph.append("rect")
.attr("x", 0)
.attr("y", y(0))
.attr("width", 100)
.attr("height", y(1))
.attr("class", "rect_");
I'm getting this :
I'm afraid it`s complete incorrect way , need someone help, thanx!
Related
I am trying to convert a bubble chart from d3v3 to v4. Running into x,y,d missing variables?
In this version -- a rect is applied to the svg - and then a circle is cut -- so its like an inverse bubble chart.
I am keen to work out a set radius for the chart as a maxium -- if it should act like a score between 0 and 100? What kind of math to apply that a max radius has been reached to signify that the value is very big?
I also tried to have the svg mask adapt - if the browser or its container changed size -- ideally would want it to response during the change - rather than resizeEnd
//version 3
https://jsfiddle.net/8ag1vf6e/1/
//current version 4
https://jsfiddle.net/d56g9r0y/
// filters go in defs element
var defs = innversebubble.append("defs");
var mask = defs.append("mask")
.attr("id", "myMask");
mask.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", width)
.attr("height", height)
.style("fill", "white")
.style("opacity", 1);
var invisiblebubble = mask.append("circle")
.data(data);
//create a fixed bubble first
invisiblebubble
.attr("cx", "50%")
.attr("cy", "50%")
.attr("r", function(d) {
return d.value - 20;
});
//now mask the fixed circle
var masker = defs.append(function() {
return mask.node().cloneNode(true)
})
.attr("id", "myMaskForPointer")
.select("rect")
.style("fill", "white")
.style("opacity", 1);
invisiblebubble
.attr("r", 10);
//apply the rest of the chart elements
var rect = innversebubble
.attr("class", "series")
.append("g")
.attr("transform", "translate(0,0)")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", "100%")
.attr("height", "100%")
.attr("mask", "url(#myMask)")
.style("fill", backcolor)
.style("opacity", backopacity);
//animate this circle
invisiblebubble
.attr("cx", "50%")
.attr("cy", "50%")
.transition()
.duration(1800)
.attr("r", 10)
.transition()
.duration(900)
.attr("r", function(d) {
return d.value;
});
latest jsfiddle - 15th June -- needs fixing
https://jsfiddle.net/xmrtahns/
"I am keen to work out a set radius for the chart as a maxium -- if it should act like a score between 0 and 100? What kind of math to apply that a max radius has been reached to signify that the value is very big?
I also tried to have the svg mask adapt - if the browser or its container changed size -- ideally would want it to response during the change - rather than resizeEnd"
I've fixed the conversion and the data source - but still need issues to resolve.
var backcolor = $this.data("color");
var backopacity = $this.data("opacity");
var width = $this.data("width");
var height = $this.data("height");
var data = [{
"label": $this.data("label-name"),
"centralLabel": $this.data("central-label"),
"xPer": $this.data("displace-left"),
"yPer": $this.data("displace-top"),
"value": $this.data("bubble-value")
}];
http://jsfiddle.net/hLymw8et/2/
--I am keen to work out a set radius for the chart as a maximum -- if it should act like a score between 0 and 100?
--What kind of math to apply that a max radius has been reached to signify that the value is very big?
--I also tried to have the svg mask adapt - if the browser or its container changed size -- ideally would want it to response during the change - rather than resizeEnd –
I have been looking into this d3.js block Timeline with Zoom. However, I am not able to figure out how the zoom function is actually implemented. Could somebody help me understand?
Frankly, there is no zoom happening.
var brush = d3.svg.brush()
.x(x)
.on("brush", display);//this calls display function on brush event drag.
Inside display function.
minExtent = brush.extent()[0],//this give the brush extent min
maxExtent = brush.extent()[1],//this give the brush extent max
Based on the max and min of the brush filter the data:
visItems = items.filter(function(d) {return d.start < maxExtent && d.end > minExtent;});
Reset the domain with the brush's max and min.
x1.domain([minExtent, maxExtent]);
Select all rectangles in the upper area not having the brush associate data to the DOM.
update it with the new scale values
rects = itemRects.selectAll("rect")
.data(visItems, function(d) { return d.id; })
.attr("x", function(d) {return x1(d.start);})
.attr("width", function(d) {return x1(d.end) - x1(d.start);});
create any new rectangles if the data is present but DOM is not present.
rects.enter().append("rect")
.attr("class", function(d) {return "miniItem" + d.lane;})
.attr("x", function(d) {return x1(d.start);})
.attr("y", function(d) {return y1(d.lane) + 10;})
.attr("width", function(d) {return x1(d.end) - x1(d.start);})
.attr("height", function(d) {return .8 * y1(1);});
Remove all the rectangle outsside the brush extent or not in the filtered item list visItems
rects.exit().remove();
Exactly the same for labels as done for rectangles above.
Hope this clears all your doubts.
I'm not sure but I think this is just a trick with D3 scales.
What happens is that it gets the selection below (which is a projection a 100% of with from time 0 to time 100) and plots into a new scale from time 50 to time 80 with the same width.
This will make the scale change in a way that looks like you zoomed on that time moment in time.
After a while I finally figured how to scale data in d3 linear.
But if you look at the following screenshot you might notice that numbers do not seem to scale appropriately:
So: e.g. 4.55 and 16.2 are almost same length, which they shouldn't be (also 4 should be much closer to the left as I scale between 0 and 565)
so this is how I create the linear scale:
var scaledData = d3.scale.linear()
.domain(d3.extent(data, function(d){return d.Betrag;}))
.range([0, width-35]);
and this is how I draw the bars:
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", function(d) { return scaledData(Math.abs(Math.round(d.Betrag))); })
.attr("height", barHeight - 1);
bar.append("text")
.attr("x",function(d) { return scaledData(Math.abs(Math.round(d.Betrag)))+3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return Math.abs(d.Betrag); });
});
I have tried around different things with this part scaledData(Math.abs(Math.round(d.Betrag))) but no matter what I do it doesn't do what I think it should... Perhaps as a newbie I still don't understand the scales thing completely... What I figure is that the problem comes from how I set the domain. if I replace the d3.extend function by [0,2000] it's all good...
You'll have to show your data to know for sure, but I think you have negative values in your data, so your domain looks like it goes from about [-600, 1800]. But when you calculate your width you first take the absolute value of your data, so your lowest possible value is 0. The solution is in your d3.extent accessor function, to evaluate the absolute value of your data (if that's actually what you want).
Using D3.js Is there an option to overlay one bar over another?
I need two independent columns to indicate start and end time (x axis) against a count (y axis). I want BOTH columns to be overlaid over each other (similar start time e.g x1=8:45am, x2=10:05, and same end times. y1=90, y2=108), both columns will have transparency around 0.5, so each column can be seen over the common time/count range.
A similar example using Highcharts:
http://jsfiddle.net/gopinaghr/q8Udk/
// This page provides an example in highcharts
{ I need same for D3}
I need to create a chart where
Column width dependant on (end_time - start_time)
Column x origin is dependant on start time
Column height dependant on y value
The columns need opacity less than 1.
d3.js requires you to explicitly place your bars at coordinates, so, you can put your bars where ever you like:
// create a group for your overlapped bars
var g = svg.selectAll(".bars")
.data(data)
.enter().append("g")
// place the first bar
g.append("rect")
.attr("class", "bar1")
.attr("x", function(d) {
return x(d.letter) + 10; // center it
})
.attr("width", x.rangeBand() - 20) // make it slimmer
.attr("y", function(d) {
return y(d.col1);
})
.attr("height", function(d) {
return height - y(d.col1);
});
// place the second bar on top of it
g.append("rect")
.attr("class", "bar2")
.attr("x", function(d) {
return x(d.letter);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.col2);
})
.attr("height", function(d) {
return height - y(d.col2);
});
Here's a quick example.
EDITS
To add in time, you have to make a number of changes.
Set up a time formatter, to parse your date/times out of your file:
// say date/times are local 20160622 15:00
var timeFormatter = d3.time.format("%Y%m%d %H:%M")
Set up a time x-scale for your axis:
// x scale showing 1 day - 06/22/2015
var x = d3.time.scale()
.range([0,width])
.domain([timeFormatter.parse("20150621 00:00"), timeFormatter.parse("20150622 00:00")])
And when you draw the rect, with width is the number of pixels from endTime to startTime:
g.append("rect")
.attr("class", "bar1")
.attr("x", function(d) {
return x(d.startTime1); // start at startTime
})
.attr("width", function(d,i){
return x(d.endTime1) - x(d.startTime1); // pixel width from end to start
})
.attr("y", function(d) {
return y(d.col1);
})
.attr("height", function(d) {
return height - y(d.col1);
});
Example here.
I'm currently looking at this bar chart example.
http://jsfiddle.net/enigmarm/3HL4a/13/
In my own version I've been using a json array as the data and is structured like so.
[{"irish":"154187","non_irish":"309638","area":"Connacht"},
{"irish":"588725","non_irish":"2182932","area":"Ireland"},
{"irish":"180755","non_irish":"1017491","area":"Leinster"},
{"irish":"189395","non_irish":"672660","area":"Munster"},
{"irish":"64388","non_irish":"183143","area":"Ulster"}]
My question is how would I apply both data.irish and data.non_irish to the "y" attribute and generate bars for both as currently I can't work out how to apply both because the "y" attribute will only take one in its parameter.
var bar = svg.selectAll("rect")
.data(data)
.enter().append("g")
.attr("class", "bar");
var bartwo =bar.append("rect")
.attr("class", "bar")
.style("fill", function(d,i) {
return colours[i];
})
.attr("x", function(d,i) { return x(data[i].area); })
.attr("y", function(d,i) { return y(data[i].irish); })
.attr("width", barWidth)
.attr("height", function(d,i) { return height - y(data[i].irish); })
Any help would be truely appreciated.
This dual bar-chart might help you: http://nvd3.org/examples/multiBarHorizontal.html. It emphasizes on the contrast of the two dimensions as well as comparison of multiple groups in one dimension (E.g the number of Irish speakers in different areas).