卡片列表項緩緩往下展示 效果實現
阿新 • • 發佈:2018-12-01
不久前在某運動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(); }