用于React的逼真的<Spoiler />
组件
受Telegram剧透功能启发,spoiled渲染一个动画粒子云覆盖文本、内联或块级元素,将其隐藏直到被揭示。
- 使用**CSS绘制API(Houdini)实现内联元素的逼真渲染。提供静态图像备用方案**;
- 支持浅色/深色/系统模式;
- 动画内容过渡(淡入淡出/光圈),或自定义;
- 遵循
prefers-reduced-motion
; - 控制性能:FPS、密度、颜色等;
CSS绘制API在Firefox和Safari中仍不受支持。 我们为这些浏览器提供静态备用图像,你可以通过
fallback
属性自定义。此外,还有一个可用的polyfill。
如何使用?
安装包,需要React 18:
npm i spoiled
或使用你喜欢的包管理器:
pnpm add spoiled
yarn add spoiled
用剧透包裹你的文本,以保持情节转折隐藏:
import { Spoiler } from "spoiled";
// 悬停时揭示
<Spoiler>
霍格沃茨是一个高科技<b>创业孵化器</b>
</Spoiler>;
默认情况下,剧透功能:
- 悬停时揭示(非受控)
- 使用系统配色方案
- 将内容包裹在
span
元素中 - 注入少量CSS用于内容过渡(请阅读下面如何选择退出)
所有标准属性都被代理到底层span
元素。你也可以使用tagName
属性更改标签:
<Spoiler className="custom" aria-label="完全保密">
尼奥开设了一个数字健康retreat
</Spoiler>;
// 你也可以隐藏块级元素!
<Spoiler tagName="div">
<img />
</Spoiler>;
隐藏和揭示剧透
<Spoiler />
是非受控的,默认隐藏。使用revealOn
属性来设置点击或悬停时揭示内容:
<Spoiler revealOn="click">点击我</Spoiler>;
<Spoiler revealOn="hover">悬停我</Spoiler>;
// 点击隐藏剧透
<Spoiler defaultHidden={false} revealOn="click">
弗罗多开始了一个戒指主题的珠宝系列
</Spoiler>;
然而,我们建议传递hidden
属性从你的应用控制剧透状态:
const [hidden, setHidden] = useState(true);
<Spoiler hidden={hidden} onClick={() => setHidden((s) => !s)} />;
主题
剧透适应当前的配色方案,但你也可以覆盖主题和噪点的强调色:
/**
* 主题
*/
<Spoiler /> // 默认主题是`system`
<Spoiler theme="dark" />
<Spoiler theme="light" />
/**
* 自定义噪点的主要颜色
*/
<Spoiler accentColor="red" />
// 使用浅色和深色颜色数组实现
// 动态强调色
<Spoiler accentColor={["black", "white"]} />
性能
Spoiled使用IntersectionObserver
在元素离开视口时停止动画。
你还可以使用fps
和density
属性控制性能:
// 默认FPS是24,但16-20也应该看起来不错
<Spoiler fps={16} />
// 默认:0.12
// 控制渲染的粒子数量
// 越高,噪点越密集
<Spoiler density={0.2}>重要秘密</Spoiler>
单词形状
当应用于内联元素时,<Spoiler />
会尝试模仿段落中单词的形状(伪造单词间的空格)。
由于可能不准确,使用mimicWords
设置来禁用它:
<Spoiler mimicWords={false}>这将被渲染为一行实心文本</Spoiler>
样式
Spoiled会按需将一个小的<style>
标签注入文档,其中包含用于隐藏和揭示过渡动画的CSS。你可以使用无样式版本,然后以不同方式加载这些样式。
import { Spoiler } from "spoiled/no-css";
// 如果你使用Vite或类似的打包工具,这些样式将被写入最终的CSS包中
import "spoiled/style.css";
免责声明
截至2024年,CSS Houdini API得到了70%浏览器的支持(我们确实有备用方案!)。当用于大块文本时,动画可能不流畅且性能不佳。
此外,我们不保证秘密会保持隐藏。使用风险自负。