what I want to achieve is ability to pan the entire SVG "image" during the dragging operation.
now im playing wit this example: https://bl.ocks.org/mbostock/6123708 as I found it most suitable for me (most because it's handle the drag "correctly", most other examples just center the dot during drag operation I will drag more complex object so to me this feature that I increment the position not change it is more suitable) but don't really know how I could handle this feature of pan during drag
As far I know that I must:
Sorry for english mistakes it's not my native one, fell free to ask any questions that could solve this issue :)
Update
As for now I end with souch a code for drag:
var drag = d3.behavior.drag()
.on("dragstart", function () {
//d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}).on("drag", function () {
var $this = d3.select(this);
var t = d3.transform($this.attr("transform"));
t.translate[0] += d3.event.dx;
t.translate[1] += d3.event.dy;
$this.attr("transform", "translate(" + t.translate + ")");
}).on("dragend", function () {
console.log("dragend");
d3.select(this).classed("dragging", false);
});
And souch for zoom:
var zoom = d3.behavior.zoom()
.scaleExtent([0.1, 2])
.on("zoomstart", function() {
if (d3.event.sourceEvent.buttons != 2) {
savedTranslation = zoom.translate();
} else {
savedTranslation = null;
}
}).on("zoom", function() {
var translate = d3.event.translate;
if (d3.event.sourceEvent.buttons != 2) {
zoom.translate(savedTranslation);
translate = savedTranslation;
}
svgContainer.attr("transform", "translate(" + translate + ")scale(" + d3.event.scale + ")");
}).on("zoomend", function() {
if (savedTranslation) {
zoom.translate(savedTranslation);
savedTranslation = null;
}
});
The usage of the zoom + prevent context menu popup (also block the double click to zoom as it will be use to popup edit popup modal)
var svg = d3.select("#svg-workspace")
.call(zoom)
.on("dblclick.zoom", null)
.on('contextmenu',function () {
d3.event.preventDefault();
return false;
});
And the attach od D3.JS
d3.select($foreignObject.get(0))
.call(drag);
The $foreignObject is jQuery grabbed object
And stil the problem is to start panning when dragging.
This is probably really hard to achive in D3JS so I end up with writing some JS code. Really helpfull was this page: http://www.petercollingridge.co.uk/interactive-svg-components/pan-and-zoom-control
var transMatrix = [1,0,0,1,0,0];
var $svg = $("#svg-workspace");
mapMatrix = $("#svg-workspace-group")[0];
function pan(dx, dy)
{
transMatrix[4] += dx;
transMatrix[5] += dy;
newMatrix = "matrix(" + transMatrix.join(' ') + ")";
mapMatrix.setAttributeNS(null, "transform", newMatrix);
}
function zoom(scale, mousex, mousey)
{
for (var i=0; i < transMatrix.length; i++)
{
transMatrix[i] *= scale;
}
transMatrix[4] += (1-scale) * mousex;
transMatrix[5] += (1-scale) * mousey;
newMatrix = "matrix(" + transMatrix.join(' ') + ")";
mapMatrix.setAttributeNS(null, "transform", newMatrix);
}
$svg.contextmenu(function () {return false;});
var drag = false;
var distanceX = 0;
var distanceY = 0;
var initX = 0;
var initY = 0;
$svg.on("mousedown", function(evt) {
if(evt.originalEvent.which == 1) {
drag = true;
distanceX = 0;
distanceY = 0;
}
});
$svg.on("mouseup", function(evt) {
if (evt.originalEvent.which == 1) {
drag = false;
initX = parseInt($("#dragtest").attr("cx"));
initY = parseInt($("#dragtest").attr("cy"));
}
});
$svg.on("mousemove", function(evt) {
if( (evt.originalEvent.buttons & 2) == 2) {
pan(evt.originalEvent.movementX, evt.originalEvent.movementY);
} else if(drag) {
distanceX += evt.originalEvent.movementX;
distanceY += evt.originalEvent.movementY;
$("#dragtest").attr("cx", initX + distanceX / transMatrix[0]);
$("#dragtest").attr("cy", initY + distanceY / transMatrix[0]);
}
});
$svg.on("mousewheel", function(evt) {
if(evt.originalEvent.deltaY > 0) {
zoom(0.9, evt.originalEvent.offsetX, evt.originalEvent.offsetY);
} else if (evt.originalEvent.deltaY < 0) {
zoom(1.1, evt.originalEvent.offsetX, evt.originalEvent.offsetY);
}
});
The corresponding HTML code:
<svg id="svg-workspace" xmlns="http://www.w3.org/2000/svg" width="900" height="600" viewBox="0 0 900 600" style="display: block; margin: 0 auto; border: 1px solid #ddd;">
<g id="svg-workspace-group" transform="translate(0,0)scale(1)">
<circle cx="0" cy="0" r="5" stroke="black" stroke-width="1" fill="red" />
<circle cx="100" cy="-100" r="5" stroke="black" stroke-width="1" fill="red" />
<circle cx="100" cy="100" r="5" stroke="black" stroke-width="1" fill="red" />
<circle cx="-100" cy="100" r="5" stroke="black" stroke-width="1" fill="red" />
<circle id="dragtest" cx="-100" cy="-100" r="5" stroke="black" stroke-width="1" fill="red" />
</g>
</svg>
I found only one issue with this code Dragging is not working properly with zooming, but yea I could live with that ;)