evan-switch.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <view @click="toggle" class="evan-switch" :class="{'evan-switch--disabled':disabled}" :style="{backgroundColor:currentValue===activeValue?activeColor:inactiveColor}">
  3. <view class="evan-switch__circle" :style="{transform:currentValue===activeValue?`translateX(${29}px)`:`translateX(0)`}"></view>
  4. </view>
  5. </template>
  6. <script>
  7. export default {
  8. name: 'EvanSwitch',
  9. props: {
  10. value: {
  11. type: [String, Number, Boolean],
  12. default: false
  13. },
  14. activeColor: {
  15. type: String,
  16. default: '#108ee9'
  17. },
  18. inactiveColor: {
  19. type: String,
  20. default: '#fff'
  21. },
  22. size: {
  23. type: Number,
  24. default: 30
  25. },
  26. disabled: {
  27. type: Boolean,
  28. default: false
  29. },
  30. activeValue: {
  31. type: [String, Number, Boolean],
  32. default: true
  33. },
  34. inactiveValue: {
  35. type: [String, Number, Boolean],
  36. default: false
  37. },
  38. beforeChange: {
  39. type: Function,
  40. default: null
  41. },
  42. extraData: null,
  43. contextLevel: {
  44. type: Number,
  45. default: 1
  46. }
  47. },
  48. computed: {
  49. switchHeight() {
  50. // #ifdef APP-NVUE
  51. return this.size + 2 + 'px'
  52. // #endif
  53. // #ifndef APP-NVUE
  54. return this.size + 'px'
  55. // #endif
  56. }
  57. },
  58. watch: {
  59. value: {
  60. immediate: true,
  61. handler(value) {
  62. this.currentValue = value
  63. }
  64. }
  65. },
  66. data() {
  67. return {
  68. currentValue: false
  69. }
  70. },
  71. methods: {
  72. toggle() {
  73. if (!this.disabled) {
  74. if (this.beforeChange && typeof this.beforeChange === 'function') {
  75. let context = this
  76. for (let i = 0; i < this.contextLevel; i++) {
  77. context = context.$options.parent
  78. }
  79. const result = this.beforeChange(this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue,
  80. this.extraData, context)
  81. if (typeof result === 'object') {
  82. result.then(() => {
  83. this.toggleValue()
  84. }).catch(() => {})
  85. } else if (typeof result === 'boolean' && result) {
  86. this.toggleValue()
  87. }
  88. } else {
  89. this.toggleValue()
  90. }
  91. }
  92. },
  93. toggleValue() {
  94. this.currentValue = this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue
  95. this.$emit('input', this.currentValue)
  96. this.$emit('change', this.currentValue)
  97. }
  98. }
  99. }
  100. </script>
  101. <style lang="scss" scoped>
  102. .evan-switch {
  103. position: relative;
  104. border-width: 1px;
  105. border-color: rgba(0, 0, 0, 0.1);
  106. border-style: solid;
  107. transition: background-color 0.3s;
  108. width: 100upx;
  109. height: 36upx;
  110. background: #0bb3f2;
  111. border-radius: 18upx;
  112. /* #ifndef APP-NVUE */
  113. box-sizing: content-box;
  114. /* #endif */
  115. }
  116. .evan-switch--disabled {
  117. opacity: 0.3;
  118. }
  119. .evan-switch__circle {
  120. position: absolute;
  121. left: -4upx;
  122. top: -8upx;
  123. width: 50upx;
  124. height: 50upx;
  125. background: #FFFFFF;
  126. box-shadow: 0px 2px 10px 0px rgba(166, 217, 212, 0.49);
  127. border-radius: 50%;
  128. /* #ifndef APP-NVUE */
  129. box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
  130. /* #endif */
  131. /* #ifdef APP-NVUE */
  132. box-shadow: 1px 0 0px 0 rgba(0, 0, 0, 0.05);
  133. /* #endif */
  134. transition: transform 0.3s;
  135. }
  136. </style>