Mouseevent div cover div on chart - javascript

I have a gantt chart in d3.js gantt chart. I use a scroll and zoom gantt chart: http://codepen.io/Pau/pen/FKzEa
But I have problem. This is my modification: http://codepen.io/anon/pen/pgVdgm I want add mouseevent (simple alert) when user mouse over line or tasks. But this doesen't work. I added this events to line and tasks:
svg.select(".gantt-chart-canvas").append("line").attr(
{
"class":"verticalDeadLine",
"x1" : x(testDate),
"y1" : 0,
"x2" : x(testDate),
"y2" : height,
"fill" : "none",
"shape-rendering" : "crispEdges",
"stroke" : "red",
"z-index" : "550",
"stroke-width" : "2px"
}).on('mouseover', function(event) {
alert("abcd");
})
.on('mouseout', function() {
});
I think problem is in this line where added rect, class pane
chart.append("rect")
.attr("class", "pane")
.attr("width", width)
.attr("height", height-margin.top-margin.bottom)
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
pane in css class:
.pane {
fill: none;
pointer-events: all;
}
and this div cover line and tasks mousevents.
Mouseevent over line and tasks work, when I change in class pane: pointer-events: all; to pointer-events: auto;
But after this change, my zoom and scroll not work...
How to change it? I want to zoom-scroll on chart and mousevents on line and tasks work both. I think I must change in line class pointer-events property. But how?
Summary, simpler example. I have two class.
<div class="A">
<div class="B">
</div">
</div">
Both class have mousevent, But class A cover class B. How to set that both mousevents work?

For this first change:
make the fill transparent from none
.pane {
cursor: move;
fill: transparent;
pointer-events: auto;
}
Second change make the rectangle above .gantt-chart class group
Like this:
var chart = d3.select("body")
.append("svg")
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var drw = chart.append("rect")
.attr("class", "pane")
.attr("width", width)
.attr("height", height-margin.top-margin.bottom)
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
//now append ganttchart group
var svg = chart.append("g")
.attr("class", "gantt-chart")
.attr("width", width)
.attr("height", height-margin.top-margin.bottom)
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");
working code here
hope this helps!

Related

SVG not displaying correctly in D3.js dataviz

In this datavisualization, I have a curious problem : my svg is not correctly aligned with the whole container.
I'm using a viewbox:
var svg = d3.select("#viz")
.attr("viewBox", [
margin.left,
margin.top,
(width+margin.left),
(height+margin.bottom)
].join(" "))
.append("svg")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
Does anyone have any idea why?

D3 updating data on box plot without removing previous SVG first

I'm following the box plot on this page Box Plot Link. In this example it reads in the box plot values from a data file. I'm trying to add a button that will read in new data from another data file and update the box plot.
Here's the code they use to first create the box plot.
var svg = d3.select("#viz").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "box")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.bottom + margin.top)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(chart.duration(1000));
and this to update the box plots every second
setInterval(function() {
svg.datum(randomize).call(chart.duration(1000));
}, 2000);
When I click on the update button it calls my snippet here:
var svg = d3.select("#viz").selectAll("svg")
.data(data)
.enter().append("svg")
.attr("class", "box")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.bottom + margin.top)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.call(chart.duration(1000));
However this won't update my boxplot. If I want the box plot to change, I have to first remove the box plot SVG first
d3.selectAll('svg').remove();
But I'd like to have an transition rather than new box plots. Why do I have to remove the previous SVG first? Any help?
So I made the following changes to the update of the data
var svg = d3.select("#viz").selectAll("svg").data(data)
svg.call(chart.duration(duration));
svg.enter().append("svg")
.attr("class", "box")
.attr("id", function (d, i) {
return "box_" + i;
})
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.bottom + margin.top)
.append("g")
.attr("id", function (d, i) {
return "g_" + i;
})
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(chart.duration(duration))
svg.exit().remove();
and there is actually some bugs with that box.js code that needs to be fixed which I found about here:
D3 Datum Update Boxplot

Set background for d3.js collabsible tree

I create a collabsible tree like in this example (http://bl.ocks.org/mbostock/4339083). I tried to change the background color of the SVG. Therefor I use a "rect" element before inserting the "g" element:
svg = d3.select("#"+targetDIVName).append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.attr("id", "svg_graph")
.append("rect")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "green") //for example
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
With this method the graph is hidden. Is there any solution to set the "rect" element as background and get the graph visible?
Thank You
SVG elements are drawn in the order in which they are added. So if you want the rect to be in the background, add it as the first element after creating the SVG.
To get a solid background colour, you could alternatively use the viewport-fill attribute, which is not supported by all browsers though.

d3 ignore SVG on selectAll

Still learning d3.js.
I would like to ignore the selection of an SVG panel when using .selectAll("svg").
I am building a visualization comprising four SVG panels. The top SVG panel is used to display header/title information for the visualization.
var svgHeader = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 100)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("g");
The next two SVG panels are dynamically created using a range of two numbers representing two years.
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(2012, 2013))
.enter().append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", 200)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("g");
The final SVG contains detail information as the user interacts with the visualization.
Problem: I want to exclude the first SVG panel from the .selectAll("svg") which is used to create the two middle panels. I would like to dynamically build SVG panels and have them locate underneath the previously created header SVG.
Is there any way to exclude the header SVG when dynamically creating the middle panels?
I think the best way you should be going about this is taking advantage of classes and adding an appropriate class to the different svgs and then selecting based on the class rather than the svg. This way you know what each of the svgs represent and you can easily reference them.'
var svgHeader = d3.select("body")
.append("svg")
.attr("class", "svgHeader")
.attr("width", width + margin.left + margin.right)
.attr("height", 100)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("g");
And then the other two you add a different class name
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(2012, 2013))
.enter().append("svg")
.attr("class", "data")
.attr("width", width + margin.left + margin.right)
.attr("height", 200)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append("g");
Now you can do d3.selectAll("svg.data") and select only svg elements with the class data
Alternatively, you can embed your svg elements in different divs. Assuming you have a div whose id is 'center-div' the following snippet returns you only the svgs contained in it.
d3.selectAll("#center-div svg")
Please also consider that you can append whatever DOM element via d3, so divs can be dinamically generated.

SVG path element .transition() - where to add?

Basically, I want my graph to start at the x-axis and grow over two seconds to the actual data values. This is probably a simple thing, but I can't seem to get it to work.
I'm appending an area element, in which the d="" attribute is built by a function (area) and I'm not sure where to add a transition.
First I thought to do this in the area function, but this fails. I've also tried to do this when the area element is added without success.
Here is my code:
// Create the area element for each object - a function that will be passed to "path"
var area = d3.svg.area()
.x(function(d) { return x(d.year); })
.y0(height)
//.y1(height)
//.transition()
//.duration(2000)
.y1(function(d) { return y(d.average); });
// build the container SVG element
var svg = d3.select("#co2").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
svg.append("path")
// pull in data to the path
.datum(data)
.attr("class", "area")
// passing in the area function, for each object
.attr("d", area)
// starts the graph opacity at 0 and fades to 1 over 2.5 seconds
.style("fill-opacity", "0")
.transition()
.duration(2500)
.style("fill-opacity", "1");
Rather than try to use transition on the shape of the area graph, you could apply a scale(x,y) transform against the whole svg element that you want to animate. The advantage of this approach is that it is not limited to a particular rendering implementation (eg: not path/d3.area specific).
There are a couple of gotchas to note though:
To avoid the transition() behaviour, working on the margin adjustments, make sure you have a separate 'g' element for the transition() transforms to act on
SVG has its origin (0,0) in the top-left, so in addition to scaling the SVG area, you need to set the base of the graph
This is put together below:
'g' element:
var svg = d3.select("#co2").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left, "," + margin.top + ")")
// define a new 'g' to scope the transition, and keep separate from the margin adjusting transform above
.append("g");
transition() including base adjustment:
svg
.attr("transform", "translate(0," + height + ") scale(1, 0)")
.transition().duration(2000)
.attr("transform", "translate(0,0) scale(1, 1)");
As ever, this is best illustrated with the complete example: http://bl.ocks.org/4239516

Categories