Vue balanced sliders
The sum of the sliders will always be 100
HTML
<div id="vue">
<sliders v-model="sliders"></sliders>
{{sliders.map(n => Math.floor(n))}}<br>
Sum:{{Math.round(sliders.reduce((sum, val) => sum + val, 0))}}
</div>
CSS
.sliders input{
width:100%;
}
JavaScript
Vue.component('sliders', {
template:`
<div class="sliders">
<input
v-for="slider, i in sliders"
v-model.number="sliders[i]"
type="range"
@input="input(i)"
step="0.01"
>
</div>
`,
model:{
prop:'sliders'
},
props:{
sliders:{type:Array, required:true}
},
methods:{
input(n){
const sum = this.sliders.reduce((sum, val) => sum + val, 0)
const diff = sum - 100
let remainder = 0
console.log(diff)
for(let i in this.sliders){
if(i != n){ //don't modify the slider which is being dragged
let val = this.sliders[i] - diff / (this.sliders.length - 1)
if(val < 0){
remainder += val
val = 0
}
this.$set(this.sliders, i, val)
}
}
if(remainder){
const filteredLength = this.sliders.filter((val, key) => val > 0 && key != n).length
for(let i in this.sliders){
if(i != n && this.sliders[i] > 0){
this.$set(this.sliders, i, this.sliders[i] + remainder / filteredLength)
}
}
}
this.$emit('input', this.sliders)
}
}
})
new Vue({
el:'#vue',
data(){
return {
sliders:[25,25,25,24,5,10]
}
}
})