卡片列表项缓缓往下展示 效果实现
不久前在某运动APP上看到一个卡片缓缓往下展示的效果,感觉这动画还可以
似乎项目中也有类似的卡片列表,列表的展示是直接显示出来的,加上动效之后应该更有活力,便照着样子实现了一下
这种效果,核心点就是添加了个CSS动画,主要控制了四个属性
先看HTML结构部分
<body> <article> <!-- 卡片容器 --> <div class="items"></div> <a href="javascript:;" class="items-more-btn">展开</a> </article> <!-- 模板结构 --> <script type="text/template" id="item-tpl"> <div class="item item__anim item__anim-{{index}}"> <h2>标题{{index}}</h2> <p>{{content}}</p> </div> </script
绑定事件,点击展开则添加一组卡片,JS部分也不复杂
<script> function addEvent(elem, type, handler) { elem.addEventListener(type, handler, false); } function qs(selector) { return document.querySelector(selector); } function qsa(selectors) { return document.querySelectorAll(selectors); } var mockData = ['内容1', '内容2', '内容3', '内容4', '内容5']; addEvent(qs('.items-more-btn'), 'click', function() { renderList(mockData); }); var itemTpl = qs('#item-tpl').innerHTML; var itemsDOM = qs('.items'); /** * 渲染数据 * @param {[type]} data [description] * @return {[type]} [description] */ function renderList(data) { var data = data.map(function(val, index) { return { index: index + 1, content: val }; }); var html = ''; var fragment = document.createDocumentFragment(); data.forEach(function(item) { var divTemp = document.createElement('div'); // 模板替换 divTemp.innerHTML = itemTpl.replace(/{{(\w+)}}/g, function(input, match) { return match ? item[match] || '' : ''; }); fragment.appendChild(divTemp.firstElementChild); }); // 渲染 itemsDOM.appendChild(fragment); } </script>
最后便是由CSS控制的部分了
每个卡片都有个类名 item__anim ,用以设置动画
动画展开时主要包含四种效果
由上到下的衔接效果:每个卡片自带一个类 item__anim-n ,用以设置延时,当然了,这里就需要引入scss来提高生产力了
往下掉的效果:使用 translate3d 控制y轴位移
渐显效果: 使用 opacity
放大效果:使用 scale
body { background: #f2f2f2; } article { margin-bottom: 100px; width: 500px; text-align: center; } .items { width: 400px; margin: 30px auto; } .items-more-btn { margin-bottom: 20px; } @keyframes showBox { to { opacity: 1; transform: scale(1) translate3d(0, 0, 0); } } .item { position: relative; margin-top: 10px; width: 100%; height: 150px; background: #fff; border-radius: 10px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; color: #666; opacity: 0; transform: scale(.9) translate3d(0, -10px, 0); &:nth-child(odd) { height: 200px; } h2 { width: 100%; font-size: 18px; } &.item__anim { animation-name: showBox; animation-duration: .4s; animation-fill-mode: forwards; } &__anim-1 { animation-duration: .6s; } @mixin showingDelay() { @for $n from 1 through 30 { &__anim-#{$n} { animation-delay: #{(0.05 + $n / 10)}s; } } } @include showingDelay(); }