Skip to content Skip to sidebar Skip to footer

Loadfromjson At Different Screen Resolutions And Aspect Ratios

I need to be able to use loadFromJSON with canvas resolutions/aspect ratios other than the one that the JSON data was generated at, while maintaining the relationships of the graph

Solution 1:

Finally solved this after trying many different approaches (and much anguish).

The gist is to select all objects and then scale and center. A tricky thing is that the first object in my data is an image which all the drawn elements need to stay in register with. So I first correct the image path and then, after the selection has been scaled, I shift the selection to that the image remains centered on-screen.

Looking at the code now, I can see places to optimize it (e.g. since there is only ever one image in my data, there is no need to loop through all the remaining data after the images has been found)


loadData(data) {

    var jsonObj = JSON.parse(data);

    jsonObj.objects.forEach(element => {
      if (element.type == "image") {
        var imgPath = element.src.split("assets")

        if (imgPath.length > 1) {
          element.src = upath.joinSafe(projectDirectory, "assets", imgPath[1])
        }
      }
    });

    varself = this;
    this.canvas.loadFromJSON(jsonObj, function () {

      var selection = new fabric.ActiveSelection(self.canvas.getObjects(), { canvas: self.canvas });


      // var selectionWidth = (selection.width >  self.canvas.getWidth()) ?  self.canvas.getWidth() : selection.width// var selectionHeight = (selection.height > self.canvas.getHeight()) ? self.canvas.getHeight() : selection.heightvar sizeObj = self.resizer(
        { width: self.canvas.getWidth(), height: self.canvas.getHeight() },
        { width: selection.width, height: selection.height });

      // console.log('sizeObj', sizeObj);// selection.scaleToWidth(sizeObj.width, false)// selection.scaleToWidth(sizeObj.width, true)
      selection.scaleToHeight(sizeObj.height)
      // selection.scaleToHeight(sizeObj.height, true)

      selection.center();


      /**
       * ------------------------------------------
       * This keeps the IMAGE centered on the canvas instead of 
       * just centering  the selection – otherwise the image will shift 
       */var selectionObjs = selection.getObjects();
      var imgObj = selectionObjs[0]
      var matrix = selection.calcTransformMatrix();
      var finalPosition = fabric.util.transformPoint({ x: imgObj.left, y: imgObj.top }, matrix);

      sizeObj = self.resizer(
        { width: self.canvas.getWidth(), height: self.canvas.getHeight() },
        { width: imgObj.getScaledWidth(), height: imgObj.getScaledHeight() });

      selection.left += sizeObj.x - finalPosition.x;
      selection.top += sizeObj.y - finalPosition.y;
      // ------------------------------------------

      selection.setCoords()
      selection.destroy()

      self.canvas.renderAll();
      self.canvas.calcOffset()

    }, function (o, object) {

    })

    self.setObjectsSelectable(self.toolbarIsVisible)
    self.toolActive = false
  }

resizer(canvas, imageObj) {
    var imageAspectRatio = imageObj.width / imageObj.height;
    var canvasAspectRatio = canvas.width / canvas.height;
    var renderableHeight, renderableWidth, xStart, yStart;

    // If image's aspect ratio is less than canvas's we fit on height// and place the image centrally along widthif (imageAspectRatio < canvasAspectRatio) {
      renderableHeight = canvas.height;
      renderableWidth = imageObj.width * (renderableHeight / imageObj.height);
      xStart = (canvas.width - renderableWidth) / 2;
      yStart = 0;
    }

    // If image's aspect ratio is greater than canvas's we fit on width// and place the image centrally along heightelseif (imageAspectRatio > canvasAspectRatio) {
      renderableWidth = canvas.width
      renderableHeight = imageObj.height * (renderableWidth / imageObj.width);
      xStart = 0;
      yStart = (canvas.height - renderableHeight) / 2;
    }

    // Happy path - keep aspect ratioelse {
      renderableHeight = canvas.height;
      renderableWidth = canvas.width;
      xStart = 0;
      yStart = 0;
    }
    return { x: xStart, y: yStart, width: renderableWidth, height: renderableHeight }
  }

Post a Comment for "Loadfromjson At Different Screen Resolutions And Aspect Ratios"