前端使用Driver.js快速实现新手指引全步骤及实现原理
作者:yuan溜溜
前言
在当今复杂的前端应用生态中,一个清晰、友好的新手指引(Tour Guide)对于提升用户体验和留存率至关重要。它能够帮助用户快速熟悉产品功能,降低学习成本。在众多的指引库中,Driver.js 以其轻量、灵活和无依赖的特性脱颖而出。
本文将带你快速上手 Driver.js,并深入剖析其背后的实现原理,让你不仅会使用,更能理解其工作机制。
一、什么是 Driver.js?
Driver.js 是一个轻量级(~4kB)、无外部依赖、高度可定制且强大的引导库。它能够通过高亮、弹窗解释和聚焦的方式,将用户的注意力吸引到页面的特定元素上,从而完成产品引导、功能介绍或焦点聚焦等任务。
核心特点:
- 零依赖:基于纯 JavaScript 实现,不依赖 jQuery、React 等。
- 轻量级:极小的体积,对项目性能影响微乎其微。
- 高可定制性:可以自定义弹出框的样式、文字、位置、动画等。
- 强大的 API:提供丰富的生命周期钩子和方法,满足各种复杂交互。
- 无障碍支持:对屏幕阅读器友好,遵循可访问性最佳实践。
二、快速上手:5分钟实现新手指引
步骤 1:安装
你可以通过 npm/yarn 安装,也可以直接通过 CDN 引入。
方式一:NPM/Yarn
npm install driver.js # 或 yarn add driver.js
方式二:CDN (直接在 HTML 中引入)
<!-- 引入 CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.css" rel="external nofollow" /> <!-- 引入 JS --> <script src="https://cdn.jsdelivr.net/npm/driver.js@1.0.1/dist/driver.js.iife.js"></script>
步骤 2:初始化并启动引导
假设我们有一个react页面,需要引导用户使用
JavaScript 代码:
import React, { useEffect, useRef } from 'react' import { driver } from 'driver.js' import "driver.js/dist/driver.css"; import './test.less' const Driver = () => { const driverRef = useRef(null); // 添加全局函数供弹出框使用 window.handleGuideClick = () => { driverRef.current.destroy(); }; const WELCOME_IMAGE = 'https://images.unsplash.com/photo-1533750349088-cd871a92f312?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80'; const guide = () => { if (driverRef.current) { driverRef.current.destroy(); } driverRef.current = driver({ allowClose: false, // 是否有关闭按钮 popoverClass: 'custom-driver-popover', // 添加自定义class showProgress: false, // 首先确保配置中关闭进度显示 steps: [{ element: ".step1-pop", popover: { popoverClass:'step1', title: "欢迎使用", description: ` <div class="custom-popover-content"> <p>这是一个功能强大的应用程序,将帮助您提高工作效率。</p> <img src="${WELCOME_IMAGE}" alt="欢迎" /> <div class="button-container"> <button class="custom-button" onclick="handleGuideClick()">跳过</button> </div> </div>`, showButtons: ["next"], nextBtnText: "下一步", onNext: () => { console.log("正在从第一步移动到第二步"); return true; // 返回false可阻止继续 } } }, { element: ".step2-pop", popover: { popoverClass:'step2', description:'step2', // showButtons: ["next", "previous"], nextBtnText: "下一步", prevBtnText: "上一步", } }, { element: ".step3-pop", popover: { title: "完成", description: "done", nextBtnText: "关闭", prevBtnText: "上一步" } }] }) driverRef.current.drive() } useEffect(()=>{ guide() },[]) return ( <div> <div className='step1-pop'>步骤一</div> <div className='step2-pop'>步骤二</div> <div className='step3-pop'>步骤三</div> </div> ) } export default Driver
less 代码:
.custom-driver-popover { // text-align: left; background-color: #fff; height: auto; } .custom-popover-content img { width: 100%; border-radius: 5px; margin: 10px 0; } .custom-button { background-color: #3b82f6; color: white; border: none; padding: 8px 16px; border-radius: 4px; margin-top: 10px; cursor: pointer; } .step1-pop,.step2-pop,.step3-pop{ position: fixed; width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fff; font-weight: 600; } .step1-pop{ left: 100px; top: 100px; background-color: pink; } .step2-pop{ left: 100px; bottom: 100px; background-color: palegreen; } .step3-pop{ right: 100px; bottom: 100px; background-color: orange; }
只需以上几步,一个基础但完整的新手指引功能就实现了!
效果:
进阶配置:生命周期钩子
Driver.js 提供了强大的生命周期钩子,让你在引导的各个阶段执行自定义逻辑。
onHighlightStarted: (element) => { console.log('开始高亮元素:', element); // 例如,可以在高亮前先滚动到该元素 element.scrollIntoView({ behavior: 'smooth' }); }, onHighlighted: (element) => { console.log('元素高亮完成:', element); }, onDeselected: (element) => { console.log('元素取消高亮:', element); }, onReset: (element) => { console.log('引导被关闭或完成'); }
三、实现原理剖析
理解了如何使用,我们再深入一层,看看 Driver.js 是如何在幕后工作的。其核心原理可以概括为以下几点:
1. 元素高亮与聚焦
这是 Driver.js 最核心的视觉效果。它通过动态计算目标元素的位置和尺寸来实现。
- 计算位置:使用
Element.getBoundingClientRect()
API 获取目标元素相对于视口(viewport)的精确位置(top, left, width, height)。 - 创建高亮层:在页面中动态插入一个
div
作为高亮层。这个层的尺寸和位置被设置为与目标元素完全一致(加上配置的padding
)。 - CSS 样式:为该高亮层应用特定的样式,通常是
border
(如发光效果)和box-shadow
,并设置z-index
为一个极高的值(如 10000),确保它浮在所有常规内容之上。 - 遮罩背景:在整个页面上创建一个巨大的遮罩层(Overlay),覆盖整个视口。这个遮罩层通常有一个半透明的背景色(由
opacity
配置),并设置pointer-events: auto
来拦截页面上的点击。然后,在高亮层对应的区域使用clip-path
或CSS Mask
等技术“挖”一个洞,或者更简单的,在高亮层区域设置pointer-events: none
来让点击“穿透”到目标元素。Driver.js 采用的是后一种 pointer-events 方案,它创建了一个全屏遮罩,但将高亮层区域的pointer-events
设为none
。
2. 弹窗定位
解释性弹窗(Popover)的位置是动态计算的。
- 可用空间检查:根据配置的
position
(如'top'
),Driver.js 会检查那个方向是否有足够的空间来显示弹窗(不会超出屏幕边界)。 - 动态定位:如果首选方向空间不足,它会自动寻找最佳位置(例如,如果
top
不够,就尝试bottom
)。 - CSS 绝对定位:弹窗使用
position: fixed
定位,并通过 JavaScript 动态计算并设置其top
和left
值,使其精确地出现在高亮元素的旁边。
四、总结
Driver.js 通过巧妙的 动态 DOM 操作、精确的几何计算 和 简单的状态管理,为我们提供了一个强大而易用的新手指引解决方案。
它的优势在于:
- 开箱即用:简单配置即可实现大部分常见需求。
- 侵入性低:不需要修改你现有的业务组件代码。
- 原理清晰:理解了其原理后,可以更好地应对各种边界情况和自定义需求。
附:Driver.js导入报错解决方案
使用driver.js进行系统流程引导时,发现怎么导入都报错,官方代码是这样的
import { driver } from "driver.js"; import "driver.js/dist/driver.css"; const driverObj = driver(); driverObj.highlight({ element: "#some-element", popover: { title: "Title", description: "Description" } });
这里我使用的是driver.js@1.3.6,代码如下
import { Driver } from 'driver.js'; import 'driver.js/dist/driver.css'; const driver = new Driver({ animate: true, overlayColor: 'rgba(0, 0, 0, 0.7)', opacity: 0.7, padding: 10, allowClose: true, doneBtnText: '完成', nextBtnText: '下一步', prevBtnText: '上一步', stageBackground: '#fff', primaryColor: '#409EFF', }); export const startTour = (steps: any) => { driver.defineSteps(steps); driver.start(); }; export default driver;
报错Driver only refers to a type, but is being used as a value here
查看driver.js发现Drivers只是一个接口类型,而实际创建实例的是driver()工厂函数,创建实例的方式是通过driver(options)函数创建实例而非new Driver()(这个只是接口,不能实例化)
另外还需要导入类型定义,用于TypeScript类型提示
更正后代码如下
tour.ts
import { driver } from 'driver.js'; import 'driver.js/dist/driver.css'; // 导入类型定义(可选,用于 TypeScript 类型提示) import type { Config, DriveStep } from 'driver.js'; // 通过 driver() 函数创建实例(传入配置项) const driverInstance = driver({ animate: true, overlayColor: 'rgba(0, 0, 0, 0.7)', opacity: 0.7, padding: 10, allowClose: true, doneBtnText: '完成', nextBtnText: '下一步', prevBtnText: '上一步', stageBackground: '#fff', primaryColor: '#409EFF', } as Config); // 类型断言确保配置符合 Config 类型 // 定义步骤类型(直接使用 driver.js 的 DriveStep 接口) export const startTour = (steps: DriveStep[]) => { driverInstance.setSteps(steps); driverInstance.drive(); }; export default driverInstance;
这时候就能够在其他组件中使用了
<script setup lang="ts"> import { startTour } from '../tour.ts'; const startGuide = () => { startTour([ { element: '.aside-class', popover: { title: '', description: '' } },{ element: '.aside-class-1', popover: { title: '', description: '' } }, ]) }; </script> <template> <el-button id="re_main" @click="startGuide">功能引导</el-button> </template> <style scoped> </style>
driver.js是能够跨组件引导的,只要元素已挂载到DOM中,并且通过element参数传入css选择器或者直接传入DOM元素对象,driver.js都能够识别并引导,当然跨组件引导的核心是确保目标元素的选择器唯一且在引导执行时已存在于 DOM 中
到此这篇关于前端使用Driver.js快速实现新手指引全步骤及实现原理的文章就介绍到这了,更多相关前端Driver.js实现新手指引内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!