文字滚动效果
一个类似于新闻播报的效果。
思路
实现一个效果,应该从以下方面切入:
- 页面初始化的时候需要做什么?(init)
- 页面存在什么交互,分别需要做什么?(交互函数)
js动画思路:
- 起始位置start 结束位置end
- 多长时间执行完此动画total 动画间隔时间duration
- 计算出该段时间需要移动次数 计算出每次需要移动的距离
- 执行动画
必要时刻回调函数是可以出奇迹的
案例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文字滚动效果</title>
<link rel="stylesheet" href="./index.css" />
<!-- <script src="./index.js" defer></script> -->
<script src="./myScroll.js" defer></script>
</head>
<body>
<div class="container">
<h1 class="title">最新公告</h1>
<ul class="list">
<!-- 乱数假文 -->
<li>把大象装冰箱总共分几步?</li>
<li>1. 邓哥打开冰箱门</li>
<li>2. 邓哥把大象放进去</li>
<li>3. 邓哥关上冰箱门</li>
</ul>
</div>
</body>
</html>css
.container {
background: #bfedfc;
overflow: hidden;
padding: 20px 0;
}
/* .container::after {
content: '';
display: block;
clear: both;
} */
.title {
float: left;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-left: 20px;
margin-top: 5px;
border-right: 2px solid #ccc;
padding-right: 30px;
}
.list {
float: left;
list-style: none;
padding: 0;
height: 30px;
overflow: hidden ;
margin: 0;
margin-left: 50px;
}
.list li {
height: 30px;
line-height: 30px;
}js
(function () {
// 初始化:一开始做什么
var list = document.querySelector('.list');
// 1. 将列表中的第一个元素,克隆到列表的最后一个
function cloneFirstItem() {
var firstItem = list.children[0];
var newItem = firstItem.cloneNode(true);
list.appendChild(newItem);
}
cloneFirstItem();
// 2. 滚动:每隔一段时间,将列表滚动到下一个位置
var duration = 2000; // 滚动的间隔时间
setInterval(moveNext, duration);
var itemHeight = 30; // 每一项的高度
var curIndex = 0; // 目前展示的是第几项
// 将列表滚动到下一个位置
function moveNext() {
var from = curIndex * itemHeight; // 开始的滚动高度
curIndex++;
var to = curIndex * itemHeight; // 下一项的滚动高度
// 让list的scrollTop,从from慢慢变为to
// 慢慢变为:在一段时间内,每隔一小段时间,变化一点
var totalDuration = 300; // 变化的总时间
var duration = 10; // 变化的间隔时间
var times = totalDuration / duration; //变化的次数
var dis = (to - from) / times; // 每次变化的量
var timerId = setInterval(function () {
from += dis;
if (from >= to) {
// 到达目标值了
clearInterval(timerId); // 停止计时器
// 滚动完成后,如果是最后一项
if (curIndex === list.children.length - 1) {
from = 0;
curIndex = 0;
}
}
list.scrollTop = from;
}, duration);
}
})();js
const list = document.querySelector('.list');//获取到ul
/* 1. 页面初始的时候做什么 */
// 克隆第一个元素
function cloneFirst() {
const first = list.children[0];
const clone = first.cloneNode(true);
list.appendChild(clone);
}
cloneFirst();
/* 2. 页面有什么交互 */
let currentIndex = 0;//当前的索引
let distance = 0;//向上滚动的距离
const itemHeight = 30;//每个列表项的高度
const duration = 1000;//滚动的间隔时间
// 移动列表滚动
function moveNext() {
// JS动画
const start = currentIndex * itemHeight;
currentIndex++;
const to = currentIndex * itemHeight;
easeAnimation(start, to, 500, (offset, isEnd) => {
let dy = offset;
const isExceed = currentIndex === list.children.length - 1;
//边界判断
if (isEnd && isExceed) {
currentIndex = 0;
dy = 0;
}
list.scrollTop = dy;
});
}
/**
*
* @param {*} start 起始位置
* @param {*} end 结束位置
* @param {*} totalDuration 动画执行总时长
* @param {*} cb 回调函数
*/
function easeAnimation(start, end, totalDuration, cb) {
const duration = 10;//动画间隔时间,越小越平滑
const times = totalDuration / duration;//算出该段距离动画需要执行多少次
const distance = (end - start) / times;//计算每次移动的距离
let timer;
let isEnd = false;//动画是否结束
timer = setInterval(() => {
start += distance;
if (start >= end) {
clearInterval(timer);
isEnd = true;
}
cb && cb(start, isEnd);
}, duration)
}
setInterval(() => {
moveNext(distance);
}, duration);