Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将指针事件重新触发到下层(用于使用interact.js进行不规则形状的拖动)_Javascript_Jquery_Interact.js - Fatal编程技术网

Javascript 将指针事件重新触发到下层(用于使用interact.js进行不规则形状的拖动)

Javascript 将指针事件重新触发到下层(用于使用interact.js进行不规则形状的拖动),javascript,jquery,interact.js,Javascript,Jquery,Interact.js,我需要手动构造/触发mousedown事件,就像自然的mousedown事件一样,任何相关的事件处理程序(在straight JS、jQuery或interact.JS中)都可以处理它。然而,这一事件似乎并没有像我预期的那样触发任何事情 我试图使用interact.js库制作一些形状不规则的图像。这些图像只是带有透明部分的矩形img元素。在每个元素上,我定义了2个interact.js事件侦听器: 检查单击是否在图像区域内,如果不在,则禁用拖动(在“向下”事件时触发) 处理拖动(在“拖动”事件时

我需要手动构造/触发mousedown事件,就像自然的mousedown事件一样,任何相关的事件处理程序(在straight JS、jQuery或interact.JS中)都可以处理它。然而,这一事件似乎并没有像我预期的那样触发任何事情

我试图使用interact.js库制作一些形状不规则的图像。这些图像只是带有透明部分的矩形img元素。在每个元素上,我定义了2个interact.js事件侦听器:

  • 检查单击是否在图像区域内,如果不在,则禁用拖动(在“向下”事件时触发)
  • 处理拖动(在“拖动”事件时激发)
  • 但是,如果img元素重叠,并且用户单击顶部元素的透明区域但单击下部元素的填充区域,则下部元素应成为拖动的目标。在尝试了几件事情(见下文)之后,我确定了以下解决方案:在步骤1中禁用拖动的同时重新排序元素的z索引,然后在所有较低的元素上重新触发mousedown事件。我使用的是“本机”事件类型(不是jQuery或interact.js),希望它能够复制原始的mousedown事件

    // code to re-assign "zIndex"s
    function demote(element, interactible, event){
    
        // block dragging on element
        interactible.draggable(false);
    
        // get all images lower than the target 
        var z = element.css("zIndex");
        var images = $("img").filter(function() {
        return Number($(this).css("zIndex")) < z;
        });
    
        // push the target to the back
        element.css("zIndex",1);
    
        // re-process all lower events
        $(images).each( function () {
              // move element up
              $(this).css("zIndex",Number($(this).css("zIndex"))+1);
    
              // re-fire event if element began below current target
              elem = document.getElementById($(this).attr('id'));
    
              // Create the event.
              e = new MouseEvent("mousedown", {clientX: event.pageX, clientY: event.pageY});
              var cancelled = !elem.dispatchEvent(e);
        });
    }
    
    //重新分配“zIndex”的代码
    功能降级(元素、可交互、事件){
    //块在元素上拖动
    可交互。可拖动(错误);
    //获取低于目标的所有图像
    var z=element.css(“zIndex”);
    var images=$(“img”).filter(函数(){
    返回编号($(this.css(“zIndex”))
    不幸的是,这不起作用,因为mousedown事件没有向任何处理程序注册。为什么?

    我在这里有所有(相关)代码: 请注意,这个JSFIDLE似乎不像在普通浏览器窗口中那样顺利工作,但我认为它展示了预期的功能

    我尝试过的其他事情:

    许多人提出了不同的方案来处理类似的问题(例如,将事件转发到较低的层,使用指针事件:none等),但似乎没有一个方案能够触发interact.js处理程序并在正确的元素上启动拖动交互。我也尝试过使用interaction.start(由interaction.js提供),但它似乎有问题——在这个主题上至少有一个开放的问题,当我尝试在我选择的目标上启动一个新的拖动交互时,我从库的代码中得到了很多错误


    我并不反对重新访问这些解决方案本身,但我也想知道为什么手动触发mousedown事件不起作用。

    您是否尝试在更高级别上设置css属性
    指针事件:none
    (也可以通过javascript设置)?

    这个想法是监听父元素上的
    事件,并选择手动拖动目标。另外,我没有使用z-index来选择要拖动的图像,因为z-index不适用于
    position:static
    。我并没有把优先权放在图像上,一切都取决于你

    var-dragTarget;
    函数dragMoveListener(事件){
    var target=event.target,
    //在data-x/data-y属性中保持拖动位置
    x=(parseFloat(target.getAttribute('data-x'))| | 0)+event.dx,
    y=(parseFloat(target.getAttribute('data-y'))| | 0)+event.dy;
    //翻译元素
    target.style.webkitTransform=
    target.style.transform=
    '翻译('+x+'px',+y+'px)';
    //更新posiion属性
    target.setAttribute('data-x',x);
    target.setAttribute('data-y',y);
    }
    函数setDragTarget(事件){
    //选择要拖动的图元
    dragTarget=$(“#父项”).find('img'))
    .过滤器(功能(i、el){
    var clickCandicateCrect=el.getBoundingClientRect();
    返回InsideBondingDirect(event.x、event.y、clickCandicateRect);
    }).sort(按优先级).get(0);
    }
    函数inlineBondingDirect(x,y,rect){
    返回(rect.left=y);
    }
    按优先级排序的函数(a,b){
    返回$(b).data('priority')-$(a).data('priority');
    }
    功能启动(事件){
    var交互=事件交互;
    var目标=牵引目标;
    如果(!interaction.interacting()){
    interaction.start({name:'drag'},event.interactiable,target);
    }
    }
    //按你的意愿优先考虑
    $('#face1')。数据('优先级',2);
    $('#face2')。数据('优先级',1);
    交互(“#父项”)。可拖动({
    //使用manualStart确定要拖动的元件
    手动启动:正确,
    onmove:dragMoveListener,
    限制:{
    限制:“家长”,
    是的,
    elementRect:{top:0,left:0,bottom:1,right:1}
    },
    })
    .on('down',setDragTarget)
    .on('move',startDrag);
    
    您正在使用哪个浏览器?IE不支持构建
    Event
    对象-您必须使用静态方法,如
    document.createEvent()
    或其他什么。我在Chrome中工作。不过,我希望最大限度地提高兼容性,因此我将尝试重构以使用createEvent()。MDN表示createEvent()已被弃用,并且事件构造函数(您正在使用)是创建事件对象的首选方法。了解性能是否是一个关键方面对我很有帮助。我认为为了完成这项任务,你需要知道给定坐标下的给定像素是否可见。但是,此操作可能有点昂贵。性能不是太关键。我是
    var dragTarget;
    
    function dragMoveListener (event) {
      var target = event.target,
          // keep the dragged position in the data-x/data-y attributes
          x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
          y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
    
      // translate the element
      target.style.webkitTransform =
        target.style.transform =
        'translate(' + x + 'px, ' + y + 'px)';
    
      // update the posiion attributes
      target.setAttribute('data-x', x);
      target.setAttribute('data-y', y);
    }
    
    function setDragTarget(event) {
      //choose element to drag
      dragTarget = $('#parent').find('img')
        .filter(function(i, el) {
          var clickCandicateRect = el.getBoundingClientRect();
          return insideBoundingRect(event.x, event.y, clickCandicateRect);
        }).sort(byPriority).get(0);
    }
    
    function insideBoundingRect(x, y, rect) {
      return (rect.left <= x) && (rect.top <= y) && (rect.right >= x) && (rect.bottom >= y);
    }
    
    function byPriority (a, b) {
      return $(b).data('priority') - $(a).data('priority');
    }
    
    function startDrag(event) {
      var interaction = event.interaction;
      var target = dragTarget;
    
      if (!interaction.interacting()) {
        interaction.start({ name: 'drag' }, event.interactable, target);
      }
    }
    
    //Give priority as you wish
    $('#face1').data('priority', 2);
    $('#face2').data('priority', 1);
    
    interact('#parent').draggable({
      //use manualStart to determine which element to drag
      manualStart: true,
      onmove: dragMoveListener,
      restrict: {
        restriction: "parent",
        endOnly: true,
        elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
      },
    })
    .on('down', setDragTarget)
    .on('move', startDrag);