四零语境前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
4.5 KiB

  1. <template>
  2. <view v-if="visible" class="circle y-flex" ref="loading" :style="{
  3. width: pixelSize + 'px',
  4. height: pixelSize + 'px',
  5. 'border-radius': pixelSize + 'px'
  6. }">
  7. <view
  8. class="line y-flex"
  9. :style="{
  10. 'border-top-width': (pixelSize / 4) + 'px',
  11. 'border-bottom-width': (pixelSize / 4) + 'px',
  12. 'border-top-color': item.top,
  13. 'border-bottom-color': item.bottom,
  14. width: (pixelSize / 12) + 'px',
  15. left: ((pixelSize / 2) - (pixelSize / 24)) + 'px',
  16. }"
  17. :class="'line_' + index"
  18. v-for="(item, index) in rgbs" :key="index"></view>
  19. </view>
  20. </template>
  21. <script>
  22. // #ifdef APP-NVUE
  23. const Binding = uni.requireNativePlugin('bindingx');
  24. // #endif
  25. export default {
  26. props: {
  27. visible: {
  28. type: Boolean,
  29. default: true
  30. },
  31. size: {
  32. type: [Number, String],
  33. default: 40
  34. },
  35. color: {
  36. type: String,
  37. default: '#333333'
  38. }
  39. },
  40. computed: {
  41. rgbs () {
  42. const rgb = this.hexToRgb(this.color).replace('rgb(', '').replace(')', '')
  43. return [{
  44. top: `rgba(${rgb}, 1)`,
  45. bottom: `rgba(${rgb}, .4)`
  46. },{
  47. top: `rgba(${rgb}, .4)`,
  48. bottom: `rgba(${rgb}, .5)`
  49. },{
  50. top: `rgba(${rgb}, .4)`,
  51. bottom: `rgba(${rgb}, .6)`
  52. },{
  53. top: `rgba(${rgb}, .4)`,
  54. bottom: `rgba(${rgb}, .7)`
  55. },{
  56. top: `rgba(${rgb}, .4)`,
  57. bottom: `rgba(${rgb}, .8)`
  58. },{
  59. top: `rgba(${rgb}, .4)`,
  60. bottom: `rgba(${rgb}, .9)`
  61. }]
  62. },
  63. pixelSize () {
  64. return this.unitpixel(this.size)
  65. }
  66. },
  67. data () {
  68. return {
  69. loading_binding: null
  70. }
  71. },
  72. mounted() {
  73. // #ifdef APP-NVUE
  74. this.$nextTick( function () {
  75. if ( this.visible ) this.start()
  76. })
  77. // #endif
  78. },
  79. beforeDestroy() {
  80. // #ifdef APP-NVUE
  81. if ( this.loading_binding ) {
  82. Binding.unbind({
  83. token: this.loading_binding.token,
  84. eventType: 'timing'
  85. })
  86. this.loading_binding = null
  87. }
  88. // #endif
  89. },
  90. methods: {
  91. start () {
  92. const loading = this.getEl(this.$refs.loading);
  93. this.loading_binding = Binding.bind({
  94. eventType: 'timing',
  95. props: [{
  96. element: loading,
  97. property: 'transform.rotateZ',
  98. expression: 'floor(t/100)*30'
  99. }]
  100. });
  101. },
  102. unitpixel (size) {
  103. const text = size.toString()
  104. return text.indexOf('rpx') > -1 ? uni.upx2px(text.replace('rpx', '')) : text.indexOf('px') > -1 ? parseFloat(text.replace('px', '')) : uni.upx2px(text)
  105. },
  106. hexToRgb (hex) {
  107. hex = hex.length == 7 ? hex : '#' + hex.slice(1, 4) + hex.slice(1, 4)
  108. let str="rgb("
  109. const r = parseInt(hex.slice(1,3),16).toString(); //ff slice不包括end
  110. const g = parseInt(hex.slice(3,5),16).toString(); //00
  111. const b = parseInt(hex.slice(5,7),16).toString(); //ff
  112. str += r+","+g+","+b+")";
  113. return str
  114. },
  115. getEl (el) {
  116. if (typeof el === 'string' || typeof el === 'number') return el;
  117. if (WXEnvironment) {
  118. return el.ref;
  119. } else {
  120. return el instanceof HTMLElement ? el : el.$el;
  121. }
  122. }
  123. },
  124. watch: {
  125. visible (newVal) {
  126. // #ifdef APP-NVUE
  127. this.$nextTick(() => {
  128. if ( newVal ) {
  129. this.start()
  130. } else {
  131. if ( this.loading_binding ) {
  132. Binding.unbind({
  133. token: this.loading_binding.token,
  134. eventType: 'timing'
  135. })
  136. this.loading_binding = null
  137. }
  138. }
  139. })
  140. // #endif
  141. }
  142. }
  143. }
  144. </script>
  145. <style scoped>
  146. /* #ifndef APP-NVUE */
  147. @keyframes loading{
  148. 0% {
  149. transform: rotateZ(30deg);
  150. }
  151. 9.33333%{
  152. transform: rotateZ(60deg);
  153. }
  154. 18.66666%{
  155. transform: rotateZ(90deg);
  156. }
  157. 27.99999%{
  158. transform: rotateZ(120deg);
  159. }
  160. 37.33332%{
  161. transform: rotateZ(150deg);
  162. }
  163. 46.66665%{
  164. transform: rotateZ(180deg);
  165. }
  166. 55.99998%{
  167. transform: rotateZ(210deg);
  168. }
  169. 65.33331%{
  170. transform: rotateZ(240deg);
  171. }
  172. 74.66664%{
  173. transform: rotateZ(270deg);
  174. }
  175. 83.99997%{
  176. transform: rotateZ(300deg);
  177. }
  178. 93.33333%{
  179. transform: rotateZ(330deg);
  180. }
  181. 100%{
  182. transform: rotateZ(360deg);
  183. }
  184. }
  185. /* #endif */
  186. .circle {
  187. position: relative;
  188. /* #ifndef APP-NVUE */
  189. animation: loading 1200ms step-start infinite;
  190. /* #endif */
  191. }
  192. .circle .line {
  193. position: absolute;
  194. border-top-style: solid;
  195. border-bottom-style: solid;
  196. top: 0;
  197. bottom: 0;
  198. }
  199. .circle .line_0 {
  200. }
  201. .circle .line_1 {
  202. transform: rotateZ(30deg);
  203. }
  204. .circle .line_2 {
  205. transform: rotateZ(60deg);
  206. }
  207. .circle .line_3 {
  208. transform: rotateZ(90deg);
  209. }
  210. .circle .line_4 {
  211. transform: rotateZ(120deg);
  212. }
  213. .circle .line_5 {
  214. transform: rotateZ(150deg);
  215. }
  216. </style>