简体   繁体   中英

Vue mousemove only after mousedown

How can I trigger a mousemove only if the element is clicked first? I'm trying to utilize this for an audio player timeline.

.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)) + '%'}")

The method:

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
},

You will want to have a mousedown listener on your element that sets a variable to indicate dragging started. Put a listener on the window to catch mouseup anywhere and unset the variable.

You can put mousemove on the element if you are only interested in dragging that happens inside the element. Otherwise you can put the mousemove listener on window so you catch it everywhere.

 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> 

I ended up using the code provided by Roy J, refactoring it a bit to fit my need. Here it is

Template:

.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:

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

Methods:

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
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM