🆕 Bricks 2.4 已发布:查询循环性能提升 40%,迁移教程同步更新 →

首页 / 中文教程 / 教程

如何在 Bricks 中用 RoughNotation.js 实现滚动标注动画

实战技巧:如何在 Bricks 中用 RoughNotation.js 实现滚动标注动画——Bricks 实操步骤+踩坑提醒,适合外贸独立站与 WordPress 开发者。

Ray ChanRay Chan·2026-08-12·约 5 分钟

“目录”

  • text: “环境要求”

  • text: “JavaScript”

  • text: “加载脚本”

  • text: “HTML 代码”

  • text: “结论”

— 本教程提供可直接粘贴的 PHP 与 JS 代码,让你在 Bricks Builder 里用 RoughNotation 库实现「滚动到元素时触发手绘风格标注动画」——高亮、下划线、方框、圆圈、删除线等效果。 ## 目录 - 环境要求

  • JavaScript

  • 加载脚本

  • HTML 代码

  • 结论 ## 环境要求 - Bricks 主题(任意版本)

  • 已激活 Bricks 子主题 ## JavaScript 首先在子主题里创建 init.js 文件。本例在子主题的 /js/ 文件夹下创建了 roughNotation_init.js,内容如下: javascript import { annotate } from 'https://unpkg.com/rough-notation?module'; window.addEventListener('load', () =>{ const annotations = { 'highlight-1': { type: 'highlight', color: '#fcc2d2', iterations: 4, multiline: true, animate: true }, 'highlight-2': { type: 'highlight', color: 'orange', iterations: 4, multiline: true, animate: true }, 'underline': { type: 'underline', color: 'yellow', iterations: 4, multiline: true, animate: true }, 'box': { type: 'box', color: 'purple', iterations: 2, multiline: true, animate: true }, 'circle': { type: 'circle', color: 'green', iterations: 1, multiline: true, animate: true }, 'strike-through': { type: 'strike-through', color: 'red', iterations: 1, multiline: true, animate: true }, 'crossed-off': { type: 'crossed-off', color: 'black', iterations: 2, multiline: true, animate: true }, 'bracket': { type: 'bracket', brackets: ['left','right'], color: 'blue', iterations: 2, multiline: true, animate: true }, }; // Set the variables var iOSupported = "IntersectionObserver" in window; /* true if supported */ var box = document.querySelectorAll('.notation'); // Check if IntersectionObserver is supported by the browser if (!iOSupported) { return; } // Set the config options const config = { root: null, // sets the framing element to the viewport rootMargin: '0% 0% -25% 0%', // the animation will be triggered when at 25% from the bottom of the viewport threshold: 0 }; // Init the observer let observer = new IntersectionObserver((entries) => { entries.forEach((item) => { let annotationType = item.target.dataset.notationType; let annotation = annotate(item.target, annotations[annotationType]); if (item.isIntersecting) { // Show the annotation when intersecting and stop observing after it. annotation.show(); observer.unobserve(item.target); } else { // Add an action when the target is not intersecting anymore. } }); }, config); box.forEach((item) => { observer.observe(item); }); }) 脚本分两个部分: 第一部分是定义动画样式对象的 annotations 常量——每种标注类型可配置 type、color、iterations、padding 等大量选项,完整选项列表见作者的项目主页。为了演示全部标注类型,示例定义了以下动画: javascript const annotations = { 'highlight-1': { type: 'highlight', color: '#fcc2d2', iterations: 4, multiline: true, animate: true }, 'highlight-2': { type: 'highlight', color: 'orange', iterations: 4, multiline: true, animate: true }, 'underline': { type: 'underline', color: 'yellow', iterations: 4, multiline: true, animate: true }, 'box': { type: 'box', color: 'purple', iterations: 2, multiline: true, animate: true }, 'circle': { type: 'circle', color: 'green', iterations: 1, multiline: true, animate: true }, 'strike-through': { type: 'strike-through', color: 'red', iterations: 1, multiline: true, animate: true }, 'crossed-off': { type: 'crossed-off', color: 'black', iterations: 2, multiline: true, animate: true }, 'bracket': { type: 'bracket', brackets: ['left','right'], color: 'blue', iterations: 2, multiline: true, animate: true }, }; 第二部分负责滚动触发动画,用的是 IntersectionObserver API,非常轻量(方法同这篇教程): javascript // Set the variables var iOSupported = "IntersectionObserver" in window; /* true if supported */ var box = document.querySelectorAll('.notation'); // Check if IntersectionObserver is supported by the browser if (!iOSupported) { return; } // Set the config options const config = { root: null, // sets the framing element to the viewport rootMargin: '0% 0% -25% 0%', // the animation will be triggered when at 25% from the bottom of the viewport threshold: 0 }; // Init the observer let observer = new IntersectionObserver((entries) => { entries.forEach((item) => { let annotationType = item.target.dataset.notationType; let annotation = annotate(item.target, annotations[annotationType]); if (item.isIntersecting) { // Show the annotation when intersecting and stop observing after it. annotation.show(); observer.unobserve(item.target); } else { // Add an action when the target is not intersecting anymore. } }); }, config); box.forEach((item) => { observer.observe(item); }); 配置里 rootMargin: '0% 0% -25% 0%' 表示元素进入视口底部 25% 区域时才触发动画。 ## 加载脚本 RoughNotation 库走的是 JavaScript ES module,所以加载方式比常规脚本略特殊——需要给 <script> 标签加上 type="module"。把下面代码粘贴到子主题的 functions.php: php add_action( 'wp_enqueue_scripts', function() { // Enqueue your files on the canvas & frontend, not the builder panel. Otherwise custom CSS might affect builder) if ( ! bricks_is_builder_main() && class_exists( 'ACF' ) ) { // Rough Notation if ( get_field( 'activate_roughnotationjs' ) ) { wp_enqueue_script( 'roughNotation_init', get_stylesheet_directory_uri() . '/js/roughNotation_init.js', array(), filemtime( get_stylesheet_directory() . '/js/roughNotation_init.js' ) ); } } }); // Add type="module" to our script tag function add_type_attribute( $tag, $handle, $src ) { // if not your script, do nothing and return original $tag if ( 'roughNotation_init' !== $handle ) { return $tag; } // change the script tag by adding type="module" and return it. $tag = '<script type="module" src="' . esc_url( $src ) . '"></script>'; return $tag; } add_filter( 'script_loader_tag', 'add_type_attribute' , 10, 3 ); > 💡 译者注:原文此处爬取文本里混入了 markdown 链接残留(class_exists( 'ACF' )),已按实际用途修正为 class_exists( 'ACF' )。 这里还用了一个 ACF 字段(activate_roughnotationjs)按页控制是否加载脚本,方法见这篇教程。 ## HTML 代码 通常我们只想标注标题(Heading)、基础文本(Basic)或富文本(Rich)元素里的部分文字。做法:把目标文字包进 <span> 标签,加上触发滚动动画的类,并指定要运行的动画类型。下面是对标题应用高亮效果的示例: html I am an awesome <span class="notation" data-notation-type="highlight-1">heading</span> - .notation 类负责让 IntersectionObserver 脚本盯住这个元素;

  • data-notation-type="highlight-1" 属性告诉脚本使用前面 annotations 常量中定义的 highlight-1 配置。 如果打算标注整个元素而不是其中一部分,就不需要包 <span>——直接用 Bricks 内置字段给元素添加 .notation 类和 data-notation-type 属性即可。 > 相关阅读:

结论 一切正常的话,前端效果就是滚动到标注文字时出现手绘风格的涂抹高亮动画。祝标注愉快,下篇教程见!

常见误区与性能提示

几个坑:一是给大段正文都加手绘标注,滚动时满屏涂抹线,反而干扰阅读;二是没尊重 prefers-reduced-motion,晕动症用户不适,加媒体查询关掉;三是 RoughNotation 库没做按需加载,每页都引,浪费请求。它适合点缀标题、关键词这类少量重点,别当全文高亮笔用;标注元素少、只在关键句上用,才是正确打开方式。

延伸阅读

常见问题(FAQ)

RoughNotation 要引库吗? 要,在页面加载 RoughNotation 库(CDN 或本地),Bricks 本身不带。

标注太多会怎样? 满屏涂抹线干扰阅读,适合只点缀标题/关键词,别全文高亮。

怎么照顾晕动症用户? 用 @media (prefers-reduced-motion: reduce) 在开启减弱动效时关闭标注动画。

每页都引库浪费吗? 按需加载,只在用了标注的页面引,别全站无差别加载。

Ray Chan

站长

Ray Chan

WordPress Developer & Bricks Specialist

WordPress developer with 10+ years of client builds. Switched to Bricks in 2023 — now builds fast WordPress sites and migrates legacy Elementor/Divi projects.

延伸阅读