找回密码
 立即注册
首页 业界区 业界 Uniapp 实现新手引导访问功能组件

Uniapp 实现新手引导访问功能组件

枢覆引 2025-10-5 16:40:43
最近有个需求需要在小程序中实现一个新手引导组件,通过遮罩、高亮区域和提示框的组合,为应用提供流畅的用户引导体验。
组件功能概述

这个引导组件提供了以下核心功能:

  • 分步引导:支持多步骤引导流程
  • 智能定位:自动计算高亮区域位置
  • 遮罩效果:突出显示目标元素
  • 方向感知:根据位置调整提示框方向
  • 进度控制:下一步/跳过/完成操作
  • 状态保存:使用 localStorage 记录完成状态(已取消,可扩展)
核心实现代码分析

组件模板结构
  1. <template>
  2.   <view v-if="visible" >
  3.    
  4.     <view  :></view>
  5.     <view  :></view>
  6.     <view  :></view>
  7.     <view  :></view>
  8.    
  9.     <view
  10.       v-if="currentStep"
  11.       
  12.       :
  13.     ></view>
  14.    
  15.     <view  :>
  16.       <text >{{ currentStep.tip }}</text>
  17.       <view  :></view>
  18.       <view >
  19.         <button @tap="nextStep">{{ isLast ? "完成" : "下一步" }}</button>
  20.         <button  @tap="skip">跳过</button>
  21.       </view>
  22.     </view>
  23.    
  24.     <image
  25.       
  26.       src="更换为自己的图标"
  27.       :
  28.       mode="widthFix"
  29.     />
  30.   </view>
  31. </template>
复制代码
组件逻辑实现
  1. export default {
  2.   props: {
  3.     steps: { type: Array, required: true }, // 引导步骤配置
  4.     guideKey: { type: String, default: "default_guide_key" }, // 引导标识键,用于确认是否做过引导,可以扩展
  5.   },
  6.   data() {
  7.     return {
  8.       stepIndex: 0, // 当前步骤索引
  9.       visible: false, // 是否显示引导
  10.     };
  11.   },
  12.   computed: {
  13.     // 当前步骤配置
  14.     currentStep() {
  15.       return this.steps[this.stepIndex];
  16.     },
  17.     // 是否为最后一步
  18.     isLast() {
  19.       return this.stepIndex === this.steps.length - 1;
  20.     },
  21.     // 高亮区域样式
  22.     highlightStyleStr() {
  23.       // 计算样式逻辑...
  24.     },
  25.     // 机器人图标位置
  26.     tooltipStyleImg() {
  27.       // 根据提示位置计算坐标...
  28.     },
  29.     // 提示框样式
  30.     tooltipStyleStr() {
  31.       // 根据位置计算提示框方向...
  32.     },
  33.     // 遮罩层样式计算
  34.     maskStyles() {
  35.       // 计算四块遮罩的位置和尺寸...
  36.     },
  37.   },
  38.   methods: {
  39.     // 开始引导
  40.     start(force = false) {
  41.       if (!force) return;
  42.       this.stepIndex = 0;
  43.       this.visible = true;
  44.     },
  45.     // 下一步
  46.     nextStep() {
  47.       this.isLast ? this.finish() : this.stepIndex++;
  48.     },
  49.     // 跳过引导
  50.     skip() {
  51.       this.finish();
  52.     },
  53.     // 完成引导
  54.     finish() {
  55.       this.visible = false;
  56.       this.$emit("finish");
  57.       localStorage.setItem(this.guideKey, "completed");
  58.     },
  59.   },
  60. };
复制代码
样式实现
  1. .guide-mask {
  2.   position: fixed;
  3.   top: 0;
  4.   left: 0;
  5.   width: 100vw;
  6.   height: 100vh;
  7.   z-index: 1000001;
  8. }
  9. .highlight {
  10.   position: absolute;
  11.   border: 2px solid #fff;
  12.   border-radius: 8px;
  13.   box-shadow: 0 0 10px #fff;
  14. }
  15. .tooltip {
  16.   position: absolute;
  17.   background: white;
  18.   padding: 10px 16px;
  19.   border-radius: 12px;
  20.   box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  21.   min-width: 250rpx;
  22. }
  23. /* 箭头方向样式 */
  24. .tip-arrow.bottom {
  25.   bottom: -8px;
  26.   border-left: 8px solid transparent;
  27.   border-right: 8px solid transparent;
  28.   border-top: 8px solid white;
  29. }
  30. /* 其他方向样式... */
  31. .robot-img {
  32.   position: absolute;
  33.   width: 150rpx;
  34.   z-index: 10003;
  35. }
复制代码
关键实现技术

1. 智能遮罩计算

组件将遮罩分为四个部分(上、下、左、右),通过计算目标元素的位置动态设置每块遮罩的尺寸:
  1. maskStyles() {
  2.         const { top, left, width, height } = this.currentStep
  3.         const windowWidth = uni.getSystemInfoSync().windowWidth
  4.         const windowHeight = uni.getSystemInfoSync().windowHeight
  5.         return {
  6.                 top: `... height: ${top}px; ...`,
  7.                 bottom: `... top: ${top + height}px; height: ${windowHeight - (top + height)}px; ...`,
  8.                 left: `... top: ${top}px; width: ${left}px; height: ${height}px; ...`,
  9.                 right: `... left: ${left + width}px; width: ${windowWidth - (left + width)}px; ...`
  10.         }
  11. }
复制代码
2. 动态提示框定位

根据目标元素位置自动调整提示框方向:
  1. tooltipStyleStr() {
  2.         const top = this.currentStep.top + this.currentStep.height + 10
  3.         const left = this.currentStep.left
  4.         const right = this.currentStep.right
  5.         const tipPosition = this.currentStep.tipPosition || 'left'
  6.         const { windowWidth } = uni.getSystemInfoSync();
  7.         return tipPosition === 'left'
  8.                 ? `right:${windowWidth - right}px;`
  9.                 : `left:${left}px;`
  10. }
复制代码
3. 引导机器人位置计算

根据提示方向计算机器人图标位置:
  1. tooltipStyleImg() {
  2.         const { top, left, width, height, tipPosition = 'left' } = this.currentStep
  3.         let x = 0, y = 0
  4.         switch (tipPosition) {
  5.                 case 'left':
  6.                         x = left - width
  7.                         y = top + height
  8.                         break
  9.                 case 'right':
  10.                         x = left + width / 5 * 3
  11.                         y = top + height
  12.                         break
  13.                 // 其他情况...
  14.         }
  15.         return `top:${y}px;left:${x}px;`
  16. }
复制代码
完整代码
  1. <template>
  2.   <view v-if="visible" >
  3.    
  4.     <view  :></view>
  5.     <view  :></view>
  6.     <view  :></view>
  7.     <view  :></view>
  8.     <view
  9.       v-if="currentStep"
  10.       
  11.       :
  12.     ></view>
  13.     <view  :>
  14.       <text >{{ currentStep.tip }}</text>
  15.       <view  :></view>
  16.       <view >
  17.         <button @tap="nextStep">{{ isLast ? "完成" : "下一步" }}</button>
  18.         <button  @tap="skip">跳过</button>
  19.       </view>
  20.     </view>
  21.     <image
  22.       
  23.       src="@/images/static/robot.png"
  24.       :
  25.       mode="widthFix"
  26.     />
  27.   </view>
  28. </template>
复制代码
使用示例
  1. const guideSteps = [
  2.         {
  3.                 tip: "这是 AI 聊天功能,点击进行聊天",
  4.                 top: 100,
  5.                 left: 50,
  6.                 width: 200,
  7.                 height: 40,
  8.                 tipPosition: "bottom"
  9.         },
  10.         {
  11.                 tip: "这是个人中心入口",
  12.                 top: 500,
  13.                 left: 300,
  14.                 width: 80,
  15.                 height: 80,
  16.                 tipPosition: "left"
  17.         }
  18. ]
  19. // 在组件中使用
  20. <GuideMask :steps="guideSteps" guideKey="home_guide" @finish="onGuideFinish"/>
复制代码
组件不足


  • tip&icon 定位:这里的组件定位主要是做了左右适配定位,如果需要兼容可以进行扩展或者优化
  • 高亮区域:组件高亮区域当前只是对于定位区域宽高进行高亮,可以做往外扩展,例如椭圆形的
  • 跨页面:目前只能对同个单一的页面进行引导式访问,无法做到跨页面跳转的引导式访问
  • 多端适配:暂无进行多端的适配测试,目前看来应该兼容的,实用还是得做下测试进行优化
  • 遮罩层:这里遮罩层做的是根据定位区域来实现覆盖的,没有进行穿透效果,兼容可以好点,但也可以进行其他方面的优化例如各种形状或者区域高亮扩展,这时候就需要更复杂的计算,扩展性维护性就差点
优化方向

不足的地方都可以进行优化,下面就只是扩展方向:

  • 动画效果:为高亮区域和提示框添加过渡动画
  • 自动定位:通过选择器自动获取元素位置(使用 createSelectorQuery 和 boundingClientRect)
  • 主题定制:支持自定义颜色和样式
  • 手势支持:添加滑动手势切换步骤
  • 语音引导:结合语音 API 提供语音提示
  • 引导记忆:组件有个标识专门针对已经做过引导访问的页面进行标识,如果遇到可以不再引导,也可以强制引导
总结

这个只是做了简单的示例,有需要可以进行优化改善,没有太大要求的话可以直接复制粘贴使用。效果图片想想还是贴下吧:
1.png


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册