All files / src/components/Spinner/variants PulseDots.vue

100% Statements 11/11
100% Branches 2/2
100% Functions 4/4
100% Lines 9/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89                    25x           25x 25x   25x 25x 25x         24x               72x 73x                                                                                                          
<script setup lang="ts">
import { computed } from 'vue'
import { scaleSize, toCssSize } from '../../../utils/size'
 
interface Props {
  size?: number | string
  color?: string
  speed?: number
}
 
const props = withDefaults(defineProps<Props>(), {
  size: 40,
  color: 'currentColor',
  speed: 1,
})
 
const boxSize = computed(() => toCssSize(props.size))
const dotSize = computed(() => scaleSize(props.size, '/', 5))
 
const duration = computed(() => {
  const speed = props.speed > 0 ? props.speed : 1
  return 1 / speed
})
</script>
 
<template>
  <div
    class="vslk-pulse-orbit"
    :style="{
      width: boxSize,
      height: boxSize,
      color: props.color,
    }"
  >
    <span
      v-for="i in 3"
      :key="i"
      class="dot"
      :style="{
        width: dotSize,
        height: dotSize,
        backgroundColor: props.color,
        animationDuration: duration + 's',
        animationDelay: ((i - 1) * duration / 3) + 's'
      }"
    />
  </div>
</template>
 
<style scoped>
.vslk-pulse-orbit {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16%;
}
 
/* سه نقطه روی یک خط افقی، با فاصله نسبی */
.dot {
  flex: 0 0 auto;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  transform-origin: center;
  animation-name: vslk-pulse-orbit-pulse;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  will-change: transform;
}
 
@keyframes vslk-pulse-orbit-pulse {
  0% {
    transform: translateY(-25%) scale(0.7);
    opacity: 0.5;
  }
  35% {
    transform: translateY(10%) scale(1.35);
    opacity: 1;
  }
  60% {
    transform: translateY(10%) scale(1.35);
    opacity: 1;
  }
  100% {
    transform: translateY(-25%) scale(0.7);
    opacity: 0.5;
  }
}
</style>