首页 > 解决方案 > 如何将指针事件沿层堆栈中的对象冒泡?

问题描述

fabric.Object.prototype.objectCaching = false;
var canvasBackground = new fabric.Canvas('backgroundcanvas');
var canvas = new fabric.Canvas('paintcanvas');
var canvas_2 = new fabric.Canvas('paintcanvas_2');
var canvas_3 = new fabric.Canvas('paintcanvas_3');
var canvas_4 = new fabric.Canvas('paintcanvas_4');


fabric.Image.fromURL('https://dev.loversloc.com/media/collection/templates/confetti_easy_01.png', function(myImg) {
 var img1 = myImg.set({ 
    top: 0,
    left: 0,
    scaleX: canvas.width/myImg.width,
    scaleY: canvas.height/myImg.height,
		selectable : false,
    evented: false
 });
 canvas.add(img1); 
});

fabric.Image.fromURL('https://beautymode.fr/wp-content/uploads/2017/09/636096742373357996142416222_fashion-beauty-tips.jpg', function(myImg) {
 var img1 = myImg.set({ 
    top: 20,
    left: 20,
    width: 300,
    height: 300,
		globalCompositeOperation: 'source-atop'
 });
 canvas.add(img1);
});


fabric.Image.fromURL('https://dev.loversloc.com/media/collection/templates/confetti_easy_02.png', function(myImg) {
 var img1 = myImg.set({ 
    top: 0,
    left: 0,
    scaleX: canvas.width/myImg.width,
    scaleY: canvas.height/myImg.height,
		selectable : false,
    evented: false
 });
 canvas_2.add(img1); 
});

fabric.Image.fromURL('https://beautymode.fr/wp-content/uploads/2017/09/636096742373357996142416222_fashion-beauty-tips.jpg', function(myImg) {
 var img1 = myImg.set({ 
    top: 20,
    left: 420,
    width: 300,
    height: 300,
		globalCompositeOperation: 'source-atop'
 });
 canvas_2.add(img1);
});


fabric.Image.fromURL('https://dev.loversloc.com/media/collection/templates/confetti_easy_03.png', function(myImg) {
 var img1 = myImg.set({ 
    top: 0,
    left: 0,
    scaleX: canvas.width/myImg.width,
    scaleY: canvas.height/myImg.height,
		selectable : false,
    evented: false
 });
 canvas_3.add(img1); 
});

fabric.Image.fromURL('https://beautymode.fr/wp-content/uploads/2017/09/636096742373357996142416222_fashion-beauty-tips.jpg', function(myImg) {
 var img1 = myImg.set({ 
    top: 220,
    left: 220,
    width: 300,
    height: 300,
		globalCompositeOperation: 'source-atop'
 });
 canvas_3.add(img1);
});


fabric.Image.fromURL('https://dev.loversloc.com/media/collection/templates/confetti_easy_04.png', function(myImg) {
 var img1 = myImg.set({ 
    top: 0,
    left: 0,
    scaleX: canvas.width/myImg.width,
    scaleY: canvas.height/myImg.height,
		selectable : false,
    evented: false
 });
 canvas_4.add(img1); 
});

fabric.Image.fromURL('https://beautymode.fr/wp-content/uploads/2017/09/636096742373357996142416222_fashion-beauty-tips.jpg', function(myImg) {
 var img1 = myImg.set({ 
    top: 420,
    left: 420,
    width: 300,
    height: 300,
		globalCompositeOperation: 'source-atop'
 });
 canvas_4.add(img1);
});


fabric.Image.fromURL('https://dev.loversloc.com/media/collection/templates/confetti_easy.png', function(myImg) {
 var img1 = myImg.set({ 
 		globalCompositeOperation: 'destination-over',
    top: 0,
    left: 0,
    scaleX: canvasBackground.width/myImg.width,
    scaleY: canvasBackground.height/myImg.height,    
		selectable : false,
    evented: false
 });
 canvasBackground.add(img1); 
});


var $con_1 = $('.paintcanvas');
var $con_2 = $('.paintcanvas_2');
var $con_3 = $('.paintcanvas_3');
var $con_4 = $('.paintcanvas_4');

canvas.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_2.css('pointer-events',/*!*/'none');
      } else {
        $con_2.css('pointer-events',/*!*/'all');
      }
    },
});

canvas_2.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_2.css('pointer-events',/*!*/'all');
      } else {
        $con_2.css('pointer-events',/*!*/'none');
      }
    }
});

canvas_3.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_4.css('pointer-events',/*!*/'none');
      } else {
        $con_4.css('pointer-events',/*!*/'all');
      }
    }
});

canvas_4.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_4.css('pointer-events',/*!*/'all');
      } else {
        $con_4.css('pointer-events',/*!*/'none');
      }
    }
});
.parent {
  position: relative;
  background: black;
}


.backgroundcanvas {
  position: absolute;
  left: 0;
  top: 0;
}

.paintcanvas, .paintcanvas_2, .paintcanvas_3, .paintcanvas_4 {
  position: absolute;
  left: 0px;
  top: 0px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<div class="parent">
<script
  src="https://code.jquery.com/jquery-3.4.1.min.js"
  integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
  crossorigin="anonymous"></script>
  <div class="backgroundcanvas">
    <canvas id="backgroundcanvas"  width="800" height="800"></canvas>  
  </div>
  <div class="paintcanvas">
    <canvas id="paintcanvas" width="800" height="800" ></canvas>  
  </div>
  <div class="paintcanvas_2">
    <canvas id="paintcanvas_2" width="800" height="800" ></canvas>  
  </div>
  <div class="paintcanvas_3">
    <canvas id="paintcanvas_3" width="800" height="800" ></canvas>  
  </div>
  <div class="paintcanvas_4">
    <canvas id="paintcanvas_4" width="800" height="800" ></canvas>  
  </div>
</div>

我设法在一堆画布中创建了几个蒙面画布元素。这些每个都带有经过globalCompositeOperation处理的掩码,用户应该能够将照片上传到该掩码中。

现在,每个上传的图像元素都应该在每个画布中都可以移动/缩放。我尝试通过冒泡的指针事件来实现这一点。

我这样做是因为您不能在一个画布中独立屏蔽多个重叠元素(屏蔽会影响所有像素),并且由于底层设计和性能,svg 是不可能的。因为“destination-over”在这种组合中不起作用,所以背景被排除在静态画布中。

使用两层/画布可以这样解决:

var $con_1 = $('.paintcanvas');
var $con_2 = $('.paintcanvas_2');

canvas_1.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_1.css('pointer-events',/*!*/'all');
      } else {
        $con_1.css('pointer-events',/*!*/'none');
      }
    }
});

canvas_2.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_2.css('pointer-events',/*!*/'none');
      } else {
        $con_2.css('pointer-events',/*!*/'all');
      }
    }
});

但是,我需要四层,并且不明白如何将事件冒泡。

我在这里为此创建了一个小提琴(画布内容 3+4 可编辑): https ://jsfiddle.net/Metamagikum/2Lpwchzd/199/

标签: javascriptlogiclayerevent-bubblingpointer-events

解决方案


我是这样解决的。它正在工作,但仍在寻找更好的解决方案。

var $con_1 = $('.paintcanvas');
var $con_2 = $('.paintcanvas_2');
var $con_3 = $('.paintcanvas_3');
var $con_4 = $('.paintcanvas_4');

canvas.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_1.css('pointer-events',/*!*/'all');
      } else {
        $con_2.css('pointer-events',/*!*/'all');
        $con_3.css('pointer-events',/*!*/'all');
        $con_4.css('pointer-events',/*!*/'all');
      }
    },
});

canvas_2.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_2.css('pointer-events',/*!*/'all');
      } else {
        $con_2.css('pointer-events',/*!*/'none');
      }
    }
});

canvas_3.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_3.css('pointer-events',/*!*/'all');
      } else {
        $con_3.css('pointer-events',/*!*/'none');
      }
    }
});

canvas_4.on({
    'mouse:move': function(e) {
      if (e.target) {
        $con_4.css('pointer-events',/*!*/'all');
      } else {
        $con_4.css('pointer-events',/*!*/'none');
      }
    }
});

推荐阅读