简体   繁体   中英

Fabric.js bounding box with blurred shadows

I'm trying to draw a bounding box around objects that have a shadow. object.getBoundingRect() does not take into account shadows. Regular shadows are straightforward, but when blur is added it is more difficult.

Is there a way to get the bounds?

https://jsfiddle.net/e77c0owf/

        function getObjBounds(obj) {
          var bounds = obj.getBoundingRect();
          var shadow = obj.getShadow();

          if (shadow !== null) {
            var blur = shadow.blur;
            var signX = shadow.offsetX >= 0.0 ? 1.0 : -1.0;
            var signY = shadow.offsetY >= 0.0 ? 1.0 : -1.0;
            var offsetX = (shadow.offsetX + (signX * blur)) * Math.abs(obj.scaleX);
            var offsetY = (shadow.offsetY + (signY * blur)) * Math.abs(obj.scaleY);

            if (offsetX > 0) {
              bounds.width += offsetX;
            } else if (offsetX < 0) {
              bounds.width += Math.abs(offsetX);
              bounds.left -= Math.abs(offsetX);
            }

            if (offsetY > 0) {
              bounds.height += offsetY;
            } else if (offsetY < 0) {
              bounds.height += Math.abs(offsetY);
              bounds.top -= Math.abs(offsetY);
            }
          }

          return bounds;
        }

You have to check fabricjs calculations for blurring and scaling, plus you have to take in account situation where offset of shadow is smaller than blur value.

function getObjBounds(obj) {
  var bounds = obj.getBoundingRect();
  var shadow = obj.getShadow();

  if (shadow !== null) {
    var blur = shadow.blur;
    var mBlur = blur * Math.abs(obj.scaleX + obj.scaleY) / 4
    var signX = shadow.offsetX >= 0.0 ? 1.0 : -1.0;
    var signY = shadow.offsetY >= 0.0 ? 1.0 : -1.0;
    var mOffsetX = shadow.offsetX * Math.abs(obj.scaleX);
    var mOffsetY = shadow.offsetY * Math.abs(obj.scaleY); 
    var offsetX = mOffsetX + (signX * mBlur);
    var offsetY = mOffsetY + (signY * mBlur);

    if (mOffsetX > mBlur) {
      bounds.width += offsetX;
    } else if (mOffsetX  < -mBlur) {
      bounds.width -= offsetX;
      bounds.left += offsetX;;
    } else {
      bounds.width += mBlur * 2;
      bounds.left -= mBlur - mOffsetX;
    }

    if (mOffsetY > mBlur) {
      bounds.height += offsetY;
    } else if (mOffsetY < -mBlur) {
      bounds.height -= offsetY;
      bounds.top += offsetY;
    } else {
      bounds.height += mBlur * 2;
      bounds.top -= mBlur - mOffsetY;
    }
  }

  return bounds;
}

resulting fiddle: https://jsfiddle.net/e77c0owf/1/

 // ************************************ // Bounding box calculation logic // ************************************ function getObjBounds(obj) { var bounds = obj.getBoundingRect(); var shadow = obj.getShadow(); if (shadow !== null) { var blur = shadow.blur; var mBlur = blur * Math.abs(obj.scaleX + obj.scaleY) / 4 var signX = shadow.offsetX >= 0.0 ? 1.0 : -1.0; var signY = shadow.offsetY >= 0.0 ? 1.0 : -1.0; var mOffsetX = shadow.offsetX * Math.abs(obj.scaleX); var mOffsetY = shadow.offsetY * Math.abs(obj.scaleY); var offsetX = mOffsetX + (signX * mBlur); var offsetY = mOffsetY + (signY * mBlur); if (mOffsetX > mBlur) { bounds.width += offsetX; } else if (mOffsetX < -mBlur) { bounds.width -= offsetX; bounds.left += offsetX;; } else { bounds.width += mBlur * 2; bounds.left -= mBlur - mOffsetX; } if (mOffsetY > mBlur) { bounds.height += offsetY; } else if (mOffsetY < -mBlur) { bounds.height -= offsetY; bounds.top += offsetY; } else { bounds.height += mBlur * 2; bounds.top -= mBlur - mOffsetY; } } return bounds; } // ************************************ // Draw a ton of test cases below here // ************************************ // Create a canvas var canvas = new fabric.Canvas('c', { backgroundColor: '#FFFFFF' }); canvas.add(new fabric.Rect({ fill: 'red', left: 100, top: 100, width: 50, height: 50, shadow: { color: 'black', blur: 0, offsetX: -20, offsetY: -10 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 30, top: 20, width: 50, height: 50, shadow: { color: 'black', blur: 0, offsetX: -20, offsetY: 0 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 30, top: 250, width: 50, height: 50, shadow: { color: 'black', blur: 0, offsetX: 60, offsetY: -60 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 180, top: 20, width: 50, height: 50, shadow: { color: 'black', blur: 10, offsetX: 20, offsetY: 20 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 180, top: 150, width: 50, height: 50, shadow: { color: 'black', blur: 20, offsetX: 0, offsetY: 0 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 220, top: 280, width: 50, height: 50, shadow: { color: 'black', blur: 20, offsetX: -10, offsetY: -10 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 280, top: 20, width: 50, height: 50, scaleX: 2.3, scaleY: 2.3, shadow: { color: 'black', blur: 10, offsetX: 20, offsetY: 20 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 360, top: 230, width: 50, height: 50, scaleX: 0.5, scaleY: 0.5, shadow: { color: 'black', blur: 20, offsetX: 0, offsetY: 0 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 380, top: 290, width: 50, height: 50, scaleX: 2.0, scaleY: 2.0, shadow: { color: 'black', blur: 10, offsetX: 0, offsetY: 0 } })); canvas.add(new fabric.Rect({ fill: 'red', left: 140, top: 380, width: 50, height: 50, scaleX: -4.0, scaleY: 0.5, shadow: { color: 'black', blur: 20, offsetX: -10, offsetY: -10 } })); // Draw bounding boxes var objs = canvas.getObjects(); var boxes = []; for (var i = 0; i < objs.length; i++) { var box = getObjBounds(objs[i]); boxes.push(new fabric.Rect({ fill: '', stroke: 'blue', strokeWidth: 1, left: box.left, top: box.top, width: box.width, height: box.height })); } for (var j = 0; j < boxes.length; j++) { canvas.add(boxes[j]); } canvas.renderAll(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.js"></script> <canvas id="c" width="550" height="450"></canvas> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM