Disable SVG drag - javascript

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 :)

Related

D3 force graph doesn't pan or zoom as expected

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!

d3 v4: Clip path not updating after pan and zoom

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");

d3.js - scaling bubble chart app

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.

D3js zoom does not work

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.

getting svg elements bounded by a region - javascript

Im using d3.js to draw a scatterplot in javascript and this is my first javascript program. The user can draw a click n drag SVGRectangle to calculate the average of the points that get bounded by the rectangle. I have implemented the rectangle drawing part, I'm stuck with the part where I have to determine which points (SVGCircles) are inside the rectangle. Im trying to get all the circle elements in an array allCircles, and then filtering out the circles that are in the rectangle region. However I cannot figure out how to get the coordinates of the circles. The way I did it below doesnt seem to work.
var 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 + ")");
var allCircles = svg.selectAll("circle.circles"); //circles is the class for all points
//I have to do the following line coz for some reason the entire array comes as one single //element
allCircles = allCircles[0];
for (var j = 0; j < allCircles.length; j++) {
if (allCircles[j].top > startY && allCircles[j].left > startX
&& (allCircles[j].height + allCircles[j].top) < rectHeight + startY
&& (allCircles[j].width + allCircles[j].left) < rectWidth + startX) {
selectedCircles.push(allCircles[j]);
}
}
Any fixes, suggestions, hints, links would be appreciated as Im really short on time !
When selecting objects with D3, you can't access those attributes directly -- use the .attr() function. That is, instead of allCircles[j].top you would do d3.select(allCircles[j]).attr("top") or allCircles[j].getAttribute("top"). Note that you need to have set those attributes explicitly.
The D3 way to do something like that would be to use the .filter() function on your selection, i.e. something like
svg.selectAll("circle.circles")
.filter(function(d) { return d.top > startY && /* etc */; })
.each(function(d) {
// do something with the selected circles
});

Categories