GSAP

3Blue1Brown给我留下了深刻印象。利用动画制作视频,内容简洁,演示清晰。前两天刚好碰到一件事,我就顺便学习了一下怎么用代码做动画。

javascrip为例,有两个动画引擎,GSAPAnimajs。由于网速的原因,询问了GPT后,我选择了GSAP来制作我的第一个动画视频。

制作动画视频不同于动画,要协调多个动作,还需要对齐时间,所以使用时间线Timeline是必要的。

需要两条时间线分别播放字幕和动画,这需要协调好他们

而且很多片段需要后期调整,所以也必须使用相对时间><,label这三种模式。

制作动画重要的是想好脚本,然后声明HTML元素,再恰当时刻将元素呈现出来

预览

代码

代码无需开启web服务器,可以直接再浏览器中打开

<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/TextPlugin.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/fontawesome.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/js/all.min.js"></script>
<style>
#screen{
height: 720px;
width: 1280px;
position: relative;
background-color: black;
}
#screen > *{
position: absolute;
display: inline-block;
}
.person_{
top:20px;
color: white;
transform: scale(0,0);
}
#person3_{
left: 905px;
}
#person2_{
left: 590px;
}
#person1_{
left: 290px;
}
#person1,#person2,#person3{
width: 50px;
height: 50px;
background-color: green;
border: 5px;
color: white;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
padding: 5px;
top: 50px;
left: -100px;
}
#text{
position: absolute;
width: 100%;
text-align: center;
color: white;
bottom: 10px;
} .year{
position: absolute;
width: 120px;
height: 30px;
left:130px;
color: white;
font-size: 18px;
transform:scale(0,0)
}
#year2000{
top:120px;
}
#year2000_{
top:200px;
}
#year2001{
top:600px;
}
.food{
color: bisque;
width: 50px;
height: 30px;
transform: scale(0,0);
}
#food1{
top:120px;
left: 290px;
}
#food2{
top:120px;
left: 560px;
}
#food3{
top:120px;
left: 890px;
}
#food4{
top:120px;
left: 290px;
}
#food5{
top:120px;
left: 560px;
}
#food6{
top:120px;
left: 890px;
}
#food7,#food8,#food9,#food10{
top:200px;
left: 290px;
}
#food11{
top:600px;
left: 290px;
}
#food12{
top:600px;
left: 560px;
}
#food13{
top:600px;
left: 890px;
}
#food14{
top:600px;
left: 890px;
}
.coins{
color: gold;
width: 50px;
height: 30px;
transform: scale(0,0);
}
.iconnum{
padding-left: 5px;
}
#coin1{
top: 120px;
left: 610px;
}
#coin2{
top: 120px;
left: 610px;
}
#coin3{
top: 200px;
left: 610px;
}
#coin4{
top: 280px;
left: 610px;
}
#coin5{
top: 600px;
left: 610px;
}
.industry{
color: rgb(204, 203, 203);
width: 50px;
height: 30px;
transform: scale(0,0);
}
#ind1{
top: 120px;
left: 340px;
}
#ind2{
top: 120px;
left: 660px;
}
#ind3{
top: 120px;
left: 940px;
}
#ind4{
top: 120px;
left: 340px;
}
#ind5{
top: 120px;
left: 660px;
}
#ind6{
top: 120px;
left: 940px;
}
#ind7{
top: 200px;
left: 940px;
}
#ind8{
top: 200px;
left: 940px;
}
#ind9{
top: 600px;
left: 340px;
}
#ind10{
top: 600px;
left: 660px;
}
.yearnext{
color: white;
width: 50px;
height: 50px;
transform: scale(1,0);
left: 160px;
}
#yn1{
top: 140px;
}
#yn2{
top: 220px;
}
.yearnext_{
color: white;
width: 50px;
height: 50px;
transform: scale(1,0);
}
#yn1_1{
left: 120px;
top:160px;
}
#yn1_2{
left: 180px;
top:160px;
}
#yn2_3{
left: 120px;
top:300px;
}
.changeline{
color: white;
transform: scale(0,1);
}
#cl1{
top: 285px;
left: 530px;
}
#cl2{
top: 285px;
left: 710px;
}
#cl3{
top: 290px;
left: 900px;
}
#cl4{
top: 340px;
left: 340px;
}
#cl5{
top: 350px;
left: 900px;
}
#curve{
top: 455px;
left: -180px;
transform: scale(1,0);
}
#complete{
color: white;
left: 50px;
top:340px;
transform: scale(0);
}
</style>
</head>
<body>
<div id="screen">
<div id="person1_" class="person_">租地农场主</div>
<div id="person2_" class="person_">领主、地主</div>
<div id="person3_" class="person_">工厂主</div>
<div id="person1" class="person">生产阶级</div>
<div id="person2" class="person">土地所有者</div>
<div id="person3" class="person">非生产阶级</div>
<div id="text"></div>
<div class="year" id="year2000">1758 年初</div>
<div class="year" id="year2000_">1758 年末</div>
<div class="year" id="year2001">1759 年初</div>
<div class="coins" id="coin1"><i class="fa-solid fa-coins"></i><span class="iconnum">20</span></div>
<div class="coins" id="coin2"><i class="fa-solid fa-coins"></i><span class="iconnum">20</span></div>
<div class="coins" id="coin3"><i class="fa-solid fa-coins"></i><span class="iconnum" id="coin3_num">20</span></div>
<div class="coins" id="coin4"><i class="fa-solid fa-coins"></i><span class="iconnum" id="coin4_num">10</span></div>
<div class="coins" id="coin5"><i class="fa-solid fa-coins"></i><span class="iconnum" id="coin5_num">20</span></div>
<div class="industry" id="ind1"><i class="fa-solid fa-gears"></i><span class="iconnum">10</span></div>
<div class="industry" id="ind2"><i class="fa-solid fa-gears"></i><span class="iconnum">10</span></div>
<div class="industry" id="ind3"><i class="fa-solid fa-gears"></i><span class="iconnum">10</span></div>
<div class="industry" id="ind4"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind4_num">10</span></div>
<div class="industry" id="ind5"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind5_num">10</span></div>
<div class="industry" id="ind6"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind6_num">0</span></div>
<div class="industry" id="ind7"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind7_num">10</span></div>
<div class="industry" id="ind8"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind8_num">10</span></div>
<div class="industry" id="ind9"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind9_num">10</span></div>
<div class="industry" id="ind10"><i class="fa-solid fa-gears"></i><span class="iconnum" id="ind10_num">10</span></div>
<div class="food" id="food1"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum">20</span></div>
<div class="food" id="food2"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum">10</span></div>
<div class="food" id="food3"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum">20</span></div>
<div class="food" id="food4"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food4_num">20</span></div>
<div class="food" id="food5"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food5_num">10</span></div>
<div class="food" id="food6"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food6_num">10</span></div>
<div class="food" id="food7"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food7_num">10</span></div>
<div class="food" id="food8"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food8_num">10</span></div>
<div class="food" id="food9"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food9_num">10</span></div>
<div class="food" id="food10"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food10_num">20</span></div>
<div class="food" id="food11"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food11_num">20</span></div>
<div class="food" id="food12"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food12_num">10</span></div>
<div class="food" id="food13"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food13_num">10</span></div>
<div class="food" id="food14"><i class="fa-solid fa-wheat-awn"></i><span class="iconnum" id="food14_num">10</span></div>
<div class="yearnext" id="yn1"><i class="fa-solid fa-arrow-down-long"></i></div>
<div class="yearnext" id="yn2"><i class="fa-solid fa-arrow-down-long"></i></div>
<div class="yearnext_" id="yn1_1">生产</div>
<div class="yearnext_" id="yn1_2">消费</div>
<div class="yearnext_" id="yn2_3">流通</div>
<div class="changeline" id="cl1"><i class="fa-solid fa-minus"></i></div>
<div class="changeline" id="cl2"><i class="fa-solid fa-minus"></i></div>
<div class="changeline" id="cl3"><i class="fa-solid fa-minus"></i></div>
<div class="changeline" id="cl4"><i class="fa-solid fa-minus"></i></div>
<div class="changeline" id="cl5"><i class="fa-solid fa-minus"></i></div>
<div id="complete">完成循环</div>
<div id="curve">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<!-- 定义箭头样式 -->
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto">
<path d="M0,0 L0,6 L9,3 z" fill="white" />
</marker>
</defs>
<path d="M300 150 Q 150 75, 300 0 " style="fill:none;stroke:white;stroke-width:1;marker-end: url(#arrow);" />
</svg>
</div>
</div>
<div style="padding: 10px;">
<input id="seek" type="range" oninput="setcur()" style="width: 800px;"/>
<button onclick="seekto()">跳转</button>
<span>当前</span>
<input id="cur" type="number" />
<span>总时长</span>
<input id="total" type="number" />
</div>
<!-- 字幕 -->
<script>
let tlzm = gsap.timeline(); tlzm
.to("#text", {
text: {
value: "在魁奈的《经济表》中",
delimiter:" "
},
duration:0,
ease: "none"
},1)
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=3')
.to("#text", {
text: {
value: "商品货币循环被一个连线图表构造出来",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "这个循环在3大阶级之间进行",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=4')
.to("#text", {
text: {
value: "而阶级内部的交换不在考虑范围内",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "这三个阶级分别是",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=4')
.to("#text", {
text: {
value: "非生产阶级,可以认为是工厂主和工人",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "土地所有者阶级,通常是领主、地主",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "生产阶级,可以认为是租地农场主和农业工人",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "所有循环都有开端",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=4')
.to("#text", {
text: {
value: "我们把《经济表》发表的那年作为开端",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=4')
.to("#text", {
text: {
value: "首先是生产阶级",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=3')
.to("#text", {
text: {
value: "生产阶级手中拥有价值20亿利弗尔的农产品,作为种子和食物",
delimiter:" "
},
duration:6,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "同时,他们还拥有价值100亿利弗尔的工业品作为生产资料和生活用品",
delimiter:" "
},
duration:0,
ease: "none"
},'>+1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "分摊到每一年,生产资料和生活用品会损耗或消耗10亿利弗尔",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "然后是土地所有者阶级",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=3')
.to("#text", {
text: {
value: "他们有价值10亿利弗尔的食物,20亿利弗尔货币和价值10亿利弗尔的工业品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "最后是非生产阶级",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=4')
.to("#text", {
text: {
value: "他们的初始条件是价值20亿利弗尔的农业品原料和食物",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "在这一年内,三大阶级进行了生产和消费,直到年末",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "生产阶级消耗工业品和农产品,生产出价值50亿利弗尔的农产品原料",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "土地所有者阶级则什么也没生产,只是消费。最终剩下的是20亿利弗尔货币",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "非生产阶级则消耗20亿利弗尔农产品,生产出20亿利弗尔的工业品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "生产消费阶段结束,接下来是交换阶段",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "我们把各阶级的产品和货币各自划分为若干份",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "以方便接下来的交换",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "首先发起交换的,只能是拥有货币的土地所有者阶级",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "他们用10亿利弗尔货币从生产阶级那交换等价的农产品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "再用剩下的10亿利弗尔货币从非生产阶级那交换等价的工业品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "之后土地所有者阶级退出流通环节",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "接下来非生产者阶级使用手中的10亿利弗尔货币,从生产阶级那里交换10亿利弗尔的农产品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=9')
.to("#text", {
text: {
value: "然后他们就耗尽货币,只能等待生产阶级先发起交换",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "生产阶级花费10亿利弗尔货币从非生产阶级那里交换10亿利弗尔的工业品",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "非生产阶级再次获得10亿利弗尔货币",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "他们将用来交换到最后所需的农产品原料和粮食",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "至此三大阶级交换完成,货币和产品都到了所需的人手中",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "接下来就是领主和地主老爷的收税和收租环节",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "生产阶级交换所得到的货币又作为租金,回到了土地所有者阶级手中",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=7')
.to("#text", {
text: {
value: "好了,现在其实整个经济循环已经回到了初始状态,但为了明显一点,让我们整理一下",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "将各阶级的产品和货币各自汇总",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "和上一年初的初始状态对比一下会发现他们并没有什么变化",
delimiter:" "
},
duration:0,
ease: "none"
},'>')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=6')
.to("#text", {
text: {
value: "马克思评价说",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=4')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=3')
.to("#text", {
text: {
value: "魁奈的《经济表》用几根粗线条表明,国民生产的具有一定价值的年产品",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=8')
.to("#text", {
text: {
value: "要怎样通过流通进行分配,才能在其他条件不变的情况下,使它的的简单再生产(即原有规模的再生产)进行下去",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=9')
.to("#text", {
text: {
value: "上一年的收获,当然构成生产期间的起点",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=5')
.to("#text", {
text: {
value: "无数单个流通(交换)行为,从一开始就被综合为,根据他们所具有的社会特征划分出来的大体量运动。——几个巨大的、职能确定的、经济上的社会阶级之间的流通",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=15')
.to("#text", {
text: {
value: "《经济表》提醒我们,价值的创造固然重要,但在目前的商品社会中,商品和货币的循环也是极其重要的、为生产创造条件的活动",
delimiter:" "
},
duration:0,
ease: "none"
},'>+=1')
.to("#text", { text: { value: "", delimiter:" " }, duration:0, },'>+=12')
</script>
<!-- 动画 -->
<script>
gsap.registerPlugin(TextPlugin)
// 创建Timeline类型的实例
let tl = gsap.timeline();
function seekto(){
var cur=document.getElementById("seek").value;
tl.seek(cur);
tlzm.seek(cur);
}
function setcur(){
var cur=document.getElementById("seek").value;
document.getElementById("cur").value=cur;
} //非生产阶级,可以认为是工厂主和工人 4s
tl.to("#person3", {
x: 1000,
duration:1
},3+1+5+1+3+1+4+1+3+1)
tl.to("#person3_", {
scale: 1,
duration:1
},'>+0.5')
//土地所有者阶级,通常是领主、地主 5s
.to("#person2", {
x: 700,
duration:1
},'>+2.5')
tl.to("#person2_", {
scale: 1,
duration:1
},'>+0.5')
//生产阶级,可以认为是租地农场主和农业工人 6s
.to("#person1", {
x: 400,
duration:1
},'>+3.5')
tl.to("#person1_", {
scale: 1,
duration:0.5
},'>+0.5')
//所有循环都有开端 4s
.to("#year2000", {
scale: 1,
duration:0.5
},'>+5')
//首先是生产阶级
.to("#food1", {
scale: 1,
duration:0.5
},'>+14')
//同时,他们还拥有价值100亿利弗尔的工业品作为生产资料和生活用品
.to("#ind1", {
scale: 1,
duration:0.5
},'>+18')
//然后是土地所有者阶级
.to("#food2", {
scale: 1,
duration:0.5
},'>+10')
.to("#coin1", {
scale: 1,
duration:0.5
},'>+1.5')
.to("#ind2", {
scale: 1,
duration:0.5
},'>+1.5')
//最后是非生产阶级
.to("#food3", {
scale: 1,
duration:0.5
},'>+8')
//在这一年内,三大阶级进行了生产和消费,直到年末
.to("#year2000_", {
scale: 1,
duration:0.5
},'>+8')
.to("#yn1", {
scaleY: 3,
duration:0.5,
transformOrigin: "center 0%"
},'>+1')
.to("#yn1_1", {
scaleY: 1,
duration:0.5,
transformOrigin: "center 0%"
},'>+1')
.to("#yn1_2", {
scaleY: 1,
duration:0.5,
transformOrigin: "center 0%"
},'>+1')
.addLabel("food4")
//生产阶级消耗工业品和农产品,生产出价值50亿利弗尔的农产品原料
.to("#food4", {
y: 80,
duration:1
},'food4+=3')
.to("#food4", {
scale: 1,
duration:0
},'food4+=3')
.to("#food4_num", {
innerHTML: 50,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food4+=3')
.to("#ind4", {
y: 80,
duration:1
},'food4+=3')
.to("#ind4", {
scale: 1,
duration:0
},'food4+=1')
.to("#ind4_num", {
innerHTML: 0,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food4+=3')
.to("#ind4", {
scale:0,
duration:0.5,
},'>+0.5')
.addLabel("food5")
//土地所有者阶级则什么也没生产,只是消费。最终剩下的是20亿利弗尔货币
.to("#food5", {
scale: 1,
duration:0
},'food5+=8')
.to("#food5", {
y: 80,
duration:1
},'food5+=8')
.to("#coin2", {
scale: 1,
duration:0
},'food5+=8')
.to("#coin2", {
y: 80,
duration:1
},'food5+=8')
.to("#ind5", {
scale: 1,
duration:0
},'food5+=8')
.to("#ind5", {
y: 80,
duration:1
},'food5+=8')
.to("#food5_num", {
innerHTML: 0,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food5+=8')
.to("#ind5_num", {
innerHTML: 0,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food5+=8')
.to("#food5", {
scale: 0,
duration:0.5,
},'>+1')
.to("#ind5", {
scale: 0,
duration:0.5,
},'<')
.addLabel("food6")
//非生产阶级则消耗20亿利弗尔农产品,生产出20亿利弗尔的工业品
.to("#food6", {
scale: 1,
duration:0
},'food6+=2')
.to("#food6", {
y: 80,
duration:1
},'food6+=2')
.to("#ind6", {
scale: 1,
duration:0
},'food6+=2')
.to("#ind6", {
y: 80,
duration:1
},'food6+=2')
.to("#food6_num", {
innerHTML: 0,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food6+=2')
.to("#ind6_num", {
innerHTML: 20,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food6+=2')
.to("#food6", {
scale: 0,
duration:0.5
},'>+1')
//生产消费阶段结束,接下来是交换阶段
.to("#yn2", {
scaleY: 15,
duration:0.5,
transformOrigin: "center 0%"
},'>+5')
.to("#yn2_3", {
scaleY: 1,
duration:0.5,
transformOrigin: "center 0%"
},'>+1')
.addLabel("food7")
//我们把各阶级的产品和货币各自划分为若干份
.to("#food7", {
y: 80,
duration:1
},'food7+=2')
.to("#food7", {
scale: 1,
duration:0
},'food7+=2')
.to("#food8", {
y: 140,
duration:1
},'food7+=2')
.to("#food8", {
scale: 1,
duration:0
},'food7+=2')
.to("#food9", {
y: 200,
duration:1
},'food7+=2')
.to("#food9", {
scale: 1,
duration:0
},'food7+=2')
.to("#food10", {
y: 260,
duration:1
},'food7+=2')
.to("#food10", {
scale: 1,
duration:0
},'food7+=2')
.to("#coin3", {
scale: 1,
duration:0
},'>+2')
.to("#coin3", {
y: 80,
duration:1
},'<')
.to("#ind7", {
scale: 1,
duration:0
},'>+2')
.to("#ind7", {
y: 80,
duration:1
},'<')
.to("#ind8", {
scale: 1,
duration:0
},'<')
.to("#ind8", {
y: 140,
duration:1
},'<')
.addLabel("change1")
//首先发起交换的,只能是拥有货币的土地所有者阶级
//他们用10亿利弗尔货币从生产阶级那交换等价的农产品
.to("#coin3_num", {
text: {
value:10
},
duration:0
},'change1+=12')
.to("#coin4", {
scale:1,
duration:0
},'change1+=12')
.to("#coin4", {
x:-320,
duration:1
},'change1+=12')
.to("#food7", {
x:270,
duration:1
},'change1+=12')
.to("#cl1", {
scaleX:14,
duration:0.5,
transformOrigin: "100% center"
},'change1+=10')
.addLabel("change2")
//再用剩下的10亿利弗尔货币从非生产阶级那交换等价的工业品
.to("#cl2", {
scaleX:14,
duration:0.5,
transformOrigin: "0% center"
},'change2+=3')
.to("#coin3", {
x:335,
duration:1,
},'change2+=4')
.to("#ind7", {
x:-285,
duration:1,
},'change2+=4')
.addLabel("change3")
//生产阶级花费10亿利弗尔货币从非生产阶级那里交换10亿利弗尔的工业品
.to("#cl3", {
scaleX:40,
rotation:-5,
duration:0.5,
transformOrigin: "100% center"
},'change3+=11')
.to("#food8", {
x:655,
y:80,
duration:1,
},'change3+=13')
.to("#coin3", {
y:140,
x:-320,
duration:1,
},'change3+=13')
.addLabel("change4")
.to("#cl4", {
scaleX:41,
duration:0.5,
transformOrigin: "0% center"
},'change4+=12')
.to("#coin3", {
y:140,
x:335,
duration:1,
},'change4+=14')
.to("#ind8", {
x:-655,
duration:1,
},'change4+=14')
.addLabel("change5")
//非生产阶级再次获得10亿利弗尔货币
//他们将用来交换到最后所需的农产品原料和粮食
.to("#cl5", {
scaleX:40,
rotation:-5,
duration:0.5,
transformOrigin: "100% center"
},'change5+=9')
.to("#food9", {
x:655,
y:140,
duration:1,
},'change5+=11')
.to("#coin3", {
x:-320,
y:200,
duration:1,
},'change5+=11')
.addLabel("tex")
//三大阶级交换完成
.to("#coin3", {
x:0,
y:80,
duration:1,
},'tex+=12.5')
.to("#coin4", {
x:0,
y:0,
duration:1,
},'tex+=12.5')
.to("#coin4", {
scaleY:0,
duration:0,
},'tex+=13.5')
.to("#coin3_num", {
innerHTML: 20,
snap: 'innerHTML',
duration:1,
ease: "none",
},'tex+=13.5')
//好了,现在其实整个经济循环已经回到了初始状态,但为了明显一点,让我们整理一下
.to("#year2001",{
scale:1,
duration:0.5
},">+5.5")
.to("#food11",{
scale:1,
duration:0
},">+5.5")
.fromTo("#food11",{
y:-140,
},{
y:0,
duration:1
},">")
.to("#ind9",{
scale:1,
duration:0
},">+0.5")
.fromTo("#ind9",{
y:-260,
x:-50,
},{
y:0,
x:0,
duration:1
},">")
.to("#food12",{
scale:1,
duration:0
},">+0.5")
.fromTo("#food12",{
y:-320,
},{
y:0,
duration:1
},">")
.to("#coin5",{
scale:1,
duration:0
},">+0.5")
.fromTo("#coin5",{
y:-320,
},{
y:0,
duration:1
},">")
.to("#ind10",{
scale:1,
duration:0
},">+0.5")
.fromTo("#ind10",{
y:-320,
},{
y:0,
duration:1
},">")
.addLabel("food13")
.to("#food13",{
scale:1,
duration:0
},"food13+=0.5")
.fromTo("#food13",{
y:-320,
x:55
},{
y:0,
x:0,
duration:1
},"food13+=0.5")
.to("#food14",{
scale:1,
duration:0
},"food13+=0.5")
.fromTo("#food14",{
y:-320,
x:55
},{
y:0,
x:0,
duration:0.7
},"food13+=0.5")
.addLabel("food14")
.to("#food14",{
scale:0,
duration:0
},"food14+=0")
.to("#food13_num", {
innerHTML: 20,
snap: 'innerHTML',
duration:1,
ease: "none",
},'food14+=0')
.to("#curve",{
scaleY:3.1,
duration:1,
transformOrigin: "100% 100%"
},">+1")
.to("#complete",{
scale:1,
duration:1
},">+1") // .to("#coin1", {
// x: 330,
// y:80,
// duration:1
// },'>+1') let duration=tl.duration();
document.getElementById("total").value=duration;
document.getElementById("seek").max=duration;
document.getElementById("seek").min=0;
document.getElementById("seek").value=0;
</script>
<script type="text/template">
经济循环由3大阶级构成
1.租地农场主、土地所有者、工厂主依次进场
</script>
</body>
</html>

视频观看

B站链接——《经济表》动画

我录制运行结果后,又通过tts给视频配了音,发布在了bilibili,欢迎来查看效果

不过要吐槽的是B站把60帧的选项给搞没了,投上去的720P60帧视频全都变成了30帧

导致高速动画效果惨不忍睹,要是没有大会员,那观看起来真的不太好

使用GSAP制作动画视频的更多相关文章

  1. 在线Youtube视频下载,修改文本,剪切制作动画的最新方法

    刚刚(减去编写本文章的时间,大概20分钟前吧)在看国外最新技术资讯的时候发现有个方法可以让我们快速去下载Youtube上面的视频,不敢独享,我自己都没有怎么玩就所以立刻post上来广而告之,希望对大家 ...

  2. 如何用 Keynote 制作动画演示(转)

    原文:如何用 Keynote 制作动画演示 Keynote 里的很多特效可以用来制作效果不错的演示,一页页的将需要演示的内容交代清楚后,直接输出成 m4v 的视频格式,为了方便贴到博客或者发布到 Tw ...

  3. 前端制作动画的几种方式(css3,js)

    制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...

  4. CSS3制作动画的三个属性

    CSS3属性中有关于制作动画的三个属性:Transform,Transition,Animation:我们一起学习完了Transform和Transition,让我们对元素实现了一些基本的动画效果,这 ...

  5. requestAnimationFrame制作动画:旋转风车

    在以往,我们在网页上制作动画效果的时候,如果是用javascript实现,一般都是通过定时器和间隔来实现的,出现HTML5之后,我们还可以用CSS3 的transitions和animations很方 ...

  6. canvas学习之制作动画

    html部分 ...... <body> <canvas id="myCanvas" width="400" height="400 ...

  7. html5 requestAnimationFrame制作动画:旋转风车

    详细内容请点击 在以往,我们在网页上制作动画效果的时候,如果是用javascript实现,一般都是通过定时器和间隔来实现的,出现HTML5之后,我们还可以用CSS3 的transitions和anim ...

  8. Python+Matplotlib制作动画

    注: 在"实验设计与数据处理"的课后作业中,有一个数据可视化的作业,利用课程上学习的某种方法找一个二维函数的最大值,并将这个寻找的过程可视化.在作业里面利用了Matplotlib的 ...

  9. HTML5标签canvas制作动画

    摘要: canvas可以绘制图像,自然而然的就可以制作动画,因为动画的每一帧都是图像.我们可以利用javascript的setInterval函数来实现动画效果. 下面是一个例子,小圆绕着红点圆心不停 ...

  10. 手把手教你制作AppPreview视频并上传到appStore进行审核

    手把手教你制作AppPreview视频并上传到appStore进行审核 注意,你需要使用iMovie才能够制作AppPreview视频文件,用QuickTime录制的无效! 最终效果 1. 新建一个事 ...

随机推荐

  1. 基于FPGA的电子琴设计(按键和蜂鸣器)----第一版

    欢迎各位朋友关注"郝旭帅电子设计团队",本篇为各位朋友介绍基于FPGA的电子琴设计(按键和蜂鸣器)----第一版. 功能说明: 外部输入七个按键,分别对应音符的"1.2. ...

  2. kubernetes 之网络(canal)

    https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/ 所有节点重设 ...

  3. Kubernetes:kubelet 源码分析之探针

    0. 前言 kubernetes 提供三种探针,配置探针(Liveness),就绪探针(Readiness)和启动(Startup)探针判断容器健康状态.其中,存活探针确定什么时候重启容器,就绪探针确 ...

  4. PasteSpider之appsettings.json中的Serilog的配置,分流不同日志层级的信息!

    在实际使用Serilog中,我们通常会有不一样的需求,常见的比如 1.按照等级,高级哪个等级的才记录 2.记录文件每个多大,超过的划分到下一个文件中 3.不同等级的记录到不同的位置中 4.按照不一样的 ...

  5. FolkMq v1.4.6 发布(可以内嵌的消息中间件)

    功能简表 角色 功能 生产者(客户端) 发布消息.定时消息(或叫延时).顺序消息.可过期消息.事务消息.支持 Qos0.Qos1 消费者(客户端) 订阅.取消订阅.消费-ACK(自动.手动) 服务端 ...

  6. Android 13 - Media框架(11)- MediaCodec(一)

    关注公众号免费阅读全文,进入音视频开发技术分享群! MediaCodec 是 Android 平台上音视频编解码的标准接口,无论是使用软解还是硬解都要通过调用 MediaCodec来完成,是学习 An ...

  7. 使用 TestContainers 进行数据库集成测试

    在软件开发过程中,集成测试是至关重要的一环.它确保不同组件之间的协作正常,并验证系统在整体上的功能和性能.然而,传统的集成测试往往需要依赖于外部资源,如数据库.消息队列等,这给测试环境的搭建和维护带来 ...

  8. 提速15%,PaddleOCRSharp新版v4.3发布

    PaddleOCRSharp v4.3版本,已经于5月23日发布.该版本的发布,在不影响识别精度的同时,带来了10%~15%速度的提升. 项目地址:https://gitee.com/raoyutia ...

  9. Vue插槽与作用域插槽

    title: Vue插槽与作用域插槽 date: 2024/6/1 下午9:07:52 updated: 2024/6/1 下午9:07:52 categories: 前端开发 tags: VueSl ...

  10. C基本知识

    1 C基本数据类型 C基本的数据类型说明: 2 字节序 测试代码: #include <stdio.h> typedef unsigned char *byte_pointer; void ...