JavaScript常见运动效果实现:图片缩放、滑动淡入与无缝滚动
本文深入剖析了前端开发中三种经典的JavaScript运动特效实现方案,包括利用缓冲运动算法实现的图片平滑放大缩小、结合链式动画的信息条目滑动淡入加载,以及处理边界条件以实现列表内容的无缝循环滚动。这些实例展示了原生JS在DOM操作、定时器和样式动态计算方面的核心应用。
构建通用运动引擎
上述三个案例均依赖一个核心的缓冲运动函数 startMove。该函数通过实时读取元素当前属性值(如宽度、高度、透明度),计算其与目标值之间的差距,并按比例产生速度,从而实现减速停止的平滑视觉效果。
function startMove(obj, json, fn)
{
// 清除原有定时器,防止多重动画冲突
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var bStop = true; // 用于标记是否所有属性均已到达目标值
for (var attr in json) {
var iCur = 0;
// 针对opacity属性需特殊处理百分比
if (attr == 'opacity') {
iCur = parseInt(parseFloat(getStyle(obj, attr)) * 100);
} else {
iCur = parseInt(getStyle(obj, attr));
}
// 计算速度:距离除以系数(缓冲效果)
var iSpeed = (json[attr] - iCur) / 8;
// 速度取整,避免小数点导致的像素模糊
iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
// 若仍有属性未达标,继续运行动画
if (iCur != json[attr]) {
bStop = false;
}
// 执行样式更新
if (attr == 'opacity') {
obj.style.filter = 'alpha(opacity:' + (iCur + iSpeed) + ')';
obj.style.opacity = (iCur + iSpeed) / 100;
} else {
obj.style[attr] = iCur + iSpeed + 'px';
}
}
// 全部达标后清除定时器,并执行回调
if (bStop) {
clearInterval(obj.timer);
if (fn) {
fn();
}
}
}, 30); // 30ms刷新率约等于33FPS
}
// 兼容性获取样式辅助函数
function getStyle(obj, attr) {
return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, false)[attr];
}
第一场景:图片列表的放大与复原
此场景常用于画廊或产品陈列。当用户将鼠标悬停在图片上时,图片平滑放大并置顶;移开后则恢复原状并还原层级。操作关键在于布局转换和z-index的管理。
- 布局转换:初始状态下列表通常为流式布局。JS需在加载时遍历列表项,将其位置固定(absolute),记录其当前的offsetLeft和offsetTop,以便后续定位。
- 鼠标进入:触发
onmouseover事件。首先提升zIndex确保浮出其他元素上方,随后调用startMove改变宽高,并配合marginLeft和marginTop负值调整位置,使放大后的图片视觉上保持居中。 - 鼠标离开:触发
onmouseout事件。重置宽高为原始尺寸,偏移量归零。
第二场景:消息条目的滑动淡入显示
适用于聊天窗口或新闻列表的动态加载。新内容从下方滑入的同时透明度逐渐显现,提升阅读体验。
操作步骤:
- 创建节点:根据输入内容生成新的
<div>元素,插入到容器顶部(或使用insertBefore)。 - 设定初始状态:为了制造“滑入”效果,先强制设置新元素的高度为
0,此时它是不可见的且占据空间为零。 - 链式动画:
- 第一步:调用
startMove将高度从0动画过渡到实际内容高度iH。 - 第二步:在高度动画完成回调函数(
fn)中,再次调用startMove,将opacity从0过渡到100。
- 第一步:调用
第三场景:图片/内容的无缝循环滚动
常用于广告栏或资讯跑马灯。通过将内容复制一份拼接到末尾,并在移动到边界时瞬间复位,肉眼观察不到断裂,形成连续滚动的错觉。
实现逻辑:
- 内容复制:获取目标滚动容器的HTML内容,将其拼接自身一次:
oUl.innerHTML += oUl.innerHTML。这样无论向左还是向右,都有足够的冗余数据供滚动。 - 宽度重置:由于内容加倍,必须重新计算
ul的总宽度以适应容器,防止换行。 - 边界判断(核心):在定时器移动过程中,实时监控
offsetLeft。- 向左滚动(负值方向):当滚动位置超过一半(即第二组数据的起始位置,
< -oUl.offsetWidth / 2)时,立即将位置强行设为0(回到第一组的起始位置),实现无缝衔接。 - 向右滚动(正值方向):当滚动回退到起始位置
> 0时,立即跳变至-oUl.offsetWidth / 2。
- 向左滚动(负值方向):当滚动位置超过一半(即第二组数据的起始位置,
- 交互控制:提供按钮切换速度正负,并支持
onmouseover/onmouseout暂停/恢复滚动,方便用户查看。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













