|
| 1 | +/* |
| 2 | + * MVVM模式下自定义滚动条和进度条组件 |
| 3 | + * ~屏蔽压缩报错 |
| 4 | + * author:紫苏 |
| 5 | + */ |
| 6 | +~(function() { |
| 7 | + //在闭包中获取全局变量 |
| 8 | + var window = this || (0, eval)('this'); |
| 9 | + //获取页面字体大小,作为页面UI尺寸参照物 |
| 10 | + var FONTSIZE = function() { |
| 11 | + //获取页面body元素字体大小并转化成整数 |
| 12 | + return parseInt(document.body.currentStyle ? document.body.currentStyle['fontSize'] : getComputedStyle(document.body, false)['fontSize']); |
| 13 | + }(); |
| 14 | + //视图模型对象 |
| 15 | + var VM = function() { |
| 16 | + //组件创建策略对象 |
| 17 | + var Method = { |
| 18 | + /* |
| 19 | + * 进度条组件 创建方法 |
| 20 | + * dom 进度条容器 |
| 21 | + * data 进度条数据模型 |
| 22 | + */ |
| 23 | + progressbar: function(dom, data) { |
| 24 | + var progress = document.createElement('div'), |
| 25 | + //数据模型数据,结构:{position:50} |
| 26 | + param = data.data; |
| 27 | + //设置进度完成容器尺寸 |
| 28 | + progress.style.width = (param.position || 100) + '%'; |
| 29 | + |
| 30 | + //为进度条组件添加UI样式 |
| 31 | + dom.className += 'ui-progressbar'; |
| 32 | + //进度条完成容器元素插入进度条容器中 |
| 33 | + dom.appendChild(progress); |
| 34 | + }, |
| 35 | + /* |
| 36 | + * 滑动条组件创建方法 |
| 37 | + * dom 滑动条容器 |
| 38 | + * data 滑动条数据模型 |
| 39 | + */ |
| 40 | + slider: function(dom, data) { |
| 41 | + //滑动条拨片 |
| 42 | + var bar = document.createElement('span'), |
| 43 | + //滑动条进度容器 |
| 44 | + progress = document.createElement('div'), |
| 45 | + //滑动条容量提示信息 |
| 46 | + totleText = null, |
| 47 | + //滑动条拨片提示信息 |
| 48 | + progressText = null, |
| 49 | + //数据模型数据,结构 {position:60,totle:200} |
| 50 | + param = data.data, |
| 51 | + //容器元素宽度 |
| 52 | + width = dom.clientWidth, |
| 53 | + //容器元素横坐标值 |
| 54 | + left = dom.offsetLeft, |
| 55 | + //拨片位置(以模型数据中position数据计算) |
| 56 | + realWidth = (param.position || 100) * width / 100; |
| 57 | + //清空滑动条容器 为创建滑动条做准备 |
| 58 | + dom.innerHTML = ''; |
| 59 | + //如果模型数据中提供容器总量信息(param.data),则创建滚动条提示文案 |
| 60 | + if (param.totle) { |
| 61 | + //容器总量提示文案 |
| 62 | + text = document.createElement('b'); |
| 63 | + //拨片位置提示信息 |
| 64 | + progressText = document.createElement('em'); |
| 65 | + //设置容器总量提示文案 |
| 66 | + text.innerHTML = param.totle; |
| 67 | + //将容器总量提示文案元素添加到滑动条组件中 |
| 68 | + dom.appendChild(text); |
| 69 | + //将拨片位置提示信息元素添加到滑动组件中 |
| 70 | + dom.appendChild(progressText); |
| 71 | + } |
| 72 | + //设置滑动条 |
| 73 | + setStyle(realWidth); |
| 74 | + //为滑动条组件添加UI样式 |
| 75 | + dom.className += 'ui-slider'; |
| 76 | + //将进度容器添加到滑动条组件中 |
| 77 | + dom.appendChild(progress); |
| 78 | + dom.appendChild(bar); |
| 79 | + //设置滑动条 |
| 80 | + function setStyle(w) { |
| 81 | + //设置进度容器宽度 |
| 82 | + progress.style.width = w + 'px'; |
| 83 | + //设置拨片横坐标 |
| 84 | + bar.style.left = w - FONTSIZE / 2 + 'px'; |
| 85 | + //如果拨片有提示信息 |
| 86 | + if (progressText) { |
| 87 | + //设置拨片提示文案横坐标 |
| 88 | + progressText.style.left = w - FONTSIZE / 2 * 2.4 + 'px'; |
| 89 | + //设置拨片刻度提示文案内容 |
| 90 | + progressText.innerHTML = parseFloat(w / width * 100).toFixed(2) + '%'; |
| 91 | + }; |
| 92 | + } |
| 93 | + |
| 94 | + /* |
| 95 | + * 创建组件逻辑 |
| 96 | + * 按下拨片 |
| 97 | + */ |
| 98 | + bar.onmousedown = function() { |
| 99 | + document.onmousemove = function(event) { |
| 100 | + //获取事件源 |
| 101 | + var e = event || window.event; |
| 102 | + var w = e.clientX - left; |
| 103 | + setStyle(w < width ? (w > 0 ? w : 0) : width); |
| 104 | + } |
| 105 | + //阻止页面滑动选项事件 |
| 106 | + document.onselectstart = function() { |
| 107 | + return false; |
| 108 | + } |
| 109 | + //停止滑动交互 |
| 110 | + document.onmouseup = function() { |
| 111 | + document.onmousemove = null; |
| 112 | + document.onselectstart = null; |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + /** |
| 119 | + * 获取视图层组件渲染数据的映射信息 (PS:很高端 完全不懂要映射什么数据) |
| 120 | + * dom 组件元素 |
| 121 | + */ |
| 122 | + function getBindData(dom) { |
| 123 | + //获取组件自定义属性data-bind值 |
| 124 | + var data = dom.getAttribute('data-bind'); |
| 125 | + //将自定义属性data-bind转化为Obj才可以使用 |
| 126 | + return !!data && (new Function("return ({" + data + "})"))(); |
| 127 | + } |
| 128 | + /* |
| 129 | + * 组件实例化方法 |
| 130 | + * |
| 131 | + */ |
| 132 | + return function() { |
| 133 | + //获取页面中所有元素 |
| 134 | + var doms = document.body.getElementsByTagName('*'), |
| 135 | + //元素自定义数据句柄 |
| 136 | + ctx = null; |
| 137 | + //ui处理是会向页面中插入数据,此时doms.length 会改变 ,此时动态获取dom.length |
| 138 | + for (var i = 0; i < doms.length; i++) { |
| 139 | + //获取元素自定义数据 |
| 140 | + ctx = getBindData(doms[i]); |
| 141 | + //如果元素是UI组件,则根据自定义属性中组件类型,渲染该组件 |
| 142 | + ctx.type && Method[ctx.type] && Method[ctx.type](doms[i], ctx); |
| 143 | + } |
| 144 | + } |
| 145 | + }(); |
| 146 | + //将视图模型对象绑定在window上,供外部使用 |
| 147 | + window.VM = VM; |
| 148 | +})(); |
| 149 | + var demo1 = { |
| 150 | + position: 60, |
| 151 | + totle: 200 |
| 152 | + }, |
| 153 | + demo2 = { |
| 154 | + position: 20 |
| 155 | + }, |
| 156 | + demo3 = { |
| 157 | + position: 50 |
| 158 | + }; |
| 159 | + window.onload = function() { |
| 160 | + VM(); |
| 161 | + }; |
| 162 | + |
0 commit comments