赞
踩
我发现大多数前端UI库都是圆形的滑块,而且圆形的滑块都没有紧贴进度条,都是超出了首尾端,所以亲自写一个矩形的滑块,我使用了微信小程序的wxs的事件通信写法,官方说这样写好,也不知道好哪里了。样式如下图:
js
- // components/slider/index.js
- Component({
- // 启用插槽
- options: {
- multipleSlots: true
- },
- /**
- * 组件的属性列表
- */
- properties: {
-
- disabled: {
- type: Boolean,
- value: false,
- observer(val, oldVal) {
- if (val !== this.value) {
- this.setData({
- ['propValue.disabled']: val
- })
- }
- },
- },
- max: {
- type: Number,
- value: 100,
- observer(val, oldVal) {
- if (val !== this.value) {
- this.setData({
- ['propValue.max']: val
- })
- }
- },
- },
- min: {
- type: Number,
- value: 0,
- observer(val, oldVal) {
- if (val !== this.value) {
- this.setData({
- ['propValue.min']: val
- })
- }
- },
- },
- step: {
- type: Number,
- value: 1,
- observer(val, oldVal) {
- if (val !== this.value) {
- this.setData({
- ['propValue.step']: val
- })
- }
- },
- },
- value: {
- type: null,
- value: 0,
- observer(val, oldVal) {
- if (val !== this.value) {
- this.setData({
- ['propValue.value']: val
- })
- }
- },
- }
- },
-
- /**
- * 组件的初始数据
- */
- data: {
- propValue: {
- disabled: null,
- max: null,
- min: null,
- step: null,
- value: null
- }
- },
- lifetimes: {
- attached() {
- this.data.propValue.disabled = this.data.disabled;
- this.data.propValue.max = this.data.max;
- this.data.propValue.min = this.data.min;
- this.data.propValue.step = this.data.step;
- this.data.propValue.value = this.data.value;
- this.setData({
- propValue: this.data.propValue
- })
- }
- },
-
- /**
- * 组件的方法列表
- */
- methods: {
- setVal(val) {
- // this.setData({
- // value: val
- // })
- }
- }
- })
wxml
- <!--自定义滑块组件-->
- <wxs module="computed" src="./index.wxs"></wxs>
-
-
- <view class="n-slider {{disabled?'n-slider__disabled':''}}" change:prop="{{computed.propObserver}}" prop="{{propValue}}" bind:tap="{{computed.onClick}}" bind:touchstart="{{computed.onTouchStart}}" catch:touchmove="{{computed.onTouchMove}}" bind:touchend="{{computed.onTouchEnd}}" bind:touchcancel="{{computed.onTouchEnd}}">
-
- <view class="n-slider-rail">
-
-
- <view class="n-slider-rail__fill"></view>
-
- <view class="n-slider-handles">
- <view class="n-slider-handle-wrapper">
-
- <view class="n-slider-handle">
- <slot></slot>
- </view>
-
-
- </view>
- </view>
- </view>
- </view>
wxs
- var DRAG_STATUS = {
- START: 'start',
- MOVING: 'moving',
- END: 'end',
- };
-
- var dragStatus = DRAG_STATUS.START;
-
-
- var propValue = {
- disabled: false,
- max: 100,
- min: 0,
- step: 1,
- value: 0
- }
-
- var newValue;
-
-
- function onTouchStart(event, ins) {
-
-
- var disabled = propValue.disabled;
- if (disabled) {
- return;
- }
-
- newValue = propValue.value;
- dragStatus = DRAG_STATUS.START;
- }
-
-
- function onTouchMove(event, ins) {
-
- var disabled = propValue.disabled;
- if (disabled) {
- return;
- }
-
- if (dragStatus === DRAG_STATUS.START) {
- ins.triggerEvent('drag-start');
- }
-
- dragStatus = DRAG_STATUS.MOVING;
-
- var touch = event.touches[0];
- var rect = ins.selectComponent('.n-slider-handles').getBoundingClientRect();
- var percentage = (touch.clientX - rect.left) / rect.width;
-
- newValue = percentageToValue(percentage);
- updateValue(ins, newValue, false, true);
- }
-
-
- function onTouchEnd(event, ins) {
- var disabled = propValue.disabled;
- if (disabled) {
- return;
- }
- if (dragStatus === DRAG_STATUS.MOVING) {
- dragStatus = DRAG_STATUS.END;
- updateValue(ins, newValue, true);
- ins.triggerEvent('drag-end');
- }
-
-
- }
-
- function onClick(event, ins) {
- var disabled = propValue.disabled;
- if (disabled) {
- return;
- }
-
- var touch = event.touches[0];
- var rect = ins.selectComponent('.n-slider-handles').getBoundingClientRect();
- var percentage = (touch.clientX - rect.left) / rect.width;
- updateValue(ins, percentageToValue(percentage), true);
-
- }
-
- /**
- * 限制拖动值不能超出最小和最大范围
- * @param value
- */
- function format(value) {
-
- return Math.round(Math.max(propValue.min, Math.min(value, propValue.max)) / propValue.step) * propValue.step;
- }
-
-
- /**
- *
- * @param ins
- * @param val 不能和value重复
- * @param end
- * @param drag
- */
- function updateValue(ins, val, end, drag) {
- value = format(val);
- ins.selectComponent('.n-slider-handle-wrapper').setStyle({
- "left": getOffsetWidth(value),
- "transition": drag ? "none" : "all .2s"
- });
-
- ins.selectComponent('.n-slider-rail__fill').setStyle({
- "width": getOffsetWidth(value),
- "transition": drag ? "none" : "all .2s"
- });
-
- if (drag) {
- ins.triggerEvent('drag', {
- value: value
- });
- }
- if (end) {
-
- ins.triggerEvent('change', value);
- }
- if (drag || end) {
- // ins.callMethod('setVal', value);
-
- }
- }
-
-
- function getScope() {
- return Number(propValue.max) - Number(propValue.min);
- }
-
-
- function getOffsetWidth(current) {
- var scope = getScope();
- // 避免最小值小于最小step时出现负数情况
- return "".concat(Math.max(((current - Number(propValue.min)) * 100) / scope, 0), "%");
- }
-
-
- function percentageToValue(percentage) {
- return propValue.min + (propValue.max - propValue.min) * percentage
- }
-
- function propObserver(newValue, oldValue, ownerInstance, instance) {
-
- //这里判断一下newValue.value是否等于0,否则等于0的情况下不会执行这里
- if (newValue.value || newValue.value === 0) {
- propValue = newValue;
- updateValue(ownerInstance, propValue.value);
- }
-
- }
-
- module.exports = {
- onTouchStart: onTouchStart,
- onTouchMove: onTouchMove,
- onTouchEnd: onTouchEnd,
- onClick: onClick,
- propObserver: propObserver
- }
wxss
- .n-slider {
- position: relative;
- z-index: 0;
- width: 100%;
- /* 增大点击范围 */
- padding: 7px 0;
- }
-
- .n-slider__disabled {
- opacity: .5;
- }
-
- .n-slider .n-slider-rail {
- width: 100%;
- position: relative;
- height: 10rpx;
- background-color: rgb(219, 219, 223);
- border-radius: 10rpx;
- }
-
- .n-slider .n-slider-rail .n-slider-rail__fill {
- position: absolute;
- top: 0;
- bottom: 0;
- background-color: #FA6800;
- left: 0;
- /* 改变这个 */
- width: 0%;
- border-radius: inherit;
-
- }
-
- .n-slider .n-slider-handles {
- position: absolute;
- top: 0;
- bottom: 0;
- /* 这里是滑块宽度的一半 */
- left: 80rpx;
- right: 80rpx;
- }
-
- .n-slider .n-slider-handles .n-slider-handle-wrapper {
- outline: none;
- position: absolute;
- top: 50%;
- transform: translate(-50%, -50%);
- display: flex;
- /* 改变这个 */
- left: 0%;
- z-index: 0;
- /* transition: all .2s; */
- }
-
- .n-slider .n-slider-handles .n-slider-handle-wrapper .n-slider-handle {
- height: 42rpx;
- line-height: 42rpx;
- width: 160rpx;
- overflow: hidden;
- background-color: #FFFFFF;
- /* box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05); */
- opacity: .8;
- font-size: 26rpx;
- text-align: center;
- border: 1px solid #b9b9b9;
- box-sizing: border-box;
- border-radius: 6rpx;
- color: #333333;
- }
如果觉得可以,请微信关注《华音有声剧社》公众号,进入小程序听书
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。