【JavaScript吉光片羽】--- 滑动条
2016-12-24 23:03 stoneniqiu 阅读(750) 评论(0) 编辑 收藏 举报灯光的亮度控制需要一个滑动条,先借用lamp源码中Bar:

var Bar = function (opt) { var defaults = { $id: "", // 进度条dom节点id min: 1, // 刻度最小值 stepCount: 5, // 刻度步数 step: 1, // 刻度步长 $alpha: "",//显示亮度的id touchEnd: function () { } // 拖动完成回调 }; this.option = $.extend(defaults, opt); this.barNode = $("#" + this.option.$id); this.parentNode = this.barNode.parents(".J_slider_box"); this.sliderNode = this.barNode.find(".J_slider"); this.fillNode = this.barNode.find(".J_fill"); this.valNode = this.barNode.find(".J_value"); this.val = this.option.min; // this.valNode.text(this.val); this._init(); return this; } Bar.prototype = { /** * 根据比例值来重新渲染进度条的位置 * @param ratio 取值:0~1 */ refreshPos: function (ratio) { if (ratio >= 1 || ratio < 0) { // 等于1时,js的%取值有问题,故排除 return; } // 根据触点位置更新进度条 var percentage = ratio * 100; this.sliderNode.css("left", percentage + "%"); this.fillNode.css("width", percentage + "%"); var unit = 1 / this.option.stepCount, halfUnit = unit / 2, a = Math.floor(ratio / unit), b = ratio % unit, index = a + (b < halfUnit ? 0 : 1); this.val = this.option.min + index * this.option.step; if (this.option.$alpha) { $("#" + this.option.$alpha).html(this.val); } else { this.valNode.text(this.val); } }, /** * 设置指定的进度值 */ setVal: function (val) { var ratio = (val - this.option.min) / (this.option.step * this.option.stepCount); this.refreshPos(ratio); }, _init: function () { var bar = this; if (!(bar.barNode.width() > 0)) { setTimeout(function () { bar._init(); }, 100); // 直到vm渲染完成之后才能取得正确的dom高宽 return; } bar.leftDis = bar.barNode.offset().left; bar.sliderWidth = bar.barNode.width(); bar.barNode.on("touchmove", function (e) { e.preventDefault(); // bar.parentNode.addClass("on"); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio = (touch.pageX - bar.leftDis) / bar.sliderWidth; bar.refreshPos(ratio); }); bar.barNode.on("touchend", function (e) { e.preventDefault(); //bar.parentNode.removeClass("on"); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio = (touch.pageX - bar.leftDis) / bar.sliderWidth; bar.refreshPos(ratio); bar.option.touchEnd(bar.val); }); bar.refreshPos(this.val); } };
html:
<div class="lightsider"> <div id="lightsider" class="slider_box J_slider_box"> <i class="slider_box_icon icon dark"></i> <div id="lightBar" class="slider_box_bar"> <div class="slider_box_slider J_slider" style="left:0%"> <p class="slider_box_slider_label J_value"></p> <i class="slider_box_slider_touch"></i> </div> <div class="slider_box_line"> <span class="slider_box_line_fill J_fill" style="width:0%"></span> </div> </div> <i class="slider_box_icon icon light"></i> </div> </div>
css:
.slider_box { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; } .slider_box_icon { display: block; width: 35px; height: 35px; } .slider_box_bar { position: relative; margin: 0 10px; padding: 33px 0; -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; } .slider_box_slider { position: absolute; height: 33px; top: 0; left: 0; z-index: 1; -webkit-transform: translate(-50%, 0); -ms-transform: translate(-50%, 0); transform: translate(-50%, 0); } .slider_box_slider_touch { position: absolute; left: 50%; bottom: -11px; margin-left: -8px; width: 20px; height: 20px; border-radius: 15px; background-color: white; border: 1px solid rgb(195, 194, 194); } .slider_box_line { position: relative; height: 4px; border-radius: 4px; background-color: rgb(195, 194, 194); } .slider_box_line_fill { position: absolute; top: 0; left: 0; height: 4px; background-color: gold; border-radius: 4px; }
JavaScript 调用:
var bar = new Bar({ $id: "lightsider", stepCount: 100, min: 0, $alpha: "alpha" });
stepCount相当于最大长度。$alpha用来显示亮度值。效果如下
主要的原理就是监听 touchmove事件,通过移动的pageX减去圆点左边的位置除以滑动条的总长度得到比率,最后换算成step
bar.leftDis = bar.barNode.offset().left; bar.sliderWidth = bar.barNode.width(); bar.barNode.on("touchmove", function (e) { e.preventDefault(); // bar.parentNode.addClass("on"); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio = (touch.pageX - bar.leftDis) / bar.sliderWidth; bar.refreshPos(ratio); });
如果是竖着的滑动条呢? 暂且定义一个UpBar对象:

var UpBar = function (opt) { var defaults = { $id: "", // 进度条dom节点id min: 1, // 刻度最小值 stepCount: 5, // 刻度步数 step: 1, // 刻度步长 $alpha: "",//显示亮度的id touchEnd: function () { } // 拖动完成回调 }; this.option = $.extend(defaults, opt); this.barNode = $("#" + this.option.$id); this.parentNode = this.barNode.parents(".J_slider_box"); this.sliderNode = this.barNode.find(".J_slider"); this.fillNode = this.barNode.find(".J_fill"); this.valNode = this.barNode.find(".J_value"); this.val = this.option.min; // this.valNode.text(this.val); this._init(); return this; } UpBar.prototype = { /** * 根据比例值来重新渲染进度条的位置 * @param ratio 取值:0~1 */ refreshPos: function (ratio) { if (ratio >= 1 || ratio < 0) { // 等于1时,js的%取值有问题,故排除 return; } // 根据触点位置更新进度条 var percentage = ratio * 100; this.sliderNode.css("bottom", percentage + "%"); this.fillNode.css("height", percentage + "%"); var unit = 1 / this.option.stepCount, halfUnit = unit / 2, a = Math.floor(ratio / unit), b = ratio % unit, index = a + (b < halfUnit ? 0 : 1); this.val = this.option.min + index * this.option.step; if (this.option.$alpha) { $("#" + this.option.$alpha).html(this.val); } else { // this.valNode.text(this.val); } }, /** * 设置指定的进度值 */ setVal: function (val) { var ratio = (val - this.option.min) / (this.option.step * this.option.stepCount); this.refreshPos(ratio); }, _init: function () { var bar = this; if (!(bar.barNode.height() > 0)) { setTimeout(function () { bar._init(); }, 100); // 直到vm渲染完成之后才能取得正确的dom高宽 return; } bar.topDis = bar.barNode.offset().top; bar.sliderHeight = bar.barNode.height(); bar.barNode.on("touchmove", function (e) { e.preventDefault(); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio =1- (touch.pageY - bar.topDis) / bar.sliderHeight; bar.refreshPos(ratio); }); bar.barNode.on("touchend", function (e) { e.preventDefault(); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio =1- (touch.pageY - bar.topDis) / bar.sliderHeight; bar.refreshPos(ratio); bar.option.touchEnd(bar.val); }); bar.refreshPos(this.val); } };
css:
.slider_box_slider_up { position: absolute; width: 33px; top: 0; right: -20px; z-index: 1; -webkit-transform: translate(-50%, 0); -ms-transform: translate(-50%, 0); transform: translate(-50%, 0); } .slider_box_slider_touch_up { position: absolute; width: 20px; height: 20px; bottom: -10px; left: 0; border-radius: 15px; background-color: white; border: 1px solid rgb(195, 194, 194); } .slider_box_line_up { width: 4px; height: 100%; border-radius: 4px; position: relative; margin: 0 auto; background-color: rgb(195, 194, 194); } .slider_box_line_fill_up { position: absolute; bottom:0; left: 0; width: 4px; background-color: gold; border-radius: 4px; }
html:
<div class="soundBar"> <div id="soundBar" class="slider_box_up J_slider_box"> <div class="slider_box_line_up"> <span class="slider_box_line_fill_up J_fill" style="height: 0%"></span> </div> <div class="slider_box_slider_up J_slider" style="bottom: 0%"> <i class="slider_box_slider_label J_value"></i> <i class="slider_box_slider_touch_up"></i> </div> </div> </div>
调用:
var bar = new UpBar({ $id: "soundBar", stepCount: 100, min: 0 });
效果如下:
主要的区别是left-->bottom,width-->height,另外一个因为y轴是以左上角为0,0的,touch.pageY越往下越大,所以算比率的时候用要这样:
bar.topDis = bar.barNode.offset().top; bar.sliderHeight = bar.barNode.height(); bar.barNode.on("touchmove", function (e) { e.preventDefault(); var touch = e.changedTouches ? e.changedTouches[0] : e; var ratio =1- (touch.pageY - bar.topDis) / bar.sliderHeight; bar.refreshPos(ratio); });
有兴趣也可以合二为一。如需要获取值,就订阅touchEnd事件。
关注书山有路,用自己的知识体系去丈量世界!
书山有路群:452450927
书山有路群:452450927
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义