源代码下载
https://github.com/comehope/front-end-daily-challenges
代码解读
定义dom,容器中包含2个子容器,.horizontal代表水平的线段,.vertical代表垂直的线段,每个子容器中包含4个子元素:
<divclass="container">
<divclass="horizontal">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<divclass="vertical">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
居中显示:
body{
margin:0;
height:100vh;
display:flex;
align-items:center;
justify-content:center;
background-color:skyblue;
}
设置容器尺寸,其中--side-length是方阵的每一边的元素数量:
.container{
--side-length:2;
position:relative;
width:calc(40px*calc(var(--side-length)));
height:calc(40px*calc(var(--side-length)));
}
用grid布局排列子元素,4个元素排列成2*2的方阵:
.container.horizontal,
.container.vertical{
position:absolute;
top:0;
left:0;
display:grid;
grid-template-columns:repeat(var(--side-length),1fr);
}
设置子元素的样式,.horizontal内的子元素是横条,.vertical内的子元素是竖条:
.container.horizontalspan{
width:40px;
height:10px;
background:#fff;
margin:15px0;
}
.container.verticalspan{
width:10px;
height:40px;
background:#fff;
margin:015px;
}
至此,静态布局完成,接下来用d3批量处理子元素。
引入d3库:
<scriptsrc="https://d3js.org/d3.v5.min.js"></script>
删除掉html文件中的子元素dom节点,删除掉css文件中声明的css变量。
定义方阵每一边的元素数量,并把这个数值赋给css变量:
constSIDE_LENGTH=2;
letcontainer=d3.select('.container')
.style('--side-length',SIDE_LENGTH);
定义一个添加span子元素的函数,分别添加横向和竖向的子元素:
functionappendSpan(selector){
container.select(selector)
.selectAll('span')
.data(d3.range(SIDE_LENGTH*SIDE_LENGTH))
.enter()
.append('span');
}
appendSpan('.horizontal');
appendSpan('.vertical');
此时,布局已改为动态的,可以通过修改SIDE_LENGTH的值来创建不同边长的方阵,比如以下语句将创建5*5的方阵:
constSIDE_LENGTH=5;
接下来用GSAP创建动画。(注:因scrimba在使用gsap时会崩溃,所以视频演示采用css动画,但codepen和github均采用gsap动画)
引入GSAP库:
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
声明动画变量animation,声明代表dom元素的变量$horizontalSpan和$verticalSpan:
letanimation=newTimelineMax({repeat:-1});
let$horizontalSpan='.container.horizontalspan';
let$verticalSpan='.container.verticalspan';
先创建横条的动画,共分成4步,每个to语句的最后一个参数是步骤的名称:
animation.to($horizontalSpan,1,{rotation:45},'step1')
.to($horizontalSpan,1,{x:'-10px',y:'-10px'},'step2')
.to($horizontalSpan,1,{rotation:0,x:'0',y:'0',scaleY:2,scaleX:0.5},'step3')
.to($horizontalSpan,1,{rotation:90,scaleY:1,scaleX:1},'step4')
再创建竖条的动画,to语句的步骤名称与横条的步骤名称相同,以便与横条保持动画同步:
animation.to($verticalSpan,1,{rotation:45},'step1')
.to($verticalSpan,1,{x:'10px',y:'10px'},'step2')
.to($verticalSpan,1,{x:'0',y:'0',scaleX:2,scaleY:0.5},'step3')
.to($verticalSpan,1,{rotation:90,scaleX:1,scaleY:1},'step4');
在动画的末尾用时间尺度缩放函数让动画播放速度加快一倍:
animation.timeScale(2);
最后,把方阵的边长改为10,方阵越大就越有气势:
constSIDE_LENGTH=10;
大功告成!
Tag:
如何
效果