本教程提供可直接粘贴的 PHP 与 JS 代码,让你在 Bricks Builder 里用 RoughNotation 库实现「滚动到元素时触发手绘风格标注动画」——高亮、下划线、方框、圆圈、删除线等效果。
目录
环境要求
JavaScript
首先在子主题里创建 init.js 文件。本例在子主题的 /js/ 文件夹下创建了 roughNotation_init.js,内容如下:
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 等大量选项,完整选项列表见作者的项目主页。为了演示全部标注类型,示例定义了以下动画:
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,非常轻量(方法同这篇教程):
// 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:
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](https://brickslabs.com/go/acf)' )),已按实际用途修正为class_exists( 'ACF' )。
这里还用了一个 ACF 字段(activate_roughnotationjs)按页控制是否加载脚本,方法见这篇教程。
HTML 代码
通常我们只想标注标题(Heading)、基础文本(Basic)或富文本(Rich)元素里的部分文字。做法:把目标文字包进 <span> 标签,加上触发滚动动画的类,并指定要运行的动画类型。下面是对标题应用高亮效果的示例:
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 属性即可。
结论
一切正常的话,前端效果就是滚动到标注文字时出现手绘风格的涂抹高亮动画。祝标注愉快,下篇教程见!