【问题标题】:FabricJS Catch click on object inside groupFabricJS Catch单击组内的对象
【发布时间】:2016-03-06 22:49:47
【问题描述】:

我尝试了很多事情,比如计算位置,处理我们在原始 fabricjs 中的事件。有没有人这样做过?

【问题讨论】:

    标签: onclick fabricjs


    【解决方案1】:

    可以通过向 fabric.Group 对象添加选项:subTargetCheck: true 来监听内部对象上的事件。

        // create a group
        let group = new fabric.Group([circle, rect], {
            subTargetCheck: true
        });
    
        circle.on('mousedown', function(e) { 
            // e.target should be the circle
            console.log(e.target);
        });
    

    【讨论】:

    【解决方案2】:

    我从asturur repo 下载了fabricjs。 构建 fabric.js 文件

    node build.js modules=ALL exclude=json,gestures
    

    它有效!

    然后您可以在组中的对象上使用事件。

    canvas._objects[0]._objects[0].on('mousedown', function(e){ this.stroke = 'black'});
    

    在我的应用中,我决定从 mousedown 回调中搜索事件

    group.on('mousedown', function(e){
        var innerTarget  = group._searchPossibleTargets(e.e);
        console.log(innerTarget);
    });
    
    group._searchPossibleTargets = function(e) {
        var pointer = this.canvas.getPointer(e, true);
        var i = objects.length,
            normalizedPointer = this.canvas._normalizePointer(this, pointer);
    
        while (i--) {
            if (this.canvas._checkTarget(normalizedPointer, this._objects[i])) {
                return this._objects[i];
            }
        }
        return null;
    }
    

    【讨论】:

    • 在我这边不起作用......无论我点击哪里,它都会返回所有......
    【解决方案3】:

    在 FabricJS 中,一旦对象被组合到一个组中,事件只会在那里发生,即使是选定的事件 - 所以您无法检测到组中的哪些项目被选中。事件处理程序内部

    var g = new fabric.Group([ rect, text ], {
    g.on('mousedown', function(e) {
        // Inspect, for a collection of the objects in this group
        this._objects
    });
    

    即使在组装到组之前将事件处理程序附加到对象,处理程序也不会触发:(

    【讨论】:

    • 我的意思是,Fabric 不支持您想要的内容,无需编辑其核心或覆盖某些例程/事件处理程序
    • 是的,我知道。这真的很有用,我相信有人已经这样做了。
    • dblclick 如何获得相同的效果?
    【解决方案4】:

    这可能对你有帮助http://jsfiddle.net/UKbaseduser/Kt9Mk/1/

    $("#1").click(function(){
      ZoomIn('tmp1');
    });
    $("#2").click(function(){
      ZoomOut('tmp1');
    });
    $("#3").click(function(){
      ZoomIn('tmp2');
    });
    $("#4").click(function(){
      ZoomOut('tmp2');
    });
    
    var canvas = new fabric.Canvas('c');
    
    var rect1 = new fabric.Rect({ left: 150, top: 150, width: 100, height: 100, fill: 'green'});
    var rect2 = new fabric.Rect({ left: 250, top: 250, width: 100, height: 100, fill: 'green'});
    rect1.grp='tmp1';
    rect2.grp='tmp1';
    var c = new fabric.Circle({
            left: 200,
            top: 200,
            radius: 50,
            fill: 'red',
            opacity:0.8
          });
    c.grp='tmp2';
    canvas.add(rect1);
    canvas.add(rect2);
    canvas.add(c);
    canvas.renderAll();
    
    function ZoomIn(inGrp){
        var SCALE_FACTOR = 1.2;
        var objects = canvas.getObjects();
        objects.forEach(function(obj){
            if (obj.grp==inGrp){     
                var scaleX = obj.scaleX;
                var scaleY = obj.scaleY;
                var left = obj.left;
                var top = obj.top;
    
                var tempScaleX = scaleX * SCALE_FACTOR;
                var tempScaleY = scaleY * SCALE_FACTOR;
                var tempLeft = left * SCALE_FACTOR;
                var tempTop = top * SCALE_FACTOR;
                obj.scaleX = tempScaleX;
                obj.scaleY = tempScaleY;
                obj.left = tempLeft;
                obj.top = tempTop;
                obj.setCoords();
                }
            });
        canvas.renderAll();
     }
    function ZoomOut(inGrp){
        var SCALE_FACTOR = 1.2;
        var objects = canvas.getObjects();
        objects.forEach(function(obj){
            if (obj.grp==inGrp){     
                var scaleX = obj.scaleX;
                var scaleY = obj.scaleY;
                var left = obj.left;
                var top = obj.top;
    
                var tempScaleX = scaleX * 1/SCALE_FACTOR;
                var tempScaleY = scaleY * 1/SCALE_FACTOR;
                var tempLeft = left * 1/SCALE_FACTOR;
                var tempTop = top * 1/SCALE_FACTOR;
                obj.scaleX = tempScaleX;
                obj.scaleY = tempScaleY;
                obj.left = tempLeft;
                obj.top = tempTop;
                obj.setCoords();
                }
            });
        canvas.renderAll();
     }
    

    这里也有类似的讨论https://groups.google.com/forum/#!topic/fabricjs/hQwHxGfyx6w 可能会给你一些建议。

    【讨论】:

    • 在您的 jsfiddle 链接上是空画布。你的功能看起来做放大和缩小。单击组内的对象时没有任何内容。
    【解决方案5】:

    这对我有用:

    // create a group
    let group = new fabric.Group([circle, rect], {
        subTargetCheck: true
    });
    
    canvas.on('mouse:down', function (e) {
    // clicked item will be
      console.log(e.subTargets[0])  
    });
    

    【讨论】:

    • 如何获得 dblclick 的子目标?
    【解决方案6】:

    我没有足够的声誉来评论现有的答案,所以就这样吧。我正在使用 v2.X 的 Fabric,所有现有的解决方案都不起作用。不再存在的方法的控制台错误或在containsPoint 的情况下总是false 所以我自己构建了。

    js
    const getSelectedObject = (target, e) => {
      const point = target.canvas.getPointer(e, false);
    
      const objects = findSubTargets(target, []);
    
      const objectIndex = objects
        .reduce((reduction, object, index) => {
          reduction.push(
            getBoundingPoints(
              object,
              index === 0 ? 0 : reduction[0].start.x,
              index === 0 ? 0 : reduction[0].start.y
            )
          );
    
          return reduction;
        }, [])
        .reverse()
        .findIndex((bounds) => pointIsInBounds(point, bounds));
    
      return objects.reverse()[objectIndex];
    };
    

    和辅助函数

    js
    const getBoundingPoints = (object, deltaX, deltaY) => {
      const coords = object.get("aCoords");
    
      const x1 = coords.tl.x + deltaX;
      const y1 = coords.tl.y + deltaY;
      const x2 = coords.br.x + deltaX;
      const y2 = coords.br.y + deltaY;
    
      return {
        start: { x: x1, y: y1 },
        finish: { x: x2, y: y2 }
      };
    };
    
    
    const pointIsInBounds = (point, bounds) => {
      const xIsInBounds = point.x >= bounds.start.x && point.x <= bounds.finish.x;
      const yIsInBounds = point.y >= bounds.start.y && point.y <= bounds.finish.y;
    
      return xIsInBounds && yIsInBounds;
    };
    
    
    const findSubTargets = (target, objects) => {
      if (target.isType("group")) {
        objects.push(target);
        target.forEachObject((object) => findSubTargets(object, objects));
      }
    
      return objects;
    };
    

    我已经用简单的组、嵌套组和组内组内的组对此进行了测试。

    【讨论】:

      【解决方案7】:

      您可以将subTarget 添加到该组。子目标对象将被添加到目标事件中。

      let group = new fabric.Group([circle, rect], {
          subTargetCheck: true
      });
      
      canvas.on('mouse:down', (event) => {
          const { subTargets } = event; // subTargets will include circle object
          .... 
      })
      

      【讨论】:

        猜你喜欢
        • 2014-06-18
        • 1970-01-01
        • 2019-06-01
        • 2017-01-29
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 2015-10-12
        • 2018-08-16
        相关资源
        最近更新 更多