Files
sdk4.0/src/Obj/Element/cy_html_slider.js
2025-07-03 13:54:01 +08:00

265 lines
10 KiB
JavaScript

class cy_slider {
constructor(ele, options = undefined) {
var that = this
this.options = options
//slider 盒子,顶层元素
this.slider_box = ele
if (this.slider_box == null) {
return
}
//slider 手柄
this.handler = this.slider_box.querySelector('.handler')
//slider 有值块
this.light = this.slider_box.querySelector('.light')
//是否是垂直
if (this.slider_box.classList.contains("vertical")) {
this.is_vertical = true
}
//是否是禁用
if (this.slider_box.attributes.getNamedItem("disabled") && this.slider_box.attributes.getNamedItem("disabled").value.toLowerCase() != "false") {
this.is_disabled = true
}
this.is_initialize = true
this.max_data = 100
this.min_data = 0
this.step_separates = []
this.step_percents = []
if (options) {
//参数校验,必要内置参数预算
var u_max_data = parseFloat(options.max_data)
if (u_max_data || u_max_data == 0) {
this.max_data = u_max_data
}
var u_min_data = parseFloat(options.min_data)
if (u_min_data || u_min_data == 0) {
if (u_min_data < this.max_data) {
this.min_data = u_min_data
} else {
this.min_data = this.max_data
}
}
//步长分割
var data_area = this.max_data - this.min_data
var u_step = Math.abs(parseFloat(options.step))
if (u_step) {
if (data_area / u_step > 200) {
u_step = data_area / 200
}
} else {
u_step = Math.floor(data_area / 100)
}
var added_step = this.min_data
this.step_separates.push(added_step)
while (added_step < this.max_data) {
added_step += parseFloat(u_step)
added_step = parseFloat(added_step.toFixed(3))
if (added_step > this.max_data) {
added_step = this.max_data
}
this.step_separates.push(added_step)
}
for (var i = 0; i < this.step_separates.length; i++) {
if (this.step_separates.length == 1) {
this.step_percents.push(1)
break
}
var step_percent = i / (this.step_separates.length - 1)
this.step_percents.push(step_percent)
}
}
this.slider_box.addEventListener('click', (ev) => {
//点击设置值
if (that.is_disabled) {
return
}
if (ev.target.nodeName != "SPAN") {
if (that.is_vertical) {
if (ev.target.classList.contains("light")) {
that._setPosition(that.slider_box.offsetHeight - (that.slider_box.offsetHeight - that.light.offsetHeight + ev.offsetY))
}
else {
that._setPosition(that.slider_box.offsetHeight - ev.offsetY)
}
} else {
that._setPosition(ev.offsetX)
}
}
})
this.movementX = 0
this.movementY = 0
this.previousTouch = null
this.crt_val = 0
this.slider_box.addEventListener('mousedown', (ev) => {
//标准端拖动开始
if (that.is_disabled) {
return
}
that.movementX = 0
that.movementY = 0
that.previousTouch = null
if (that.is_vertical) {
that.crt_val = that.slider_box.offsetHeight * (that.handler.style.bottom.replace("%", "") / 100)
} else {
that.crt_val = that.slider_box.offsetWidth * (that.handler.style.left.replace("%", "") / 100)
}
document.documentElement.addEventListener('mousemove', _dragMove)
document.documentElement.addEventListener('mouseup', () => {
document.documentElement.removeEventListener('mousemove', _dragMove)
})
})
this.slider_box.addEventListener('touchstart', (ev) => {
//touch端拖动开始
if (that.is_disabled) {
return
}
that.movementX = 0
that.movementY = 0
that.previousTouch = null
if (that.is_vertical) {
that.crt_val = that.slider_box.offsetHeight * (that.handler.style.bottom.replace("%", "") / 100)
} else {
that.crt_val = that.slider_box.offsetWidth * (that.handler.style.left.replace("%", "") / 100)
}
document.documentElement.addEventListener('touchmove', _dragMove)
document.documentElement.addEventListener('touchend', () => {
document.documentElement.removeEventListener('touchmove', _dragMove)
})
})
function _dragMove(ev) {
if (ev.type == "touchmove") {
//touch端
if (that.previousTouch) {
that.movementX += ev.touches[0].pageX - that.previousTouch.pageX;
that.movementY += ev.touches[0].pageY - that.previousTouch.pageY;
};
that.previousTouch = ev.touches[0];
if (that.is_vertical) {
var new_val = that.crt_val - that.movementY
if (new_val < 0) {
new_val = 0
} else if (new_val > that.slider_box.offsetHeight) {
new_val = that.slider_box.offsetHeight
}
that._setPosition(new_val)
} else {
var new_val = that.crt_val + that.movementX
if (new_val < 0) {
new_val = 0
} else if (new_val > that.slider_box.offsetWidth) {
new_val = that.slider_box.offsetWidth
}
that._setPosition(new_val)
}
} else {
//标准端
that.movementX += ev.movementX
that.movementY += ev.movementY
if (that.is_vertical) {
var new_val = that.crt_val - that.movementY
if (new_val < 0) {
new_val = 0
} else if (new_val > that.slider_box.offsetHeight) {
new_val = that.slider_box.offsetHeight
}
that._setPosition(new_val)
} else {
var new_val = that.crt_val + that.movementX
if (new_val < 0) {
new_val = 0
} else if (new_val > that.slider_box.offsetWidth) {
new_val = that.slider_box.offsetWidth
}
that._setPosition(new_val)
}
}
ev.preventDefault()
}
//根据相关值设置 slider 样式
this._setPosition = function (val, noCallback) {
var percent
if (this.is_vertical) {
percent = parseFloat(val) / this.slider_box.offsetHeight
} else {
percent = parseFloat(val) / this.slider_box.offsetWidth
}
var resultData
var closest_index = Math.floor(this.step_separates.length * percent)
if (closest_index >= this.step_separates.length) {
closest_index = this.step_separates.length - 1
}
resultData = this.step_separates[closest_index]
percent = this.step_percents[closest_index]
var percentCss = percent * 100 + '%'
if (this.is_vertical) {
this.light.style.height = percentCss
this.handler.style.bottom = percentCss
} else {
this.light.style.width = percentCss
this.handler.style.left = percentCss
}
this.slider_box.dataset.value = resultData
if (!this.is_initialize) {
if (this.options) {
if (this.options.callback instanceof Function && !noCallback) {
this.options.callback(resultData)
}
}
}
}
//设置初始默认值
if (this.options) {
var default_data = parseFloat(this.options.default_data)
if (default_data || default_data == 0) {
this.setSliderData(default_data)
} else {
this.setSliderData(this.min_data)
}
this.is_initialize = false
}
}
//用户公开的方法,设置 slider 值
setSliderData(data, noCallback = false) {
if (data < this.min_data) {
data = this.min_data
}
if (data > this.max_data) {
data = this.max_data
}
var percent
var min_differ = Number.MAX_VALUE
for (var i = 0; i < this.step_separates.length; i++) {
var crt_differ = Math.abs(data - this.step_separates[i])
if (crt_differ < min_differ) {
min_differ = crt_differ
percent = this.step_percents[i]
}
if (crt_differ == 0) {
break
}
}
var move_val
if (this.is_vertical) {
move_val = parseFloat(this.slider_box.offsetHeight * percent)
} else {
move_val = parseFloat(this.slider_box.offsetWidth * percent)
}
this._setPosition(move_val, noCallback)
}
//用户公开的方法,设置是否禁用
setDisabled(is_disabled) {
this.is_disabled = is_disabled
if (!this.slider_box || !this.slider_box.attributes) {
return
}
if (is_disabled) {
var attr_disabled = document.createAttribute("disabled")
this.slider_box.attributes.setNamedItem(attr_disabled)
} else {
this.slider_box.attributes.removeNamedItem("disabled")
}
}
}
export default cy_slider