0

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.

manymanymore
  • 2,251
  • 3
  • 26
  • 48
  • I think you are misunderstanding the purpose of `viewBox`. It defines the region of the document that is visible in the viewBort. It makes no sense to use percentage units here. If you want to see the region of the document to the right of the viewPort, then set the viewBox x to the viewBox width. – Paul LeBeau Jun 03 '18 at 13:47
  • @PaulLeBeau, ok. The `viewBox` width is `100%`, it does not allow to use percents for `x` and `y` attributes of the `viewBox`, so I can not set the `x` to be equal the `width` of the `viewBox` in the case. – manymanymore Jun 03 '18 at 15:06
  • Percentage units are not valid anywhere in a `viewBox`.The values have to be ordinary numbers. https://www.w3.org/TR/SVG/single-page.html#coords-ViewBoxAttribute – Paul LeBeau Jun 03 '18 at 16:57
  • @PaulLeBeau, the percents are valid as `width` and `height` attributes values for the `viewBox`. – manymanymore Jun 03 '18 at 18:13
  • No they aren't. Read the definition of viewBox again. It says "four numbers". [Then look at the definition of number](https://www.w3.org/TR/SVG/single-page.html#types-DataTypeNumber). – Paul LeBeau Jun 03 '18 at 18:25
  • @PaulLeBeau, thank you. Should I delete the question? – manymanymore Jun 03 '18 at 19:58
  • No need to delete. It may help other people. – Paul LeBeau Jun 04 '18 at 10:34

0 Answers0