它必须支持沿着滑块的非线性标签,例如400K、500K、750K、1M,但视觉上间隔均匀。
我已经接近这个目标,但我无法按预期将中间的标签放入空格中。 当有 3 个选项时,中间标签位置正确,但当有 4 个或更多步骤时,中间标签与点不对齐。
<div id="sliders-container">
<div id="slider1" class="slider-container" data-title="With 5 options" data-values='{"$500":500,"$1,000":1000,"$2,500":2500,"$5,000":5000,"$10,000":10000}' data-start-value="5000"></div>
<div id="slider3" class="slider-container" data-title="With 3 options" data-values='{"$50K":50000,"$100K":100000,"$200K":200000}' data-start-value="100000"></div>
<div id="slider2" class="slider-container" data-title="With 4 options" data-values='{"$50K":50000,"$100K":100000,"$200K":200000, "$1M":1000000}' data-start-value="50000"></div>
</div>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.slider-container {
max-width: 480px;
margin: 50px auto;
position: relative;
}
.slider {
z-index: 1;
position: relative;
}
.slider-dots {
top: 6px;
margin-left: auto;
margin-right: auto;
position: absolute;
width: 100%;
display: flex;
justify-content: space-between;
pointer-events: none;
z-index: 0;
}
.slider-dots div {
background-color: #cbcbcb;
width: 12px;
height: 12px;
border-radius: 50%;
}
.form-range::-webkit-slider-runnable-track {
background: #cbcbcb;
height: 2px;
}
.form-range::-webkit-slider-thumb {
width: 1.5rem;
height: 1.5rem;
cursor: pointer;
-webkit-appearance: none;
appearance: none;
border-radius: 50%;
border: 2px solid purple;
box-shadow: inset 0px 0px 0px 2px white;
background-color: purple;
margin-top: -0.75rem;
}
.dynamic-slider-values span {
flex-basis: 100%;
text-align: center;
}
.dynamic-slider-values span:first-of-type {
text-align: left;
}
.dynamic-slider-values span:last-of-type {
text-align: right;
}
</style>
<script>
function createSliderContainer(sliderData) {
const container = document.createElement('div');
container.classList.add('slider-container');
container.innerHTML = `
<b>${sliderData.title}</b>
<div class="row">
<div class="col-8 col-sm-9">
<div style="position: relative;">
<input type="range" min="1" max="1" value="1" class="form-range slider dynamic-slider">
<div class="slider-dots dynamic-slider-dots"></div>
<div class="d-flex justify-content-between small dynamic-slider-values"></div>
</div>
</div>
<div class="col-4 col-sm-3">
<select class="form-select dynamic-value-select"></select>
</div>
</div>
`;
return container;
}
function initializeSlider(sliderContainer, keyValuePairs, startValue) {
const slider = sliderContainer.querySelector('.dynamic-slider');
const sliderDots = sliderContainer.querySelector('.dynamic-slider-dots');
const sliderValues = sliderContainer.querySelector('.dynamic-slider-values');
const valueSelect = sliderContainer.querySelector('.dynamic-value-select');
const keys = Object.keys(keyValuePairs); // Extract the labels
const values = Object.values(keyValuePairs); // Extract the actual values
// Update the slider max attribute based on the number of values
slider.max = keys.length;
// Initialize the select dropdown
valueSelect.innerHTML = '';
keys.forEach((key, index) => {
const option = document.createElement('option');
option.value = values[index];
option.textContent = key;
valueSelect.appendChild(option);
});
// Set the start value for the slider and select dropdown
const startIndex = values.indexOf(startValue);
if (startIndex !== -1) {
slider.value = startIndex + 1;
valueSelect.value = values[startIndex];
} else {
slider.value = 1; // Default to the first value if startValue is not found
valueSelect.value = values[0];
}
// Create dots and value labels
sliderDots.innerHTML = '';
sliderValues.innerHTML = '';
keys.forEach((key, index) => {
// Create dots
const dot = document.createElement('div');
sliderDots.appendChild(dot);
// Create value labels
const valueLabel = document.createElement('span');
valueLabel.textContent = key;
sliderValues.appendChild(valueLabel);
});
// Sync slider with select dropdown
slider.oninput = function() {
valueSelect.value = values[this.value - 1];
};
// Sync select dropdown with slider
valueSelect.onchange = function() {
slider.value = values.indexOf(parseInt(this.value)) + 1;
};
}
function createSliders() {
const sliders = document.querySelectorAll('.slider-container');
sliders.forEach(slider => {
const title = slider.getAttribute('data-title');
const keyValuePairs = JSON.parse(slider.getAttribute('data-values'));
const startValue = parseInt(slider.getAttribute('data-start-value'), 10);
const sliderContainer = createSliderContainer({
title
});
slider.appendChild(sliderContainer);
initializeSlider(sliderContainer, keyValuePairs, startValue);
});
}
// Initialize sliders based on the HTML data attributes
createSliders();
</script>
将标签贴在点上的建议有效。 这是完成的版本:
<html>
<body>
<div class="container mt-5">
<div class="comborange-init mb-5" data-values='{"$50K":50000,"$100K":100000,"$200K":200000}' data-start-value="100000"></div>
<div class="comborange-init mb-5" data-values='{"$50K":50000,"$100K":100000,"$200K":200000, "$1M":1000000}' data-start-value="50000"></div>
<div class="comborange-init mb-5" data-values='{"$500":500,"$1,000":1000,"$2,500":2500,"$5,000":5000,"$10,000":10000}' data-start-value="5000"></div>
</div>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.comborange-inner-container {
position: relative;
height: 50px;
}
.form-range {
z-index: 1;
position: relative;
}
.comborange-dots {
z-index: 0;
top: 6px;
margin-left: auto;
margin-right: auto;
position: absolute;
width: 100%;
display: flex;
justify-content: space-between;
pointer-events: none;
}
.comborange-dots div {
background-color: #cbcbcb;
width: 12px;
height: 12px;
border-radius: 50%;
position: relative;
}
.comborange-dots div span {
position: absolute;
width: 100px;
word-break: keep-all;
text-align: center;
left: -44px;
top: 16px;
}
.comborange-dots div:first-of-type span {
text-align: left;
left: 0px;
}
.comborange-dots div:last-of-type span {
text-align: right;
left: -88px;
}
.form-range::-webkit-slider-runnable-track {
background: #cbcbcb;
height: 2px;
}
.form-range::-webkit-slider-thumb {
width: 1.5rem;
height: 1.5rem;
cursor: pointer;
-webkit-appearance: none;
appearance: none;
border-radius: 50%;
border: 2px solid purple;
box-shadow: inset 0px 0px 0px 2px white;
background-color: purple;
margin-top: -0.75rem;
}
</style>
<script>
function createComborangeContainer(comborangeData) {
const container = document.createElement('div');
container.classList.add('row');
container.classList.add('combo-range');
container.innerHTML = `
<div class="col-sm-9">
<div class="comborange-inner-container">
<input type="range" min="1" max="1" value="1" class="form-range">
<div class="comborange-dots"></div>
</div>
</div>
<div class="col-sm-3">
<select class="form-select comborange-dropdown"></select>
</div>
`;
return container;
}
function initializeComborange(comborangeContainer, keyValuePairs, startValue) {
const keys = Object.keys(keyValuePairs);
const values = Object.values(keyValuePairs);
// Build the select list; this will be the value that gets submitted in the form
const dropdown = comborangeContainer.querySelector('.comborange-dropdown');
keys.forEach((key, index) => {
const option = document.createElement('option');
option.value = values[index];
option.textContent = key;
dropdown.appendChild(option);
});
// Build the range for visualization of options
const comborange = comborangeContainer.querySelector('input[type=range]');
comborange.max = keys.length;
// Set the initial value for the comborange and select dropdown
const startIndex = values.indexOf(startValue);
if (startIndex !== -1) {
comborange.value = startIndex + 1;
dropdown.value = values[startIndex];
} else {
comborange.value = 1; // Default to the first value if startValue is not found
dropdown.value = values[0];
}
// Create the dots and labels below each step on the range
const comborangeDots = comborangeContainer.querySelector('.comborange-dots');
keys.forEach((key, index) => {
const dot = document.createElement('div');
comborangeDots.appendChild(dot);
const valueLabel = document.createElement('span');
valueLabel.textContent = key;
dot.appendChild(valueLabel);
});
// Sync comborange with select dropdown
comborange.oninput = function() {
dropdown.value = values[this.value - 1];
};
// Sync select dropdown with comborange
dropdown.onchange = function() {
comborange.value = values.indexOf(parseInt(this.value)) + 1;
};
}
function createComboranges() {
const comboranges = document.querySelectorAll('.comborange-init');
comboranges.forEach(comborange => {
const keyValuePairs = JSON.parse(comborange.getAttribute('data-values'));
const startValue = parseInt(comborange.getAttribute('data-start-value'), 10);
const comborangeContainer = createComborangeContainer();
comborange.appendChild(comborangeContainer);
initializeComborange(comborangeContainer, keyValuePairs, startValue);
});
}
createComboranges();
</script>
</body>
</html>