如果元素的父元素有“margin:0 auto”,如何在光标下定位元素?

时间:2016-12-27 07:36:03

标签: javascript html css vue.js

我正在构建一个简单的可拖动功能:

<div id="app">
  <div id="i-plane">
    <div
      id="i-interact"
      v-bind:style="position"
      v-on:mousedown="handleDown"
      v-on:mousemove="handleMove"
      v-on:mouseout="handleUp">
    </div>
  </div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    field: {
      x: 200,
      y: 200
    },
    dragging: false
  },
  computed: {
    position: function() {
      return 'transform: translate(' + this.field.x + 'px,' + this.field.y + 'px)'
    }
  },
  methods: {
    handleUp: function(e) {
      this.dragging = false
    },
    handleDown: function(e) {
      this.dragging = true
    },
    handleMove: function(e) {
      if (this.dragging) {
        this.field.x = e.clientX
        this.field.y = e.clientY
      }
    }
  }
});
</script>

<style>
#i-plane {
  background: red;
  width: 400px;
  height: 400px;
  margin: 0 auto
}

#i-interact {
  background: black;
  width: 40px;
  height: 40px;
}
</style>

如果单击#i-interact,元素不会位于光标下方,但它会向右飞行。

如何修改代码,以便#i-interact在光标下移动?

Codepen:https://codepen.io/alexcheninfo/pen/XNLNvM

1 个答案:

答案 0 :(得分:3)

这里有几个问题。首先,由于您使用translate移动元素,因此您需要知道它的相对位置。因此,您不必指定鼠标在移动时屏幕上的位置,而是必须指定鼠标相对于鼠标向下移动的位置移动的像素数。 (另一种选择是绝对定位元素,但我假设你想坚持使用translate。)

另一个问题是你的鼠标处理程序都在监听你正在移动的元素上的事件。这将导致非常不可靠的行为,因为例如,如果您通过快速移动鼠标将鼠标移动到元素之外,则将不再跟踪您的移动。

请参阅CodePen的my fork。我添加了一个对象来了解原始start坐标,我已经在文档范围内创建了鼠标事件监听器,并将它们移动到created()

created() {
  document.addEventListener('mousedown', this.handleDown)
  document.addEventListener('mouseup', this.handleUp)
  document.addEventListener('mousemove', this.handleMove)
},

这在您的具体示例中运行良好,但仍然不是完美,因为start位置基于您最初点击元素移动它的位置,还有您可能只想在给定容器中跟踪鼠标事件。为了做得更好,您可以在mouseup实际将元素移动到新位置并将translate重置为零,然后在下一个mousedown上设置新的start位置。

由于你可以在这里找到许多可能的路线,我不想只是猜测你的要求是什么,所以我只提供你的例子的基本工作版本。希望它足以满足您的需求!