我正在使用计算器,它需要有四个输入,每个输入的最大值为100,且四个输入的总和始终等于100。 实现良好UX的最佳方法是,在将任何滑块向上移动之前将其向下移动。如果滑块还不为零,则在滑块向下移动之后立即向上滑动。
我尝试匹配输入名称并添加公式。我真的不知道解决此问题的最佳方法。
答案 0 :(得分:2)
<!-- Author: devninja67 -->
<!-- ***** -->
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
// Returns all selector elements
const getRanges = () => Array.from(document.querySelectorAll('.hrange'));
// return value to change
const minValue = (v1, v2) => {
if(v1 < 0) return Math.abs(v1) < v2 ? v1 : -v2;
else return v1 < 100 - v2 ? v1 : 100 - v2;
}
// Gets us an ability to sum selectors (can exclude a selector if required)
const sumSelectors = (exclude) => getRanges()
.filter((r) => (exclude) ? r !== exclude : true)
.map(r => parseInt(r.value))
.reduce((a, s) => a + s);
// changing before or after slider
const checkRanges = (idx) => {
// after element for increasing and before element for decreasing
let stride = (sumSelectors() > 100) ? 1 : -1;
let selectorId = idx;
// changing slider's value until sliders's sum equal 100
while(true) {
selectorId = (selectorId + stride + 4) % 4;
let selector = document.querySelector("#range" + selectorId);
let selectorValue = parseInt(selector.value);
selector.value = selectorValue + minValue(100 - sumSelectors(), selectorValue);
if(sumSelectors() !== 100) continue;
else break;
}
document.querySelector('#amount').value = sumSelectors();
};
// Listening inputing slider
document.addEventListener('DOMContentLoaded', function() {
getRanges().forEach((r, idx) => {
r.addEventListener('input', (event) => {
checkRanges(idx);
});
});
});
</script>
<style type="text/css">
.hrange {
display: block;
}
</style>
</head>
<body>
<div class="hThree">
<input type="range" id="range0" orient="vertical" value="25" class="hrange" min="0" max="100" />
<input type="range" id="range1" orient="vertical" value="25" class="hrange" min="0" max="100" />
<input type="range" id="range2" orient="vertical" value="25" class="hrange" min="0" max="100" />
<input type="range" id="range3" orient="vertical" value="25" class="hrange" min="0" max="100" />
<input id="amount" type="number" value="100" min="0" max="100" />
</div>
</body>
</html>
答案 1 :(得分:1)
我认为这对您有用。 让我知道。
一些注意事项:
// Returns all selector elements
const getRanges = () => Array.from(document.querySelectorAll('.hrange'));
// Gets us an ability to sum selectors (can exclude a selector if required)
const sumSelectors = (exclude) => getRanges()
.filter((r) => (exclude) ? r !== exclude : true)
.map(r => parseInt(r.value))
.reduce((a, s) => a + s);
// Get the selector with highest current value.
const maxSelector = (exclude) => getRanges()
.filter(r => (exclude) ? exclude !== r : true)
.reduce((a, r) => (parseInt(r.value) > parseInt(a.value)) ? r : a);;
const minSelector = (exclude) => getRanges()
.filter(r => (exclude) ? exclude !== r : true)
.reduce((a, r) => (parseInt(r.value) < parseInt(a.value)) ? r : a);
;
const checkRanges = (r) => {
while (sumSelectors() !== 100) {
let stride = (sumSelectors() > 100) ? -1 : 1;
let selector = (stride === -1) ? maxSelector(r) : minSelector(r);
selector.value = parseInt(selector.value) + stride;
}
document.querySelector('#amount').value = sumSelectors();
};
document.addEventListener('DOMContentLoaded', function() {
getRanges().forEach(r => {
r.addEventListener('change', (event) => {
checkRanges(r);
});
});
checkRanges();
});
.hrange {
display: block;
}
<div class="hThree">
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input id="amount" type="number" value="100" min="0" max="100" />
</div>
答案 2 :(得分:0)
const getRanges = () => Array.from(document.querySelectorAll('.hrange'));
const minValue = (v1, v2) => {
if(v1 < 0) return Math.abs(v1) < v2 ? v1 : -v2;
else return v1 < 100 - v2 ? v1 : 100 - v2;
}
const sumSelectors = (exclude) => getRanges()
.filter((r) => (exclude) ? r !== exclude : true)
.map(r => parseInt(r.value))
.reduce((a, s) => a + s);
const objSelector = (selectorId) => {
let result
getRanges().forEach((object, index) => {
if(index === selectorId) result = object
})
return result
}
const checkRanges = (changed_obj, changed_idx) => {
let stride = (sumSelectors() > 100) ? 1 : -1;
let selectorId = changed_idx;
while(true) {
selectorId = (selectorId + stride + 4) % 4;
let selector = objSelector(selectorId)
let selectorValue = parseInt(selector.value);
selector.value = selectorValue + minValue(100 - sumSelectors(), selectorValue);
if(sumSelectors() !== 100) continue;
else break;
}
document.querySelector('#amount').value = sumSelectors();
};
document.addEventListener('DOMContentLoaded', function() {
getRanges().forEach((object, index) => {
object.addEventListener('input', (event) => {
event.target.value = (event.target.value < 0 ? 0 : (event.target.value > 100 ? 100: event.target.value));
checkRanges(object, index);
});
});
});
.hrange {
display: block;
}
<div class="hThree">
<input type="range" orient="vertical" value="100" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input type="range" orient="vertical" value="0" class="hrange" min="0" max="100" />
<input id="amount" type="number" value="100" min="0" max="100" />
</div>
答案 3 :(得分:0)
<!DOCTYPE html>
<html>
<head>
<title>Sliders</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
</head>
<body>
<div id="Sliders">
<div>
<input type="range" id="0" name="1"
min="0" max="100" v-model.number="countity_sliders[0]" step="1" @input="reorder">
<label for="volume">First: {{ countity_sliders[0] }}</label>
</div>
<div>
<input type="range" id="1" name="2"
min="0" max="100" v-model.number="countity_sliders[1]" step="1" @input="reorder">
<label for="volume">Second: {{ countity_sliders[1] }}</label>
</div>
<div>
<input type="range" id="2" name="3"
min="0" max="100" v-model.number="countity_sliders[2]" step="1" @input="reorder">
<label for="volume">Third: {{ countity_sliders[2] }}</label>
</div>
<div>
<input type="range" id="3" name="4"
min="0" max="100" v-model.number="countity_sliders[3]" step="1" @input="reorder">
<label for="volume">Fourth: {{ countity_sliders[3] }}</label>
</div>
<div>
<hr>
summ: {{ summa }} <br>
</div>
</div>
<script>
var app = new Vue({
el: '#Sliders',
data: {
countity_sliders: [100,0,0,0],
sliders_order: [0,1,2,3],
summa: 0
},
methods: {
reorder($element) {
this.sliders_order=[parseInt($element.target.id)].concat(this.sliders_order);
this.sliders_order = Array.from(new Set(this.sliders_order));
this.check_summ_rule()
},
check_summ_rule() {
this.summa = (this.countity_sliders[0] + this.countity_sliders[1]+ this.countity_sliders[2] + this.countity_sliders[3])
if (this.summa > 100) {
if (this.countity_sliders[this.sliders_order[1]]>0) {
this.countity_sliders[this.sliders_order[1]] = this.countity_sliders[this.sliders_order[1]]-(this.summa -100);
} else if (this.countity_sliders[this.sliders_order[2]]>0) {
this.countity_sliders[this.sliders_order[2]] = this.countity_sliders[this.sliders_order[2]]-(this.summa -100);
} else if (this.countity_sliders[this.sliders_order[3]]>0) {
this.countity_sliders[this.sliders_order[3]] = this.countity_sliders[this.sliders_order[3]]-(this.summa -100);
}
}
this.summa = (this.countity_sliders[0] + this.countity_sliders[1]+ this.countity_sliders[2] + this.countity_sliders[3])
if (this.summa < 100) {
if (this.countity_sliders[this.sliders_order[1]]>-1) {
this.countity_sliders[this.sliders_order[1]] = this.countity_sliders[this.sliders_order[1]]+(100 - this.summa);
} else if (this.countity_sliders[this.sliders_order[2]]>-1) {
this.countity_sliders[this.sliders_order[2]] = this.countity_sliders[this.sliders_order[2]]+(100 - this.summa);
} else if (this.countity_sliders[this.sliders_order[3]]>-1) {
this.countity_sliders[this.sliders_order[3]] = this.countity_sliders[this.sliders_order[3]]+(100 - this.summa);
}
}
if (this.countity_sliders[0] < 0 ) this.countity_sliders[0] = 0
if (this.countity_sliders[1] < 0 ) this.countity_sliders[1] = 0
if (this.countity_sliders[2] < 0 ) this.countity_sliders[2] = 0
if (this.countity_sliders[3] < 0 ) this.countity_sliders[3] = 0
this.summa = (this.countity_sliders[0] + this.countity_sliders[1]+ this.countity_sliders[2] + this.countity_sliders[3])
}
}
})
</script>
</body>
</html>
答案 4 :(得分:0)
<!-- Author : Mehran -->
<!DOCTYPE html>
<html>
<head>
<title>Four Sliders</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
</head>
<body>
<div id="FourSliders">
<input type="range" id="0" min="0" max="100" v-model="val[0]" @input="changed" /><br/>
<input type="range" id="1" min="0" max="100" v-model="val[1]" @input="changed" /><br/>
<input type="range" id="2" min="0" max="100" v-model="val[2]" @input="changed" /><br/>
<input type="range" id="3" min="0" max="100" v-model="val[3]" @input="changed" /><br/>
Sum : <input type="number" value="100" v-model="sum" />
</div>
<script>
var app = new Vue({
el: '#FourSliders',
data: {
val: [100, 0, 0, 0],
sum: 100
},
methods : {
changed(e) {
var i;
var dif = Number(this.val[0]) + Number(this.val[1]) + Number(this.val[2]) + Number(this.val[3]) - Number(this.sum);
for (i = 0; i < 4; i++) {
if (i == e.target.id) continue;
if (dif > 0) {
if (this.val[i] - dif > 0) {
this.val[i] -= dif;
break;
}
else
dif -= this.val[i], this.val[i] = 0;
}
else {
if (this.val[i] - dif <= 100) {
this.val[i] -= dif;
break;
}
else
dif += (100-this.val[i]), this.val[i] = 100;
}
}
}
}
})
</script>
</body>
</html>