WHAT - CSS Animationtion 动画系列(四)- 移动端全屏动画

news2024/11/23 12:57:32

目录

  • 一、背景
    • 1.1 GIF & Video
    • 1.2 存在的问题
  • 二、技术方案
    • 2.1 使用CSS动画和JavaScript
    • 2.2 使用JavaScript库
    • 2.3 使用序列帧
      • 1. css animation 帧动画
      • 2. JavaScript requestAnimationFrame 帧动画
    • 2.4 使用Canvas
      • 1. html 和 canvas 中的 video
      • 2. 基于Canvas的动画库

今天我们主要介绍在移动端(IOS和安卓)实现全屏动画播放。

一、背景

1.1 GIF & Video

在移动端(iOS 和安卓)实现全屏动画播放,尤其是对于 webview h5 来说,想要播放一个比较复杂的动画,可能我们会马上想到要么使用 GIF 图片、要么使用 视频(video)。

使用视频(video)或 GIF 图片也是实现全屏动画的有效方案之一,它们具有一些优势和适用场景:

  1. 简单易用: 对于一些简单的动画效果,特别是循环播放的动画,使用 GIF 图片可能是最简单、最快速的解决方案。只需将 GIF 图片嵌入到页面中即可,不需要编写额外的代码。

  2. 跨浏览器兼容性好: GIF 图片和视频都有很好的跨浏览器兼容性,可以在各种现代浏览器和移动设备上播放。

  3. 文件大小较小: 对于简单的动画效果,GIF 图片通常比视频文件的大小更小,因此可以更快地加载和播放,节省带宽和用户流量。

  4. 支持透明度: GIF 图片支持透明度,可以实现更多种类的动画效果,比如带有透明背景的动画。

<img src="example.gif" alt="GIF Example" width="100%" height="100%">

<video controls width="100%" height="100%">
	<source scr="example.mp4" type="video/mp4">
	Your browser does not support the video tag.
</video>

1.2 存在的问题

但是,全屏动画场景下,对于前者来说,容易造成资源太大导致页面加载卡顿的问题,因为在移动设备网络速度可能相对较慢,加载 GIF 图片需要发送 http 请求,加载和解析过程可能会影响页面的响应性和交互性,用户可能会感受到页面卡顿或响应不及时的问题;对于后者来说,虽然是边加载边播放,但各种终端不同兼容性让人抓狂,比如:虽然支持不同 source 源,但是对于某些机型只能读取第一个 source,而且对于各种视频格式并不是所有机型都能支持,另外视频还有自动播放问题和静音问题,甚至有些机型(如ios)会自动打开一个播放器来全屏播放,无法做到在 webview 内正常内联播放。

最后,尤其对于复杂的动画效果、需要交互性、需要动态生成内容或需要更高的性能要求的情况,可能更适合使用其他方案,如使用 CSS 动画JavaScript 动画库Canvas 动画。这些方案提供了更多的灵活性和控制能力,可以实现更复杂、更高性能的动画效果。

二、技术方案

在移动端(iOS 和安卓)实现全屏动画播放,可以采用以下几种方案:

2.1 使用CSS动画和JavaScript

使用CSS动画来创建全屏动画效果,然后通过JavaScript来控制动画的播放、暂停和进度控制等功能。可以使用CSS中的@keyframes规则来定义动画,然后通过JavaScript来触发动画的播放和暂停。

下面是一个示例代码,演示了如何使用 CSS 动画创建全屏动画效果,并通过 JavaScript 控制动画的播放、暂停和进度控制:

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fullscreen Animation</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="container">
    <div class="animation"></div>
  </div>
  <button onclick="playAnimation()">Play</button>
  <button onclick="pauseAnimation()">Pause</button>
  <input type="range" min="0" max="100" value="0" step="1" onchange="setAnimationProgress(this.value)">
</body>
<script src="script.js"></script>
</html>

CSS (styles.css):

.container {
  width: 100px;
  height: 300px;
  background-color: blue;
  position: relative;
  overflow: hidden;
}

.animation {
  width: 10px;
  height: 10px;
  background-color: white;
  animation: slide 5s linear infinite;
}

@keyframes slide {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(calc(-100% + 300px));
  }
}

JavaScript (script.js):

var animation = document.querySelector('.animation');
var animationPaused = false;

function playAnimation() {
  animation.style.animationPlayState = 'running';
  animationPaused = false;
}

function pauseAnimation() {
  animation.style.animationPlayState = 'paused';
  animationPaused = true;
}

function setAnimationProgress(progress) {
  if (!animationPaused) {
    pauseAnimation();
  }
  const containerHeight = document.querySelector('.container').clientHeight;
  const animationHeight = animation.clientHeight;
  const maxTranslateY = containerHeight - animationHeight;
  const translateY = (maxTranslateY) * (progress / 100);
  animation.style.animation = 'none';
  animation.style.transform = 'translateY(' + translateY + 'px)';
}

在这个示例中,.container 容器包含一个高度为300px的动画元素.animation,通过 CSS 动画定义了一个垂直向上滑动的动画效果。页面中有三个按钮分别用于播放、暂停和设置动画进度。通过 JavaScript 控制动画的播放状态和进度,playAnimation() 函数用于播放动画,pauseAnimation() 函数用于暂停动画,setAnimationProgress() 函数用于设置动画的进度,参数是一个介于0和100之间的值,表示动画播放进度的百分比。

请添加图片描述

2.2 使用JavaScript库

该方案主要是对于第一种方案的优化,通过第三方动画库丰富的、方便使用的 API 来实现动画。

使用现成的JavaScript动画库,如GSAP(GreenSock Animation Platform)或者Anime.js等,这些库提供了丰富的动画功能和API,可以方便地实现全屏动画效果,并且具有良好的跨浏览器兼容性和性能优化。

请添加图片描述

2.3 使用序列帧

前面两种方案主要是针对各种比较规律的动画的实现,那假如要全屏展示一段复杂的动画或视频内容呢?

有两种方案:

  1. 序列帧
  2. canvas

我们先介绍序列帧。

序列帧又分为 css animation 帧和 JavaScript requestAnimationFrame 帧。

1. css animation 帧动画

使用 sprite 图和 background-position ,再加上 animation 的 step 函数,可以实现序列帧动画。

以一个 3s 的全屏动画为例,我们可以拆为 36 张图,1s 12帧,一张图宽度375px,那么36张图合成一张横图13500px。再利用 css animation 播放:

.video {
	width: 100%;
	height: 100%;
	background: url('test.png')
	overflow: hidden;
	animation: a_video 3s steps(36);
}

@keyframe a_video {
	from {
		background-position: 0 0;
	}
	to {
		background-position: 13500px 0;
	}
}

当然,很明显合成一个完整的图片会太长,而且图片大小非常夸张,
这种图片在移动端也会造成卡顿的。当然,如果是小范围 div 内(非全
屏)的动画需求,应该可以忽略资源大小的问题。

因此,我们可以进一步分成多个阶段,比如:

3s 我们可以分成 3 个 1s,做 3 张图,1 张图包含 1s 内的 15 帧:

请添加图片描述
具体代码:

.video {
	width: 100%;
	height: 100%;
	position: absolute;
	left: 0px;
	top: 0px;
	background-size: 500% 300%;
	background-repeat: no-repeat;
	animation: a_video 3s steps(1, end);
}

@keyframe a_video {
	0% {
		background-image: url("video-1.jpg");
		background-position: 0 0;
	}
	6% {
		background-image: url("video-1.jpg");
		background-position: 25% 0;
	}
	12% {
		background-image: url("video-1.jpg");
		background-position: 50% 0;
	}
	18% {
		background-image: url("video-1.jpg");
		background-position: 75% 0;
	}
	24% {
		background-image: url("video-1.jpg");
		background-position: 100% 0;
	}
	30% {
		background-image: url("video-1.jpg");
		background-position: 0% 50%;
	}
	36% {
		background-image: url("video-1.jpg");
		background-position: 25% 50%;
	}
	/*...*/
	60% {
		background-image: url("video-1.jpg");
		background-position: 0% 100%;
	}
	66% {
		background-image: url("video-1.jpg");
		background-position: 25% 100%;
	}
	/*...*/
	100% {
		background-image: url("video-1.jpg");
		background-position: 100% 100%;
	}
}

2. JavaScript requestAnimationFrame 帧动画

使用 requestAnimationFrame 来逐帧渲染雪碧图可以实现流畅的动画效果。下面是一个简单的示例,演示了如何使用 requestAnimationFrame 来实现逐帧渲染雪碧图:

css:

  #sprite {
    width: 100px;
    height: 150px;
    background-image: url('spritesheet.png');
    background-size: cover;
  }

JavaScript (script.js):

const sprite = document.getElementById('sprite');
const frameWidth = 100; // 每帧宽度
const frameHeight = 150; // 每帧高度
const totalFrames = 15; // 总帧数
const framesPerSecond = 10; // 每秒播放帧数

let currentFrame = 0;
let lastFrameTime = 0;

function animate(timestamp) {
  // 在 requestAnimationFrame 回调函数中,timestamp 是一个 DOMHighResTimeStamp 类型的参数,表示当前回调函数被触发的时间戳
  // 该时间戳是一个高分辨率的值,通常以 ms 为单位,相对于页面加载开始时的性能时间原点
  // 这里我们用这个 timestamp 来计算动画的进度
  const elapsed = timestamp - lastFrameTime;
  if (elapsed > (1000 / framesPerSecond)) { // 每秒要播放10帧 一帧持续100ms
    // 当超过 100ms 即表示要切换到下一帧
    lastFrameTime = timestamp;
    
    // 计算当前帧的位置
    const frameX = currentFrame % 3 * frameWidth;
    const frameY = Math.floor(currentFrame / 3) * frameHeight;
    
    // 设置背景位置
    sprite.style.backgroundPosition = `-${frameX}px -${frameY}px`;
    
    // 更新当前帧(的索引)
    // 注意 这里 % totalFrames 的作用是实现循环播放
    currentFrame = (currentFrame + 1) % totalFrames;
  }

  requestAnimationFrame(animate);
}

// 开始动画
requestAnimationFrame(animate);

在这个示例中,我们首先定义了一个包含 15 帧的 3x5 的雪碧图,每帧的宽度为 100px,高度为 150px。然后,我们使用 requestAnimationFrame 来启动动画循环,在每帧中更新雪碧图的背景位置,从而实现逐帧渲染的效果。

2.4 使用Canvas

使用HTML5 Canvas元素来绘制全屏动画效果。

1. html 和 canvas 中的 video

在 HTML 和 Canvas 中使用视频(video)有一些不同之处,主要涉及到了它们的用途、控制方式和性能等方面:

  1. 用途

    • 在 HTML 中使用视频(video)元素主要用于在网页中展示和播放视频内容。视频元素可以通过 HTML 标签直接嵌入到页面中,并提供了一些内置的控制功能,如播放、暂停、音量调节等。
    • 在 Canvas 中使用视频通常是为了在画布上绘制视频的每一帧,并实现更加灵活的视频处理和展示效果。Canvas 提供了绘图 API,可以将视频的每一帧绘制到画布上,并进行自定义的处理和动画效果。
  2. 控制方式

    • 在 HTML 中,视频元素具有内置的控制功能,用户可以通过浏览器提供的默认 UI 来控制视频的播放、暂停、音量调节等操作,也可以通过 JavaScript 来动态控制视频的行为。
    • 在 Canvas 中,要实现对视频的控制,通常需要使用 JavaScript 来处理视频的播放和暂停等操作,以及绘制视频的每一帧到画布上。
  3. 性能

    • 在 HTML 中使用视频元素通常具有较好的性能和兼容性,因为视频的播放和渲染是由浏览器内核直接处理的,可以充分利用硬件加速来提高性能。
    • 在 Canvas 中使用视频需要将视频的每一帧绘制到画布上,这涉及到大量的图像处理和绘制操作,可能会对性能产生一定影响,特别是在处理大尺寸或高分辨率视频时。

总的来说,HTML 中的视频元素适用于简单的视频展示和播放场景,而 Canvas 中的视频处理适用于需要更多自定义和交互性的视频处理和展示效果。选择使用哪种方式取决于具体的需求和场景。

另外,在 Canvas 中渲染视频通常不会涉及到使用原生播放器,因为视频的播放和渲染是由 Canvas 直接控制的,而不是依赖于浏览器提供的原生播放器。因此,与使用 HTML5 <video> 元素播放视频相比,Canvas 中渲染视频可以更灵活地控制视频的播放、渲染和效果。

但是,需要注意的是,Canvas 中渲染视频可能会涉及到一些其他方面的问题,例如:

  1. 性能问题:在 Canvas 中渲染视频可能需要大量的计算和绘制操作,特别是在处理高分辨率或大尺寸的视频时,可能会对性能造成一定的影响,需要进行优化和考虑性能问题。

  2. 兼容性问题:Canvas 的功能和性能在不同浏览器和设备上可能会有所不同,需要进行兼容性测试和调整。

  3. 实现复杂度:相比于使用原生播放器播放视频,Canvas 中渲染视频可能需要更多的编程和实现复杂度,包括视频的解码、帧的处理、渲染效果的实现等。当然利用第三方库可以一定程度避免该问题。

总的来说,Canvas 中渲染视频可以提供更多的自定义和控制能力,但也需要考虑到性能、兼容性和实现复杂度等方面的问题。

2. 基于Canvas的动画库

有许多基于 Canvas 的动画库可以帮助开发者更轻松地创建各种动态和交互式的 Canvas 动画。以下是一些常用的基于 Canvas 的动画库:

  1. PixiJS:PixiJS 是一个功能强大的 WebGL 渲染引擎,提供了丰富的 API 和工具,用于创建高性能的交互式 2D 游戏和图形应用。它可以与 Canvas 兼容,并且支持 WebGPU、WebGL 和 Canvas 2D 渲染。它提供了易于使用的 API,适合用于创建各种类型的 Canvas 动画和游戏。

  2. CreateJS:CreateJS 是一个包含多个模块的 JavaScript 库,其中包括 EaselJS、TweenJS、SoundJS 和 PreloadJS。其中的 EaselJS 模块提供了一套简单易用的 API,用于在 Canvas 上绘制图形和创建动画。它可以用来创建各种类型的 Canvas 动画和交互式应用。

  3. Two.js:Two.js 是一个轻量级的 2D 绘图库,它提供了一系列的 API 和工具,用于在 Canvas 上创建图形、动画和交互式应用。它具有简单易用的 API,适合用于创建简单的 Canvas 动画和图形应用。

  4. Three.js: 一个用于创建 3D 图形的 JavaScript 库,虽然它主要用于 WebGL,但也可以在 Canvas 上创建 3D 图形,并提供了丰富的 3D 渲染功能和特效支持。

这些基于 Canvas 的动画库都具有不同的特点和适用场景,开发者可以根据自己的需求和偏好选择合适的库来创建 Canvas 动画和应用。

更多关于 Canvas 内容可以阅读 HOW - Canvas 入门系列(一)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1672482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程:服务器模型-并发服务器-多进程

并发服务器概念&#xff1a; 并发服务器同一时刻可以处理多个客户机的请求 设计思路&#xff1a; 并发服务器是在循环服务器基础上优化过来的 &#xff08;1&#xff09;每连接一个客户机&#xff0c;服务器立马创建子进程或者子线程来跟新的客户机通信 &#xff08;accept之后…

达梦数据库 报错 数据类型不匹配

达梦数据库 报错 数据类型不匹配 背景描述问题分析问题处理方案1&#xff1a;方案2&#xff1a;TO_CHAR(str)CAST(value AS type)CONVERT(type,value)DBMS_LOB 包TEXT_EQUAL(n1,n2) 写在最后 背景描述 本文写于初接触到达梦(DM)数据库&#xff0c;之前没有用过&#xff0c;因此…

网络协议的分类

1.概要 网络协议可以分为三类&#xff1a; 封装协议路由协议功能类协议 2.分类说明 OSPF报文直接调用_ IP协议__协议进行封装&#xff0c;以目的地址_244.0.0.5 __发送到所有的OSPF路由器? 244.0.0.1 所有主机&#xff1b;244.0.0.2 所有路由器&#xff1b;244.0.0.6 指定…

SpringSecurity6集成数据库

本文章对应视频可在B站查看SpringSecurity6对应视频教程&#xff0c;记得三连哦&#xff0c;这对我很重要呢&#xff01; 温馨提示&#xff1a;视频与文章相辅相成&#xff0c;结合学习效果更强哦&#xff01; 系列文章链接 1、初识SpringSecurity&#xff0c;认识主流Java权限…

win10系统解除微软账户和本地账户绑定

折腾了好久&#xff0c;终于找到一种方法可以退出微软账号了&#xff0c;不过这种方法我测试是成功的&#xff0c;有人留言自己不成功&#xff0c;具体解决方法只能看这些留言了 win10当中没有注销按钮&#xff0c;win x 弹出的菜单里面有关闭或注销&#xff0c;可以选择注销…

Unity射击游戏开发教程:(15)添加推进器推进和推进器推进动画

这是一个可以添加到我的游戏中的简单而有趣的功能。当玩家按住 Shift 按钮时,速度会加快,松开 Shift 按钮时,速度会恢复到原来的速度。 这需要不同的输入检测。通常使用的是Input.GetKeyDown并传入你想要获取的key。这只会检测在当前帧期间是否按下了按钮,但如果按住,将不…

Hive的join操作

假设有三张表&#xff0c;结构和数据如下&#xff1a;-- 创建表 test_a,test_b,test_c CREATE TABLE test_a( id int, name string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t;--分别导入数据到三个表中 --test_a 1 a1 2 a2 4 a4 --test_b 1 b1 3 b3 4 b4 --…

Ubuntu 20.04在Anaconda虚拟环境中配置PyQt4

一、创建一个虚拟环境 1 创建一个python2.7的虚拟环境&#xff1a; conda create -n pyqt4 numpy matplotlib python2.72 在环境中安装几个需要的包&#xff1a; pip install Theano pip install python-opencv3.4.0.14 pip install qdarkstyle pip install dominate二、在主…

打造清洁宜居家园保护自然生态环境,基于YOLOv7【tiny/l/x】参数系列模型开发构建自然生态场景下违规违法垃圾倾倒检测识别系统

自然生态环境&#xff0c;作为我们人类赖以生存的家园&#xff0c;其健康与否直接关系到我们的生活质量。然而&#xff0c;近年来&#xff0c;一些不法分子为了个人私利&#xff0c;在河边、路边等公共区域肆意倾倒垃圾&#xff0c;严重破坏了环境的健康与平衡。这种行为不仅损…

【Python探索之旅】选择结构(条件语句)

文章目录 条件结构&#xff1a; 1.1 if单分支结构 1.2 if-else 多分支结构 1.3 if-elif 多重结构&#xff1a; 完结撒花​ 前言 Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。 Python提供了顺序、选择、循环三…

2024.5.19 机器学习周报

引言 Abstract 文献阅读 1、题目 X-HRNET: TOWARDS LIGHTWEIGHT HUMAN POSE ESTIMATION WITH SPATIALLY UNIDIMENSIONAL SELF-ATTENTION 2、引言 高分辨率表示是人体姿态估计实现高性能所必需的&#xff0c;随之而来的问题是高计算复杂度。特别地&#xff0c;主要的姿态估…

AI算法-高数5.1-线性代数-向量间的关系

线性代数基础概念见&#xff1a;AI算法-高数5-线性代数1-基本概念、向量-CSDN博客 宋浩老师课程学习&#xff1a; 3.2 向量间的线性关系&#xff08;一&#xff09;_哔哩哔哩_bilibili 向量间的关系&#xff1a; ​ ​ ​ ​ 判断向量贝塔(β)是否是阿尔法(α)的线性组…

4.2 试编写一程序,要求比较两个字符串STRING1和STRING2所含字符是否相同,若相同则显示“MATCH”,若不相同则显示“NO MATCH”

方法一&#xff1a;在程序内部设置两个字符串内容&#xff0c;终端返回是否匹配 运行效果&#xff1a; 思路&#xff1a; 1、先比较两个字符串的长度&#xff0c;如果长度不一样&#xff0c;则两组字符串肯定不匹配&#xff1b;如果长度一样&#xff0c;再进行内容的匹配 2、如…

红外遥控和LCD1602

26.1.1 红外线简介 人的眼睛能看到的可见光按波长从长到短排列&#xff0c;依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为 0.62&#xff5e;0.76μm&#xff1b;紫光的波长范围为 0.38&#xff5e;0.46μm。比紫光波长还短的光叫紫外线&#xff0c;比红光波长还长的…

利用光学和SAR数据进行亚马逊热带雨林监测

亚马逊热带雨林&#xff0c;670万平方公里&#xff0c;物种丰富&#xff0c;森林历史悠久。巴西环保局用光学和SAR数据进行森林监测&#xff0c;主要监测森林砍伐范围、人为破坏、非法采矿和隐蔽的飞机跑道。 图 2011年12月森林砍伐范围 在SAR强度数据上&#xff0c;被砍伐的森…

C#语言进阶

一、简单数据结构类 1. ArrayList ArrayList是一个 C# 为我们封装好的类&#xff0c;它的本质是一个 object 类型的数组。ArrayList类帮助我们实现了很多方法&#xff0c;比如数组的增删查改 1.1 声明 using System.Collections;ArrayList array new ArrayList(); 1.2 增…

RabbitMQ--死信队列

目录 一、死信队列介绍 1.死信 2.死信的来源 2.1 TTL 2.2 死信的来源 3.死信队列 4.死信队列的用途 二、死信队列的实现 1.导入依赖 pom.xml 2.application.properties 3.配置类 4.生产者 5.业务消费者&#xff08;正常消费者&#xff09; 6.死信队列消费者 一、…

STM32-LCD液晶屏(ILI9341)

MCU&#xff1a;STM32F103VET6 开发环境&#xff1a;STM32CubeMXMDK5 目录 STM32液晶屏LCD&#xff08;ILI9341&#xff09; LCD液晶显示 液晶控制原理 ILI9341液晶控制器简介 8080写时序 8080读时序 FSMC模拟8080时序 液晶屏的信号线 STM32CubeMX配置FSMC 测试部分 …

工作玩手机监测识别摄像机

工作场所的员工玩手机已经成为了一种常见的现象&#xff0c;特别是在办公室、生产车间等地方。而这种现象不仅仅影响了员工的工作效率&#xff0c;还可能会对工作安全造成一定的隐患。为了监测和识别员工玩手机的情况&#xff0c;工作玩手机监测识别摄像机应运而生。工作玩手机…

05 | 如何确保消息不会丢失?

检测消息丢失的方法 我们可以利用消息队列的有序性来验证是否有消息丢失。在 Producer 端,我们给每个发出的消息附加一个连续递增的序号,然后在 Consumer 端来检查这个序号的连续性。 如果没有消息丢失,Consumer 收到消息的序号必然是连续递增的,或者说收到的消息,其中的…