Frontend Development 11 min read

Implementing Entry Animations and Seamless Scrolling in a Vue 3 Big‑Screen Visualization Project

This article demonstrates how to add entry animations and implement seamless horizontal and vertical scrolling in a Vue 3‑based big‑screen visualization project using ECharts, Gaode map, Pinia, CSS keyframes, and the animejs library, with complete code examples and component packaging.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Implementing Entry Animations and Seamless Scrolling in a Vue 3 Big‑Screen Visualization Project

This tutorial describes a big‑screen visualization project built with Vue 3, ECharts, Gaode map, and Pinia, providing features such as screen adaptation, chart component encapsulation, map component encapsulation, drag‑drop layout, entry animations, and seamless scrolling.

Screen adaptation

Chart component (ECharts) encapsulation

Gaode map component encapsulation

Drag‑drop layout

Entry animations

Seamless scrolling

Source code: https://github.com/vangleer/es-big-screen

Online demo: https://vangleer.github.io/es-big-screen/#/screen

Preface

The previous article covered screen adaptation, chart component encapsulation, drag‑drop layout, and map component encapsulation. This post focuses on implementing entry animations and seamless scrolling.

Entry Animations

Final effect demonstration (image omitted)

Header Animation

File: src/views/screen/components/Header.vue – a simple fade‑in animation.

.es-screen-header {
  animation: fade 3s;
}
@keyframes fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

Left Side Animation

File: src/views/screen/components/left/index.vue

.es-screen-left-item {
  /* ... */
  &:nth-child(1) { height: 550px; animation-duration: .8s; }
  &:nth-child(2) { animation-duration: 1.5s; }
}
@keyframes slide {
  0%   { transform: translateX(-100%); }
  80%  { transform: translateX(20px); }
  100% { transform: translateX(0); }
}

The left side defines a slide‑in animation that starts from -100% and bounces to the final position.

Right Side Animation

File: src/views/screen/components/right/index.vue

.es-screen-right-item {
  /* ... */
  animation-name: slide;
  &:nth-child(1) { animation-duration: 0.5s; }
  &:nth-child(2) { animation-duration: 1s; }
  &:nth-child(3) { animation-duration: 1.5s; }
}
@keyframes slide {
  0%   { transform: translateX(100%); }
  80%  { transform: translateX(-20px); }
  100% { transform: translateX(0); }
}

The right side uses the same keyframes but moves in the opposite direction.

Center Map Entry Animation

File: src/views/screen/components/center/index.vue

.es-center {
  animation: slideAndFade 1.5s;
}
@keyframes slideAndFade {
  0% { transform: translateY(218px); opacity: 0; }
  100% { transform: translateX(0); opacity: 1; }
}

The map slides up from the bottom while fading in.

Seamless Scrolling Component

Seamless scrolling is common in big‑screen dashboards. The following custom hook uses animejs to create a reusable horizontal/vertical scrolling solution.

Install the dependency:

yarn add animejs

Hook implementation ( useSeamlessScroll ) – full code kept intact:

import { onMounted, shallowRef, Ref } from 'vue'
import anime from 'animejs/lib/anime.es.js'

export type OptionsType = {
  direction?: 'horizontal' | 'vertical'
  gap?: number
  duration?: number
}

export function useSeamlessScroll(listRef: Ref
, options: OptionsType = {}) {
  const { direction = 'horizontal', gap = 10, duration = 10000 } = options
  const animation = shallowRef
>(null)

  function init() {
    const isHorizontal = direction === 'horizontal'
    const translateKey = isHorizontal ? 'translateX' : 'translateY'
    const transKey = isHorizontal ? 'x' : 'y'
    const children = listRef.value?.children || []
    if (!children.length) return
    const firstEl = children[0] as HTMLElement
    const firstDiff = (isHorizontal ? firstEl.offsetWidth : firstEl.offsetHeight) + gap
    listRef.value!.style.transform = `${translateKey}(-${firstDiff}px)`
    const transList: any[] = []
    let total = 0
    anime.set(children, {
      [translateKey]: (el: HTMLElement, i) => {
        const distance = (isHorizontal ? el.offsetWidth : el.offsetHeight) + gap
        total += distance
        transList[i] = { [transKey]: total - distance }
      }
    })
    listRef.value!.style[isHorizontal ? 'width' : 'height'] = total + 'px'
    animation.value = anime({
      targets: transList,
      duration,
      easing: 'linear',
      direction: isHorizontal ? undefined : 'reverse',
      [transKey]: `+=${total}`,
      loop: true,
      update: () => {
        anime.set(children, {
          [translateKey]: (el, i) => transList[i][transKey] % total
        })
      }
    })
  }
  function pause() { animation.value!.pause() }
  function play() { animation.value!.play() }
  onMounted(() => { init() })
  return { listRef, pause, play, animation }
}

The hook accepts a listRef (a Vue Ref pointing to the scrolling container) and an optional options object to configure direction, gap, and duration.

Using the Hook

<template>
  <div class="es-center-bottom">
    <div ref="listRef" class="es-bottom-list">
      <div v-for="item in 10" class="es-bottom-item">{{ item }}</div>
    </div>
  </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue'
import { useSeamlessScroll } from '@/utils/useSeamlessScroll'

const listRef = ref()
useSeamlessScroll(listRef)
</script>

<style scoped lang='scss'>
.es-center-bottom { position: relative; width: 100%; overflow: hidden; height: 150px; }
.es-bottom-item { position: absolute; top: 0; left: 0; width: 170px; height: 150px; display: flex; flex-direction: column; justify-content: center; align-items: center; background-color: var(--es-block-bg); font-size: 22px; font-weight: 600; }
</style>

The component version simplifies usage:

<template>
  <SeamlessScroll class="es-center-bottom">
    <div v-for="item in 10" class="es-bottom-item">{{ item }}</div>
  </SeamlessScroll>
</template>

<script setup lang='ts'>
import SeamlessScroll from '@/components/SeamlessScroll.vue'
</script>

By default the component scrolls horizontally; set :option="{ direction: 'vertical' }" for vertical scrolling.

Conclusion

The article covered the implementation of entry animations and seamless scrolling, providing reusable code and component wrappers that can be customized for any big‑screen Vue project.

For more details, explore the GitHub repository and the online demo links provided above.

frontendcomponentVueCSS animationAnimejsSeamless Scroll
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.