Suggestion - tweek the mouse move behaviour
reppair opened this issue · comments
Hi @xinnks, first of all thanks for that medium article it was very helpful to me. Then I decided to give this one a go due to it's simplicity and I could not use it due to just one small issue that I found - it does not account for mouse move outside of the wrapper div.
For example if you have a really slim wrapper div like mine,
then it is hard to keep the mouse pointer in it, so I needed a way of updating the progress during mousemove
event outside the wrapper div.
I ended up doing component on my own based on your article with some small changes to it for handling this. Here is my local component:
<template>
<div class="h-8 flex items-center cursor-pointer" ref="slider">
<div class="w-full h-1 bg-white-25 rounded-full">
<div class="rounded-full h-1 bg-white-75" :style="'width: '+ progress +'%'"></div>
</div>
</div>
</template>
<script>
export default {
name: 'Slider',
data: () => ({
progress: 0,
wrapperWidth: 0,
seekOffsetLeft: 0,
}),
watch: {
wrapperWidth() {
this.seekOffsetLeft = 0
},
},
mounted(){
this.$refs.slider.addEventListener("click", this.getClickPosition, false)
window.addEventListener('resize', e => this.wrapperWidth = this.$refs.slider.offsetWidth, false)
this.$refs.slider.addEventListener("mousedown", this.detectMouseDown, false)
this.$refs.slider.addEventListener("mousedown", this.detectMouseDown, false)
document.addEventListener("mouseup", this.detectMouseUp, false)
},
methods: {
getClickPosition(e) {
if (e.target.nodeType === 3) e.target = e.target.parentNode // fix for a safari bug
this.wrapperWidth = this.wrapperWidth || e.target.offsetWidth // set initial wrapper width
let seekWidth = e.offsetX
this.progress = (seekWidth / this.wrapperWidth) * 100
},
mouseMove(e) {
if (e.target.nodeType === 3) e.target = e.target.parentNode // fix for a safari bug
this.wrapperWidth = this.wrapperWidth || e.target.offsetWidth // set initial wrapper width
if (!this.seekOffsetLeft) this.seekOffsetLeft = e.target.offsetLeft // set the offset left (document -> seek el left side)
let x = e.pageX,
seekRight = this.seekOffsetLeft + this.wrapperWidth,
progress
if (x < this.seekOffsetLeft) progress = 0
else if (x > seekRight) progress = 100
else progress = ((x - this.seekOffsetLeft) / this.wrapperWidth) * 100
this.progress = progress
},
detectMouseDown(e) {
e.preventDefault()
document.addEventListener("mousemove", this.mouseMove, false)
},
detectMouseUp(e) {
document.removeEventListener("mousemove", this.mouseMove, false)
},
},
}
</script>
The result should be obvious by reading the code it think, but still:
- able to control the progress on mouse move event outside the wrapper div
- going to the left of the wrapper div will result in setting progress to 0,
- going to the right of it - set progress to 100
- default - set progress 0-100
If you like the idea maybe you will add it to your component in some form or I can try to fit it into your component in a more consistent way and do a PR for it :) would be happy to contribute tiny little bit :)
BTW I'm also thinking of adding mouse wheel scroll event listener too..
@reppair It's a sound feature. What about making it optional based on the height of the wrapper, say below a certain optional height limit then it's applicable. Because having it on wrappers width large widths will almost seem unnecessary a feature. What do you think?
Hi @xinnks, nice idea, for the height that you are using by default it is OK this way, however slim sliders it is much needed.
@reppair The default height is 60px which I can say is OK, you can this as an optionally activated feature, applicable from a wrapper height of 20px and below. Just submit a PR on the dev branch.
Kind of really busy this and next month, feel free to close this issue and I will do a PR when I have a little free time, have to get familiar with your build tool first etc.. if needed you can re-open the issue later, cheers! Happy holidays!
Happy holidays.