I can not make zoom work. Tried everything.
My goal:
zoom on mouse scroll
drag the tree by a mouse
The code is here:
svg = d3.select("#tree-container")
.append("svg").attr("width", width)
.attr("height", height)
.call(zm = d3.behavior.zoom().scaleExtent([1, 3]).on("zoom", redraw))
.append("g")
.attr("transform", "translate(" + 350 + "," + 20 + ")");
jsFiddle
P.S. sorry for spaggeti code
It's the declaration of your redraw function that causes the problem -- if you declare it as a function, it works fine:
function redraw() {
// etc
}
Complete example here.
Related
I've built a D3 force graph largely based on these really helpful examples.
I wanted to add pan and zoom functionality, which I tried to do using another example (looks like I can only include two links, but Google "d3 force zoom eyaler" to find it).
Unfortunately, when I zoom out on a graph that is larger than the initial SVG, I get something like this:
Result of dragging and dropping
Here's the relevant code:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().scaleExtent([0.5,2]).on("zoom", redraw));
function redraw() {
svg.attr("transform",
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
How can I change the pan and zoom behaviour so that it scrolls and makes it possible to see the rest of the graph, rather than just allowing me to move the square that was originally visible?
OK, looks like I worked it out... you need to perform the transform on a <g> rather than on the SVG itself. So:
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().scaleExtent([0.5,2]).on("zoom", redraw));
var g = svg.append("g"); // add <g>
function redraw() {
g.attr("transform", // perform transform on g, not svg
"translate(" + d3.event.translate + ")"
+ " scale(" + d3.event.scale + ")");
}
Just putting this here in case anyone else made the same mistake!
I have a rect holding a clip path, which I'm applying to a group (holding a tree). I have a zoom function bound to the rect which transforms the group, which works fine. I've applied the clip path to the group, and when it first renders it looks like it should. However, after panning or zooming, the drawn tree extends beyond the bounds of the clip path while maintaining its previously-clipped appearance.
var svg = d3.select(this.$.chart);
var svg2 = svg.select("svg");
var main = svg2.append("g")
.attr("class","main")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var treeContainer = svg2.append('g')
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")")
var treeBaseRect = treeContainer.append("rect") // the rectangle which holds the clip path and zoom actions for the tree.
.attr("width", width + margin2.right)
.attr("height", height2)
.style("fill", "#eee")
.style("pointer-events", "all")
.call(d3.zoom().scaleExtent([0.1, 3]).on("zoom", function () {
svgGroup.attr("transform", d3.event.transform)
}));
treeContainer.append('defs').append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width + margin2.right)
.attr("height", height2);
var svgGroup = treeContainer.append("g")
.attr("clip-path","url(#clip)");
Here's some screenshots. First one shows the initial render, which is fine (the clip area is the darker grey rectangle):
Then after doing a scroll zoom or pan, note how the tree is still 'originally' clipped, and not being clipped properly outside of the gray area:
And this is my clip path rect in the DOM structure:
You can tell that the clip rect is still where it's meant to be, but the tree is completely ignoring it. No idea why.
Apparently I hadn't added enough groups. The easy solution was to add another append("g") to the svgGroup I was creating, for a last line looking like this:
var svgGroup = treeContainer.append("g")
.attr("clip-path","url(#clip)")
.append("g");
I'm trying to implement a simple d3 svg zoom functionality. On double clicking the rectangle the zoom functionality is working fine.
Now i'm trying to implement the same functionality on a jquery button click function. But i'm getting following error in the console.
Uncaught TypeError: Cannot read property 'translate' of null
Following is my code.
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", zoomed);
var vis = d3.select("#svg-canvas").append("svg")
.attr("width", "550")
.attr("height", "200")
.append("g")
.attr("class", "svg-container")
.attr("transform", "translate(10,10)")
.call(zoom);
vis.append("rect")
.attr("x", 10)
.attr("y", 10)
.attr("width", 100)
.attr("height", 40)
.style("fill", "#444");
function zoomed() {
d3.select(".svg-container").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
$(document).ready(function() {
$("#zoom").click(function() {
zoomed();
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="svg-canvas">
</div>
<button id="zoom">
Zoom
</button>
The functionality is not working. What am i doing wrong or is it possible to implement such functionality ?
At the time of the click you don't have d3.event set, because no events is comming from d3, hence you have to specify yourself the scale / translate parameters
function zoomClicked(translate, scale) {
d3.select(".svg-container").attr("transform", "translate(" + translate + ")scale(" + scale + ")");
}
$(document).ready(function() {
$("#zoom").click(function() {
zoomClicked(4, 4);
});
});
D3 has its own event generating mechanism on double click. As you have the click handler on an element that is not handled by D3, you don't have a d3.event.
d3.select(".svg-container")
.attr("transform", scale(2)");
I would like to disable drag and drop on this SVG element, but failed with several tries,
/// Define drag beavior
var drag = d3.behavior.drag()
.on("drag", dragmove);
function dragmove(d) {
// if the event.x goes over a boundry, trigger "dragend"
if(d3.event.x > 200){
//drag.dragend();
drag.trigger("dragend");
}
var x = d3.event.x;
var y = d3.event.y;
d3.select(this).attr("transform", "translate(" + x + "," + y + ")");
}
svgContainer.call(drag);
JSFiddle - http://jsfiddle.net/nhe613kt/76/
I want disable drag on my chart or matrix you can say, I want it fixed and zoom able.
I am following this jsfiddle - http://jsfiddle.net/typeofgraphic/Ne8h2/4/ but it doesn't has any method
drag.dragend();
//drag.trigger("dragend");
Exception here as it throws - Uncaught TypeError: undefined is not a function
I've fixed you drag capability. You had two zoom variables, the first one called zoomed which was also a variable but wasn't declared until after it was called which wouldn't work. Also called your zoom variable as soon as you made your SVG. Yours was jittery as you appended a 'g' element after you made the SVG and then called your zoom so your zoom was being put on the 'g' element inside your SVG not on your actual SVG.
JSFiddle update : http://jsfiddle.net/nhe613kt/90/
var svgContainer = d3.select("body").append("svg")
.call(zoom) //called earlier
.attr("width", width)
.attr("height", height)
.style("background-color", "black")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.right + ")");
Like mentioned in the comments, whats your end goal ? How come you want to disable your drag ? Do you wish to drag each rectangle individually ? If so you'll have to call the drag on each individual rectangle :) Tell me what else you want it to do and ill give it a go :)
I have a bubble force chart application, and I've created various instances of it. However I can not seem to scale the bubbles in relation to the height/width of the svg.
http://jsfiddle.net/pPMqQ/138/
I've placed an inverse on the heights/widths to alter the viewport - but it doesn't feel like the right approach to me. Does anyone have any experience as to how to correct this?
var inverseHeight = 1/h * 100000;
var inverseWidth = 1/w * 100000;
var svg = d3.select(selector)
.append("svg")
.attr("class", "bubblechart")
.attr("width", parseInt(w + padding,10))
.attr("height", parseInt(h + padding,10))
.attr('viewBox', "0 0 "+parseInt(inverseWidth,10)+" "+parseInt(inverseHeight,10))
.attr('perserveAspectRatio', "xMinYMid")
.append("g")
.attr("transform", "translate(" + (w/4) + "," + (h/4) + ")");
I've tried to scale the actual bubbles
http://jsfiddle.net/pPMqQ/143/
var scale = methods.width*.005;
Its producing an ideal effect - but the chart is not always central.