最近有个需求需要在小程序中实现一个新手引导组件,通过遮罩、高亮区域和提示框的组合,为应用提供流畅的用户引导体验。
组件功能概述
这个引导组件提供了以下核心功能:
- 分步引导:支持多步骤引导流程
- 智能定位:自动计算高亮区域位置
- 遮罩效果:突出显示目标元素
- 方向感知:根据位置调整提示框方向
- 进度控制:下一步/跳过/完成操作
- 状态保存:使用 localStorage 记录完成状态(已取消,可扩展)
核心实现代码分析
组件模板结构
- <template>
- <view v-if="visible" >
-
- <view :></view>
- <view :></view>
- <view :></view>
- <view :></view>
-
- <view
- v-if="currentStep"
-
- :
- ></view>
-
- <view :>
- <text >{{ currentStep.tip }}</text>
- <view :></view>
- <view >
- <button @tap="nextStep">{{ isLast ? "完成" : "下一步" }}</button>
- <button @tap="skip">跳过</button>
- </view>
- </view>
-
- <image
-
- src="更换为自己的图标"
- :
- mode="widthFix"
- />
- </view>
- </template>
复制代码 组件逻辑实现
- export default {
- props: {
- steps: { type: Array, required: true }, // 引导步骤配置
- guideKey: { type: String, default: "default_guide_key" }, // 引导标识键,用于确认是否做过引导,可以扩展
- },
- data() {
- return {
- stepIndex: 0, // 当前步骤索引
- visible: false, // 是否显示引导
- };
- },
- computed: {
- // 当前步骤配置
- currentStep() {
- return this.steps[this.stepIndex];
- },
- // 是否为最后一步
- isLast() {
- return this.stepIndex === this.steps.length - 1;
- },
- // 高亮区域样式
- highlightStyleStr() {
- // 计算样式逻辑...
- },
- // 机器人图标位置
- tooltipStyleImg() {
- // 根据提示位置计算坐标...
- },
- // 提示框样式
- tooltipStyleStr() {
- // 根据位置计算提示框方向...
- },
- // 遮罩层样式计算
- maskStyles() {
- // 计算四块遮罩的位置和尺寸...
- },
- },
- methods: {
- // 开始引导
- start(force = false) {
- if (!force) return;
- this.stepIndex = 0;
- this.visible = true;
- },
- // 下一步
- nextStep() {
- this.isLast ? this.finish() : this.stepIndex++;
- },
- // 跳过引导
- skip() {
- this.finish();
- },
- // 完成引导
- finish() {
- this.visible = false;
- this.$emit("finish");
- localStorage.setItem(this.guideKey, "completed");
- },
- },
- };
复制代码 样式实现
- .guide-mask {
- position: fixed;
- top: 0;
- left: 0;
- width: 100vw;
- height: 100vh;
- z-index: 1000001;
- }
- .highlight {
- position: absolute;
- border: 2px solid #fff;
- border-radius: 8px;
- box-shadow: 0 0 10px #fff;
- }
- .tooltip {
- position: absolute;
- background: white;
- padding: 10px 16px;
- border-radius: 12px;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
- min-width: 250rpx;
- }
- /* 箭头方向样式 */
- .tip-arrow.bottom {
- bottom: -8px;
- border-left: 8px solid transparent;
- border-right: 8px solid transparent;
- border-top: 8px solid white;
- }
- /* 其他方向样式... */
- .robot-img {
- position: absolute;
- width: 150rpx;
- z-index: 10003;
- }
复制代码 关键实现技术
1. 智能遮罩计算
组件将遮罩分为四个部分(上、下、左、右),通过计算目标元素的位置动态设置每块遮罩的尺寸:- maskStyles() {
- const { top, left, width, height } = this.currentStep
- const windowWidth = uni.getSystemInfoSync().windowWidth
- const windowHeight = uni.getSystemInfoSync().windowHeight
- return {
- top: `... height: ${top}px; ...`,
- bottom: `... top: ${top + height}px; height: ${windowHeight - (top + height)}px; ...`,
- left: `... top: ${top}px; width: ${left}px; height: ${height}px; ...`,
- right: `... left: ${left + width}px; width: ${windowWidth - (left + width)}px; ...`
- }
- }
复制代码 2. 动态提示框定位
根据目标元素位置自动调整提示框方向:- tooltipStyleStr() {
- const top = this.currentStep.top + this.currentStep.height + 10
- const left = this.currentStep.left
- const right = this.currentStep.right
- const tipPosition = this.currentStep.tipPosition || 'left'
- const { windowWidth } = uni.getSystemInfoSync();
- return tipPosition === 'left'
- ? `right:${windowWidth - right}px;`
- : `left:${left}px;`
- }
复制代码 3. 引导机器人位置计算
根据提示方向计算机器人图标位置:- tooltipStyleImg() {
- const { top, left, width, height, tipPosition = 'left' } = this.currentStep
- let x = 0, y = 0
- switch (tipPosition) {
- case 'left':
- x = left - width
- y = top + height
- break
- case 'right':
- x = left + width / 5 * 3
- y = top + height
- break
- // 其他情况...
- }
- return `top:${y}px;left:${x}px;`
- }
复制代码 完整代码
- <template>
- <view v-if="visible" >
-
- <view :></view>
- <view :></view>
- <view :></view>
- <view :></view>
- <view
- v-if="currentStep"
-
- :
- ></view>
- <view :>
- <text >{{ currentStep.tip }}</text>
- <view :></view>
- <view >
- <button @tap="nextStep">{{ isLast ? "完成" : "下一步" }}</button>
- <button @tap="skip">跳过</button>
- </view>
- </view>
- <image
-
- src="@/images/static/robot.png"
- :
- mode="widthFix"
- />
- </view>
- </template>
复制代码 使用示例
- const guideSteps = [
- {
- tip: "这是 AI 聊天功能,点击进行聊天",
- top: 100,
- left: 50,
- width: 200,
- height: 40,
- tipPosition: "bottom"
- },
- {
- tip: "这是个人中心入口",
- top: 500,
- left: 300,
- width: 80,
- height: 80,
- tipPosition: "left"
- }
- ]
- // 在组件中使用
- <GuideMask :steps="guideSteps" guideKey="home_guide" @finish="onGuideFinish"/>
复制代码 组件不足
- tip&icon 定位:这里的组件定位主要是做了左右适配定位,如果需要兼容可以进行扩展或者优化
- 高亮区域:组件高亮区域当前只是对于定位区域宽高进行高亮,可以做往外扩展,例如椭圆形的
- 跨页面:目前只能对同个单一的页面进行引导式访问,无法做到跨页面跳转的引导式访问
- 多端适配:暂无进行多端的适配测试,目前看来应该兼容的,实用还是得做下测试进行优化
- 遮罩层:这里遮罩层做的是根据定位区域来实现覆盖的,没有进行穿透效果,兼容可以好点,但也可以进行其他方面的优化例如各种形状或者区域高亮扩展,这时候就需要更复杂的计算,扩展性维护性就差点
优化方向
不足的地方都可以进行优化,下面就只是扩展方向:
- 动画效果:为高亮区域和提示框添加过渡动画
- 自动定位:通过选择器自动获取元素位置(使用 createSelectorQuery 和 boundingClientRect)
- 主题定制:支持自定义颜色和样式
- 手势支持:添加滑动手势切换步骤
- 语音引导:结合语音 API 提供语音提示
- 引导记忆:组件有个标识专门针对已经做过引导访问的页面进行标识,如果遇到可以不再引导,也可以强制引导
总结
这个只是做了简单的示例,有需要可以进行优化改善,没有太大要求的话可以直接复制粘贴使用。效果图片想想还是贴下吧:
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |