2 years ago

#61344

test-img

Gerd Torf

FabricJS - Object is removed if top left corner is moved out of viewport

I have a canvas. The users are able to draw rectangles in it using fabricjs. The second feature is that you are able to move around in the canvas (called panning). When I am in the drawing mode and than start to pan around, the rectangle disappears if I am moving the top left corner of the rectangle out of the canvas. If you move the viewport, so that the top left corner is in the canvas back again, the rectangle becomes visible again. If you move other corners of the rectangle out of the canvas, the rectangle stays visible.

Is there a way to prevent that behavior?

Steps to reproduce:

  1. use snippet below
  2. click the "rect" button
  3. hold the left mouse key and draw a new rectangle (keep the mouse key pressed) - this will create a yellow rect
  4. press and hold the "alt" key on your keyboard and move the mouse (the mouse key is still pressed) - you are panning around now
  5. move the view, so that the top left corner of the rect will be outside the canvas - the yellow rect will disappear

Goal:

The rect will stay visible even if I am moving the top left corner out of the canvas.

(function() {

      var drawMode = false
      var isDrawing = false
      var isPanning = false
      document.getElementById("rect").onclick = function() {
        drawMode = !drawMode
        document.getElementById("rect").style["background-color"] = drawMode ? "lightblue" : "lightgrey"
      }

      var canvas = new fabric.Canvas("canvas")

      canvas.on("mouse:down", function(opt) {
        var evt = opt.e
        this.selection = false

        if (drawMode) {
          isDrawing = true
          this.startPosX = evt.clientX
          this.startPosY = evt.clientY
          this.drawRect = new fabric.Rect({
            left: evt.clientX,
            top: evt.clientY,
            fill: "yellow",
          })
          canvas.add(this.drawRect)
        } else if (evt.altKey === true) {
          isPanning = true
          this.lastPosX = evt.clientX
          this.lastPosY = evt.clientY
        }
      })

      canvas.on("mouse:move", function(opt) {
        var evt = opt.e
        if (evt.altKey === true && isPanning) {
          var vpt = this.viewportTransform
          if (this.lastPosX) vpt[4] += evt.clientX - this.lastPosX
          if (this.lastPosY) vpt[5] += evt.clientY - this.lastPosY
          this.requestRenderAll()
          this.lastPosX = evt.clientX
          this.lastPosY = evt.clientY
        } else if (isDrawing) {
          this.drawRect.set({
            width: evt.clientX - this.startPosX,
            height: evt.clientY - this.startPosY,
          })
          canvas.renderAll()
        }
      })

      canvas.on("mouse:up", function(opt) {
        // on mouse up we want to recalculate new interaction
        // for all objects, so we call setViewportTransform
        var evt = opt.e
        this.setViewportTransform(this.viewportTransform)
        isPanning = false
        this.selection = true
        if (isDrawing) {
          this.drawRect.set({
            width: evt.clientX - this.startPosX,
            height: evt.clientY - this.startPosY,
            fill: "orange",
          })
          isDrawing = false
        }
      })

      document.addEventListener("keydown", function(opt) {
        if (opt.key === "Alt") {
          if (!isPanning) isPanning = true
          if (drawMode) drawMode = false
        }
      })

      document.addEventListener("keyup", function(opt) {
        if (opt.key === "Alt") {
          if (isPanning) isPanning = false
        }
      })
    })()
<html>
  <body style="margin: 0">
    <canvas id="canvas" width=500 height=300 style="border: 1px solid blue"></canvas>
    <h3>Tools</h3>
    <button id="rect" style="background-color: lightgrey">rect</button>
    <h3>Features</h3>
    <ul>
      <li>draw rectangle (activate draw mode with above button</li>
      <li>move around (need to hold alt-key)</li>
    </ul>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.4.0/fabric.min.js"></script>
  </body>
</html>

fabricjs

0 Answers

Your Answer

Accepted video resources