当前位置:   article > 正文

微信小程序 实现滑块是矩形的slider组件

微信小程序 实现滑块是矩形的slider组件

我发现大多数前端UI库都是圆形的滑块,而且圆形的滑块都没有紧贴进度条,都是超出了首尾端,所以亲自写一个矩形的滑块,我使用了微信小程序的wxs的事件通信写法,官方说这样写好,也不知道好哪里了。样式如下图:

js

  1. // components/slider/index.js
  2. Component({
  3. // 启用插槽
  4. options: {
  5. multipleSlots: true
  6. },
  7. /**
  8. * 组件的属性列表
  9. */
  10. properties: {
  11. disabled: {
  12. type: Boolean,
  13. value: false,
  14. observer(val, oldVal) {
  15. if (val !== this.value) {
  16. this.setData({
  17. ['propValue.disabled']: val
  18. })
  19. }
  20. },
  21. },
  22. max: {
  23. type: Number,
  24. value: 100,
  25. observer(val, oldVal) {
  26. if (val !== this.value) {
  27. this.setData({
  28. ['propValue.max']: val
  29. })
  30. }
  31. },
  32. },
  33. min: {
  34. type: Number,
  35. value: 0,
  36. observer(val, oldVal) {
  37. if (val !== this.value) {
  38. this.setData({
  39. ['propValue.min']: val
  40. })
  41. }
  42. },
  43. },
  44. step: {
  45. type: Number,
  46. value: 1,
  47. observer(val, oldVal) {
  48. if (val !== this.value) {
  49. this.setData({
  50. ['propValue.step']: val
  51. })
  52. }
  53. },
  54. },
  55. value: {
  56. type: null,
  57. value: 0,
  58. observer(val, oldVal) {
  59. if (val !== this.value) {
  60. this.setData({
  61. ['propValue.value']: val
  62. })
  63. }
  64. },
  65. }
  66. },
  67. /**
  68. * 组件的初始数据
  69. */
  70. data: {
  71. propValue: {
  72. disabled: null,
  73. max: null,
  74. min: null,
  75. step: null,
  76. value: null
  77. }
  78. },
  79. lifetimes: {
  80. attached() {
  81. this.data.propValue.disabled = this.data.disabled;
  82. this.data.propValue.max = this.data.max;
  83. this.data.propValue.min = this.data.min;
  84. this.data.propValue.step = this.data.step;
  85. this.data.propValue.value = this.data.value;
  86. this.setData({
  87. propValue: this.data.propValue
  88. })
  89. }
  90. },
  91. /**
  92. * 组件的方法列表
  93. */
  94. methods: {
  95. setVal(val) {
  96. // this.setData({
  97. // value: val
  98. // })
  99. }
  100. }
  101. })

wxml

  1. <!--自定义滑块组件-->
  2. <wxs module="computed" src="./index.wxs"></wxs>
  3. <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}}">
  4. <view class="n-slider-rail">
  5. <view class="n-slider-rail__fill"></view>
  6. <view class="n-slider-handles">
  7. <view class="n-slider-handle-wrapper">
  8. <view class="n-slider-handle">
  9. <slot></slot>
  10. </view>
  11. </view>
  12. </view>
  13. </view>
  14. </view>

wxs 

  1. var DRAG_STATUS = {
  2. START: 'start',
  3. MOVING: 'moving',
  4. END: 'end',
  5. };
  6. var dragStatus = DRAG_STATUS.START;
  7. var propValue = {
  8. disabled: false,
  9. max: 100,
  10. min: 0,
  11. step: 1,
  12. value: 0
  13. }
  14. var newValue;
  15. function onTouchStart(event, ins) {
  16. var disabled = propValue.disabled;
  17. if (disabled) {
  18. return;
  19. }
  20. newValue = propValue.value;
  21. dragStatus = DRAG_STATUS.START;
  22. }
  23. function onTouchMove(event, ins) {
  24. var disabled = propValue.disabled;
  25. if (disabled) {
  26. return;
  27. }
  28. if (dragStatus === DRAG_STATUS.START) {
  29. ins.triggerEvent('drag-start');
  30. }
  31. dragStatus = DRAG_STATUS.MOVING;
  32. var touch = event.touches[0];
  33. var rect = ins.selectComponent('.n-slider-handles').getBoundingClientRect();
  34. var percentage = (touch.clientX - rect.left) / rect.width;
  35. newValue = percentageToValue(percentage);
  36. updateValue(ins, newValue, false, true);
  37. }
  38. function onTouchEnd(event, ins) {
  39. var disabled = propValue.disabled;
  40. if (disabled) {
  41. return;
  42. }
  43. if (dragStatus === DRAG_STATUS.MOVING) {
  44. dragStatus = DRAG_STATUS.END;
  45. updateValue(ins, newValue, true);
  46. ins.triggerEvent('drag-end');
  47. }
  48. }
  49. function onClick(event, ins) {
  50. var disabled = propValue.disabled;
  51. if (disabled) {
  52. return;
  53. }
  54. var touch = event.touches[0];
  55. var rect = ins.selectComponent('.n-slider-handles').getBoundingClientRect();
  56. var percentage = (touch.clientX - rect.left) / rect.width;
  57. updateValue(ins, percentageToValue(percentage), true);
  58. }
  59. /**
  60. * 限制拖动值不能超出最小和最大范围
  61. * @param value
  62. */
  63. function format(value) {
  64. return Math.round(Math.max(propValue.min, Math.min(value, propValue.max)) / propValue.step) * propValue.step;
  65. }
  66. /**
  67. *
  68. * @param ins
  69. * @param val 不能和value重复
  70. * @param end
  71. * @param drag
  72. */
  73. function updateValue(ins, val, end, drag) {
  74. value = format(val);
  75. ins.selectComponent('.n-slider-handle-wrapper').setStyle({
  76. "left": getOffsetWidth(value),
  77. "transition": drag ? "none" : "all .2s"
  78. });
  79. ins.selectComponent('.n-slider-rail__fill').setStyle({
  80. "width": getOffsetWidth(value),
  81. "transition": drag ? "none" : "all .2s"
  82. });
  83. if (drag) {
  84. ins.triggerEvent('drag', {
  85. value: value
  86. });
  87. }
  88. if (end) {
  89. ins.triggerEvent('change', value);
  90. }
  91. if (drag || end) {
  92. // ins.callMethod('setVal', value);
  93. }
  94. }
  95. function getScope() {
  96. return Number(propValue.max) - Number(propValue.min);
  97. }
  98. function getOffsetWidth(current) {
  99. var scope = getScope();
  100. // 避免最小值小于最小step时出现负数情况
  101. return "".concat(Math.max(((current - Number(propValue.min)) * 100) / scope, 0), "%");
  102. }
  103. function percentageToValue(percentage) {
  104. return propValue.min + (propValue.max - propValue.min) * percentage
  105. }
  106. function propObserver(newValue, oldValue, ownerInstance, instance) {
  107. //这里判断一下newValue.value是否等于0,否则等于0的情况下不会执行这里
  108. if (newValue.value || newValue.value === 0) {
  109. propValue = newValue;
  110. updateValue(ownerInstance, propValue.value);
  111. }
  112. }
  113. module.exports = {
  114. onTouchStart: onTouchStart,
  115. onTouchMove: onTouchMove,
  116. onTouchEnd: onTouchEnd,
  117. onClick: onClick,
  118. propObserver: propObserver
  119. }

wxss 

  1. .n-slider {
  2. position: relative;
  3. z-index: 0;
  4. width: 100%;
  5. /* 增大点击范围 */
  6. padding: 7px 0;
  7. }
  8. .n-slider__disabled {
  9. opacity: .5;
  10. }
  11. .n-slider .n-slider-rail {
  12. width: 100%;
  13. position: relative;
  14. height: 10rpx;
  15. background-color: rgb(219, 219, 223);
  16. border-radius: 10rpx;
  17. }
  18. .n-slider .n-slider-rail .n-slider-rail__fill {
  19. position: absolute;
  20. top: 0;
  21. bottom: 0;
  22. background-color: #FA6800;
  23. left: 0;
  24. /* 改变这个 */
  25. width: 0%;
  26. border-radius: inherit;
  27. }
  28. .n-slider .n-slider-handles {
  29. position: absolute;
  30. top: 0;
  31. bottom: 0;
  32. /* 这里是滑块宽度的一半 */
  33. left: 80rpx;
  34. right: 80rpx;
  35. }
  36. .n-slider .n-slider-handles .n-slider-handle-wrapper {
  37. outline: none;
  38. position: absolute;
  39. top: 50%;
  40. transform: translate(-50%, -50%);
  41. display: flex;
  42. /* 改变这个 */
  43. left: 0%;
  44. z-index: 0;
  45. /* transition: all .2s; */
  46. }
  47. .n-slider .n-slider-handles .n-slider-handle-wrapper .n-slider-handle {
  48. height: 42rpx;
  49. line-height: 42rpx;
  50. width: 160rpx;
  51. overflow: hidden;
  52. background-color: #FFFFFF;
  53. /* box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.3), inset 0 0 1px 0 rgba(0, 0, 0, 0.05); */
  54. opacity: .8;
  55. font-size: 26rpx;
  56. text-align: center;
  57. border: 1px solid #b9b9b9;
  58. box-sizing: border-box;
  59. border-radius: 6rpx;
  60. color: #333333;
  61. }

如果觉得可以,请微信关注《华音有声剧社》公众号,进入小程序听书

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/159332?site
推荐阅读
相关标签
  

闽ICP备14008679号