Pan, zoom canvas together with drag nodes in D3
I have the following code in D3 (from basic examples) for panning and zooming a canvas - and the second code block for dragging individual elements. What I would like is to both be able to pan/zoom on the entire canvas and also be allowed move a single object around when user's drag starts on a specific object.
The pan/zoom code I have is:
var svgCanvas = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var g = svgCanvas.append("g")
$('body').append(
$("<div>", {id: "canvas-wrapper" })
.append("<div/>", { id: "canvas" })
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
root.append("rect")
.attr("x", 50).attr("y", 50)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
root.append("rect")
.attr("x", 150).attr("y", 150)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
The drag code I have is:
var svg = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var nodes = svg
.selectAll('.node')
.data([
{ x: 10, y: 10 },
{ x: 100, y: 100 }
])
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag()
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
.on('start', function (d, i) {})
.on('end', function (d, i) {});
}());
nodes.append("svg:rect")
.attr("width", 100)
.attr("height", 100)
.style("fill", "red")
What do I need to do to allow dragging each object individually - in addition to drag on the entire canvas when user drags on an open are?
Obviously the difference between the two code sections is that one is working on entire canvas and one on individual elements (the first has the additional outer container) - how can I combine the two?
I have tried to simply combine the two code examples by adding nodes to the outer container and add drag handling to each node but the canvas seems to capture all events thus ignoring the drag on nodes.
The combined non-working code:
d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800);
$('body').append(
$("<div>", {
id: "canvas-wrapper"
}).append("<div/>", {
id: "canvas"
})
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
SOLVED:
By detecting mouse event locations in the canvas one may hide/show the canvas which is overlaying the SVG canvas. Therefore when there are mouse events which are started over a node then canvas should be hidden allowing drag to function while other events should be caught by canvas allowing pan/zoom
d3.js
add a comment |
I have the following code in D3 (from basic examples) for panning and zooming a canvas - and the second code block for dragging individual elements. What I would like is to both be able to pan/zoom on the entire canvas and also be allowed move a single object around when user's drag starts on a specific object.
The pan/zoom code I have is:
var svgCanvas = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var g = svgCanvas.append("g")
$('body').append(
$("<div>", {id: "canvas-wrapper" })
.append("<div/>", { id: "canvas" })
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
root.append("rect")
.attr("x", 50).attr("y", 50)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
root.append("rect")
.attr("x", 150).attr("y", 150)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
The drag code I have is:
var svg = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var nodes = svg
.selectAll('.node')
.data([
{ x: 10, y: 10 },
{ x: 100, y: 100 }
])
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag()
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
.on('start', function (d, i) {})
.on('end', function (d, i) {});
}());
nodes.append("svg:rect")
.attr("width", 100)
.attr("height", 100)
.style("fill", "red")
What do I need to do to allow dragging each object individually - in addition to drag on the entire canvas when user drags on an open are?
Obviously the difference between the two code sections is that one is working on entire canvas and one on individual elements (the first has the additional outer container) - how can I combine the two?
I have tried to simply combine the two code examples by adding nodes to the outer container and add drag handling to each node but the canvas seems to capture all events thus ignoring the drag on nodes.
The combined non-working code:
d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800);
$('body').append(
$("<div>", {
id: "canvas-wrapper"
}).append("<div/>", {
id: "canvas"
})
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
SOLVED:
By detecting mouse event locations in the canvas one may hide/show the canvas which is overlaying the SVG canvas. Therefore when there are mouse events which are started over a node then canvas should be hidden allowing drag to function while other events should be caught by canvas allowing pan/zoom
d3.js
look at the d3-force examples from the docs, it is calleddrag
– rioV8
Nov 21 '18 at 22:14
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
drag is not aforce
feature, it is independent and can be used on any element
– rioV8
Nov 22 '18 at 3:43
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01
add a comment |
I have the following code in D3 (from basic examples) for panning and zooming a canvas - and the second code block for dragging individual elements. What I would like is to both be able to pan/zoom on the entire canvas and also be allowed move a single object around when user's drag starts on a specific object.
The pan/zoom code I have is:
var svgCanvas = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var g = svgCanvas.append("g")
$('body').append(
$("<div>", {id: "canvas-wrapper" })
.append("<div/>", { id: "canvas" })
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
root.append("rect")
.attr("x", 50).attr("y", 50)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
root.append("rect")
.attr("x", 150).attr("y", 150)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
The drag code I have is:
var svg = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var nodes = svg
.selectAll('.node')
.data([
{ x: 10, y: 10 },
{ x: 100, y: 100 }
])
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag()
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
.on('start', function (d, i) {})
.on('end', function (d, i) {});
}());
nodes.append("svg:rect")
.attr("width", 100)
.attr("height", 100)
.style("fill", "red")
What do I need to do to allow dragging each object individually - in addition to drag on the entire canvas when user drags on an open are?
Obviously the difference between the two code sections is that one is working on entire canvas and one on individual elements (the first has the additional outer container) - how can I combine the two?
I have tried to simply combine the two code examples by adding nodes to the outer container and add drag handling to each node but the canvas seems to capture all events thus ignoring the drag on nodes.
The combined non-working code:
d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800);
$('body').append(
$("<div>", {
id: "canvas-wrapper"
}).append("<div/>", {
id: "canvas"
})
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
SOLVED:
By detecting mouse event locations in the canvas one may hide/show the canvas which is overlaying the SVG canvas. Therefore when there are mouse events which are started over a node then canvas should be hidden allowing drag to function while other events should be caught by canvas allowing pan/zoom
d3.js
I have the following code in D3 (from basic examples) for panning and zooming a canvas - and the second code block for dragging individual elements. What I would like is to both be able to pan/zoom on the entire canvas and also be allowed move a single object around when user's drag starts on a specific object.
The pan/zoom code I have is:
var svgCanvas = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var g = svgCanvas.append("g")
$('body').append(
$("<div>", {id: "canvas-wrapper" })
.append("<div/>", { id: "canvas" })
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
root.append("rect")
.attr("x", 50).attr("y", 50)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
root.append("rect")
.attr("x", 150).attr("y", 150)
.attr("width", 50).attr("height", 50)
.style("fill", "blue")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
The drag code I have is:
var svg = d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800)
var nodes = svg
.selectAll('.node')
.data([
{ x: 10, y: 10 },
{ x: 100, y: 100 }
])
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag()
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
.on('start', function (d, i) {})
.on('end', function (d, i) {});
}());
nodes.append("svg:rect")
.attr("width", 100)
.attr("height", 100)
.style("fill", "red")
What do I need to do to allow dragging each object individually - in addition to drag on the entire canvas when user drags on an open are?
Obviously the difference between the two code sections is that one is working on entire canvas and one on individual elements (the first has the additional outer container) - how can I combine the two?
I have tried to simply combine the two code examples by adding nodes to the outer container and add drag handling to each node but the canvas seems to capture all events thus ignoring the drag on nodes.
The combined non-working code:
d3.select('body')
.append("svg:svg")
.attr("width", 800)
.attr("height", 800);
$('body').append(
$("<div>", {
id: "canvas-wrapper"
}).append("<div/>", {
id: "canvas"
})
);
var svg = d3.select("svg");
var canvas = d3.select("#canvas");
var canvasWrapper = d3.select("#canvas-wrapper");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")")
});
canvasWrapper.call(zoom);
SOLVED:
By detecting mouse event locations in the canvas one may hide/show the canvas which is overlaying the SVG canvas. Therefore when there are mouse events which are started over a node then canvas should be hidden allowing drag to function while other events should be caught by canvas allowing pan/zoom
d3.js
d3.js
edited Nov 22 '18 at 5:25
Evan M.
asked Nov 21 '18 at 20:59
Evan M.Evan M.
938
938
look at the d3-force examples from the docs, it is calleddrag
– rioV8
Nov 21 '18 at 22:14
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
drag is not aforce
feature, it is independent and can be used on any element
– rioV8
Nov 22 '18 at 3:43
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01
add a comment |
look at the d3-force examples from the docs, it is calleddrag
– rioV8
Nov 21 '18 at 22:14
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
drag is not aforce
feature, it is independent and can be used on any element
– rioV8
Nov 22 '18 at 3:43
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01
look at the d3-force examples from the docs, it is called
drag
– rioV8
Nov 21 '18 at 22:14
look at the d3-force examples from the docs, it is called
drag
– rioV8
Nov 21 '18 at 22:14
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
drag is not a
force
feature, it is independent and can be used on any element– rioV8
Nov 22 '18 at 3:43
drag is not a
force
feature, it is independent and can be used on any element– rioV8
Nov 22 '18 at 3:43
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01
add a comment |
1 Answer
1
active
oldest
votes
As the first thing add a rect
to the svg
and call zoom on this rect
. Any mouse event not catched by an element will be used for zoom, remove the canvas wrapper.
For Chrome you can call zoom on the svg
, no need for the additional rect
.
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420396%2fpan-zoom-canvas-together-with-drag-nodes-in-d3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
As the first thing add a rect
to the svg
and call zoom on this rect
. Any mouse event not catched by an element will be used for zoom, remove the canvas wrapper.
For Chrome you can call zoom on the svg
, no need for the additional rect
.
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
add a comment |
As the first thing add a rect
to the svg
and call zoom on this rect
. Any mouse event not catched by an element will be used for zoom, remove the canvas wrapper.
For Chrome you can call zoom on the svg
, no need for the additional rect
.
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
add a comment |
As the first thing add a rect
to the svg
and call zoom on this rect
. Any mouse event not catched by an element will be used for zoom, remove the canvas wrapper.
For Chrome you can call zoom on the svg
, no need for the additional rect
.
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
As the first thing add a rect
to the svg
and call zoom on this rect
. Any mouse event not catched by an element will be used for zoom, remove the canvas wrapper.
For Chrome you can call zoom on the svg
, no need for the additional rect
.
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
var dataArray = [{x:100, y:100}, {x:200, y:200}];
var svgWidth = 800, svgHeight = 800;
var svg = d3.select('body')
.append("svg:svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var zoomRect = svg.append('rect')
.attr("width", svgWidth)
.attr("height", svgHeight)
.attr("fill", "white");
var root = svg.append("g");
var nodes = root
.selectAll('.node')
.data(dataArray)
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function (data) {
return "translate(" + [data.x, data.y] + ")";
})
.call(function () {
return d3.drag().on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", function () {
return "translate(" + [d.x, d.y] + ")";
});
})
}());
nodes.append("svg:rect")
.attr("width", 50)
.attr("height", 50)
.style("fill", "#ffb5b5")
.style("stroke", "green").style("stroke-width", "3px");
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", function () {
var t = d3.event.transform;
root.attr("transform", t);
//canvas.style("transform", "translateX(" + t.x + "px) translateY(" + t.y + "px) scale(" + t.k + ")");
});
zoomRect.call(zoom);
<script src="http://d3js.org/d3.v5.min.js"></script>
answered Nov 22 '18 at 9:42
rioV8rioV8
4,5142312
4,5142312
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53420396%2fpan-zoom-canvas-together-with-drag-nodes-in-d3%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
look at the d3-force examples from the docs, it is called
drag
– rioV8
Nov 21 '18 at 22:14
From what I have seen this forces positioning of nodes too right? I need node positioning to be exactly as user sets it without any additional automatic positioning, gravity etc
– Evan M.
Nov 22 '18 at 3:02
drag is not a
force
feature, it is independent and can be used on any element– rioV8
Nov 22 '18 at 3:43
I think I have found a direction (will update question shortly) - all I need is to be able to remove/hide/move z-index of canvas which is overlaying the SVG when mouse down starts over one of the nodes.
– Evan M.
Nov 22 '18 at 4:01