原生微信小程序实现导航漫游(Tour)

效果:

小程序实现导航漫游

1、组件

miniprogram/components/tour/index.wxml

<!--wxml-->
<view class="guide" wx:if="{{showGuide}}"><view style="{{guideStyle}}" class="guide-box"><view class="tips guide-step-tips" style="{{tipPosition}}"><view class="text">{{ guideList[index].tips }}</view><view class="step-indicator"><text class="step-text">{{index + 1}}/{{guideList.length}}</text></view><view class="tool-btn"><text bind:tap="skip">跳过</text><view class="btn-group"><view class="prev" bind:tap="prev" wx:if="{{index > 0}}">上一步</view><view class="next" bind:tap="next">{{index === guideList.length - 1 ? '完成' : '下一步'}}</view></view></view></view><view class="arrow" style="{{arrowTop}}"></view></view><!-- 遮罩层,防止点击 --><view class="v-model"></view>
</view>

miniprogram/components/tour/index.ts 

// components/xky-guideStep/xky-guideStep.jsimport { handleChangeTourType } from "@/utils/util";// 添加必要的接口定义
interface GuideItem {el: string;width: number;height: number;left: number;top: number;style?: string;
}interface Step {name: string;guideList: GuideItem[];
}interface DomInfo {width: number;height: number;left: number;top: number;[key: string]: any;
}Component({/*** 组件的属性列表*/properties: {step: {type: Object,value: {} as Step,},},/*** 组件的初始数据*/data: {stepName: "step", //该提示步骤的名称,用于不在重复展示guideList: [] as GuideItem[],index: 0, // 当前展示的索引showGuide: true, // 是否显示引导guideStyle: "", // 默认样式arrowTop: "", //步骤提示三角形的定位tipPosition: "", //步骤提示的定位systemInfo: null as WechatMiniprogram.SystemInfo | null, //屏幕宽度高度等信息tipWidth: 200, //步骤提示默认的宽度},/*** 组件的方法列表*/methods: {// 展示新手提示viewTips(data: DomInfo | null, scrollTop: number) {let {systemInfo,tipWidth,index,guideList,arrowTop,tipPosition,guideStyle,} = this.data;if (data && systemInfo) {// 如果dom宽度大于或者等于窗口宽度,需要重新调整dom展示宽度let newWidth = systemInfo.windowWidth - 20;if (data.width >= newWidth) {data.width = newWidth;}// 如果距离左边为0,自动增加一点左边距if (data.left == 0) {data.left = 10;}let domRW = systemInfo.windowWidth - data.left;let left = 0;// 如果dom距离右边没有tips的宽度大的话,就要让tips向左便宜if (domRW < tipWidth) {left = domRW - tipWidth - 30;}// const index = index;// 步骤条展示的高度需要加上屏幕滚动的高度data.top += scrollTop;// 根据实际情况需要滚动到展示区域wx.pageScrollTo({scrollTop: data.top > 20 ? data.top - 20 : 0,duration: 100,});let obj = Object.assign(guideList[index], data);// 设置三角形高度let arrArrowTop = data.height + 9;arrowTop = "top:" + arrArrowTop + "px;";// 设置提示框定位tipPosition = "top:" + (arrArrowTop + 5) + "px;left:" + left + "px;";// 重新设置guideList的值guideList.splice(index, 1, obj);guideStyle = this.getStyle();this.setData({arrowTop,tipPosition,guideList,guideStyle,});} else {index += 1;this.setData({index,});this.getDomInfo();}},// 获取步骤提示的主要样式getStyle() {const { guideList, index } = this.data;const { width, height, left, top, style } = guideList[index];let newStyle = "width:" + width + "px;";newStyle += "height:" + height + "px;";newStyle += "left:" + left + "px;";newStyle += "top:" + top + "px;";newStyle +="box-shadow: rgb(33 33 33 / 80%) 0px 0px 0px 0px, rgb(33 33 33 / 50%) 0px 0px 0px 5000px;";newStyle += style;return newStyle;},// 获取dom信息getDomInfo() {const { guideList, index } = this.data;const { el } = guideList[index];const query = wx.createSelectorQuery();setTimeout(() => {query.select(el).boundingClientRect();query.selectViewport().scrollOffset();query.exec( (res)=> {let data = res[0]; // #the-id节点的上边界坐标let scrollTop = res[1].scrollTop; // 显示区域的竖直滚动位置this.viewTips(data, scrollTop);});}, 10);},updateTourMap() {handleChangeTourType(this.data.stepName)},skip() {this.setData({showGuide: false,});this.updateTourMap()},// 添加上一步方法prev() {let { index } = this.data;if (index > 0) {index -= 1;this.setData({index});this.getDomInfo();}},// 下一步,修改显示文案next() {let { index, guideList } = this.data;if (index === guideList.length - 1) {this.setData({showGuide: false,});this.updateTourMap()} else {index += 1;this.setData({index,});this.getDomInfo();}},},lifetimes: {attached () {const { step } = this.properties;let { guideList, stepName } = this.data;guideList = step.guideList;stepName = step.name;this.setData({guideList,stepName,systemInfo: wx.getSystemInfoSync(),});const guide = wx.getStorageSync('tourMap');if (!guide || !guide[step.name]) {this.getDomInfo();} else {this.setData({showGuide: false,});}},detached () {// 在组件实例被从页面节点树移除时执行},},
});

miniprogram/components/tour/index.scss 

/* wxss */
.v-model {position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: 1000;
}
.guide {z-index: 1001;
}
.guide-box {position: absolute;z-index: 10001;transition: all 0.2s;}
.guide-box::before {content: '';height: 100%;width: 100%;border: 1px dashed #fff;border-radius: 8rpx;position: absolute;top: -8rpx;left: -8rpx;padding: 7rpx;
}
.arrow {height: 20rpx;width: 20rpx;background: #1cbbb4;position: absolute;top: 144rpx;left: 45%;transform: rotate(45deg);
}
.tips {width: 400rpx;background: linear-gradient(180deg, #1cbbb4, #0081ff);box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.1);color: #fff;position: absolute;top: 152rpx;left: -50%;padding: 15rpx 20rpx;font-size: 28rpx;border-radius: 12rpx;
}
.tool-btn {display: flex;justify-content: space-between;align-items: center;padding-right: 0rpx;margin-top: 20rpx;
}/* 新增样式 */
.step-indicator {display: flex;justify-content: flex-end;margin-top: 10rpx;
}
.step-text {font-size: 24rpx;color: rgba(255, 255, 255, 0.8);
}
.btn-group {display: flex;align-items: center;
}
.prev {background: rgba(255, 255, 255, 0.2);height: 48rpx;width: 100rpx;text-align: center;border-radius: 8rpx;color: #fff;line-height: 48rpx;font-size: 24rpx;margin-right: 10rpx;
}
.next {background: #fff;height: 48rpx;width: 100rpx;text-align: center;border-radius: 8rpx;color: #666;line-height: 48rpx;font-size: 24rpx
}

miniprogram/components/tour/index.json 

{"component": true,"usingComponents": {}
}

miniprogram/utils/util.ts

/** 修改本地的Tour状态 */
export const handleChangeTourType = (tourName: string) => {const tourMap = wx.getStorageSync('tourMap') || {};tourMap[tourName] = true;wx.setStorageSync('tourMap', tourMap);
};

部分转载:微信小程序首次进入引导提示自定义组件-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/34858.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python学习第十九天

Django-分页 后端分页 Django提供了Paginator类来实现后端分页。Paginator类可以将一个查询集&#xff08;QuerySet&#xff09;分成多个页面&#xff0c;每个页面包含指定数量的对象。 from django.shortcuts import render, redirect, get_object_or_404 from .models impo…

【大模型】Transformer、GPT1、GPT2、GPT3、BERT 的论文解析

前言 在自然语言处理&#xff08;NLP&#xff09;和深度学习的快速发展中&#xff0c;Transformer模型和 GPT系列模型扮演了至关重要的角色。本篇博客旨在对这些开创性的论文进行介绍&#xff0c;涵盖它们的提出时间、网络结构等关键信息&#xff0c;能够快速的理解这些模型的设…

【DeepSeek应用】本地部署deepseek模型后,如何在vscode中调用该模型进行代码撰写,检视和优化?

若已成功在本地部署了 DeepSeek 模型(例如通过 vscode-llm、ollama 或私有 API 服务),在 VS Code 中调用本地模型进行代码撰写、检视和优化的完整流程如下: 1. 准备工作:确认本地模型服务状态 模型服务类型: 若使用 HTTP API 服务(如 FastAPI/Flask 封装),假设服务地址…

【C语言】函数和数组实践与应用:开发简单的扫雷游戏

【C语言】函数和数组实践与应用&#xff1a;开发简单的扫雷游戏 1.扫雷游戏分析和设计1.1扫雷游戏的功能说明&#xff08;游戏规则&#xff09;1.2游戏的分析与设计1.2.1游戏的分析1.2.2 文件结构设计 2. 代码实现2.1 game.h文件2.2 game.c文件2.3 test.c文件 3. 游戏运行效果4…

需求分析、定义、验证、变更、跟踪(高软47)

系列文章目录 需求分析、定义、验证、变更、跟踪 文章目录 系列文章目录前言一、需求分析二、需求定义三、需求验证四、需求变更五、需求跟踪六、真题总结 前言 本节讲明需求分析、定义、验证、变更、跟踪相关知识。 一、需求分析 二、需求定义 三、需求验证 四、需求变更 五、…

【拒绝算法PUA】LeetCode 2270. 分割数组的方案数

系列文章目录 【拒绝算法PUA】0x00-位运算 【拒绝算法PUA】0x01- 区间比较技巧 【拒绝算法PUA】0x02- 区间合并技巧 【拒绝算法PUA】0x03 - LeetCode 排序类型刷题 【拒绝算法PUA】LeetCode每日一题系列刷题汇总-2025年持续刷新中 C刷题技巧总结&#xff1a; [温习C/C]0x04 刷…

uniapp 实现的步进指示器组件

采用 uniapp 实现的一款步进指示器组件&#xff0c;展示业务步骤进度等内容&#xff0c;对外提供“前进”、“后退”方法&#xff0c;让用户可高度自定义所需交互&#xff0c;适配 web、H5、微信小程序&#xff08;其他平台小程序未测试过&#xff0c;可自行尝试&#xff09; 可…

每日Attention学习26——Dynamic Weighted Feature Fusion

模块出处 [ACM MM 23] [link] [code] Efficient Parallel Multi-Scale Detail and Semantic Encoding Network for Lightweight Semantic Segmentation 模块名称 Dynamic Weighted Feature Fusion (DWFF) 模块作用 双级特征融合 模块结构 模块思想 我们提出了 DWFF 策略&am…

接上一篇,C++中,如何设计等价于Qt的信号与槽机制。

看下面例子&#xff1a; class FileManager : public QObject {Q_OBJECTpublic:FileManager(QObject* parent nullptr) : QObject(parent) {}void changeFileName(const QString& newName) {fileName newName;emit fileNameChanged(fileName);}signals:void fileNameChan…

上传本地项目到GitHub

一、在GitHub上创建仓库 1.点击右上角头像–>点击Your repositories 2.点击New 3.创建仓库 网址复制一下&#xff0c;在后面git上传时会用到 二、打开Git Bash 1.cd 进入项目所在路径 2.输入git init 在当前项目的目录中生成本地的git管理&#xff08;当前目录下出现.…

基于Python的selenium入门超详细教程(第2章)--单元测试框架unittest

学习路线 自动化测试介绍及学习路线-CSDN博客 ​自动化测试之Web自动化&#xff08;基于pythonselenium&#xff09;-CSDN博客 基于Python的selenium入门超详细教程(第1章)--WebDriver API篇-CSDN博客 目录 前言&#xff1a; 一、单元测试 1. 单元测试的定义 2. 单元测…

HTML5 drag API实现列表拖拽排序

拖拽API&#xff08;Drag and Drop API&#xff09;是HTML5提供的一组功能&#xff0c;使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能&#xff0c;用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart&#xff1…

游戏引擎学习第163天

我们可以在资源处理器中使用库 因为我们的资源处理器并不是游戏的一部分&#xff0c;所以它可以使用库。我说过我不介意让它使用库&#xff0c;而我提到这个的原因是&#xff0c;今天我们确实有一个选择——可以使用库。 生成字体位图的两种方式&#xff1a;求助于 Windows 或…

Kafka可视化工具KafkaTool工具的使用

Kafka Tool工具 介绍 使用Kafka的小伙伴&#xff0c;有没有为无法直观地查看 Kafka 的 Topic 里的内容而发过愁呢&#xff1f;下面推荐给大家一款带有可视化页面的Kafka工具&#xff1a;Kafka Tool &#xff08;目前最新版本是 3.0.2&#xff09; 注意&#xff1a;以前叫Kafk…

在Spring Boot项目中接入DeepSeek深度求索,感觉笨笨的呢

文章目录 引言1. 什么是DeepSeek&#xff1f;2. 准备工作2.1 注册DeepSeek账号 3.实战演示3.1 application增加DS配置3.2 编写service3.3 编写controller3.4 编写前端界面chat.html3.5 测试 总结 引言 在当今快速发展的数据驱动时代&#xff0c;企业越来越重视数据的价值。为了…

【数据分析】读取文件

3. 读取指定列 针对只需要读取数据中的某一列或多列的情况&#xff0c;pd.read_csv()函数提供了一个参数&#xff1a;usecols&#xff0c;将包含对应的columns的列表传入该参数即可。 上面&#xff0c;我们学习了读取 "payment" 和 "items_count" 这…

Ubuntu 优化 Vim 指南

Vim 是一款功能强大的文本编辑器&#xff0c;通过合适的配置&#xff0c;可以变成一个接近 IDE 的高效开发工具。本指南提供 最精简、最实用 的 Vim 配置&#xff0c;满足 代码补全、语法高亮、代码格式化、目录管理等常用需求。 1. 必须安装的软件 首先&#xff0c;确保你的系…

信创环境下TOP5甘特图工具对比:从功能到适配性测评

在数字化转型的浪潮中&#xff0c;项目管理的高效与否直接决定了企业能否在激烈的市场竞争中脱颖而出。而甘特图作为项目管理中不可或缺的工具&#xff0c;其重要性不言而喻。尤其是在信创环境日益受到重视的当下&#xff0c;选择一款适配性强、功能完备的甘特图工具&#xff0…

MinIO的预签名直传机制

我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口&#xff0c;然后我们在前端调用这些接口完成文件的上传下载机制&#xff0c;但是&#xff0c;当并发量过大&#xff0c;频繁访问会对后端的并发往往会对服务器造成极大的压力…

【NLP 38、实践 ⑩ NER 命名实体识别任务 Bert 实现】

去做具体的事&#xff0c;然后稳稳托举自己 —— 25.3.17 数据文件&#xff1a; 通过网盘分享的文件&#xff1a;Ner命名实体识别任务 链接: https://pan.baidu.com/s/1fUiin2um4PCS5i91V9dJFA?pwdyc6u 提取码: yc6u --来自百度网盘超级会员v3的分享 一、配置文件 config.py …