web-dev-qa-db-ja.com

Vue mousedown後のみmousemove

要素が最初にクリックされた場合にのみ、マウス移動をトリガーするにはどうすればよいですか?これをオーディオプレーヤーのタイムラインに利用しようとしています。

.player__time--bar(@mousedown="setNewCurrentPosition($event)")
    .slider(role="slider" aria-valuemin="0" :aria-valuenow="currentPosition" :aria-valuemax="trackTotalDuration" aria-orientation="horizontal")
        .player__time--bar-current-position(:style="{width:  (100 / (trackTotalDuration / currentPosition)) + '%'}")

メソッド:

setNewCurrentPosition(e) {
    let tag = e.target
    // if the click is not on 'slider', grab div with class 'slider'
    if (e.target.className === 'player__time--bar') tag = e.target.firstElementChild
    else if (e.target.className === 'player__time--bar-current-position') tag = e.target.parentElement
    const pos = tag.getBoundingClientRect()
    const seekPos = (e.clientX - pos.left) / pos.width
    this.currentPosition = parseInt(this.trackTotalDuration * seekPos)
    // updates the time in the html
    this.$refs.player.currentTime = this.currentPosition
},
6
Giacomo

ドラッグが開始されたことを示す変数を設定するmousedownリスナーがエレメントに必要になります。ウィンドウにリスナーを配置して、mouseupをキャッチし、変数を設定解除します。

要素内で発生するドラッグのみに関心がある場合は、要素にmousemoveを配置できます。それ以外の場合は、mousemoveリスナーをwindowに配置して、どこでもキャッチできるようにします。

new Vue({
  el: '#app',
  data: {
    dragging: false,
    x: 'no',
    y: 'no'
  },
  methods: {
    startDrag() {
      this.dragging = true;
      this.x = this.y = 0;
    },
    stopDrag() {
      this.dragging = false;
      this.x = this.y = 'no';
    },
    doDrag(event) {
      if (this.dragging) {
        this.x = event.clientX;
        this.y = event.clientY;
      }
    }
  },
  mounted() {
    window.addEventListener('mouseup', this.stopDrag);
  }
});
.dragstartzone {
  background-color: red;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <div class="dragstartzone" @mousedown="startDrag" @mousemove="doDrag">Start dragging here</div>
  <div>X: {{x}}, Y: {{y}}</div>
</div>
19
Roy J

結局、Roy Jが提供するコードを使用し、ニーズに合わせて少しリファクタリングしました。ここにあります

テンプレート:

.player__time--bar(@mousedown="startDrag($event)" @mouseup="stopDrag($event)" @mousemove="doDrag($event)")
    .slider(role="slider" aria-valuemin="0" :aria-valuenow="currentPosition" :aria-valuemax="trackTotalDuration" aria-orientation="horizontal")
        .player__time--bar-current-position(:style="{width:  (100 / (trackTotalDuration / currentPosition)) + '%'}")

データ:

data: () => ({
    currentPosition: 0,
    trackTotalDuration: 0,
    dragging: false
}),

方法:

startDrag() {
    this.dragging = true
},
stopDrag(event) {
    this.dragging = false
    this.setNewCurrentPosition(event)
},
doDrag(event) {
    if (this.dragging) this.setNewCurrentPosition(event)
},

setNewCurrentPosition(e) {
    let tag = e.target
    // if the click is not on 'slider', grab div with class 'slider'
    if (e.target.className === 'player__time--bar') tag = e.target.firstElementChild
    else if (e.target.className === 'player__time--bar-current-position') tag = e.target.parentElement
    const pos = tag.getBoundingClientRect()
    const seekPos = (e.clientX - pos.left) / pos.width
    this.currentPosition = parseInt(this.trackTotalDuration * seekPos)
    // updates the time in the html
    this.$refs.player.currentTime = this.currentPosition
},
0
Giacomo