HTML/CSS/JS实现点击页面区域平滑缩放至全屏效果
类Prezi视口平滑缩放转场实现方案
你要的镜头拉近式区域放大效果不需要依赖第三方动画库,用CSS过渡配合少量JS状态控制即可实现,纯CSS方案无法动态计算元素偏移量、适配不同尺寸场景,灵活性不足,优先推荐JS+CSS的轻量实现。
实现核心逻辑
- 最外层容器固定占满整个视口,设置溢出隐藏,避免缩放时出现滚动条、非目标区域漏出
- 所有缩放、平移动画统一作用在内容父容器上,用
transform属性实现动画,相比修改宽高、定位属性性能更高,不会触发页面重排 - 给容器设置自定义缓动曲线,模拟Prezi转场的丝滑感,避免生硬的线性动画
- 加状态锁防止动画过程中重复点击导致交互错乱
- 放大状态下再次点击即可回到全览初始视图,符合常规操作逻辑
完整可运行代码
HTML结构
<div class="viewport-wrap"> <div class="container" id="zoomContainer"> <div class="item item1" id="item1">Box 1(点击后放大占满视口,Box 2向右推出屏幕)</div> <div class="item item2" id="item2">Box 2(点击后放大占满视口,Box 1向左推出屏幕)</div> </div> </div>
CSS样式
/* 视口外层,固定铺满浏览器窗口,裁剪溢出内容 */ .viewport-wrap { position: fixed; inset: 0; overflow: hidden; margin: 0; padding: 0; } /* 内容容器,设置过渡动画,变换原点设为左上角简化偏移计算 */ .container { display: flex; flex-direction: row; width: 100vw; height: 100vh; transition: transform 0.8s cubic-bezier(0.25, 1, 0.5, 1); transform-origin: 0 0; } .item { border: 1px solid black; padding: 25px; width: 50%; height: 100%; box-sizing: border-box; text-align: center; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 1.2rem; } /* 放大状态下的鼠标样式提示 */ .item.active { cursor: zoom-out; }
JavaScript逻辑
const container = document.getElementById('zoomContainer'); const item1 = document.getElementById('item1'); const item2 = document.getElementById('item2'); let isZoomed = false; // 缩放状态锁,避免动画过程中重复触发 // 通用缩放方法,传入目标DOM元素即可自动对齐到视口 function zoomToTarget(target) { if (isZoomed) { // 已放大状态下点击,恢复全览视图 container.style.transform = 'scale(1) translate(0, 0)'; document.querySelectorAll('.item').forEach(item => item.classList.remove('active')); isZoomed = false; return; } // 获取目标元素的实时位置、尺寸 const targetRect = target.getBoundingClientRect(); // 计算缩放比例,让目标元素宽度刚好匹配视口宽度 const scaleRatio = window.innerWidth / targetRect.width; // 计算平移偏移量,把目标元素左上角对齐到视口左上角 const translateX = -targetRect.left * scaleRatio; const translateY = -targetRect.top * scaleRatio; // 应用变换实现转场 container.style.transform = `scale(${scaleRatio}) translate(${translateX}px, ${translateY}px)`; target.classList.add('active'); isZoomed = true; } // 绑定点击事件 item1.addEventListener('click', () => zoomToTarget(item1)); item2.addEventListener('click', () => zoomToTarget(item2)); // 窗口尺寸变化时自动修正位置,避免错位 window.addEventListener('resize', () => { if (isZoomed) { const activeItem = document.querySelector('.item.active'); zoomToTarget(activeItem); } });
扩展说明
- 该方案兼容所有内容形式:不管容器内放单张大图、多图拼接的整页图像还是纯CSS绘制的图形,只要给对应可点击区域绑定
zoomToTarget方法传入目标区域DOM,就能实现一致的转场效果 - 动画时长、缓动曲线、缩放比例都可以根据需求调整,修改
transition属性值即可获得不同的转场手感 - 如果需要制作多区域的类Prezi演示,不需要为每个区域单独写逻辑,所有区域都可以复用同一个
zoomToTarget方法
内容的提问来源于stack exchange,提问作者Katie Reynolds
相关产品推荐
相关产品推荐

