How could I implement the dragging behavior along with the responsiveness in svg
using d3.js
?
By the responsiveness I mean that if resized to any screen resolution the elements I drew in svg
element will preserve their aspect ratio.
By dragging behavior in the case I mean that if I will draw too large elements or if I will draw them out of the default viewBox
I would like the user to be able to drag the scene enough so that to see the elements which are out of bounds.
Here is my unlucky attempt to tackle the problem:
I decided to get over with the responsiveness using only %
units. So, now, for example when I draw a circle and specify its stroke-width
to be 1%
and then I decide to resize the window which displays the svg
containing the circle
or when change the device from PC to a phone the stroke-width
really will still be 1%
with the respect to the svg
element. And here the svg
width
and height
attributes are set to 100%
to cover the whole parent (for example div
).
Now I want to tackle the problem which relates to the incorporation of the dragging behavior. I may say that I have some basic skills using the viewBox
. So, I know that the desired dragging behavior may be easily achieve by manipulating the x
and y
attributes if the svg
attribute viewBox
. I will just change the x
and y
and the parts of the svg
which the user sees can be changed(user can see now the stuff in any svg
canvas part). But here is the problem I know how to do it using numbers (any units which are not %
units). So, I am expecting the %
units to behave the same. For example, the svg
always has fixed width and height even if they(width and height) are specified in %
. Hence, I expect that when I will put attribute x
of a viewBox
to be 100%
I will see exactly the part of the svg
canvas which is 100%
to the left and 100%
are determined responsively.
Here is the code I try.
Here is the .js
part:
var svg = d3.select("#drawRegion")
.append("svg")
.attr("width", "100%")
.attr("height", "100%");
svg.append("rect")
.attr("x", "0")
.attr("y", "0")
.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "yellow");
for(var i = 0; i < 10; ++i) {
svg.append("circle")
.attr("cx", ((i*20)+10)+"%")
.attr("cy", "50%")
.attr("r", "5%")
.attr("stroke", "black")
.attr("stroke-width", "1%")
.attr("fill", '#'+Math.floor(Math.random()*16777215).toString(16));
}
svg.viewBoxInfo = {
x: 0,
y: 0,
width: "100%",
height: "100%",
maxX: 150,
minX: 0,
maxY: 0,
minY: 0,
stringRepresentation: function() {
if(this.x > this.maxX) {
this.x = this.maxX;
} else if(this.x < this.minX) {
this.x = this.minX;
}
if(this.y > this.maxY) {
this.y = this.maxY
} else if(this.y < this.minY) {
this.y = this.minY;
}
return this.x + "% " + this.y + "% " + this.width + "% " + this.height + "%";
}
};
var prepareDraggingBehaviour = function(svg){
var panning = null;
var currentMouse = null;
var onMouseDownSvg = function() {
panning = d3.mouse(this);
};
var onMouseMoveSvg = function() {
currentMouse = d3.mouse(this);
if (panning) {
svg.viewBoxInfo.x += (panning[0] - currentMouse[0]);
svg.viewBoxInfo.y += (panning[1] - currentMouse[1]);
svg.attr("viewBox", svg.viewBoxInfo.stringRepresentation());
}
};
var onMouseUpSvg = function() {
panning = null;
};
svg.on("mousedown", onMouseDownSvg);
svg.on("mousemove", onMouseMoveSvg);
d3.select(window).on("mouseup", onMouseUpSvg);
};
prepareDraggingBehaviour(svg);
And when everything should work I am getting an error which tells me that the %
can not be a value for the x
and y
viewBox
attributes:
Error: attribute viewBox: Expected number, "150% 0% 100%% 100%%".`
What else could I try to get the responsiveness along with the dragging behavior? Will be grateful for any help provided.