Разница «hasPoint» между v 1.7.2 и v 2.3.1 - PullRequest
0 голосов
/ 04 июня 2018

Я вернулся к проекту FabricJS, выполненному в v 1.7.2, и получаю ошибку с v 2.3.1, которую я не смог разобрать.Я полагаю, что между этими версиями многое изменилось.

Произошла ошибка при вызове containsPoint в приведенном ниже фрагменте кода:

if (event.e.ctrlKey && canvas.containsPoint(event.e, canvas.backgroundImage)) {
  // code removed for clarity
}

Я пытаюсь проверить, произошло ли событие мышипроисходит с прямоугольником холста backgroundImage.

В консоли код завершается с ошибкой Cannot read property 'tl' of null в вызове функции _getImageLines: function(oCoords), поскольку аргумент oCoords равен нулю.

Код v1.7.2 имеет тест для oCoords и устанавливает их, если они не существуют.Если я исправлю этот тест в v2.3.1, ошибка не возникнет.

Может кто-нибудь объяснить, что изменилось между версиями, или указать мне объяснение?Я не хочу взломать v2.3.1.Должен ли я звонить setCoords() перед вызовом containsPoint()?

Кроме того, (для дополнительной путаницы), хотя версия containsPoint версии 2.3.1 позволяет передавать параметры, в моем использовании я невозможность передавать параметры, потому что функция вызывается косвенно.

(извините, это так долго!)


версия: "1.7.2"

   /**
     * Checks if point is inside the object
     * @param {fabric.Point} point Point to check against
     * @return {Boolean} true if point is inside the object
     */
    containsPoint: function(point) {
      if (!this.oCoords) {
        this.setCoords();
      }
      var lines = this._getImageLines(this.oCoords),
          xPoints = this._findCrossPoints(point, lines);

      // if xPoints is odd then point is inside the object
      return (xPoints !== 0 && xPoints % 2 === 1);
    },

версия: '2.3.1'

Эта containsPoint функция вызывает функцию containsPoint внизу страницы.

 /**
     * Checks if point is contained within an area of given object
     * @param {Event} e Event object
     * @param {fabric.Object} target Object to test against
     * @param {Object} [point] x,y object of point coordinates we want to check.
     * @return {Boolean} true if point is contained within an area of given object
     */
    containsPoint: function (e, target, point) {
      // console.log('cp',e, target, point);

      var ignoreZoom = true,
          pointer = point || this.getPointer(e, ignoreZoom),
          xy;

      if (target.group && target.group === this._activeObject && target.group.type === 'activeSelection') {
        xy = this._normalizePointer(target.group, pointer);
      }
      else {
        xy = { x: pointer.x, y: pointer.y };
      }

      // http://www.geog.ubc.ca/courses/klink/gis.notes/ncgia/u32.html
      // http://idav.ucdavis.edu/~okreylos/TAship/Spring2000/PointInPolygon.html      
      return (target.containsPoint(xy) || target._findTargetCorner(pointer));
    },

   /**
     * Checks if point is inside the object
     * @param {fabric.Point} point Point to check against
     * @param {Object} [lines] object returned from @method _getImageLines
     * @param {Boolean} [absolute] use coordinates without viewportTransform
     * @param {Boolean} [calculate] use coordinates of current position instead of .oCoords
     * @return {Boolean} true if point is inside the object
     */
    containsPoint: function(point, lines, absolute, calculate) {

      var lines = lines || this._getImageLines(
            calculate ? this.calcCoords(absolute) : absolute ? this.aCoords : this.oCoords
          ),
          xPoints = this._findCrossPoints(point, lines);

      // if xPoints is odd then point is inside the object
      return (xPoints !== 0 && xPoints % 2 === 1);
    },

 /**
     * Method that returns an object with the object edges in it, given the coordinates of the corners
     * @private
     * @param {Object} oCoords Coordinates of the object corners
     */
    _getImageLines: function(oCoords) {      
      return {
        topline: {
          o: oCoords.tl,
          d: oCoords.tr
        },
        rightline: {
          o: oCoords.tr,
          d: oCoords.br
        },
        bottomline: {
          o: oCoords.br,
          d: oCoords.bl
        },
        leftline: {
          o: oCoords.bl,
          d: oCoords.tl
        }
      };
    },

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Хорошо, сузили это:

Как отмечалось выше, в Fabric v1.7.2 была эта проверка в функции containsPoint:

   if (!this.oCoords) {
        this.setCoords();
   }

В моем пересмотренном коде, если я сделаюsetCoords() вызов до вызова containsPoint, тогда нет ошибки.Я не сталкивался с каким-либо объяснением этого изменения, предположим, что оно относится к производительности.

canvas.backgroundImage.setCoords();

if (event.e.ctrlKey && canvas.containsPoint(event.e, canvas.backgroundImage)) {
  // do some cool stuff
}

Другое различие между v1.7.2 и 2.3.1, с которым я столкнулся, заключается в том, что canvas.backgroundImage больше не имеетgetWidth() функция.Вместо этого width и height теперь являются свойствами.

0 голосов
/ 04 июня 2018

Как уже упоминалось в документе canvas.containsPoint , в качестве второго аргумента требуется объект Fabric.Если canvas.backgroundImage не равно нулю, то оно должно работать.И object.containsPoint требуется точка и линия изображения в качестве второго аргумента.

DEMO

var canvas = new fabric.Canvas('myCanvas',{
 width: 400,
 height: 400
});
var rect = new fabric.Rect({width:100,height:100});
canvas.add(rect);
canvas.on('mouse:down',function(option){
 //if(canvas.containsPoint(option.e,rect)) console.log('inside rect');
 if(rect.containsPoint(option.e)) console.log('inside rect')
})
#myCanvas {
  border: 1px solid black;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.7/fabric.js"></script>-->
<canvas id="myCanvas" ></canvas>
...