fs-switch.vue 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. <template>
  2. <view
  3. class="fs-switch"
  4. :class="[{ 'fs-switch-checked': modelValue, 'fs-switch-disabled': disabled }, 'fs-switch-' + size]"
  5. @click="handleClick"
  6. >
  7. <view class="fs-switch-text">{{ modelValue ? activeText : inactiveText }}</view>
  8. </view>
  9. </template>
  10. <script setup>
  11. import { watch, ref } from 'vue'
  12. const props = defineProps({
  13. modelValue: Boolean,
  14. disabled: Boolean,
  15. activeColor: {
  16. type: String,
  17. default: '#0063F5'
  18. },
  19. inactiveColor: {
  20. type: String,
  21. default: '#fdfdfd'
  22. },
  23. activeText: String,
  24. inactiveText: String,
  25. size: {
  26. type: String,
  27. validator(value) {
  28. return ['small', 'default', 'large'].includes(value)
  29. }
  30. }
  31. })
  32. const emits = defineEmits(['change', 'update:modelValue'])
  33. const handleClick = () => {
  34. if (!props.disabled) {
  35. emits('update:modelValue', !props.modelValue)
  36. emits('change', !props.modelValue)
  37. }
  38. }
  39. </script>
  40. <style lang="scss" scoped>
  41. .fs-switch {
  42. width: 80rpx;
  43. height: 40rpx;
  44. border-radius: 50rpx;
  45. position: relative;
  46. background-color: v-bind(inactiveColor);
  47. border: 2rpx solid rgba(0, 0, 0, 0.12);
  48. transition: background-color 0.1s;
  49. &::before {
  50. width: 36rpx;
  51. height: 36rpx;
  52. border-radius: 50%;
  53. content: '';
  54. position: absolute;
  55. top: 0;
  56. left: 0;
  57. background-color: #fff;
  58. box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  59. transition: transform 0.3s;
  60. z-index: 10;
  61. }
  62. &-text {
  63. position: absolute;
  64. top: 50%;
  65. left: 50%;
  66. transform: translateY(-50%);
  67. font-size: 12px;
  68. transition: all 0.3s;
  69. text-align: center;
  70. width: 30rpx;
  71. overflow: hidden;
  72. }
  73. &-disabled {
  74. opacity: 0.5;
  75. }
  76. &-checked {
  77. background-color: v-bind(activeColor);
  78. &::before {
  79. transform: translateX(40rpx);
  80. }
  81. .fs-switch-text {
  82. color: #fff;
  83. margin-left: -30rpx;
  84. }
  85. }
  86. &-large {
  87. transform: scale(1.2);
  88. }
  89. &-small {
  90. transform: scale(0.8);
  91. }
  92. }
  93. </style>