index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <div class="layer" @click="clickHandle($event)" ref="layer">
  3. <div class="percentage" :style="{width: left}"></div>
  4. <span class="bar" :style="{left: left}" ref="bar" @click.stop></span>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. props: {
  10. value: {
  11. type: Number | String,
  12. default: 1
  13. },
  14. min: {
  15. type:Number,
  16. default: 1
  17. },
  18. max: {
  19. type: Number,
  20. default: Infinity
  21. },
  22. isGradient:{
  23. type: Number,
  24. default: 0
  25. }
  26. },
  27. data() {
  28. let gradientArr = []
  29. if(this.max > this.isGradient){
  30. let temp = Array(Math.ceil(this.max / this.isGradient)).fill(0)
  31. gradientArr = temp.map((item,i)=>{
  32. return [i*this.isGradient,(i+1)*this.isGradient]
  33. })
  34. console.log(gradientArr);
  35. }
  36. return {
  37. current: Number(this.value),
  38. isLegal:this.max > this.isGradient && this.isGradient,
  39. gradientArr
  40. }
  41. },
  42. mounted() {
  43. this.downHandle = this.downHandle.bind(this)
  44. this.$refs.bar.addEventListener('mousedown', this.downHandle, false)
  45. this.$refs.bar.addEventListener('touchstart', this.downHandle, false)
  46. },
  47. beforeDestroy() {
  48. this.$refs.bar.removeEventListener('mousedown', this.downHandle, false)
  49. this.$refs.bar.removeEventListener('touchstart', this.downHandle, false)
  50. },
  51. methods: {
  52. toChangeNum(tmp){
  53. let max = [0,0]
  54. if (this.isLegal) {
  55. max = this.gradientArr.find(item=>{
  56. return tmp >= item[0] && tmp < item[1]
  57. })
  58. }
  59. if (tmp == 0 || tmp == this.max) {
  60. this.current = tmp
  61. return
  62. }
  63. return Number(this.isLegal ? (max ? max[1] : tmp) : tmp)
  64. },
  65. clickHandle(ev) {
  66. let tmp = this.min + this.len * (ev.offsetX / this.width)
  67. this.current = this.toChangeNum(tmp)
  68. },
  69. downHandle(ev) {
  70. let $layer = document.documentElement
  71. let startX = ev.pageX || ev.touches[0].pageX
  72. let initV = this.current
  73. let move = ev => {
  74. let tmp = initV - ((startX - (ev.pageX || ev.touches[0].pageX)) / this.width) * this.len
  75. this.current = this.toChangeNum(tmp)
  76. }
  77. let end = ev => {
  78. $layer.removeEventListener('touchmove', move, false)
  79. $layer.removeEventListener('touchend', end, false)
  80. $layer.removeEventListener('mousemove', move, false)
  81. $layer.removeEventListener('mouseup', end, false)
  82. }
  83. $layer.addEventListener('touchmove', move, false)
  84. $layer.addEventListener('touchend', end, false)
  85. $layer.addEventListener('mousemove', move, false)
  86. $layer.addEventListener('mouseup', end, false)
  87. this.$bus.once('player/mouseup', end)
  88. }
  89. },
  90. computed: {
  91. width() {
  92. return this.$refs.layer.offsetWidth
  93. },
  94. len() {
  95. return this.max - this.min
  96. },
  97. left() {
  98. return ((this.current - this.min) / this.len) * 100 + '%'
  99. }
  100. },
  101. watch: {
  102. current() {
  103. let current = Number(this.current ? this.current.toFixed(2) : this.current)
  104. if (current !== this.current) return this.current = current
  105. if (!this.current.toString()) {
  106. return this.current = 1
  107. }
  108. if (this.current < this.min) {
  109. return this.current = this.min
  110. } else if (this.current > this.max) {
  111. this.current = this.max
  112. }
  113. this.$emit('input', this.current)
  114. },
  115. value(newV, oldV) {
  116. if (newV !== this.current)
  117. console.log(newV);
  118. this.current = Number(newV)
  119. }
  120. }
  121. }
  122. </script>
  123. <style lang="less" scoped>
  124. .layer {
  125. margin: 10px 0;
  126. position: relative;
  127. width: 100%;
  128. height: 4px;
  129. cursor: pointer;
  130. border: 1px solid #5d5d5d;
  131. >.percentage {
  132. height: calc(100% + 2px);
  133. background-color: @color;
  134. position: absolute;
  135. top: -1px;
  136. left: 0;
  137. }
  138. >.bar {
  139. position: absolute;
  140. height: 15px;
  141. width: 15px;
  142. background-color: #ffffff;
  143. position: absolute;
  144. border-radius: 50%;
  145. top: 50%;
  146. transform: translate(-50%, -50%);
  147. cursor: pointer;
  148. }
  149. }
  150. </style>