相对于初始单击拖动元素

时间:2016-08-24 18:23:02

标签: javascript html css

我有一个mousemove事件,我添加到mousedown事件的元素,然后我在mouseup事件中将其删除。

在鼠标移动事件中我触发此功能,其中我减去X和Y的一半宽度和高度以使图像居中:

dragImage(e) {
    const width = this.getStyle(e.target, 'width').split('p')[0];
    const height = this.getStyle(e.target, 'height').split('p')[0];
    const X = e.pageX - (window.innerWidth / 2 - window.innerHeight / 2) || e.touches[0].clientX;
    const Y = e.pageY || e.touches[0].clientY;
    const stopTop = Y - (height / 2) > 0;
    const stopBottom = Y + (height / 2) < this.getStyle(e.target.parentNode, 'height').split('p')[0];
    const stopLeft = X - (width / 2) > 0;
    const stopRight = X + (width / 2) < this.getStyle(e.target.parentNode, 'width').split('p')[0];
    const stopTop = Y - (height / 2) > 0;
    const stopBottom = Y + (height / 2) < this.getStyle(e.target.parentNode, 'height').split('p')[0];
    const stopLeft = X - (width / 2) > 0;
    const stopRight = X + (width / 2) < this.getStyle(e.target.parentNode, 'width').split('p')[0];


    // check if element is within vertical bounds
    if (stopTop) {
        this.image.style.bottom = '';
        this.image.style.top = '0px';
    } else if (stopBottom) {
        this.image.style.top = '';
        this.image.style.bottom = '0px';
    } else {
        this.image.style.bottom = '';
        this.image.style.top = `${Y}px`;
    }

    // check if element is within horizontal bounds
    if (stopLeft) {
        this.image.style.right = '';
        this.image.style.left = '0px';
    } else if (stopRight) {
        this.image.style.left = '';
        this.image.style.right = '0px';
    } else {
        this.image.style.right = '';
        this.image.style.left = `${X}px`;
    }

    return false;
}

我已经尝试从pageXpageY中减去元素的偏移量,并且它在那里得到了一半,但被拖动的元素因为每隔一个X / Y值关闭而闪烁,因此值可以是900,500,900,500等。

可能导致价值变化的原因是什么?我过度复杂化了什么?我所要做的就是拖动一个图像,而不是将它放在指针周围,保持在一个边界内。

感谢。

E - 添加更多代码以澄清:

我在构造函数中添加了第一组mousedown,mouseup和mouseleave事件:

if (this.isMobile) {
        this.image.addEventListener('touchstart', e => this.enableDrag(e));
        this.image.addEventListener('touchend', e => this.disableDrag(e));
        this.image.addEventListener('touchcancel', () => this.disableDrag());
      } else {
        this.image.addEventListener('mousedown', e => this.enableDrag(e));
        this.image.addEventListener('mouseup', e => this.disableDrag(e));
        this.image.addEventListener('mouseleave', () => this.disableDrag());
        this.image.addEventListener('click', e => e.cancelBubble = true);
      }

这些事件添加和删除以下功能,该功能可以进行拖动:

enableDrag(e) {
      e = e || window.event;
      e.cancelBubble = true;
      e.preventDefault();

      if (this.isMobile) {
        this.image.addEventListener('touchmove', this.dragEvent);
      } else {
        this.image.addEventListener('mousemove', this.dragEvent);
      }
    }

disableDrag() {
      if (this.isMobile) {
        this.image.removeEventListener('touchmove', this.dragEvent);
      } else {
        this.image.removeEventListener('mousemove', this.dragEvent);
      }
    }

1 个答案:

答案 0 :(得分:1)

基于此:&#34;可能导致价值变化的原因是什么?我过度复杂化了什么?我所要做的就是拖动一个图像,而不是将它放在指针周围,保持在一个边界内。&#34;,我提出三个建议:

  1. 您的边界条件过于复杂,只需设置topleft属性,忘记bottomright
  2. 基于以上所述,我认为您希望拖动偏离用户启动拖动的位置。在这种情况下,您必须在mousedown事件中计算它,并在此处使用它。
  3. 我还没有完成JS代码来操纵DOM,但是在当天,getBoundingClientRect是获取DOM对象的位置/维度的首选方式(而不是查询DOM直接)
  4. 考虑到这一点,您可以简化代码:

    dragImage(e) {
        var imageBoundaries = this.image.getBoundingClientRect();
        var containerWidth = this.getStyle(e.target.parentNode, 'width').split('p')[0];
        var containerHeight = this.getStyle(e.target.parentNode, 'height').split('p')[0];
    
        const X = (e.pageX || e.touches[0].clientX) - offsetX; /* where offsetX is defined as where the user initially clicked on the image in the mousedown event */
        const Y = (e.pageY || e.touches[0].clientY) - offsetY; /* ditto */
    
        if X <= 0 {
            // hit the left boundary
            X = 0
        } else if X + imageBoundaries.width >= containerWidth {
            // hit the right boundary
            X = containerWidth - imageBoundaries.width
        }
    
        if Y <= 0 {
            // hit the top boundary
            Y = 0
        } else if Y + imageBoundaries.height >= containerHeight {
            // hit the bottom boundary
            Y = containerHeight - imageBoundaries.height
        }
    
    
        this.image.style.left = `${X}px`;
        this.image.style.top = `${Y}px`;
    
        return false;
    }
    

    这会将图像夹到窗口的边界(假设您希望始终看到整个图像)。如果你愿意让图像稍微移出视口,你可以摆弄if条件。

    最后,众所周知,拖放是很难做到的,我通常会为了这个功能而跑到第三方。像Dragula之类的东西是设置我见过的拖放最常见情况的一个例子。当然,如果这是为了学习那么是的,滚动你自己:)