打造专属插件之Easy Slider Bar

引用

<link rel="stylesheet" type="text/css" href="./index.css">
<div id="slider"></div>
<script type="text/javascript" src="./index.js"></script>
<script type="text/javascript">
	var sb = new EasySliderBar({
		el: 'slider'
	})
</script>

参数

Name

Type

Constraint

Comment

el

String

required

容器节点

max

Number

default 100

上限

min

Number

default 0

下限

scale

Integer

default 0

小数位数

trackHeight

Integer

default 10

轨道高度

type

enum['circle', 'square', 'diamond']

default 'circle'

slider bar类型

barNumber

Integer

default 1

slider bar数量

positions

Array

default [min...]

slider bar初始位置

  • 当参数 el 非法,slider bar 取消创建
  • 当其他参数非法,取默认值

方法

Name

Parameter

Return

Comment

setBarPosition

pos, index

void

设置 index 指定的 slider bar 的位置为 pos,如果index === undefined,则设置所有 slider bar 的位置为 pos

getBarPosition

index

Number | Array

获取 index 指定的 slide rbar 的位置,如果index === undefined,则返回所有 slider bar 的位置数组

源码

index.js

/**
 * Created by lonelydawn on 2017-11-20.
 * EasySliderBar - Easy slider bar
 */

// Polyfill
Array.prototype.forEach = Array.prototype.forEach || function (cb) {
	for (var i = 0; i < this.length; i++) {
		cb(this[i], i)
	}
}
Array.prototype.filter = Array.prototype.filter || function (cb) {
	var arr = []
	for (var i = 0; i < this.length; i++) {
		if (cb[this[i], i]) {
			arr.push(this[i])
		}
	}
	return arr
}

var EasySliderBar = function (options) {
	// Add class, and return the changed className
	var getPushedClass = function (className, value) {
		return typeof className === 'string' && typeof value === 'string'
			? className.split(' ').concat(value).join(' ') : className 
	}
	// Remove class, and return the changed className
	var getRemovedClass = function (className, value) {
		if (typeof className === 'string' && typeof value === 'string') {
			return className.split(' ').filter(function (item) {
				return item !== '' && item !== value
			}).join(' ')
		}
		return className
	}
	// Get parallel pixel to scale
	var getInterval = function () {
		return track.clientWidth / (max - min)
	}
	// Limit bars' moving range
	var getValidLeft = function (value) {
		if (value < 0) {
			return 0
		} else if (value > track.clientWidth) {
			return track.clientWidth
		} else {
			return value
		}
	}
	// Add trigger on slidebar
	var setBarMove = function (bar, index) {
		bar.onmousedown = function (e) {
			var start = (e || window.event).clientX
			var left = Math.floor((bar.position - min) * getInterval())
			bar.label.className = getRemovedClass(bar.label.className, 'hidden')
			// Execute callback
			onBarMoveBegin({
				index: index,
				position: Number(bar.position)
			})
			document.onmousemove = function (e) {
				var movingLeft = getValidLeft(left + (e || window.event).clientX - start)
				var movingPosition = (min + movingLeft / getInterval()).toFixed(scale)
				bar.label.innerHTML = movingPosition
				bar.style.left = movingLeft - barOffset + 'px'
				onBarMoving({
					index: index,
					position: Number(movingPosition)
				})
			}
			document.onmouseup = function (e) {
				bar.position = (min + getValidLeft(left + (e || window.event).clientX - start) / getInterval()).toFixed(scale)
				bar.label.className = getPushedClass(bar.label.className, 'hidden')
				// Execute callback
				onBarMoveEnd({
					index: index,
					position: Number(bar.position)
				})
				document.onmousemove = null
				document.onmouseup = null
				bar.releaseCapture && bar.releaseCapture()
			}
			bar.setCapture && bar.setCapture()
			return false
		}
	}
	var el = options.el
	var scale = options.scale || 0
	var min = !isNaN(options.min) ? options.min : 0
	var max = !isNaN(options.max) ? (options.max > min ? options.max : min + 100) : 100
	var barNumber = options.barNumber || 1
	var positions = Object.prototype.toString.call(options.positions) === '[object Array]' ? options.positions : []
	for (var i = 0; i < barNumber; i++) {
		positions[i] = positions[i] && positions[i] >= min && positions[i] <= max ? positions[i] : min
	}
	var type = options.type || 'circle'
	// Set bars' width and height by type
	var trackHeight = !isNaN(options.trackHeight) ? options.trackHeight : 10
	var barWidth = {
		square: trackHeight * 2,
		circle: trackHeight * 3,
		diamond: 20
	}[type]
	var barHeight = {
		square: trackHeight * 3,
		circle: trackHeight * 3,
		diamond: trackHeight
	}[type]
	var barOffset = barWidth / 2
	var labelWidth = (30 + 7 * scale) || 30
	var labelOffset = labelWidth / 2 - barOffset
	// Get customized callback
	var onBarMoveBegin = options.onBarMoveBegin || new Function()
	var onBarMoving = options.onBarMoving || new Function()
	var onBarMoveEnd = options.onBarMoveEnd || new Function()

	var wrapper = document.getElementById(el)
	if (!wrapper) {
		return
	}
	// Init wrapper height
	wrapper.style.padding = barOffset + 5 + 'px'
	wrapper.style.height = trackHeight + 'px'
	// Empty container
	var childs = wrapper.childNodes
	for (var i = childs.length - 1; i > -1; i--) {
		wrapper.removeChild(childs[i])
	}
	// Create track
	var track = document.createElement('div')
	track.className = 'slider-track'
	wrapper.appendChild(track)
	// Create slider bar
	var barStack = []
	for (var counter = 0; counter < barNumber; counter++) {
		var bar = document.createElement('div')
		bar.className = 'slider-bar ' + type
		bar.position = positions[counter]
		bar.style.width = barWidth + 'px'
		bar.style.height = barHeight + 'px'
		bar.style.top = (trackHeight - barHeight) / 2 + 'px'
		bar.style.left = Math.floor((positions[counter] - min) * getInterval()) - barOffset + 'px'
		setBarMove(bar, counter)
		// Create slider bar label
		var label = document.createElement('div')
		label.className = 'slider-label hidden'
		label.style.width = labelWidth + 'px'
		label.style.left = -labelOffset + 'px'
		label.innerHTML = positions[counter].toFixed(scale)
		bar.label = label
		// Create DOM structure
		bar.appendChild(label)
		track.appendChild(bar)
		barStack.push(bar)
	}
	return {
		// Set some bars' position. (If index is not defined, set all.)
		setBarPosition: function (pos, index) {
			var set = function (bar) {
				if (pos >= min && pos <= max) {
					bar.position = pos
					bar.style.left = Math.floor((pos - min) * getInterval()) - barOffset + 'px'
					bar.label.innerHTML = Number(pos).toFixed(scale)
				}
			}
			index ? set(barStack[index]) : barStack.forEach(function (item) {
				set(item)
			})
		},
		// Return some bars' position. (If index is not defined, return all.)
		getBarPosition: function (index) {
			return index >= 0 ? barStack[index].position : barStack.map(function (item) {
				return item.position
			})
		}
	}
}

index.css

.slider-track {
	width: 100%;
	height: 100%;
	position: relative;
	border-radius: 100px;
	font-family: Roboto;
	background-color: #e4e7ed;
}
.slider-label {
    padding: 3px 0;
    position: absolute;
    top: -40px;
    color: #fff;
    font-size: 12px;
    text-align: center;
    border-radius: 5px;
    background-color: #303133;
    transition: all 300ms linear;
}
.slider-label:after {
	width: 0px;
	height: 0px;
	border: 6px transparent solid;
	border-top-color: #303133;
	position:absolute;
	top: 100%;
	left: calc(50% - 6px);
	content:""
}
.slider-label.hidden {
	display: none;
}
.slider-bar {
	position: absolute;
	box-sizing: border-box;
}
.slider-bar:hover .slider-label {
	display: block;
}

.slider-bar.circle,
.slider-bar.square {
	border: 2px solid #409EFF;
	background-color: #FFF;
}
.slider-bar.circle {
	border-radius: 50%;
}
.slider-bar.square {
	border-radius: 3px;
}
.slider-bar.diamond {
	background-color: #409EFF;
}
.slider-bar.diamond:before {
	width: 0px;
	height: 0px;
	border: 10px transparent solid;
	border-bottom-color: #409EFF;
	position:absolute;
	bottom: 100%;
	left: 0;
	content:""
}
.slider-bar.diamond:after{
	width: 0px;
	height: 0px;
	border: 10px transparent solid;
	border-top-color: #409EFF;
	position:absolute;
	top: 100%;
	left: 0;
	content:""
}

源码奉上,任君 Hack 。

下载地址

GitHub

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mySoul

设计模式 里氏替换原则

在场景中,三毛需要什么枪支,就直接new 出一个枪支即可,然后其内通过抽象类获取到对象,然后对齐进行修饰

14260
来自专栏积累沉淀

DOM解析

Dom解析是将xml文件全部载入,组装成一颗dom树,然后通过节点以及节点之间的关系来解析xml文件 根据 DOM,XML 文档中的每个成分都是一个节点。 ...

22090
来自专栏Golang语言社区

实效go编程--2

Go函数的返回值或结果“形参”可被命名,并作为常规变量使用,就像传入的形参一样。 命名后,一旦该函数开始执行,它们就会被初始化为与其类型相应的零值; 若该函数执...

35470
来自专栏Golang语言社区

浅谈Go语言中的结构体struct &amp; 接口Interface &amp; 反射

结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套;

25040
来自专栏jeremy的技术点滴

py3_cookbook_notes_01

34480
来自专栏友弟技术工作室

golang之Struct什么是结构体struct?

最近在复习golang,学习的东西,如果不使用,很快就会忘记。所以,准备复习完golang,做一个练手的小项目,加深对golang的学习。今天开始公司,进入封闭...

62060
来自专栏Micro_awake web

Vue学习3:计算属性computed与监听器

17120
来自专栏章鱼的慢慢技术路

Go语言相关练习_选择题(1)

 解析:Go语言的内存回收机制规定,只要有一个指针指向引用一个变量,那么这个变量就不会被释放(内存逃逸),因此在Go语言中返回函数参数或临时变量是安全的。

7510
来自专栏企鹅号快讯

编写高效简洁代码的那些招式1

高效的代码,每期都会给大家介绍一下编码的技巧,让我们代码更整洁更高效。我们会从python 语言切入,讲一讲如何写的代码更pythonic 。Pythonic ...

19760
来自专栏闵开慧

java概念2

1 文件操作 public class FileTest { public static void main(String[] args) throw...

44980

扫码关注云+社区

领取腾讯云代金券