<template>
  <view
    v-if="show"
    class="u-loading"
    :style="{
      width: size + 'rpx',
      height: size + 'rpx',
      '--color': color,
    }"
  >
    <!-- circle -->
    <view
      v-if="mode === 'circle'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
      :style="{
        borderWidth: Math.max(size * 0.08, 4) + 'rpx',
      }"
    ></view>

    <!-- flower -->
    <view
      v-else-if="mode === 'flower'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    ></view>

    <!-- plane -->
    <view
      v-else-if="mode === 'plane'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
      :style="{ backgroundColor: color }"
    ></view>

    <!-- sk-chase -->
    <view
      v-else-if="mode === 'sk-chase'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 6"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
      ></view>
    </view>

    <!-- sk-circle -->
    <view
      v-else-if="mode === 'sk-circle'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 12"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
      ></view>
    </view>

    <!-- sk-cube -->
    <view
      v-else-if="mode === 'sk-cube'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 9"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
      ></view>
    </view>

    <!-- sk-fade -->
    <view
      v-else-if="mode === 'sk-fade'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 12"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
      ></view>
    </view>

    <!-- sk-fold -->
    <view
      v-else-if="mode === 'sk-fold'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view class="dot dot1"></view>
      <view class="dot dot2"></view>
      <view class="dot dot4"></view>
      <view class="dot dot3"></view>
    </view>

    <!-- pulse -->
    <view
      v-else-if="mode === 'pulse'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
      :style="{ backgroundColor: color }"
    ></view>

    <!-- rect-bounce -->
    <view
      v-else-if="mode === 'rect-bounce'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 5"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
        :style="{ backgroundColor: color }"
      ></view>
    </view>

    <!-- double-bounce -->
    <view
      v-else-if="mode === 'double-bounce'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 2"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
        :style="{ backgroundColor: color }"
      ></view>
    </view>

    <!-- three-bounce -->
    <view
      v-else-if="mode === 'three-bounce'"
      class="u-loading__item"
      :class="'u-loading__' + mode"
    >
      <view
        v-for="(n, i) in 3"
        :key="i"
        class="dot"
        :class="'dot' + (i + 1)"
        :style="{ backgroundColor: color }"
      ></view>
    </view>
  </view>
</template>

<script>
/**
 * loading 加载动画
 * @description 此组件为一个小动画，目前用在uView的loadmore加载更多和switch开关等组件的正在加载状态场景。
 * @tutorial https://www.uviewui.com/components/loading.html
 * @property {String} mode 模式选择，见官网说明（默认circle）
 * @property {String} color 动画活动区域的颜色，只对 mode != flower 模式有效（默认#c7c7c7）
 * @property {String Number} size 加载图标的大小，单位rpx（默认34）
 * @property {Boolean} show 是否显示动画（默认true）
 * @example <u-loading mode="circle"></u-loading>
 */
export default {
  name: 'u-loading',
  props: {
    // 动画的类型
    mode: {
      type: String,
      default: 'circle',
      validator: (val) => {
        return [
          'circle',
          'flower',
          'plane',
          'sk-chase',
          'sk-circle',
          'sk-cube',
          'sk-fade',
          'sk-fold',
          'pulse',
          'rect-bounce',
          'double-bounce',
          'three-bounce',
        ].includes(val)
      },
    },
    // 动画的颜色
    color: {
      type: String,
      default: '#c7c7c7',
    },
    // 加载图标的大小，单位rpx
    size: {
      type: [String, Number],
      default: '34',
    },
    // 是否显示动画
    show: {
      type: Boolean,
      default: true,
    },
  },
}
</script>

<style lang="scss" scoped>
@import '../../libs/css/style.components.scss';

.u-loading {
  position: relative;
  /* #ifndef APP-NVUE */
  display: inline-flex;
  /* #endif */
  align-items: center;
  justify-content: center;
  vertical-align: middle;
}

.u-loading__item {
  width: 100%;
  height: 100%;
  position: relative;
}

// circle
.u-loading__circle {
  border-radius: 50%;
  border: 2px solid;
  // border-color: #e5e5e5 #e5e5e5 #e5e5e5 #8f8d8e;
  border-color: #e4e4e4 #e4e4e4 #e4e4e4 var(--color);
  animation: u-circle 1s linear infinite;
}
@keyframes u-circle {
  0% {
    transform: rotate(0);
  }

  100% {
    transform: rotate(360deg);
  }
}

// flower
.u-loading__flower {
  animation: u-flower 1s steps(12) infinite;
  background: transparent
    url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=')
    no-repeat;
  background-size: 100%;
}
@keyframes u-flower {
  0% {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(1turn);
  }
}

// plane
.u-loading__plane {
  animation: u-plane 1.5s infinite ease-in-out;
}
@keyframes u-plane {
  0% {
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
  }
  50% {
    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
  }
  100% {
    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
  }
}

// sk-chase
.u-loading__sk-chase {
  width: 80%;
  height: 80%;
  animation: u-sk-chase 2.5s infinite linear both;
}
.u-loading__sk-chase .dot {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  animation: u-sk-chase-dot 2s infinite ease-in-out both;
}
.u-loading__sk-chase .dot:before {
  content: ' ';
  display: block;
  width: 25%;
  height: 25%;
  background-color: var(--color);
  border-radius: 100%;
  overflow: hidden;
  animation: u-sk-chase-dot-before 2s infinite ease-in-out both;
}
@for $i from 1 through 6 {
  .u-loading__sk-chase .dot#{$i} {
    animation-delay: -1.1s + ($i - 1) * 0.1;
  }
  .u-loading__sk-chase .dot#{$i}:before {
    animation-delay: -1.1s + ($i - 1) * 0.1;
  }
}
@keyframes u-sk-chase {
  100% {
    transform: rotate(360deg);
  }
}
@keyframes u-sk-chase-dot {
  80%,
  100% {
    transform: rotate(360deg);
  }
}
@keyframes u-sk-chase-dot-before {
  50% {
    transform: scale(0.4);
  }
  100%,
  0% {
    transform: scale(1);
  }
}

// sk-circle
.u-loading__sk-circle .dot {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
.u-loading__sk-circle .dot:before {
  content: '';
  display: block;
  margin: 0 auto;
  width: 15%;
  height: 15%;
  background-color: var(--color);
  border-radius: 100%;
  animation: u-sk-circle 1.2s infinite ease-in-out both;
}
@for $i from 2 through 12 {
  .u-loading__sk-circle .dot#{$i} {
    transform: rotate(#{($i - 1) * 30}deg);
  }
  .u-loading__sk-circle .dot#{$i}:before {
    animation-delay: -1.1s + ($i - 2) * 0.1;
  }
}
@keyframes u-sk-circle {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}

// sk-cube
.u-loading__sk-cube .dot {
  width: 33%;
  height: 33%;
  background-color: var(--color);
  float: left;
  animation: u-sk-cube 1.3s infinite ease-in-out;
}
@for $i from 1 through 9 {
  .u-loading__sk-cube .dot#{$i} {
    animation-delay: 0.2s -
      floor(($i - 1) / 3) *
      0.1 +
      floor(($i - 1) % 3) *
      0.1;
  }
}
@keyframes u-sk-cube {
  0%,
  70%,
  100% {
    transform: scale3D(1, 1, 1);
  }
  35% {
    transform: scale3D(0, 0, 1);
  }
}

// sk-fade
.u-loading__sk-fade {
  animation: sk-fade 10s infinite linear both;
}
.u-loading__sk-fade .dot {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
}
.u-loading__sk-fade .dot:before {
  content: '';
  display: block;
  margin: 0 auto;
  width: 15%;
  height: 15%;
  background-color: var(--color);
  border-radius: 100%;
  animation: sk-fade-dot 1.2s infinite ease-in-out both;
}
@for $i from 2 through 12 {
  .u-loading__sk-fade .dot#{$i} {
    transform: rotate(#{($i - 1) * 30}deg);
  }
  .u-loading__sk-fade .dot#{$i}:before {
    animation-delay: -1.1s + ($i - 2) * 0.1;
  }
}
@keyframes sk-fade {
  100% {
    transform: rotate(360deg);
  }
}
@keyframes sk-fade-dot {
  0%,
  39%,
  100% {
    opacity: 0;
  }
  40% {
    opacity: 1;
  }
}

// sk-fold
.u-loading__sk-fold {
  transform: rotateZ(45deg) scale(0.68);
}
.u-loading__sk-fold .dot {
  float: left;
  width: 50%;
  height: 50%;
  position: relative;
  transform: scale(1.1);
}
.u-loading__sk-fold .dot:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: var(--color);
  animation: sk-fold 2.4s infinite linear both;
  transform-origin: 100% 100%;
}
@for $i from 2 through 4 {
  .u-loading__sk-fold .dot#{$i} {
    transform: scale(1.1) rotateZ(#{($i - 1) * 90}deg);
  }
  .u-loading__sk-fold .dot#{$i}:before {
    animation-delay: ($i - 1) * 0.3s;
  }
}
@keyframes sk-fold {
  0%,
  10% {
    transform: perspective(140px) rotateX(-180deg);
    opacity: 0;
  }
  25%,
  75% {
    transform: perspective(140px) rotateX(0deg);
    opacity: 1;
  }
  90%,
  100% {
    transform: perspective(140px) rotateY(180deg);
    opacity: 0;
  }
}

// pulse
.u-loading__pulse {
  border-radius: 100%;
  animation: pulse 1s infinite ease-in-out;
}
@keyframes pulse {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

// rect-bounce
.u-loading__rect-bounce {
  text-align: center;
}
.u-loading__rect-bounce .dot {
  height: 100%;
  width: 10%;
  display: inline-block;
  animation: rect-bounce 1.2s infinite ease-in-out;
  margin-right: 6%;
}
.u-loading__rect-bounce .dot:last-child {
  margin-right: 0;
}
@for $i from 2 through 5 {
  .u-loading__rect-bounce .dot#{$i} {
    animation-delay: -1.1s + ($i - 2) * 0.1;
  }
}
@keyframes rect-bounce {
  0%,
  40%,
  100% {
    transform: scaleY(0.45);
  }
  20% {
    transform: scaleY(1);
  }
}

// double-bounce
.u-loading__double-bounce .dot {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  opacity: 0.6;
  position: absolute;
  top: 0;
  left: 0;
  animation: double-bounce 2s infinite ease-in-out;
}
.u-loading__double-bounce .dot2 {
  animation-delay: -1s;
}
@keyframes double-bounce {
  0%,
  100% {
    transform: scale(0);
  }
  50% {
    transform: scale(1);
  }
}

// three-bounce
.u-loading__three-bounce {
  /* #ifndef APP-NVUE */
  display: flex;
  /* #endif */
  align-items: center;
  justify-content: center;
}

.u-loading__three-bounce .dot {
  width: 30%;
  height: 30%;
  border-radius: 100%;
  margin-right: 8%;
  animation: three-bounce 1.4s infinite ease-in-out both;
}
.u-loading__three-bounce .dot:last-child {
  margin-right: 0;
}
@for $i from 1 through 3 {
  .u-loading__three-bounce .dot#{$i} {
    animation-delay: -0.32s + ($i - 1) * 0.16;
  }
}
@keyframes three-bounce {
  0%,
  80%,
  100% {
    transform: scale(0);
  }
  40% {
    transform: scale(1);
  }
}
</style>
