Module:Slider
跳转到导航
跳转到搜索
local p = {}
function p.init(frame)
local args = frame.args
local sliderId = args.id or 'slider-' .. tostring(math.random(10000))
return mw.html.create('div')
:addClass('slider-container')
:attr('id', sliderId)
:node(mw.html.create('div'):addClass('slider-track'))
:node(mw.html.create('div'):addClass('slider-thumb')
:node(mw.html.create('div'):addClass('slider-icon')))
:node(mw.html.create('div'):addClass('slider-value')
:wikitext((args.value or 50) .. ((tonumber(args.max or 100) <= 100) and '%' or '')))
:node(args['show-minmax'] ~= 'false' and
mw.html.create('div'):addClass('slider-minmax slider-min')
:wikitext(args.min or '0') or nil)
:node(args['show-minmax'] ~= 'false' and
mw.html.create('div'):addClass('slider-minmax slider-max')
:wikitext(args.max or '100') or nil)
:tag('script')
:wikitext(string.format([[
(function() {
var slider = document.getElementById('%s');
var thumb = slider.querySelector('.slider-thumb');
var track = slider.querySelector('.slider-track');
var valueDisplay = slider.querySelector('.slider-value');
// 配置
var config = {
leftColor: '%s',
rightColor: '%s',
thumbColor: '%s',
thumbIconColor: '%s',
value: %d,
min: %d,
max: %d,
step: %d
};
// 设置颜色
track.style.background = 'linear-gradient(to right, ' + config.leftColor + ', ' + config.rightColor + ')';
thumb.style.backgroundColor = config.thumbColor;
thumb.querySelector('.slider-icon').style.backgroundColor = config.thumbIconColor;
// 计算实际值
function calculateValue(percent) {
return config.min + (percent / 100) * (config.max - config.min);
}
// 计算百分比
function calculatePercent(value) {
return ((value - config.min) / (config.max - config.min)) * 100;
}
// 更新滑块位置和显示
function updateSlider(value) {
value = Math.max(config.min, Math.min(config.max, value));
var percent = calculatePercent(value);
thumb.style.left = 'calc(' + percent + '% - 12px)';
// 格式化显示值
var displayValue;
if (config.max <= 100) {
displayValue = Math.round(value) + '%%';
} else {
displayValue = Math.round(value);
}
valueDisplay.textContent = displayValue;
}
// 初始化
updateSlider(config.value);
// 事件处理
var isDragging = false;
function startDrag(e) {
isDragging = true;
e.preventDefault();
}
function drag(e) {
if (!isDragging) return;
var rect = track.getBoundingClientRect();
var clientX = e.clientX || (e.touches && e.touches[0].clientX);
if (!clientX) return;
var pos = (clientX - rect.left) / rect.width;
pos = Math.max(0, Math.min(1, pos));
var value = config.min + Math.floor(pos * (config.max - config.min) / config.step) * config.step;
updateSlider(value);
// 触发自定义事件
var event = new CustomEvent('sliderChange', {
detail: {
id: '%s',
value: value,
percent: pos * 100
}
});
slider.dispatchEvent(event);
}
function endDrag() {
isDragging = false;
}
thumb.addEventListener('mousedown', startDrag);
thumb.addEventListener('touchstart', startDrag);
document.addEventListener('mousemove', drag);
document.addEventListener('touchmove', drag);
document.addEventListener('mouseup', endDrag);
document.addEventListener('touchend', endDrag);
track.addEventListener('click', function(e) {
var rect = track.getBoundingClientRect();
var pos = (e.clientX - rect.left) / rect.width;
var value = config.min + Math.floor(pos * (config.max - config.min) / config.step) * config.step;
updateSlider(value);
var event = new CustomEvent('sliderChange', {
detail: {
id: '%s',
value: value,
percent: pos * 100
}
});
slider.dispatchEvent(event);
});
// 暴露API
slider.updateValue = function(value) {
updateSlider(value);
};
slider.getValue = function() {
return calculateValue(parseInt(thumb.style.left) / (track.offsetWidth - thumb.offsetWidth) * 100);
};
})();
]],
sliderId,
args['left-color'] or '#24b44a',
args['right-color'] or args['left-color'] or '#24b44a',
args['thumb-color'] or '#ffffff',
args['thumb-icon-color'] or '#333333',
tonumber(args.value) or 50,
tonumber(args.min) or 0,
tonumber(args.max) or 100,
tonumber(args.step) or 1,
sliderId,
sliderId))
end
return p