How do i add a clip path for my graph ? - javascript

I have this fiddle : http://jsfiddle.net/q0ubpmwj/5/
I have been trying to mess around with the clip path so the graph doesnt go outside the axis but i cant seem to get it to work.
Heres a bit of the clip path code i have used but it doesnt seem to work :/
var svg = viewer.append("svg").attr('id', 'viewerPins')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var clip = viewer.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("id", "clip-rect")
.attr("x", "0")
.attr("y", "0").attr("width", width)
.attr("height", height);
var chartBody = svg.append("g")
.attr("clip-path", "url(#clip)")
//.call(zoom)
;

You appending the defs outside of the svg:
viewer.append("defs").append("svg:clipPath")
should be
svg.append("defs").append("svg:clipPath")

Related

TopoJSON drawing solid rectangle despite using turf to rewind

I am currently trying to draw a map of the US with the counties-albers-10m.json file found on the topojson repo. I initially got a solid rectangle and, after changing fill to none, I am getting specks here and there. Going through stack, I found that the winding order may be wrong so I incorporated turf.js, but nothing is really changing. Here is the code:
var margin = {top: 0, left: 0, right: 0, bottom: 0},
height = 600 - margin.top - margin.bottom,
width = 1200 - margin.left - margin.right;
var svg = d3.select("#map")
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top +")");
d3.json("counties-albers-10m.json").then(function(data) {
console.log(data);
var projection = d3.geoAlbersUsa();
var path = d3.geoPath()
.projection(projection);
var counties = topojson.feature(data, data.objects.counties).features
console.log(counties)
counties.forEach(function(feature) {
feature.geometry = turf.rewind(feature.geometry, {reverse:true});
})
svg.selectAll(".county")
.data(counties)
.enter().append("path")
.attr("class", "county")
.attr("fill", "none")
.attr("stroke", "black")
.attr("d", path);
})
The dreaded black box

D3 V5 : sync initial zoom with zoom event

I'm trying to set an initial zoom on my network. It works fine, but as soon as I try to manually zoom on the graph, the visualisation jumps to it's natural zoom settings. Reading answers on Stack and the official documentation of d3, the following code looks right to me, but it doesn't solve the issue.
What am I doing wrong?
Many thanks for your help!
const svg = d3.select('div#network')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}),d3.zoomIdentity.scale(.2))
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.attr("transform","scale(.2)")
Solved! I was almost right! You need to make a second "call" instead of giving this transform as a parameter of the first one.
const svg = d3.select('div#reseau')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}))
.call(d3.zoom().transform,d3.zoomIdentity.scale(.2))
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
.attr("transform","scale(.2)")

D3 Zoom TypeError: t.apply is not a function

Currently, i'm trying to implement a zoom function to my data visualization. Sometimes an error occurs "d3.min.js:1 Uncaught TypeError: t.apply is not a function" when i try to zoom or to move the svg element. It looks like an internal error within d3 library.
var height = $("#content").height();
var width = $("#content").width();
var svg = d3.select("#content").append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "svg_canvas")
.append("g")
.call(d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom))
.attr("transform", "translate(" + (width / 2.0) + "," + (height /2.0 )+ ")")
.append("g")
.attr("class", "interaction_group");
zoom_layer = svg;
//Overlay for zooming
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + (-width / 2.0) + "," + -(height/2.0 ) + ")");
The event handler "zoom" is really basic:
function zoom() {
zoom_layer.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
The implementation was realized with the latest D3.js V3 version.
Firstly, declare your zoom behavior:
var myZoomBehavior=d3.behavior.zoom().scaleExtent([1, 8]).on("zoom", zoom)
Then call it to the svg root:
var svg = d3.select("#content").append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "svg_canvas").call(myZoomBehavior)
Then create the zoomable g with the same variable name as in your zoom function:
var zoom_layer=svg.append("g")

d3.js zoom without overflow

I have a force directed graph with fixed nodes. I have allowed zoom in the graph :
var force = d3.layout.force()
.on("tick", tick);
var zoom = d3.behavior.zoom()
.scaleExtent([0, 50])
.on("zoom", zoomed);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(zoom);
var graphGroup = svg.append("g")
.attr("height", graphHeight)
.attr("width", graphWidth)
.attr("class", "graph-group")
.attr("transform", "translate(" + margin + "," + margin + ")");
graphGroup.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", graphHeight)
.attr("class", "graph-limit")
.attr("width", graphWidth);
...
function zoomed() {
graphContainer.attr("transform", "translate(" + t + ")scale(" + d3.event.scale + ")");
}
I would like to limit the zoom (scale and translation) of the graph within the rectangle with class "graph-limit".
I've tried to put overflow:hidden in style, but without success.
Any idea ?
EDIT :
Here a jsfiddle
http://jsfiddle.net/Lxc43v8d/20/
This is how you can do it.
Use clip path with dimension exactly same as that off the rectangle:
//make a clip path
svg.append("defs").append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("id", "clip-rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", graphHeight)
.attr("width", graphWidth);
To the group which holds the rectangle all nodes and links add the clip path like this
var graphGroup = svg.append("g")
.attr("clip-path", "url(#clip)")//add the clip path
.attr("height", graphHeight)
.attr("width", graphWidth)
.attr("class", "graph-group");
Working code here
Hope this helps!

How to append a rectangle in SVG/3Djs?

Here is a part of code I got from some example:
svg = d3.select("body")
.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 + ")").on("click", click)
;
And here is what I am trying to do based on some other example:
var rect = svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", height)
.attr("width", width)
.style("fill", '#000');
rect.on("click", click);
Click works, but I cannot known where th clickable zone is located, it is not covering my chart, but is somewhere in a corner of it. So I tried to give it a colour (black in this case), but still it stay invisible.
I have also tried
var rect = svg.append("rect")
.attr("x", margin.left)
.attr("y", margin.top)
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.style("fill", '#000');
rect.on("click", click);
No better result.
Questions:
How can I give my rectangle a colour so that I can know where it is
on the page?
How can I have my rectangle match the whole SVG?
EDIT: I have just realised that "onclick" works because it is also attached to the "g" , but I am still interested in the answers.
You have given it a colour, #000 i.e. black.
The trouble is here
svg = d3.select("body")
.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 + ")").on("click", click)
;
The svg variable is not the <svg> element, because of chaining it's the <g> element, which has a transform on it so the rect is transformed.

Categories

Resources