<div id="screen" class="loading-screen">
    <svg
      width="100%"
      height="100vh"
      viewBox="0 0 415 1261"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      id="mjb-logo-ani"
    >
      <path
        id="keystone"
        d="M234.07 15.29L224.77 31.99L215.46 48.71C214.626 50.2488 213.392 51.5338 211.888 52.4292C210.384 53.3247 208.666 53.7973 206.915 53.7973C205.165 53.7973 203.447 53.3247 201.943 52.4292C200.439 51.5338 199.204 50.2488 198.37 48.71L189.07 31.99L179.76 15.27C178.888 13.7119 178.43 11.9558 178.43 10.17C178.32 4.82998 182.87 -0.140026 188.31 -0.0200262H225.63C227.364 -0.002113 229.062 0.480466 230.547 1.37744C232.031 2.27442 233.248 3.55298 234.07 5.07997C234.949 6.63787 235.411 8.39628 235.411 10.185C235.411 11.9737 234.949 13.7321 234.07 15.29V15.29Z"
        fill="#7A35BC"
      />
      <!-- PURPLE OUTLINE -->
      <path
        class="purple-stroke"
        id="outer-right-purple"
        d="M253 25.78C336.18 44.54 399.52 123.11 402.52 208.1C402.52 228.95 402.52 536.22 402.52 548.9"
        stroke-width="23"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="purple-stroke"
        id="outer-left-purple"
        d="M11.52 548.9V210.04C13.61 124.31 77.15 44.63 161 25.72"
        stroke-width="23"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="purple-stroke"
        id="outer-bottom-purple"
        d="M18.52 526.99H395.51"
        stroke-width="23"
        stroke-miterlimit="10"
      />
      <path
        class="inner-purple purple-stroke"
        id="inner-left-purple"
        d="M48.4199 211.64C50.5199 136.35 107.87 70.49 182.13 59.3"
        stroke-width="20"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="inner-purple purple-stroke"
        id="inner-right-purple"
        d="M364.62 211.64C362.52 136.35 305.17 70.49 230.91 59.3"
        stroke-width="20"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="purple-stroke"
        id="dome-purple"
        fill-rule="evenodd"
        clip-rule="evenodd"
        d="M206.62 87.41C136.2 86.41 76.9901 148.8 79.9901 218.99H333.28C335.73 147.99 277.91 86.99 206.62 87.41Z"
        stroke-width="5"
        stroke-linejoin="round"
      />
      <!-- WHITE OUTLINE -->
      <path
        class="white-stroke"
        id="outer-bottom-white"
        d="M18.52 526.99H395.51"
        stroke-width="23"
        stroke-miterlimit="10"
      />
      <path
        class="white-stroke"
        id="dome-white"
        fill-rule="evenodd"
        clip-rule="evenodd"
        d="M206.62 87.41C136.2 86.41 76.9901 148.8 79.9901 218.99H333.28C335.73 147.99 277.91 86.99 206.62 87.41Z"
        stroke-width="5"
        stroke-linejoin="round"
      />
      <path
        class="white-stroke"
        id="outer-right-white"
        d="M253 25.78C336.18 44.54 399.52 123.11 402.52 208.1C402.52 228.95 402.52 536.22 402.52 548.9"
        stroke-width="23"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="white-stroke"
        id="outer-left-white"
        d="M11.52 548.9V210.04C13.61 124.31 77.15 44.63 161 25.72"
        stroke-width="23"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="inner-white white-stroke"
        id="inner-left-white"
        d="M48.4199 211.64C50.5199 136.35 107.87 70.49 182.13 59.3"
        stroke-width="20"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
      <path
        class="inner-white white-stroke"
        id="inner-right-white"
        d="M364.62 211.64C362.52 136.35 305.17 70.49 230.91 59.3"
        stroke-width="20"
        stroke-miterlimit="10"
        stroke-linecap="round"
      />
    </svg>


</div>
h1 {
  color: white;
  font-family: sans-serif;
  text-align: center;
  position: fixed;
  top: 0;
width: 100%;
  margin: 0 auto;
}
.white-stroke {
  stroke: #fdfdfd;
}
.purple-stroke {
  stroke: #7a35bc;
}
svg.static {
  margin-top: 10vh;
}
body {
  min-height: 100vh;
  width: 100%;
  background-color: #2a183c;
  color: #fff;
  margin:0;
}
Vue.createApp({
  name: "LogoLoader",
  props: {
    onLoaded: Function,
  },
  data() {
    return {
      loaded: true,
      viewBox: { x: 200, y: 0, width: 415, height: 561 + 700 },
      viewBoxString: `-${415 / 2} ${0} ${415 + 0} ${561 + 700}`,
      reduceMotion: window.matchMedia("(prefers-reduced-motion: reduce)")
        .matches,
    };
  },
  watch: {
    loaded(val) {
      if (val && this.reduceMotion) setTimeout(this.onLoaded, 1000);
    },
  },
  mounted() {
    if (!this.reduceMotion) {
      var firstRepeat = false;
      const timeline = gsap.timeline({
        delay: 0.5,
        defaults: {
          y: this.viewBox.height * 0.05,
          transformOrigin: "50% 50%",
        },
        onComplete: () => {
          if (this.loaded && firstRepeat) {
            finish.play();
          } else {
            firstRepeat = true;
            gsap.delayedCall(0, () => timeline.play("loading"));
          }
        },
      });
      timeline
        // Scale and Move the keystone into place
        .from("#keystone", { scale: 50 }, "opening")
        .fromTo(
          "#keystone",
          { opacity: 0, y: this.viewBox.height },
          {
            opacity: 1,
            duration: 1.2,
            ease: "elastic.out(0.9, 0.5)",
          },
          "<"
        )
        // Make the keystone "glow"
        .to(
          "#keystone",
          { fill: "#CF9DFF", duration: 0.4, ease: "power2.in" },
          ">-0.25"
        )
        // Fade in the purple outline of the jukebox
        .fromTo(
          ".purple-stroke",
          { opacity: 0 },
          { opacity: 1, duration: 0.85, ease: "power2.out" },
          ">-0.5"
        )
        // Begin "loading animation"
        .addLabel("loading", ">")
        // Stroke the outers white
        .fromTo(
          "#outer-right-white",
          { drawSVG: "0%" },
          { drawSVG: "35% 75%", duration: 0.5, ease: "power3.in" },
          "loading"
        )
        .to(
          "#outer-right-white",
          { drawSVG: "100% 100%", ease: "sine.out" },
          ">"
        )
        .fromTo(
          "#outer-left-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "75% 35%", duration: 0.5, ease: "power3.in" },
          "loading+=0.2"
        )
        .to("#outer-left-white", { drawSVG: "0", ease: "sine.out" }, ">")
        // Stroke the inners white
        .fromTo(
          "#inner-left-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "85% 25%", duration: 0.5, ease: "power3.in" },
          "loading+=0.6"
        )
        .to("#inner-left-white", { drawSVG: "0", ease: "sine.out" }, ">")
        .fromTo(
          "#inner-right-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "85% 25%", duration: 0.5, ease: "power3.in" },
          "loading+=0.4"
        )
        .to("#inner-right-white", { drawSVG: "0", ease: "sine.out" }, ">")
        // Stroke bottom and dome
        .fromTo(
          "#dome-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "85% 25%", duration: 0.5, ease: "power3.in" },
          "loading+=0.7"
        )
        .to("#dome-white", { drawSVG: "0", ease: "sine.out" }, ">")
        .fromTo(
          "#outer-bottom-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "85% 25%", duration: 0.5, ease: "power3.in" },
          "loading+=0.4"
        )
        .to("#outer-bottom-white", { drawSVG: "0", ease: "sine.out" }, ">");

      const finish = gsap
        .timeline({
          paused: true,
          onComplete: this.onLoaded,
        })
        .fromTo(
          "#outer-right-white",
          { drawSVG: "0" },
          { drawSVG: "100%", duration: 1.5, ease: "power3.inOut" },
          ">-0.25"
        )
        .fromTo(
          "#outer-left-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "100%", duration: 1.5, ease: "power3.inOut" },
          "<"
        )
        .fromTo(
          ".inner-white",
          { drawSVG: "100% 100%" },
          { drawSVG: "100%", duration: 1, ease: "power3.inOut" },
          ">-0.85"
        )
        .fromTo(
          "#outer-bottom-white",
          { drawSVG: "50% 50%" },
          { drawSVG: "100%", duration: 1, ease: "power3.inOut" },
          "<"
        )
        .fromTo(
          "#dome-white",
          { drawSVG: "50% 50%" },
          { drawSVG: "100%", duration: 0.75, ease: "power3.inOut" },
          ">-0.75"
        )
        .to(
          "#keystone",
          { fill: "#7A35BC", duration: 0.8, ease: "power2.out" },
          ">-0.1"
        );
    } else {
      document.getElementById("mjb-logo-ani").classList += "static";
    }
  }
}).mount("#screen")

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.co/gsap@3/dist/gsap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js
  3. https://assets.codepen.io/16327/CustomEase3.min.js
  4. https://assets.codepen.io/16327/DrawSVGPlugin3.min.js
  5. https://unpkg.com/vue@next