共计 3230 个字符,预计需要花费 9 分钟才能阅读完成。
首先来看看蔚来官网长什么样子
不会做动图,所以具体效果可以去蔚来官网看
HTML
根据效果,我们来分析一下
页面加载进去后会有黑色的背景,然后慢慢地图片和文字动画加载出来说明背景图不是在父亲节点加背景图片,否则不会有黑色背景和图片的动画那么就需要一个单独的子盒子来做背景切换动画,中间居中的内容也需要盒子来包,可以得出的 HTML 结构是
.container>.items>.item>(.context>inner-box)+(.pic>img.bgp)
好了背景的盒子分析完了,再来观察一下内容
F12 发现 是一张 logo,
,是一个 p 标签,这里可以观察到,p 标签的长度和 logo 的长度一样大,如果用 letter-spacing,把他撑开很明显不太理智,所以这里选择用 text-align-last justify 这个样式,那么就需要 img 和 p 标签都包在一个盒子里
,是两个 a 标签。都需要居中对其,而且两个 a 标签中间留有空白,可以考虑使用弹性布局,那么可以得出的 HTML 结构是:
.container>.items>.item>(.context>inner-box>(.wl-logo>img+p)+(.btn-box>a*2))+(.pic>img.bgp)
好了,HTML 已经定义好了
CSS
css 我就不细讲了,就把几个难的点说出来,并贴出部分 css 样式
- 前面的大盒子,宽度全部定义为 100%
-
.context 盒子的居中
.context position absolute text-align center top 26% left 50% transform translate(-50%, -50%)
-
p 标签的拉伸
p -moz-text-align-last justify text-align-last justify
-
a 标签的弹性布局
父盒子:.btn-box display flex justify-content space-between
为了 a 标签尽可能美观一些,a:
a border 2px solid #fff text-align center width 45% height 46px line-height 46px border-radius 23px font-weight 700 font-size 16px letter-spacing 2px
-
背景图动画加载时的黑色
.pic width 100% background-color #000
JS
终于到了万众期待的 JS 部分了,这里引用了 jquery 的库,来简化我们操作
可以观察到蔚来官网,滚轮越往下滚,就会有一个从无到有的动画展现出来,那么很明显这里需要一个监听滚轮事件
$(document).scroll();
有了滚轮监听事件,还需要对有动画的元素进行操作,对每个有动画的元素加上 class
<img src="./images/a.png" class="bgp logo" alt=""> //logo
<p class="p"> 全国试驾开启 </p> //p
<a class="bat" href="#"> 报名试驾 </a> //a
<a class="bat" href="#"> 探索 ES6</a> //a
<img class="bgp" src="./images/b.jpg" alt=""> // 背景图
先定义几个全局变量
const winHeight = $(window).height(), // 浏览器可视的高度
clsarr = []; // 所有需要操作的元素
var tp = $(document).scrollTop() || 0;// 滚轮下滑的大小
那么先把所有需要操作的元素放在 clsarr 里,由于 find()得到的结果是一个数组,为了防止后面操作麻烦,把他拆开来放进 clsarr, 避免 clsarr 成为一个二维数组
[].forEach.call($('.item'),item => {pusharr(clsarr,$(item).find('.p'))
pusharr(clsarr,$(item).find('.bat'))
pusharr(clsarr,$(item).find('.bgp'))
function pusharr(arr1,arr2){if(arr2.length <= 1){arr1.push($(arr2[0]))
}else{[].forEach.call(arr2,item=>{arr1.push($(item))
})
}
}
})
现在基本数据已经处理完毕了,开始页面动画的初始化,要让所有元素隐藏,首先定义一个 css 样式:
.hid
opacity 0
然后让每个元素添加上这个 class
clsarr.forEach(item=>{item.addClass('hid')
})
现在要开始最关键的判定方法了,判断一个元素是否出现在可视区域内,来让我们看一个图:
元素需要全部在可视区域,才应该显示出来,背景只需要出现,不需要全部在可视区域就应该显示出来
如果一个元素全部展示在可视区域中,应该满足同时满足
- 滚轮滚动的长度 + 页面可视的高度 > 元素的高度 + 元素到页面顶端的长度
- 元素的高度 + 元素到页面顶端的长度度 > 滚轮滚动的长度
如果一个背景部分展示在可视区域中,应该满足同时满足
- 滚轮滚动的长度 + 页面可视的高度 > 背景到页面顶端的长度
- 背景到页面顶端的长度 + 背景的高度 > 滚轮滚动的长度
那么响应的 js 代码
function md(num){return Math.round(num)
}
function isrender(tp,wh,ot,oh){ // 元素判定方法 tp 滚轮滚动的长度,wh 页面可视的高度,ot 元素的高度,oh 元素到页面顶端的长度
if(((md(tp) + md(wh) - 20) > (md(ot) + md(oh))) && ((md(ot) + md(oh)) > md(tp))){return true}
return false
}
function isbgprender(tp,wh,ot,oh){ // 背景判定方法 tp 滚轮滚动的长度,wh 页面可视的高度,ot 背景的高度,oh 背景到页面顶端的长度
if(((md(tp) + md(wh)) > md(ot)) && (md(ot) + md(oh) > (md(tp)))){return true}
return false
}
好了,终于到最后一步了了,先把动画定义一下
.anm
opacity 1
animation pulse 1s linear 1
.show
transition all 2s ease .2s
opacity 1
@keyframes pulse {
0%,50%{
opacity: 0;
transform: translate(0, 100%);
}
100% {
opacity: 1;
transform: translate(0, 0);
}
}
然后把动画渲染到页面上去,流程图:
代码:
function render(tp,wh){
clsarr.forEach(ele=>{if(ele.hasClass('bgp')){if(ele.hasClass('logo')){if(isrender(tp,wh,ele.offset().top,ele.height())){ele.addClass('show')
}
}else{if(isbgprender(tp,wh,ele.offset().top,ele.height())){ele.addClass('show')
}
}
}else{if(isrender(tp,wh,ele.offset().top,ele.height())){ele.addClass('anm')
}
}
})
}
最后只需要在监听事件和外部调用这个方法就行啦:
render(tp,winHeight);
$(document).scroll(()=>{tp = $(document).scrollTop()
render(tp,winHeight)
});
好了,总算完成了,附上网页链接 https://cysgg.github.io/weila…
end