高效开发大屏可视化项目第二弹:入场动画和无缝滚动

2023-11-05

这是一个基于Vue 3、Echarts、高德地图和Pinia开发的大屏可视化项目,提供了如下功能

  • 大屏适配
  • 图表组件(Echarts)封装
  • 高德地图组件封装
  • 拖拽布局
  • 入场动画
  • 无缝滚动

源码地址

在线示例

前言

上一篇文章分享了大屏适配、图表组件(Echarts)封装、拖拽布局以及地图组件等功能的封装

高效开发大屏可视化项目:公共组件封装指南

今天主要分享大屏入场动画和无缝滚动相关功能的实现

入场动画

  • 最终效果展示

06.gif

主要使用了CSS动画

Header 动画

src/views/screen/components/Header.vue 一个简单的淡入动画

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

Left 左侧动画

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);
  }
}

左侧定义一个滑入动画,从左侧-100%进入到20px最后回到0原来的位置,这样定义会有一个弹的效果

Right 右侧动画

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);
  }
}

与左侧类似,只是方向变了

Center 中间地图入场动画

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;
  }
}

从下往上移动,移动的同时淡入显示

无缝滚动封装

无缝滚动在大屏可视化项目中非常常见,本小节使用animejs实现了一个支持横纵无缝滚动的自定义钩子

先安装一下 animejs 的依赖

yarn add animejs

直接上代码

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<HTMLElement | null>, options: OptionsType = {}) {
	const {
		direction = 'horizontal',
		gap = 10,
		duration = 10000
	} = options
	const animation = shallowRef<ReturnType<typeof anime>>(null)

	function init() {
		const isHorizontal = direction === 'horizontal'

		const translateKey = isHorizontal ? 'translateX' : 'translateY'

		const transKey = isHorizontal ? 'x' : 'y'

		// items
		const children = listRef.value?.children || []
		if (!children.length) return

		// 第一个元素
		const firstEl =  children[0] as HTMLElement
		const firstDiff = (isHorizontal ? firstEl.offsetWidth : firstEl.offsetHeight ) + gap

		// 默认将list元素向左或向上移动一个item的距离
		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

				const diff = (i - 1) * distance
				transList[i] = { [transKey]: diff }
				return diff
			}
		})
		// 设置list容器的宽或高
		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) => {
						return transList[i][transKey] % total
					}
				})
			}
		})
	}
	// 暂停
	function pause() {
		animation.value!.pause()
	}
	// 停止
	function play() {
		animation.value!.play()
	}

	onMounted(() => {
		init()
	})

	return {
		listRef,
		pause,
		play,
		animation
	}
}

useSeamlessScroll 接受两个参数:listRefoptionslistRef 是一个 Ref 对象,用于引用滚动列表的 DOM 元素。options 是一个配置对象,可以设置滚动的方向、间隙和持续时间。

步骤解析:

  1. 根据传入的滚动方向,确定 translateKeytransKeytranslateKey 表示 CSS 中的移动方向,transKey 表示animejs中的x/y轴方向。

  2. 获取滚动列表的子元素,并计算第一个元素的偏移量。因为默认从从第二个元素开始,这样初始移动是才不会出现空白

  3. 初始化滚动列表的位置,将其向左(横向滚动)或向上(纵向滚动)移动一个元素的距离。

  4. 遍历子元素,计算每个元素的偏移量,并将其设置为初始位置。

  5. 根据滚动方向,设置滚动列表容器的宽度或高度。

  6. 使用 animejs 库实现无缝滚动效果,在动画更新时,根据计算出的偏移量更新子元素的位置

使用 useSeamlessScroll

<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 lang='scss' scoped>
.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;
		.es-item-text {
                    margin-top: 16px;
                }
	}
}
</style>

可以看到用了两层包裹列表,最外面一层的作用是防止溢出,第二层才是偏移的列表元素

08.gif

抽离成组件简化使用方式

新建 src/components/SeamlessScroll.vue

<template>
	<div class="es-seamless-scroll">
		<div ref="listRef" class="es-seamless-scroll-list">
			<slot />
		</div>
	</div>
</template>

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

const props = defineProps({
	width: {
		type: [String, Number]
	},
	height: {
		type: [String, Number]
	},
	option: {
            type: Object as PropType<OptionsType>,
            default: () => ({})
	}
})
const listRef = ref()
useSeamlessScroll(listRef, props.option)

</script>

<style lang='scss' scoped>
.es-seamless-scroll {
	overflow: hidden;
	width: 100%;
	height: 100%;
}
</style>

使用组件

<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>

<style lang='scss' scoped>
.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;
		.es-item-text {
      margin-top: 16px;
    }
	}
}
</style>

效果和直接使用钩子一样,不过组件使用起来还是要简单一点

  • 组件默认是横向滚动,如果想纵向滚动传入direction为vertical即可
<template>
	<SeamlessScroll class="es-list" :option="{ direction: 'vertical' }">
		<div v-for="item in 15" class="es-item">{{ '热销商品的占比 ' + item }}</div>
	</SeamlessScroll>
</template>

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

</script>

<style lang='scss' scoped>
.es-list {
	position: relative;
	width: 100%;
	height: 100%;
	overflow: hidden;
	.es-item {
		position: absolute;
		height: 20px;
	}
}
</style>

09.gif

最后

本文介绍了入场动画和无缝滚动方面的实现,你可以根据示例代码进行实践和定制

如果你对该项目模板感兴趣,可以通过源码地址和在线示例链接来获取更多信息,并进行进一步的学习和应用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

高效开发大屏可视化项目第二弹:入场动画和无缝滚动 的相关文章

随机推荐

  • 实验6 Sniffer网络安全检测

    实验6 Sniffer网络安全检测 实验目的 实验环境与设备 实验要求 过程如下 实验目的 掌握利用Sniffer软件捕获网络信息数据包 同时通过数据包的分层解析 进行状态分析 掌握网络安全检测工具的实际操作方法 完成检测报告 并写出结论
  • powershell cs-UTF-16LE编码上线

    0x01前言 当我们要上线主机的时候 可能会因为你的代码含有木马字符串 导致无法上线 0x02问题 1 例子 powershell exe exec bypass encodedCommand ZQBjAGgAbwAgACIAMQAyADM
  • Limited access In Sharepoint 2010

    When a security principal is added to the scope of an item with unique permissions the security principal is immediately
  • css穿透(带案例详解)

    问题背景 在使用vue构建项目的时候 引用了第三方组件库 只需要在当前页面修改第三方组件库的样式 以做到不污染全局样式 通过在样式标签上使用scoped 达到样式只作用到本页面的目的 但是此时再修改组件样式就不起作用了 div class
  • qt creator中Q_OBJECT导致出现undefined reference to vtable for 的错误

    在qt creator中新建了一个c 的类 刚开始编译可以通过 后来不知道为什么突然就编译报错 出现了undefined reference to vtable for 的错误 一开始以为是语法错误 结果找了很久都没有找到错误 后来发现把该
  • 构建SOA架构(笔记)

    1 什么是SOA架构设计师与设计和开发人员之间的差别呢 相信这些都是使大家最容易产生迷惑的问题 举个实际的例子来说 当构建一个基于SOA架构的系统的时候 针对一个具体的 service 系统设计人员主要应该关注的是这个service能够为外
  • Android uiautomatorviewer无法启动

    Android uiautomatorviewer无法启动 uiautomatorviewer 是android sdk提供的用来抓取布局的工具 然而有时候会出现无法启动 点击闪退的现象 先说原因 JDK版本高于java8 google 没
  • 异常org.hibernate.HibernateException: The database returned no natively generated identity解决方案

    配置文件
  • php 优化代码教程,PHP代码性能优化的技巧讲解_PHP教程

    PHP代码性能优化1 不要随便就复制变量 有时候为了使 PHP 代码更加整洁 一些 PHP 新手 包括我 会把预定义好的变量复制到一个名字更简短的变量中 其实这样做的结果是增加了一倍的内存消耗 只会使程序更加慢 试想一下 在下面的例子中 如
  • 使用py2neo创建知识图谱报错The following settings are not supported:{‘http_port‘:7474}

    今天在运行创建知识图谱的代码时 报以下错 The following settings are not supported http port 7474 再查看一下自己的py2neo版本 发现是由于版本太高了 将版本降低后就可以运行了 我这
  • js取整数、取余数、取小数点后几位的方法

    取整 1 取整 丢弃小数部分 保留整数部分 parseInt 5 2 2 2 向上取整 向上取整 有小数就整数部分加1 Math ceil 5 2 3 3 向下取整 向下取整 丢弃小数部分 Math floor 5 2 2 4四舍五入 四舍
  • hexo博客网站搭建

    Hexo简介 Hexo 是一个快速 简洁且高效的博客框架 Hexo 使用 Markdown 或其他渲染引擎 解析文章 在几秒内 即可利用靓丽的主题生成静态网页 安装前提 在安装Hexo之前需要安装以下应用 Node js Git markd
  • VS Code安装教程

    一 下载 1 官网 下载地址 2 下载 根据自己电脑型号下载 此处以Windows为例 二 安装 1 下载完成后 直接点击安装包安装 即可 2 开始安装 然后下一步 3 可以在此处自定义地址 然后下一步 4 默认设置 下一步 5 设置系统的
  • c# websocketServer base64乱码

    下载地址 https download csdn net download peiranshuiyu 10168136 这个接收图片base64乱码 后来查原因 byte 102400 的参数 太短不能完整接收 太长又乱码 后来调成1024
  • 一文搞懂ES6的Map

    什么是Map Map是ECMAScript 6 的新增特性 是一种新的集合类型 为javascript带来了真正的键 值存储机 制 Map 对象存有键值对 其中的键可以是任何数据类型 Map 对象记得键的原始插入顺序 Map 对象具有表示映
  • 用 canvas 做个好玩的网站背景

    不知不觉又好久没更过博客了 老调新弹一下 之前做的一个小效果 觉得蛮有意思的 也有朋友问是怎么做的 就分享一下 写个博文吧 先上demo吧 http whxaxes github io canvas test src Funny demo
  • mysql 给查询语句中增加一列自增id

    举例 SELECT rownum rownum 1 AS id t XH t CFXFBHLB FROM SELECT rownum 0 r t xfcf tq as t 说明 SELECT rownum rownum 1 AS id t
  • windows11 Windows Terminal 添加 Git-Bash 支持

    微软于 2020 05 20 发布了 Windows Terminal 1 0 正式版 安装后默认有三种终端可选 Windows PowerShell 命令提示符 Azure Cloud Shell 升级到Windows11之后默认的终端就
  • 【数据结构】斐波那锲查找算法

    数据结构 斐波那锲查找算法 在写斐波那锲查找算法时遇到ArrayIndexOutOfBoundsException错误 错误提示如下图 即出现了k 0 程序查询第k 1个斐波那锲数列的值时出现了索引越界 下面是修改错误后运行正确的斐波那锲查
  • 高效开发大屏可视化项目第二弹:入场动画和无缝滚动

    这是一个基于Vue 3 Echarts 高德地图和Pinia开发的大屏可视化项目 提供了如下功能 大屏适配 图表组件 Echarts 封装 高德地图组件封装 拖拽布局 入场动画 无缝滚动 源码地址 在线示例 前言 上一篇文章分享了大屏适配