css3+js动画
非css的方法:js定时器 flash
能用css3就不要用js,能用requestAnimation就不用定时器
变形 transform
变形:改变元素的样式
提供的变形的效果,能用transform改变样式的就不要用其他传统方式,尤其是动画中,因为动画要求的是流畅度
scale一般不考虑缩放的问题
要搞清楚方向的问题,平面往下是正方向
transfrom:移动、缩放、旋转、斜切_xqiitan的博客-CSDN博客
translate相当于脱离文档流;会在一个新的平面;
css对于脱离了文档流的都是不同的处理,每种都是特殊的情况
transform自己去看,好多细节知识点 transform-origin tyle:2d 等等
变形不是动画,变形只是改变盒子的样式;
动画是在一定时间内慢慢去改变它的样式
过渡动画 transition
给元素设置一个过渡效果,当元素的样式发生改变不是立即改变,而是按照效果来发生改变
transition-timing-function: ease-in 加速、ease-out 减速、ease-in-out 先减速再减速、
扩展的一个小样式:
-webkit-filter: grayscale(1)
transitiond的效果,之前样式是a,现在样式是b,那么我从a到b的一个动画效果,项目中不是特别强大;
transition只能是a-b,但是如果我现在a-b,b-c,c-d,实现一个相对来说比较复杂的轨迹运动
帧(轨迹)动画 animation
事件制作好运动轨迹,即每一帧元素的样式
animation:
animation-name
// 和transition是一样的
animation-iteration-count: 播放次数,默认1次,infinite
animation-fill-mode: 控制运动状态。
沿着轨迹开始走,animation走到末尾的时候会立马蹦回第1帧的位置。
+forwards
+backwards
扩展一个强大公共的动画库:animation.css
npm init animate.css
-
使用 class="animated heartBeat infinite"
-
把公式粘进来自己改也行
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
height: 10000px;
}
@keyframes run {
0%,100%{
transform: translate(0,0);
}
25%{
transform: translate(300px,0);
}
50%{
transform: translate(300px,300px);
}
75%{
transform: translate(0,300px);
}
}
.run{
animation: run 2s linear 0s infinite;
}
</style>
</head>
<body>
<img class="run" src="./lesson.jpg" alt="" data-src="./lesson.jpg" width="220" height="394" loading="lazy">
<script>
</script>
</body>
</html>
浏览器中同步和异步
-
翻牌
-
钟摆
-
西游记
笔记链接到这个文档
js定时器动画
2种方式:
限定步长
限定时间
-
限定步长
思路分析:
从最左边运动到最右边
-
首先帧(轨迹)动画不好实现,因为不知道最右边的样式(屏宽是动态的);
-
使用transition
-
定时器动画,每一步向右10px 5px
最右边的left值:一屏幕的宽度 - 盒子的宽度
改变left或者transform:translate(translateX,0)。开启硬件加速性能更好
限定步长:
只要能知道目标和步长,设置interval定时器累加步长,在当前样式上累加步长,但是一定要有边界判断,加上步长边界判断,超过了就直接走到边界;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 10000px;
}
img{
border: 10px solid red;
width: 300px;
position: absolute;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<img class="run" src="./bg.jpg" alt="" loading="lazy">
<script>
let img=document.querySelector('.run');
let offsetWidth=img.offsetWidth;
let clientWidth=document.body.clientWidth;
let end=clientWidth-offsetWidth;
let left=0;
let step=10;
let timer=window.setInterval(()=>{
left+=step;
// 先判一下未来的,如果下一步会超过,则不加。
if(left>=end){
// 如果超出了手动回归终点
img.style.left=(clientWidth-offsetWidth)+'px';
window.clearInterval(timer);
timer=null;
return;
}
img.style.left=left+'px';
},20)
</script>
</body>
</html>
-
限定时间
限定步长:无法把控好准确的时间的
限定时间的匀速运动
引出了公式的概念
T:time 已经运动的时间
B:begin 开始位置
C:change 总距离 = Target-Begin
D:duration 总时间
curDistance=T/D*C+B
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 10000px;
}
img{
border: 10px solid red;
width: 300px;
position: absolute;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<img class="run" src="./bg.jpg" alt="" loading="lazy">
<script>
let img=document.querySelector('.run');
let offsetWidth=img.offsetWidth;
let clientWidth=document.body.clientWidth;
// 目标位置
let target=clientWidth-offsetWidth;
// 起始位置
let begin=img.offsetLeft;
// 总距离
let change=target-begin;
// 总时间
let duration=1000;
let time=0;
let timer=window.setInterval(()=>{
time+=20;
let curLeft=time/duration*change+begin;
if(time>=duration){
img.style.left=target+'px';
window.clearInterval(timer);
timer=null;
}
img.style.left=curLeft+'px';
},20)
</script>
</body>
</html>
requestAnimationFrame
几个概念:
屏幕刷新频率
……
定时器:定时器改的时候屏幕没改,你不刷新的时候屏幕改了
深入理解 RequestAnimationFrame_aiguangyuan的博客-CSDN博客_requestanimationframe执行时机
requestAnimationFrame一般用于固定步长的动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 10000px;
}
img{
border: 10px solid red;
width: 300px;
position: absolute;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<img class="run" src="./bg.jpg" alt="" loading="lazy">
<script>
let img=document.querySelector('.run');
let offsetWidth=img.offsetWidth;
let clientWidth=document.body.clientWidth;
let end=clientWidth-offsetWidth;
let left=img.offsetLeft;
let step=10;
function render() {
left+=step;
// 先判一下未来的,如果下一步会超过,则不加。
if(left>=end){
// 如果超出了手动回归终点
img.style.left=(clientWidth-offsetWidth)+'px';
return;
}
img.style.left=left+'px';
// 2.回调末尾再加上window.requestAnimationFrame实现递归
window.requestAnimationFrame(render)
}
// 1.render就是之前执行的回调
window.requestAnimationFrame(render)
</script>
</body>
</html>
jQuery动画库
如果要加上y方向上的运动:
用css3是最简单的,管你改什么值,只要样式改变了,就会有过渡效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body{
height: 100%;
}
.run{
width: 300px;
height: 178px;
position: absolute;
left: 0px;
top: 0px;
background: #0b2e13;
}
.run img{
width: 100%;
height:100%;
display: block;
}
</style>
</head>
<body>
<div class="run"><img src="./bg.jpg" alt="" loading="lazy"></div>
<script>
let img=document.querySelector('.run');
let offsetWidth=img.offsetWidth;
let clientWidth=document.documentElement.clientWidth;
// 目标位置
let target=clientWidth-offsetWidth;
let targetY=document.documentElement.clientHeight-img.offsetHeight;
// 起始位置
let begin=img.offsetLeft;
let beginY=img.offsetTop;
// 总距离
let change=target-begin;
let changeY=targetY-beginY;
// 总时间
let duration=1000;
let time=0;
let timer=window.setInterval(()=>{
time+=20;
let curLeft=time/duration*change+begin;
let curTop=time/duration*changeY+beginY;
if(time>=duration){
img.style.left=target+'px';
img.style.top=(targetY)+'px';
window.clearInterval(timer);
timer=null;
return;
}
img.style.left=curLeft+'px';
img.style.top=curTop+'px';
},20)
</script>
</body>
</html>
简易封装多方向
再加一个样式的方向,宽度也跟着变,透明度、颜色……
你告诉我目标值,目标值指定几个方向,分别求出begin change,
t b c d
t:是实时的时间,不需要外界给的
b:begin 我们自己根据元素的样式求得
c:change=target-begin
这2个是一组的,是跟target有关的
d:总时长,是需要外部调用者传入的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>title</title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,body{
height: 100%;
}
.run{
width: 300px;
height: 178px;
position: absolute;
left: 0px;
top: 0px;
background: #0b2e13;
}
.run img{
width: 100%;
height:100%;
display: block;
}
</style>
</head>
<body>
<div class="run"><img src="./bg.jpg" alt="" loading="lazy"></div>
<script>
let img=document.querySelector('.run');
let offsetWidth=img.offsetWidth;
let clientWidth=document.documentElement.clientWidth;
// 目标位置
let target=clientWidth-offsetWidth;
let targetY=document.documentElement.clientHeight-img.offsetHeight;
// 总时间
let duration=1000;
let time=0;
/**
* t b c d
* t:是实时的时间,不需要外界给的
*
* b:begin 我们自己根据元素的样式求得
* c:change=target-begin
* 这2个是一组的,是跟target有关的
*
* d:总时长,是需要外部调用者传入的
*
*/
// 封装
function animation(elem,target={},duration,callback){
// 初始化time begin change
let time=0,begin={},change={};
for(let key in target){
if(target.hasOwnProperty(key)){
begin[key]=parseFloat(window.getComputedStyle(elem)[key]);
change[key]=target[key]-begin[key];
}
}
let timer=window.setInterval(()=>{
time+=20;
if(time>=duration){
window.clearInterval(timer);
timer=null;
for(let key in target){
if(target.hasOwnProperty(key)){
elem.style[key]=target[key]+'px';
}
}
// callback && callback()
if(typeof callback ==='function'){
callback()
}
return;
}
for(let key in target){
if(target.hasOwnProperty(key)){
let cur=time/duration*change[key]+begin[key];
elem.style[key]=cur+'px';
}
}
},20)
}
animation(img,{left:target,top:targetY},duration,()=>{
img.style.transform='rotate(180deg)';
})
</script>
</body>
</html>
jQuery
stop和finish的区别:
stop:结束当前动画
finish:瞬间到当前动画的结束位置。会出现跳跃不建议
快捷用法