October 22, 2024
Chicago 12, Melborne City, USA
HTML

Spring animation is causing ellipsis element to clip


I have a crosshair component in Vue that has a scan animation triggered when its state changes to scan. The problem is that when the ellipsis in the svg containing the scan animation scales above 1, it starts clipping. I’d like the prevent that. It doesn’t clip if I remove mask='url(#mask0_0_1)' on the g element but then I lose the mask, which I need.

Crosshair.vue

<script setup lang="ts">
enum crosshairState {
  Default,
  Pulse,
  Scan
}
withDefaults(defineProps<{
  state?: crosshairState
  warningColors?: boolean
}>(), {
  state: crosshairState.Default
})
</script>

<template>
  <svg :class="{'hide': state === crosshairState.Scan}" width="400" height="338" viewBox="0 0 400 338" fill="none" xmlns="http://www.w3.org/2000/svg" style="overflow: visible;" preserveAspectRatio="xMidYMid meet">
      <mask id="mask0_0_1" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="400" height="338">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M400 0H0V338H400V0ZM200.076 240.1C232.991 240.1 261.381 223.28 274.462 199H395V140H275.147C262.391 115.02 233.577 97.5947 200.076 97.5947C154.747 97.5947 118 129.496 118 168.848C118 208.199 154.747 240.1 200.076 240.1Z" fill="#D9D9D9"/>
      </mask>
      <g mask='url(#mask0_0_1)' style="overflow: visible;">
          <ellipse v-if="state === crosshairState.Scan" cx="218.674" cy="169.497" rx="171.674" ry="148.497" fill="none" opacity="0.5" stroke-width="2" :stroke="warningColors ? '#C02A4F' : '#95F39B'"/>
          <ellipse :class="{'pulse' : state === crosshairState.Pulse, 'scan': state === crosshairState.Scan, 'opacity-40': warningColors }" cx="218.674" cy="169.497" rx="171.674" ry="148.497" :fill="warningColors ? '#C02A4F' : '#95F39B'"/>
      </g>
      <path d="M275.299 140.3C262.621 115.16 233.711 97.5947 200.076 97.5947C154.747 97.5947 118 129.496 118 168.848C118 208.199 154.747 240.1 200.076 240.1C233.122 240.1 261.607 223.146 274.618 198.71" :stroke="warningColors ? '#C02A4F' : '#58C160'" stroke-width="8" stroke-linecap="round" stroke-linejoin="round"/>
      <rect :class="{'rect-pulse' : state === crosshairState.Pulse, 'rect-scan' : state === crosshairState.Scan}" x="271.3" y="136.3" width="119" height="8" rx="4" :fill="warningColors ? '#C02A4F' : '#58C160'"/>
      <rect :class="{'rect-pulse' : state === crosshairState.Pulse, 'rect-scan' : state === crosshairState.Scan}" x="271.3" y="194.71" width="119" height="8" rx="4" :fill="warningColors ? '#C02A4F' : '#58C160'"/>
  </svg>
</template>

<style>
  @keyframes pulseAnimation {
    0%, 100% {
      opacity: 0;
      rx: 0px;
      ry: 0px;
    }
    50% {
      opacity: 1;
      rx: 171.674px;
      ry: 148.497px;
    }
  }
  @keyframes rectPulseAnimation {
    0%, 100% {
      width: 0px;
    }
    50% {
        width: 119px;
    }
}
  @keyframes scanAnimation {
    0% {
      transform: scale(0);
      opacity: 0;
      fill: #95F39B;
    }
    50% {
      transform: scale(1);
      opacity: 1;
      fill: #95F39B;
    }
    85% {
      transform: scale(1.3);
      fill: white;
    }
    100% {
      transform: scale(1);
      fill: #95F39B;
    }
  }
  @keyframes rectScanAnimation {
    0% {
        width: 0px;
    }
    75% {
        width: 125px;
    }
    100% {
        width: 119px;
    }
  }
  @keyframes hide {
    0% {
        opacity: 1
    }
    100% {
        opacity: 0;
    }
  }
  .pulse {
    animation: pulseAnimation 1.5s infinite ease-in-out;
    transform-origin: center;
  }
  .rect-pulse {
    animation: rectPulseAnimation 1.5s infinite;
  }
  .scan {
    animation: scanAnimation 3s ease forwards;
    transform-origin: center;
  }
  .rect-scan {
    animation: rectScanAnimation 3s ease forwards;
    transform-origin: center;
  }
  .hide {
    animation: hide 0.5s forwards;
    animation-delay: 3.5s;
  }
</style>

Test.vue

<script setup lang="ts">
const s = ref(1)
</script>

<template>
    <button @click="s=2">CLICK ME</button>
    <div class="fixed flex h-screen w-screen items-center justify-center">
        <CerameterCrosshair :state="s"/>
    </div>
</template>



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video