Scroll Zoom Reveal - 滚动变焦揭示特效 是做什么的?
一个即插即用、无依赖的滚动效果:
- 固定全屏场景:标题覆盖在全屏暗化场景上。
- 推拉镜头:场景轻微稳定后,“摄像机”向后拉远。场景显示在笔记本电脑屏幕上(边框和底座随之出现)。
- 应用揭示:编辑器面板(工具栏、大纲、属性、时间轴)滑入,场景缩小到其视口面板中。
- 下方文字淡入(
data-zr-fade),然后是带滑动药丸切换的标签淡入淡出画廊。
所有即用文件位于本文件旁的assets/目录中:
| 文件 | 用途 |
|---|---|
assets/zoom-reveal.css | 所有样式(.zr上的主题令牌) |
assets/zoom-reveal.js | 组件 + 淡入 + 画廊。暴露window.ZoomReveal,自动初始化[data-zoom-reveal] / [data-zr-gallery] / [data-zr-fade] |
assets/oled-field.js | 可选。光标反应式OLED子像素场(window.OledField,自动初始化[data-zr-oled])。样式在zoom-reveal.css中 |
assets/placeholder-scenes.js | 可选。在canvas上程序化绘制原始占位艺术(ZRScenes.drawCity,ZRScenes.drawCanyon),直到有真实图像 |
assets/demo.html | 完整可用页面。从此标记开始。 |
如何在网站上使用
- 将assets复制到项目中(例如
public/zoom-reveal/或src/vendor/zoom-reveal/)。仅在没有真实作品时复制placeholder-scenes.js。 - **阅读
assets/demo.html**并复制<section class="zr" data-zoom-reveal>…</section>块(如果需要画廊块也一并复制)。保持类结构完全一致:
section.zr[data-zoom-reveal] ← 滚动长度在此定义 (--zr-length)
.zr-sticky ← 固定100vh舞台
.zr-glow (可选环境光晕)
.zr-device ← 由JS缩放
.zr-lid > .zr-display
.zr-viewport > .zr-media > img | video | canvas ← 您的场景
.zr-chrome > .zr-panel.zr-toolbar / .zr-left / .zr-right / .zr-bottom (可选应用UI)
.zr-base (笔记本电脑底座;如果是显示器/平板则删除)
.zr-scrim + header.zr-intro ← 场景上的标题,先淡出
.zr-caption ← 小字说明,最后淡入
- 在
<head>中加载zoom-reveal.css,在<body>末尾加载zoom-reveal.js。 - 替换媒体:将演示canvas替换为真实场景:
- 图片:
<img src="scene.avif" alt="" decoding="async">。导出时至少为视口大小 × DPR(2560–3200像素宽)。效果从图片铺满整个屏幕开始。 - 滚动擦洗视频:
<video data-zr-scrub muted playsinline preload="auto" src="scene.mp4"></video>。JS将滚动进度映射到currentTime。编码时每帧设为关键帧以确保平滑搜索:ffmpeg -i in.mov -c:v libx264 -g 1 -crf 22 -an -movflags +faststart scene.mp4。
- 图片:
- 重写所有文字(简介语、标题、说明、面板标签、文件名、画廊标签)以匹配网站。切勿使用演示的虚构文本“Orbit / Forge”。
- 通过
.zr上的令牌进行主题化:--zr-bg、--zr-fg、--zr-muted、--zr-accent、--zr-length(滚动距离,默认360vh)。
选项
在属性中传递JSON,例如data-zoom-reveal='{"maxWidth":1000,"viewport":{"top":0,"right":0,"bottom":0,"left":0}}',或在JS中构造:new ZoomReveal(el, options)。
| 选项 | 默认值 | 含义 |
|---|---|---|
maxWidth | 1180 | 最终显示最大宽度(px) |
widthRatio / heightRatio | 0.82 / 0.64 | 最终显示大小相对于视口 |
aspect | 0.625 | 显示高度÷宽度(16:10)。手机≈2.16,超宽屏≈0.42 |
overscan | 1.04 | 显示起始处超出视口的距离(隐藏边框) |
dolly | 1.14 | 媒体的初始内部缩放;稳定到1 |
lift | 0.035 | 设备在结束时抬升的量 |
timeline | 见JS | intro、dolly、zoom、chrome、caption的[start,end]进度窗口 |
viewport | {top:6.5,right:21,bottom:22,left:15} | 应用UI内场景面板的最终内边距(显示区域的百分比)。**全部设为0并删除.zr-chrome**可实现纯“场景→设备屏幕”拉远,无应用UI |
onProgress | — | fn(p)回调,进度0..1 |
事件:section会派发zr:resize,包含{width, height, finalWidth},即媒体实际布局的像素大小。可用于调整canvas大小或选择图片源。
React / Next.js
全局导入CSS。从标记中移除data-zoom-reveal,手动构造以绑定组件生命周期(Next.js中需使用'use client'):
useEffect(() => {
import('./zoom-reveal/zoom-reveal.js').then(() => { // 注册 window.ZoomReveal
const zr = new window.ZoomReveal(ref.current, { maxWidth: 1100 });
const gal = galRef.current && new window.ZoomReveal.Gallery(galRef.current);
window.ZoomReveal.initFades();
cleanup = () => zr.destroy();
});
let cleanup = () => {};
return () => cleanup();
}, []);
将class转换为className,style="--v:78%"转换为style={{'--v':'78%'}}。
OLED像素场(光标悬停效果)
一个铺满全屏的微小RGB子像素条背景,暗淡发光。移动鼠标会扰动一个小型流体模拟。沿路径的像素亮起、生长并从紫色过渡到青色再到石灰绿再到暖白色,然后光晕沿鼠标方向漂移、扩散并淡出。点击或触摸产生涟漪。鼠标空闲时(以及触摸屏上),缓慢的“幽灵光标”维持效果。渲染使用WebGL1片段着色器,模拟使用小型CPU网格,仅在section可见时运行。没有WebGL时回退为CSS聚光灯。
放在规格/数据块、英雄区或CTA条后面。任何元素均可:添加class="zr-oled" data-zr-oled,内部放置内容,加载zoom-reveal.css + oled-field.js。组件会自动插入canvas。参见assets/demo.html中的“OLED像素场”块。
<section class="zr-oled" data-zr-oled='{"cell":7}'>
<div class="your-content">…数据 / 标题…</div>
</section>
<script src="oled-field.js"></script>
| 选项 | 默认值 | 含义 |
|---|---|---|
cell | 6 | 每个像素的CSS px(3个子像素条)。5–9合适;移动端可用更大值提升性能 |
radius | 2.4 | 画笔半径(以cell为单位) |
strength | 0.55 | 光标增加的光量。默认值故意低调;1更醒目 |
decay | 0.94 | 每帧衰减;越高则拖尾越长(0.92短…0.97长) |
flow | 0.55 | 光晕沿光标方向漂移的距离 |
diffusion | 0.35 | 光晕扩散速度 |
base | 0.09 | 未点亮网格的亮度 |
palette | ['#5a3cff','#1fd6ff','#b6ff4a','#fff4d8'] | 4种颜色,低→高能量。匹配品牌,例如暖色['#ff3c5a','#ff9a1f','#ffe14a','#fff8e8'] |
ambient / ripples | true | 空闲时幽灵光标 / 点击涟漪 |
如需更醒目的效果(接近展示效果),使用{"radius":3.2,"strength":1,"decay":0.962,"flow":0.9}。在文字密集的section后保持默认的微妙值。
API:const f = new OledField(el, opts),f.pulse(clientX, clientY)(从代码触发涟漪),f.destroy()(在React清理中调用)。为场上的文本添加柔和的深色text-shadow,以便在明亮轨迹上保持可读。
注意事项(在完成前检查)
- 粘性定位失效:如果
.zr的任何祖先元素具有overflow: hidden/auto/clip或transform,粘性定位会失效。如果必须隐藏水平溢出,请在body上使用overflow-x: clip。 - 不要将
.zr包裹在会转换页面的平滑滚动库中(如Locomotive v4等)。Lenis可以。 - 设备布局时放大然后缩小,因此媒体保持清晰。不要在
.zr-device内使用固定px大小:请使用em(1em = 显示宽度的1%)。 - 减少动画处理:section取消固定并显示最终状态;画廊停止自动播放;OLED场保持对光标反应,但移除幽灵光标和涟漪。
- 背景标签页中动画暂停(requestAnimationFrame停止)。在浏览器面板中测试OLED场时,请保持页面可见,否则看起来会冻结。
- 在约500px宽度以下,笔记本电脑显得很小。考虑使用
{"widthRatio":0.92}或将aspect匹配手机框架的宽高比。 - 在桌面端和移动端宽度下,从顶部到底部缓慢滚动测试。确认标题在拉远前淡出,开始时没有边框显示,且说明不与底座重叠。
- 使用原创或授权作品和文字。此技能重现的是运动技术;不要复制其他品牌的图片、产品渲染或文字。
