waiting for fixing font change...
This commit is contained in:
commit
784fc26311
7
README.md
Executable file
7
README.md
Executable file
@ -0,0 +1,7 @@
|
||||
# 你醒了?
|
||||
|
||||
## 诶...这是哪?
|
||||
|
||||
>欢迎来到fly316 中心知识库!这里是中国地质大学(北京)机器人 无人机 飞翼凌霄队!\
|
||||
>
|
||||
|
||||
48
_404.md
Executable file
48
_404.md
Executable file
@ -0,0 +1,48 @@
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Arial', sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #343a40;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
text-align: center;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
padding: 20px;
|
||||
}
|
||||
h1 {
|
||||
font-size: 5rem;
|
||||
margin: 0;
|
||||
color: #6c757d;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.emoji {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="emoji">😕</div>
|
||||
<h1>404</h1>
|
||||
<h2>tifisht什么没有都找到www...</h2>
|
||||
<p>页面不存在或已经被移除...</p>
|
||||
<a href="/">返回首页</a>
|
||||
</div>
|
||||
</body>
|
||||
14
_coverpage.md
Executable file
14
_coverpage.md
Executable file
@ -0,0 +1,14 @@
|
||||

|
||||
|
||||
# <big><b>fly316 中心知识库</big>
|
||||
|
||||
|
||||
中国地质大学(北京)机器人无人机队
|
||||
|
||||
## drones with ros-noetic px4
|
||||
|
||||
[fly316网盘](http://fly316.ttserver.fun:5212)
|
||||
[316git仓库](http://fly316.ttserver.fun:1114)
|
||||
[Get Started](#你醒了?)
|
||||
|
||||
|
||||
1
_navbar.md
Normal file
1
_navbar.md
Normal file
@ -0,0 +1 @@
|
||||
[316git仓库](http://fly316.ttserver.fun:1114)
|
||||
8
_sidebar.md
Executable file
8
_sidebar.md
Executable file
@ -0,0 +1,8 @@
|
||||
- 首页
|
||||
- [**招新**](recruitment)
|
||||
- [**基础设施**](infrastructure)
|
||||
|
||||
- 通用教程
|
||||
- 环境配置
|
||||
- [**[Ubuntu]基础环境+各种相机**](basicTutorial/environment/ubuntuenv)
|
||||
- [**[邪道]使用docker配置px4环境**](basicTutorial/environment/docker-px4)
|
||||
151
basicTutorial/environment/docker-px4.md
Executable file
151
basicTutorial/environment/docker-px4.md
Executable file
@ -0,0 +1,151 @@
|
||||
# 在Magicbook Pro 16 Hunter 上安装 Archlinux,Docker容器运行ros1 px4 与gazebo仿真环境
|
||||
|
||||
> hi 又是我,我是tifisht哟!今天给各位分享我自己的笔记本px4开发环境!archlinux + ros-noetic + px4而且当然可以仿真啦!\
|
||||
www因为被Ubuntu的网卡驱动和触控板驱动整破防了www
|
||||
# 动机
|
||||
因为刚刚加入了自己学校的机器人队伍,队伍中使用的环境比较老,对环境的要求又十分苛刻,所以我先加装了一块1t的ssd,安装了ubuntu20.04。但是令我机器难受的是ubuntu20.04没有内置自己intel ax201网卡的驱动,同时触摸板的驱动也没有,但是触摸板还是个小问题,但是网卡驱动可是个大问题(ubuntu。。。习惯了)
|
||||
|
||||
查了网上许多的资料,官网,某些不知名软件包,stackoverflow等各处地方,都没有找到相关的解决办法。这个时候我已经在ubuntu上花费了大量时间,同时并不太喜欢ubuntu的相关界面,而是更加喜欢archlinux,于是我做出了这个决定。。。而此时潘多拉魔盒已悄然打开。。。
|
||||
|
||||
|
||||
# 一、安装archlinux系统
|
||||
经典的三板斧,archlinux镜像下载(https://archlinux.org/download/) ,rufus烧录或者使用ventoy,进入bios选择启动设备。相关教程太多不再赘述。
|
||||
|
||||
> archlinux wiki iwctl官方文档 https://wiki.archlinuxcn.org/wiki/Iwd
|
||||
|
||||
>archlinux官方中文安装安装文档 https://wiki.archlinuxcn.org/wiki/%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97
|
||||
|
||||
> 附上b站大佬的教程 https://www.bilibili.com/read/cv20753052/?spm_id_from=333.999.collection.opus.click&opus_fallback=1
|
||||
|
||||
> 跟着教程走吧,严谨有条理,优雅
|
||||
|
||||
提醒几条:
|
||||
|
||||
1. 了解分区基础知识,确认好bios还是uefi启动。一定要注意分区的操作,一定要了解每一个行为的结果,达到你的目的。推荐使用cfdisk分区,有更良好的用户交互界面。
|
||||
|
||||
2. pacstrap安装系统时,建议跟着上述b站大佬教程安装,确认好自己需求,intel就装intel-ucode,amd就装amd的
|
||||
|
||||
3. efi分区是要挂载在/boot/efi目录的,以前装的时候直接挂载在/boot后无法开机
|
||||
|
||||
4. grub启动,关于os-prober。不喜欢,个人认为不好用,而且我没找到修改grub的os-prober启动项名称的方法,而且会把我的win11识别成win10,所以我选择修改/etc/grub.d/40_custom自建一个启动项
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
exec tail -n +3 $0
|
||||
# This file provides an easy way to add custom menu entries. Simply type the
|
||||
# menu entries you want to add after this comment. Be careful not to change
|
||||
# the 'exec tail' line above.
|
||||
#
|
||||
#上面为系统自带部分,下面是添加部分
|
||||
menuentry "windows 11 Honor" --class windows11 {
|
||||
insmod part_gpt
|
||||
insmod fat
|
||||
insmod chain
|
||||
search --no-floppy --fs-uuid --set=root F8CA-DB44
|
||||
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
|
||||
}
|
||||
```
|
||||
>———对了,grub还可以安装主题哦,我选用的是yorunoke大佬的miku主题
|
||||
https://github.com/yorunoken/HatsuneMiku
|
||||
发现在3072x1920屏幕上有点偏,字体大小有点小,于是自己fork了一个,但是要装一个Jetbrain nerd mono字体(自己常用)https://github.com/tifisht/grub_Miku/
|
||||

|
||||
|
||||
5. 我选用了plasma kde桌面环境x11环境,sddm为显示管理器(其实就是登录界面,不知道为什么起这样的名字)(请简单了解x window 的架构呢!xserver xclient )
|
||||
|
||||
# 二、桌面环境踩雷,一路火花带闪电
|
||||
|
||||
## sddm 缩放(dpi)设置
|
||||
在设置里启用同步sddm与plasma的dpi缩放后,满心欢喜,直接重启,却看见极小的ui界面,十分难受,~~如同考试感觉良好但是挂了一样~~,在这篇文章里找到了办法:https://www.zzqayy.cn/archives/sddmgao-fen-bian-lu-suo-fang-she-zhi
|
||||
|
||||
下面为关键配置:
|
||||
|
||||
```conf
|
||||
# /etc/sddm.conf
|
||||
[X11]
|
||||
EnableHiDPI=true
|
||||
|
||||
[General]
|
||||
GreeterEnvironment=QT_SCREEN_SCALE_FACTORS=2,QT_FONT_DPI=192
|
||||
```
|
||||
|
||||
## 输入法 rime 小狼毫 双拼方案
|
||||
|
||||
不知为何,在plasma环境下,使用ibus打字时只能输出英文,查找各种方案后无法解决。于是使用fcitx5,但是没法使用双拼,最后在用户目录下自己配置好双拼才成功启用方案,将小鹤双拼的方案文件导入用户文件夹,default.custom.yaml文件写入输入方案:
|
||||
```
|
||||
#default.custom.yaml
|
||||
schema_list:
|
||||
- schema: double_pinyin_flypy # 小鹤双拼 注释掉
|
||||
- schema: luna_pinyin # 全拼
|
||||
#- schema: double_pinyin # 自然码
|
||||
```
|
||||
写好后一直无法输出双拼,但是关机后一个晚上就好了,可能是重启了吧((
|
||||
|
||||
# 三、docker容器运行ros1 px4环境
|
||||
|
||||
前言:之前试过了多种方案,例如
|
||||
debootstrap 安装ubuntu根目录,然后systemd-nspawn跑容器,但是总是在更新之后无法编译px4,一堆报错,知道是环境的问题,所以继续搜索发现px4官方对于docker的支持十分完善((给我整破防了
|
||||
|
||||
> px4官方docker部署教程 https://docs.px4.io/main/en/test_and_ci/docker.html
|
||||
|
||||
先要在自己的宿主机的目录底下克隆px4源代码:
|
||||
> git clone https://github.com/PX4/PX4-Autopilot.git
|
||||
|
||||
选用合适的容器,容器列表为:
|
||||
>https://github.com/PX4/PX4-containers/tree/master?tab=readme-ov-file#container-hierarchy
|
||||
|
||||
> https://hub.docker.com/r/px4io/px4-dev-nuttx-focal/tags?page=1&ordering=last_updated
|
||||
|
||||
我要gazebo仿真,ros1环境也就是noetic,所以使用px4io/px4-dev-simulation-focal容器,有模拟环境,我自己修改后的拉取与启动命令为:
|
||||
```bash
|
||||
xhost +local:
|
||||
docker run -it --privileged \
|
||||
--env=LOCAL_USER_ID="$(id -u)" \
|
||||
-v ~/PX4-Autopilot:/src/PX4-Autopilot:rw \
|
||||
-v /tmp/.X11-unix:/tmp/.X11-unix:ro \
|
||||
-e DISPLAY=:0 \
|
||||
--network=host \
|
||||
--name=px4-ros1 \
|
||||
px4io/px4-dev-simulation-focal \
|
||||
bash
|
||||
```
|
||||
解释:
|
||||
|
||||
xhost +local:让本地的程序可以连接到x11(每次重启后都要运行,可以写入~/.bashrc在启动时自动运行)此方案存在一定不安全可能,更细粒度的控制方案可以在archwiki xhost页面上找到
|
||||
|
||||
"-it" 以容器内交互方式运行
|
||||
|
||||
"--privileged"表示这是特权容器
|
||||
|
||||
"--env=" 设置自己用户id与自己用户一致,方便x11连接
|
||||
|
||||
"-v ~/PX4-Autopilot:/src/PX4-Autopilot:rw" 绑定容器内px4目录为宿主机的位置,要自己改一下宿主机的px4源码位置哦, :前面的是宿主机位置,最后的:rw为docker目录内的文件夹权限
|
||||
|
||||
"-v /tmp/.X11-unix:/tmp/.X11-unix:ro" 将x11套接字文件夹连接到docker容器内,使容器可以与宿主机x11通信(十分重要)
|
||||
|
||||
"-e DISPLAY=:0"意思是设置DISPLAY环境变量,:0是表示在本机的0号桌面上显示
|
||||
|
||||
"--network=host"表示与宿主机使用同一套网络,px4网络功能多,所以使用映射太过麻烦,直接让容器使用宿主机网络
|
||||
|
||||
## 测试运行
|
||||
命令运行后,会进入docker内交互环境,进行测试
|
||||
```bash
|
||||
cd /src/PX4-Autopilot
|
||||
make px4_sitl_default gazebo
|
||||
```
|
||||
检查自己的x11环境是否出现了gazebo窗口,是否出现了无人机
|
||||
|
||||
## 四、qGroundControl(QGC)地面站连接
|
||||
|
||||
在宿主机下载好qgc,开机,诶,发现连不上!!!咋办呢?
|
||||
|
||||
可能是你docker命令运行时没有使用--network=host选项呢,还是不行的话自己解决吧(摆
|
||||
|
||||
# 五、docker日常的进入环境
|
||||
|
||||
> 可以自己多学习一下docker的用法,以备不时之需
|
||||
|
||||
先要启动: docker start {{docker_name}}
|
||||
|
||||
再是进入: docker exec -it {{docker_name}} bash
|
||||
|
||||
退出直接使用exit退出环境,exit会暂停容器的运行
|
||||
228
basicTutorial/environment/ubuntuenv.md
Executable file
228
basicTutorial/environment/ubuntuenv.md
Executable file
File diff suppressed because one or more lines are too long
BIN
favicon.ico
Executable file
BIN
favicon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
103
index.html
Executable file
103
index.html
Executable file
@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>fly316 中心知识库</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="description" content="Description">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="static/vue.css">
|
||||
<link rel="stylesheet" href="static/toc.css">
|
||||
<link rel="stylesheet" href="static/sidebar.min.css" />
|
||||
<link rel="stylesheet" href="static/docsify-vite-coverpage.css">
|
||||
<link rel="stylesheet" href="static/darkmode.css">
|
||||
<!-- disable darkmode -->
|
||||
<!-- <link rel="stylesheet" href="static/darkmode.min.css"> -->
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
||||
<script>
|
||||
window.$docsify = {
|
||||
// 侧栏名称
|
||||
name: '<img src="./static/logo.png"></img>fly316 中心知识库',
|
||||
|
||||
//开启封面
|
||||
coverpage: true,
|
||||
//开启侧栏
|
||||
loadSidebar: true,
|
||||
loadNavbar: true,
|
||||
//子栏最大层级数量
|
||||
subMaxLevel: 3,
|
||||
//定栏开启
|
||||
// loadNavbar: true,
|
||||
// autoHeader: true,
|
||||
//开启404页面
|
||||
notFoundPage: true,
|
||||
|
||||
// topMargin: 90,
|
||||
|
||||
// themeColor: "#42b983", //darkmode
|
||||
repo: '',
|
||||
|
||||
//rtl插件配置
|
||||
pagination: {
|
||||
previousText: '上一章节',
|
||||
nextText: '下一章节',
|
||||
crossChapter: true,
|
||||
crossChapterText: true,
|
||||
},
|
||||
|
||||
//索引栏目(右上)栏
|
||||
|
||||
toc: {
|
||||
scope: '.markdown-section',
|
||||
headings: 'h1, h2, h3, h4, h5, h6',
|
||||
title: '本文索引',
|
||||
},
|
||||
//侧边栏折叠
|
||||
sidebarDisplayLevel: 2,
|
||||
alias: {
|
||||
'/.*/_sidebar.md': '/_sidebar.md',
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
<!-- Docsify v4 -->
|
||||
<script src="static/docsify@4.js"></script>
|
||||
<!-- plugin list -->
|
||||
<script src="./static/docsify-pagination.min.js"></script>
|
||||
<script src="./static/toc.js"></script>
|
||||
<script src="./static/docsify-sidebar-collapse.min.js"></script>
|
||||
<!-- <script src="./static/dark-switcher.js"></script> -->
|
||||
<script src="./static/docsify-dark-switcher.js"></script>
|
||||
<script src="./static/fontsize.js"></script>
|
||||
|
||||
<!-- disable darkmode -->
|
||||
<!-- <script src="./static/darkmode.min.js"></script> -->
|
||||
</body>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--dark-base-background: #222;
|
||||
--dark-base-color: #bbc0c4;
|
||||
--dark-theme-color: var(--theme-color, #42b983);
|
||||
--dark-code-color: var(--dark-color);
|
||||
--dark-heading-color: var(--dark-theme-color);
|
||||
--dark-cover-background: #000000a8;
|
||||
--dark-code-background: #303030;
|
||||
--dark-tip-background: #2c0000;
|
||||
--dark-warn-background: #005842;
|
||||
--dark-icon-size: 25px;
|
||||
--dark-icon-transition: .1s ease-in-out .1s;
|
||||
--dark-moon-color: #000000;
|
||||
--dark-sun-color: #ffffff;
|
||||
--dark-moon-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M9.598 1.591a.749.749 0 0 1 .785-.175 7.001 7.001 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786m1.616 1.945a7 7 0 0 1-7.678 7.678 5.499 5.499 0 1 0 7.678-7.678'/%3E%3C/svg%3E");
|
||||
--dark-sun-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M8 12a4 4 0 1 1 0-8a4 4 0 0 1 0 8m0-1.5a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5m5.657-8.157a.75.75 0 0 1 0 1.061l-1.061 1.06a.749.749 0 0 1-1.275-.326a.749.749 0 0 1 .215-.734l1.06-1.06a.75.75 0 0 1 1.06 0Zm-9.193 9.193a.75.75 0 0 1 0 1.06l-1.06 1.061a.75.75 0 1 1-1.061-1.06l1.06-1.061a.75.75 0 0 1 1.061 0M8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0M3 8a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 3 8m13 0a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 16 8m-8 5a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13m3.536-1.464a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061M2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018l-1.06-1.06a.75.75 0 0 1 0-1.06Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</html>
|
||||
21
infrastructure.md
Executable file
21
infrastructure.md
Executable file
@ -0,0 +1,21 @@
|
||||
# 基础设施
|
||||
> hi 我是tifisht,本文档的维护者!让我向你介绍fly316的基础设施服务吧
|
||||
|
||||
|
||||
## fly316云盘服务!
|
||||
|
||||
首先致谢[cloudreve](https://cloudreve.org/)提供的社区版本cloudreve网盘系统
|
||||
|
||||
网盘服务目前只对 **中国地质大学(北京)** 内网环境开放:[**fly316 cloud storage**](http://fly316.ttserver.fun:5212)
|
||||
|
||||
目前只开放了统一账户,账号密码请咨询tc,或tifisht。我们将在验证你的队内身份后向你开放权限!
|
||||
|
||||
## 博客知识库!
|
||||
|
||||
tifisht 欢迎各位施工ing....
|
||||
|
||||
blog能让历史的问题和知识更方便的传承下来,而不是每次都赌运一样,在不靠谱的帖子中间不断试错!这件事所有计算机从业者听了,都男默女泪。
|
||||
|
||||
为了让316的新人,少走我们的弯路,更快上手,特地开创此文档以及blog,让我们的工作与名字传承下去!
|
||||
|
||||
|
||||
285
recruitment.md
Executable file
285
recruitment.md
Executable file
@ -0,0 +1,285 @@
|
||||
# 机器人队招新(无人机项目)
|
||||
```
|
||||
参考 湖科大Asterism实验室加入流程
|
||||
发布时间: 咕咕咕
|
||||
by tc
|
||||
```
|
||||
## 0. 机器人队(无人机项目)简介
|
||||
- 我们项目是机器人队中获得国家级一等奖最多的项目
|
||||
- 欢迎有责任心、对我们的项目感兴趣的同学加入我们
|
||||
- 无论你是什么专业,都可以来我们这一起玩
|
||||
- 方向分为软件以及硬件,当然你全栈也可以的(
|
||||
|
||||
## 1. 你需要做什么
|
||||
|
||||
- 认真负责,对你的比赛负起责任
|
||||
- 自发学习,增进技术
|
||||
- 有时候需要你垫钱买设备(会报销)
|
||||
## 2. 你可以获得什么
|
||||
- 参加有含金量的比赛,为保研加分
|
||||
- 锻炼你的工程能力以及学习能力
|
||||
- 得到学长学姐学业等方面的指导
|
||||
- 设备、差旅费的报销
|
||||
- 我们的实验室在教三楼316,是地大唯一一个面向本科生的实验室,24h有电+空调。只要你正式加入我们并且在比赛中做出一定的贡献,就可以申请一个自己的工位
|
||||
- 316实验室有一个6.7*4.5的室内场地,可以进行机器人有关的调试等
|
||||
## 3. 加入流程
|
||||
- 大一的同学:
|
||||
完成考核并提交 - 面试 - 加入机器人队
|
||||
|
||||
- 大二、大三的同学:
|
||||
完成更复杂的考核内容 - 面试 - 加入机器人队
|
||||
|
||||
### 3.1 完成考核并提交
|
||||
|
||||
这个阶段主要是为了:
|
||||
|
||||
- 筛选看起来**已经有机器人相关基础**或者**有明显自学能力**的同学
|
||||
- 让你初步接触这个领域,从而决定是否继续加入我们
|
||||
|
||||
完成考核并提交的同学,会被视为有意愿长期加入我们。
|
||||
|
||||
**进入下一阶段的条件:**
|
||||
完成考核内容(不要求全部完成),我们会根据完成情况联系你。
|
||||
|
||||
### 3.2 面试
|
||||
|
||||
面试会和你的考核情况有关。此阶段主要是为了确认考核是你自己做的。我们鼓励你去网上**复刻别人的教程**,或者是**拷打AI**(只要不是抄了跑通了直接交,或者是从别人的教程里截图当做自己的配图)。我们希望你**有一定的修改**或者是**熟悉这个项目的流程**,而不是完全copy 别人的 or 网上的 or 别人在网上copy的。我们不认可抄袭行为,**抄袭的同学一经发现不允许参与任何机器人队的项目**。
|
||||
|
||||
### 3.3 加入机器人队
|
||||
|
||||
完成以上的考核以及面试以后,你离参加比赛还差一些东西需要学习,具体的学习内容和比赛要求有关。你需要边参与比赛边学习有关的知识。
|
||||
|
||||
加入我们以后,我们能为你提供各种设备以及调试场地。
|
||||
我们可以提供的支持包括:
|
||||
- 3d打印机
|
||||
- nuc、香橙派等边缘计算设备
|
||||
- 2D、3D激光雷达
|
||||
- D435深度相机
|
||||
- T265相机
|
||||
- 各种飞控
|
||||
- 配备了飞控的无人机
|
||||
- 螺丝刀等工具
|
||||
- ......
|
||||
|
||||
### 3.4 参加比赛
|
||||
不完全统计,可以参加的比赛有这些:
|
||||
- 5月 中国机器人暨RoboCup世界杯中国赛 无人机实物赛、无人机仿真赛
|
||||
- 5月 ~ 暑假 中国机器人及人工智能大赛 无人协同项目
|
||||
- 5月 ~ 暑假 中国机器人及人工智能大赛 微型无人机项目
|
||||
- 5月 ~ 暑假 RAICOM空中侦察项目
|
||||
- 10月 中国机器人暨RoboCup世界杯中国赛 无人机自主竞速
|
||||
- 11月 华北五省机器人大赛(只有省赛;需要有合适的项目)
|
||||
- 12月 ~ 次年6月 RoboMaster机甲大师高校人工智能挑战赛 仿真赛、实物赛
|
||||
- 一年三场的植保机器人
|
||||
- 各种创赛
|
||||
- ......
|
||||
|
||||
|
||||
**参加比赛的流程:**
|
||||
|
||||
- 前面的考核是基础内容。为了保证参赛质量,参赛前我们可能会再发布一个**报名用的赛前考核**,证明你**已经有能力完成比赛**或者**在参赛时可以达到参赛水平**
|
||||
- 组队阶段遵循自愿组队,你要是能一个人单挑,也可以自己选择队友。最后根据报名的队伍可能会进行人员调整
|
||||
- 备赛阶段将进行检查,目的是督促备赛
|
||||
- 报名费、比赛过程中产生的材料费、差旅费、邮寄设备的费用等(除了吃饭)都可以报销,具体的报销方式入队后会发给你。**比赛时可能需要你先行垫付**
|
||||
|
||||
## 4. 考核内容
|
||||
>考核分为软件和硬件两个方向。每个方向分基础部分以及进阶部分。大一的同学至少要完成基础部分与进阶部分,最后的附加部分尝试选择一个完成。其他同学请完成全部内容。**本次发布的考核针对软件方向,硬件方向请单独联系我(qq 3352648769)**,内容与SolidWorks建模、元器件焊接等有关。如果你是飞手或者以前接触过航模、打过飞北等比赛,也请单独联系我,我们现在很需要这些方面的同学加入。
|
||||
|
||||
|
||||
考核过程没有特别要求,但我们建议:
|
||||
|
||||
- 刚开始的第一步绝对会很难,但如果你真的想在 大学阶段 学习前沿的无人机和机器人技术,并使用全校最适合无人机/机器人开发的器材进行实机实验,机器人队可能是比较合适的选择
|
||||
- 考核的题目难度不大,但是对于刚接触的同学来说可能会遇到各种奇奇怪怪的问题(网络问题、设备环境问题等)。**查阅资料、解决遇到的问题本身也是考核的一部分**。我们希望你能锻炼信息检索的能力,充分利用互联网。你可以在csdn、github、AI、b站等地方找到问题的答案。
|
||||
- 尽可能多的自己完成,但是在卡了很久(比如一两天)就应该在群里求助
|
||||
- 记录自己的学习历程,可以用来发博客,或者仅仅是留一个纪念(这个我没干但是应该干,也建议大家干)
|
||||
- 简单了解所有命令/代码的实际含义,这可以帮助你定位问题
|
||||
- 如果遇到的困难很集中,可以考虑用任何你想的到的办法,系统补一下相关知识,做一些简单实践(一类知识的学习在3-9小时左右,不超过12小时。比如学ros,学python,学C++)
|
||||
- 完成任务目标不是第一性的,在完成任务目标的过程达到对应的能力。让你们在学习的过程中具备机器人研发的思维是题目最初也是最朴素的愿望。同时,这不代表我们反对你参考各种教程、帖子或者是使用AI。事实上,我们十分鼓励你通过这些方式来增长能力
|
||||
|
||||
### 4.1 基础部分
|
||||
|
||||
*一、安装ubuntu 20.04*
|
||||
|
||||
>18.04或20.04均可,但是我们后续的开发都在20.04;同时,由于ros1不再支持ubuntu20.04之后的版本,所以我们强烈建议你使用ubuntu20.04。
|
||||
|
||||
有两种方式,使用虚拟机 和 使用双系统, 各有优劣,完成任一方案即可。虚拟机更卡但是容易配置,回滚方便;双系统比虚拟机流畅,适合进行长期的开发,但是配置门槛较高,容易把电脑搞崩。
|
||||
|
||||
参考教程:
|
||||
使用虚拟机的教程很多,也相对简单,请自行到b站搜索。
|
||||
使用双系统可以参考:
|
||||
[Windows 和 Ubuntu 双系统的安装和卸载](https://www.bilibili.com/video/BV1554y1n7zv?vd_source=ff10da97fd8eec086ca6994495450b27)
|
||||
|
||||
建议:
|
||||
- 如果是第一次装双系统的话请**备份好电脑中重要文件**
|
||||
- ubuntu现在可以安装linux版的qq、微信等,很方便
|
||||
- 双系统建议给ubuntu留200G及以上空间
|
||||
- 如果你恰好时间充裕,可以把你的ubuntu打扮得像mac,美观一点。
|
||||
- 你需要简单了解下 linux的命令
|
||||
|
||||
*晋级条件:* 安装完成ubuntu 20.04 ,显示出标志性的猎豹图案的桌面,并正常连接wifi上网
|
||||
|
||||
|
||||
*二、科学上网*
|
||||
|
||||
>机器人技术研发,或者说和电脑有关的,必须会xxxx
|
||||
|
||||
参考教程:
|
||||
如果你之前不会xxxx,这是我自用的链接[xxxx](https://link-hub.world/),签到应该可以领取几百兆免费的。
|
||||
~~本来不想放怕进🍊了~~
|
||||
|
||||
建议:
|
||||
- 如果遇到各种网络问题,有时候可能只是WIFI的问题,切换手机流量给开热点就可以了,不一定要用tizi。
|
||||
- 如果使用tizi时出现网络问题/network error 尝试更新配置,再切换节点、打开或者关闭tizi。
|
||||
|
||||
*晋级条件:* 访问 油管,并观看1080P的视频,流畅不卡
|
||||
|
||||
*三、安装ros,初步了解一下ros*
|
||||
|
||||
>官方文档对 ROS 的介绍如下:The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications. From drivers to state-of-the-art algorithms, and with powerful developer tools, ROS has what you need for your next robotics project. And it's all open source.
|
||||
|
||||
简单来说 ROS 就是一款开源的机器人操作系统,可以实现在 Linux 或 Dock 下安装并进行使用。如今已经有ros2了,但是ros1的资源更多,我们以后也使用ros1。
|
||||
|
||||
|
||||
参考教程:
|
||||
可以使用鱼香ros一键安装,请自行搜索
|
||||
|
||||
|
||||
建议:
|
||||
- ros与ubuntu版本是对应的,比如说`ubuntu18.04 - melodic`,`ubuntu20.04 - noetic`。有些老旧的教程给出的一些命令可能是针对meloldic,如果你用的是noetic请将命令里面的melodic替换成noetic。类似于`ros melodic xxx` ->`ros noetic xxx`,反过来同理。
|
||||
|
||||
- 如果你网不好建议换手机流量开热点。
|
||||
|
||||
*晋级条件:* 1. 调出小乌龟,请自行搜索这是什么; 2. 了解一些基础的工具是干啥的以及如何打开,比如说qt工具箱(这一点提交的报告不用写但是面试可能会问你)
|
||||
|
||||
### 4.2 进阶部分
|
||||
*一、安装mavros、px4、QgroundControl*
|
||||
|
||||
>实机很危险,算法一般需要现在仿真进行测试之后再搬到实机。~~316实验场地的天花板已经被击穿好几块了~~
|
||||
|
||||
参考教程:
|
||||
px4、mavros的安装的教程网上有很多,请自行搜索。
|
||||
QGC请直接去官网下载。
|
||||
|
||||
建议:
|
||||
- 建议安装px4 1.13.3版本,后续迁移无人机模型(model)、地图(world)等等相对方便。实在不行再安装最新版。
|
||||
|
||||
*晋级条件:* 在gazebo中出现一台无人机,用QGC解锁它。
|
||||
|
||||
*二、编写一个简单的发布者与接收者*
|
||||
|
||||
>无人机在比赛的过程中需要完成一些任务,比如说识别等,识别到的信息可能需要发布出来。
|
||||
|
||||
参考教程:
|
||||
[机器人操作系统 ROS 快速入门教程](https://www.bilibili.com/video/BV1BP4y1o7pw?vd_source=ff10da97fd8eec086ca6994495450b27)
|
||||
|
||||
进一步的学习可以参考赵虚左老师的教程,b站也有。不过暂时够用了。
|
||||
|
||||
建议:
|
||||
- ros的学习是一个边学边用的过程,一些东西忘记了很正常,简单查资料就能找到了,
|
||||
|
||||
*晋级条件:* 形式无所谓,你来定,在任务提交里面让我们看出来有这么个东西就行。
|
||||
|
||||
### 4.3 附加部分
|
||||
**请在以下选择一个进行:**
|
||||
|
||||
#### 4.3.1 在仿真中控制无人机
|
||||
|
||||
>死程序其实能跑的话永远是最快的(
|
||||
|
||||
*一、在仿真中控制无人机飞一个四边形*
|
||||
**大一同学选择这部分的,完成这个即可**
|
||||
|
||||
参考教程:
|
||||
px4官网给出了一个简单的c++和python历程,它让无人机悬停在了一个位置不动。接下来请你修改一下它,让他飞一个四边形。
|
||||
|
||||
建议:
|
||||
- 大致了解代码在干啥
|
||||
|
||||
*晋级条件:* 在仿真中飞一个四边形,随后降落。
|
||||
|
||||
*二、在仿真中控制无人机识别二维码,根据二维码内容进行下一步的飞行*
|
||||
**大二及以上的同学完成这部分视为完成附加题4.3.1**
|
||||
|
||||
要求:
|
||||
- 无人机起飞,扫码后根据二维码内容飞到下一个点,降落。
|
||||
- 在gazebo中自己搭建一个二维码model,然后创建一个world。
|
||||
- 为无人机添加对地摄像头。
|
||||
- 无人机知道二维码的位置,但不知道二维码里的内容。二维码里面的内容可以是一串字符串,比如`2,3,2`, 表示`x=2,y=3,z=2`的位置,单位为米。无人机起飞前往二维码位置进行扫码,根据识别到的内容飞往下一个点,随后原地降落,锁桨。
|
||||
|
||||
参考教程:
|
||||
前面所有的,熟练掌握,然后需要知道怎么在gazebo做一个world,怎么将仿真的摄像头加入无人机。
|
||||
|
||||
建议:
|
||||
熟练掌握上面的内容
|
||||
|
||||
*晋级条件:* 在仿真中完成上述内容。
|
||||
|
||||
#### 4.3.2 训练一个目标检测模型,写一个发布者发布识别结果出来。
|
||||
|
||||
> 无人机的比赛一般都有检测某物品的要求。
|
||||
|
||||
**建议有NVIDIA的gpu的同学进行尝试,没有的同学请看4.3.1**
|
||||
|
||||
要求:
|
||||
- 用给出的图片自行制作训练集等,训练一个简单的目标检测模型。
|
||||
- 安装usb_cam,发布来自摄像头识别到的图像信息
|
||||
- 将训练的模型部署在ubuntu,识别靶子的内容。请用A4纸打印几张图片,你可以外接一个摄像头或者就用电脑自带的摄像头来识别。
|
||||
- 将识别得到的结果发布出来,直接在终端echo它。
|
||||
|
||||
参考教程:
|
||||
请自行搜索,网上有很多。
|
||||
|
||||
建议:
|
||||
- 由于边缘平台算力有限,请用轻量的模型。
|
||||
|
||||
*晋级条件:* 识别给出的图片,不要求有太高的准确率。
|
||||
|
||||
## 5. 提交考核
|
||||
|
||||
**提交时间**
|
||||
初步定在寒假结束前,大约2.15号,提交审核以后我们会通知晋级的同学面试。
|
||||
|
||||
**提交格式**
|
||||
请打包成一个压缩文件,命名为`姓名-专业-学号-学院`,文件夹构成如下:
|
||||
```
|
||||
姓名 - 专业 - 学号 - 学院
|
||||
|-- 基础部分
|
||||
| |-- 安装ubuntu
|
||||
| | |-- 说明文档.doc(或.pdf)
|
||||
| | |-- 任务截图.png
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |-- 安装ros
|
||||
| | |-- 说明文档.doc(或.pdf)
|
||||
| | |-- 任务截图.png
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |--...
|
||||
|-- 进阶部分
|
||||
| |-- 安装px4
|
||||
| | |-- 说明文档.doc(或.pdf)
|
||||
| | |-- 任务截图.png
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |-- 发布者接收者
|
||||
| | |-- ros 工作空间文件夹
|
||||
| | |-- 任务截图.png
|
||||
| | |-- ros 工作空间文件夹
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |--...
|
||||
|-- 附加部分
|
||||
| |-- 飞行仿真
|
||||
| | |-- 说明文档.doc(或.pdf)
|
||||
| | |-- 任务截图.png
|
||||
| | |-- ros 工作空间文件夹
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |-- cv
|
||||
| | |-- 说明文档.doc(或.pdf)
|
||||
| | |-- 任务截图.png
|
||||
| | |-- ros 工作空间文件夹
|
||||
| | |-- 视频.mp4(若需要)
|
||||
| |--...
|
||||
|
||||
```
|
||||
|
||||
说明文档大概写一下你的流程,遇到的问题就可以了,文档可以用markdown写了转pdf,不用也没关系。文档不要写太长了,写少不扣分,写多了不加分。要没啥能写的写一行也可以。如果觉得说不清楚可以录视频。如果没完成这个任务,也可以写,做到哪一步写哪一步。总之,**提交的内容是为了让我们明白你去做了这个任务。**
|
||||
|
||||
**提交方式**
|
||||
咕咕咕收的时候会发的,要是提前完成了可以提前联系我(qq 3352648769)
|
||||
126
static/dark-switcher.js
Normal file
126
static/dark-switcher.js
Normal file
@ -0,0 +1,126 @@
|
||||
function docsifyDarkSwitcher() {
|
||||
var element = document.querySelector('body');
|
||||
element.classList.toggle("docsify-dark-mode");
|
||||
|
||||
if (element.classList.contains("docsify-dark-mode")) {
|
||||
localStorage.setItem('docsify-dark-mode', 'true');
|
||||
} else {
|
||||
localStorage.removeItem('docsify-dark-mode');
|
||||
}
|
||||
}
|
||||
|
||||
function applyInitialMode() {
|
||||
if (localStorage.getItem('docsify-dark-mode') === 'true' || window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.querySelector('body').classList.add("docsify-dark-mode");
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', applyInitialMode);
|
||||
|
||||
function styleInject(css, ref) {
|
||||
if (ref === void 0) ref = {};
|
||||
var insertAt = ref.insertAt;
|
||||
|
||||
if (!css || typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
var style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
|
||||
if (insertAt === 'top') {
|
||||
if (head.firstChild) {
|
||||
head.insertBefore(style, head.firstChild);
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = css;
|
||||
} else {
|
||||
style.appendChild(document.createTextNode(css));
|
||||
}
|
||||
}
|
||||
|
||||
var css = `
|
||||
:root {
|
||||
--dark-moon-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M9.598 1.591a.749.749 0 0 1 .785-.175 7.001 7.001 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786m1.616 1.945a7 7 0 0 1-7.678 7.678 5.499 5.499 0 1 0 7.678-7.678'/%3E%3C/svg%3E");
|
||||
--dark-sun-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M8 12a4 4 0 1 1 0-8a4 4 0 0 1 0 8m0-1.5a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5m5.657-8.157a.75.75 0 0 1 0 1.061l-1.061 1.06a.749.749 0 0 1-1.275-.326a.749.749 0 0 1 .215-.734l1.06-1.06a.75.75 0 0 1 1.06 0Zm-9.193 9.193a.75.75 0 0 1 0 1.06l-1.06 1.061a.75.75 0 1 1-1.061-1.06l1.06-1.061a.75.75 0 0 1 1.061 0M8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0M3 8a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 3 8m13 0a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 16 8m-8 5a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13m3.536-1.464a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061M2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018l-1.06-1.06a.75.75 0 0 1 0-1.06Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
button[onclick="docsifyDarkSwitcher()"] {
|
||||
position: fixed;
|
||||
right: 2rem;
|
||||
top: 4rem;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: var(--dark-icon-size);
|
||||
height: var(--dark-icon-size);
|
||||
background: var(--dark-moon-color);
|
||||
mask-image: var(--dark-moon-icon);
|
||||
mask-size: var(--dark-icon-size) var(--dark-icon-size);
|
||||
transition: var(--dark-icon-transition);
|
||||
}
|
||||
.docsify-dark-mode button[onclick="docsifyDarkSwitcher()"] {
|
||||
background: var(--dark-sun-color);
|
||||
mask-image: var(--dark-sun-icon);
|
||||
}
|
||||
.docsify-dark-mode .cover .mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--dark-cover-background);
|
||||
}
|
||||
.docsify-dark-mode,
|
||||
.docsify-dark-mode .sidebar,
|
||||
.docsify-dark-mode .search input,
|
||||
.docsify-dark-mode .app-nav li ul {
|
||||
background: var(--dark-base-background);
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section code,
|
||||
.docsify-dark-mode .markdown-section pre,
|
||||
.docsify-dark-mode .markdown-section p.tip code {
|
||||
background: var(--dark-code-background);
|
||||
color: var(--dark-code-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section p.tip {
|
||||
background: var(--dark-tip-background);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section p.warn {
|
||||
background: var(--dark-warn-background);
|
||||
}
|
||||
.docsify-dark-mode .anchor span {
|
||||
color: var(--dark-heading-color);
|
||||
}
|
||||
.docsify-dark-mode .sidebar ul li.active>a {
|
||||
color: var(--dark-theme-color);
|
||||
border-color: var(--dark-theme-color);
|
||||
}
|
||||
.docsify-dark-mode .sidebar ul li a, .docsify-dark-mode .markdown-section strong {
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section tr:nth-child(2n) {
|
||||
background-color: #3b3b3b;
|
||||
}
|
||||
@media screen and (min-width:769px) {
|
||||
.docsify-dark-mode .sidebar-toggle {
|
||||
background: rgb(0 0 0 / .6);
|
||||
}
|
||||
}
|
||||
`;
|
||||
styleInject(css);
|
||||
|
||||
function install(hook, vm) {
|
||||
hook.afterEach(function (html) {
|
||||
var docsifyDarkSwitcherButton = '<button onclick="docsifyDarkSwitcher()" aria-label="Toggle dark mode" title="Toggle dark mode"></button>';
|
||||
return docsifyDarkSwitcherButton + html;
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
51
static/darkmode.css
Normal file
51
static/darkmode.css
Normal file
@ -0,0 +1,51 @@
|
||||
:root {
|
||||
--dark-base-background: #222;
|
||||
--dark-base-color: #bbc0c4;
|
||||
--dark-theme-color: #42b983;
|
||||
--dark-heading-color: var(--dark-theme-color);
|
||||
--dark-cover-background: #000000a8;
|
||||
--dark-code-color: rgba(213, 213, 213, 0.68);
|
||||
--dark-code-background: rgba(42, 41, 41, 0.47);
|
||||
--dark-tip-background: #2c0000;
|
||||
--dark-warn-background: #005842;
|
||||
--dark-icon-size: 25px;
|
||||
--dark-icon-transition: .1s ease-in-out .1s;
|
||||
--dark-moon-color: #000000;
|
||||
--dark-sun-color: #ffffff;
|
||||
}
|
||||
|
||||
/*更改切换按钮的位置跟紫薯统计错开*/
|
||||
button[onclick="docsifyDarkSwitcher()"] {
|
||||
position: fixed;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
/*更改左下角菜单按钮防止跟深色模式冲突*/
|
||||
.docsify-dark-mode .sidebar-toggle span{
|
||||
background-color: #80eddd !important;
|
||||
}
|
||||
.docsify-dark-mode .sidebar-toggle {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
/*图片亮度*/
|
||||
.docsify-dark-mode .medium-zoom-image{
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
|
||||
/*搜索栏适配夜间模式*/
|
||||
.docsify-dark-mode .search a {
|
||||
color: rgba(255, 255, 255, 0.65);
|
||||
}
|
||||
|
||||
.docsify-dark-mode .search a:hover{
|
||||
color: #ffffff !important;
|
||||
.search-keyword {
|
||||
color: rgba(99, 246, 111, 0.78);
|
||||
}
|
||||
}
|
||||
|
||||
.docsify-dark-mode .search .search-keyword {
|
||||
color: rgba(70, 185, 66, 0.55);
|
||||
}
|
||||
|
||||
126
static/docsify-dark-switcher.js
Normal file
126
static/docsify-dark-switcher.js
Normal file
@ -0,0 +1,126 @@
|
||||
function docsifyDarkSwitcher() {
|
||||
var element = document.querySelector('body');
|
||||
element.classList.toggle("docsify-dark-mode");
|
||||
|
||||
if (element.classList.contains("docsify-dark-mode")) {
|
||||
localStorage.setItem('docsify-dark-mode', 'true');
|
||||
} else {
|
||||
localStorage.removeItem('docsify-dark-mode');
|
||||
}
|
||||
}
|
||||
|
||||
function applyInitialMode() {
|
||||
if (localStorage.getItem('docsify-dark-mode') === 'true' || window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.querySelector('body').classList.add("docsify-dark-mode");
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', applyInitialMode);
|
||||
|
||||
function styleInject(css, ref) {
|
||||
if (ref === void 0) ref = {};
|
||||
var insertAt = ref.insertAt;
|
||||
|
||||
if (!css || typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
var style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
|
||||
if (insertAt === 'top') {
|
||||
if (head.firstChild) {
|
||||
head.insertBefore(style, head.firstChild);
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = css;
|
||||
} else {
|
||||
style.appendChild(document.createTextNode(css));
|
||||
}
|
||||
}
|
||||
|
||||
var css = `
|
||||
:root {
|
||||
--dark-moon-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M9.598 1.591a.749.749 0 0 1 .785-.175 7.001 7.001 0 1 1-8.967 8.967.75.75 0 0 1 .961-.96 5.5 5.5 0 0 0 7.046-7.046.75.75 0 0 1 .175-.786m1.616 1.945a7 7 0 0 1-7.678 7.678 5.499 5.499 0 1 0 7.678-7.678'/%3E%3C/svg%3E");
|
||||
--dark-sun-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 16 16'%3E%3Cpath fill='currentColor' d='M8 12a4 4 0 1 1 0-8a4 4 0 0 1 0 8m0-1.5a2.5 2.5 0 1 0 0-5a2.5 2.5 0 0 0 0 5m5.657-8.157a.75.75 0 0 1 0 1.061l-1.061 1.06a.749.749 0 0 1-1.275-.326a.749.749 0 0 1 .215-.734l1.06-1.06a.75.75 0 0 1 1.06 0Zm-9.193 9.193a.75.75 0 0 1 0 1.06l-1.06 1.061a.75.75 0 1 1-1.061-1.06l1.06-1.061a.75.75 0 0 1 1.061 0M8 0a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0V.75A.75.75 0 0 1 8 0M3 8a.75.75 0 0 1-.75.75H.75a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 3 8m13 0a.75.75 0 0 1-.75.75h-1.5a.75.75 0 0 1 0-1.5h1.5A.75.75 0 0 1 16 8m-8 5a.75.75 0 0 1 .75.75v1.5a.75.75 0 0 1-1.5 0v-1.5A.75.75 0 0 1 8 13m3.536-1.464a.75.75 0 0 1 1.06 0l1.061 1.06a.75.75 0 0 1-1.06 1.061l-1.061-1.06a.75.75 0 0 1 0-1.061M2.343 2.343a.75.75 0 0 1 1.061 0l1.06 1.061a.751.751 0 0 1-.018 1.042a.751.751 0 0 1-1.042.018l-1.06-1.06a.75.75 0 0 1 0-1.06Z'/%3E%3C/svg%3E");
|
||||
}
|
||||
button[onclick="docsifyDarkSwitcher()"] {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 15px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
width: var(--dark-icon-size);
|
||||
height: var(--dark-icon-size);
|
||||
background: var(--dark-moon-color);
|
||||
mask-image: var(--dark-moon-icon);
|
||||
mask-size: var(--dark-icon-size) var(--dark-icon-size);
|
||||
transition: var(--dark-icon-transition);
|
||||
}
|
||||
.docsify-dark-mode button[onclick="docsifyDarkSwitcher()"] {
|
||||
background: var(--dark-sun-color);
|
||||
mask-image: var(--dark-sun-icon);
|
||||
}
|
||||
.docsify-dark-mode .cover .mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: var(--dark-cover-background);
|
||||
}
|
||||
.docsify-dark-mode,
|
||||
.docsify-dark-mode .sidebar,
|
||||
.docsify-dark-mode .search input,
|
||||
.docsify-dark-mode .app-nav li ul {
|
||||
background: var(--dark-base-background);
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section code,
|
||||
.docsify-dark-mode .markdown-section pre,
|
||||
.docsify-dark-mode .markdown-section p.tip code {
|
||||
background: var(--dark-code-background);
|
||||
color: var(--dark-code-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section p.tip {
|
||||
background: var(--dark-tip-background);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section p.warn {
|
||||
background: var(--dark-warn-background);
|
||||
}
|
||||
.docsify-dark-mode .anchor span {
|
||||
color: var(--dark-heading-color);
|
||||
}
|
||||
.docsify-dark-mode .sidebar ul li.active>a {
|
||||
color: var(--dark-theme-color);
|
||||
border-color: var(--dark-theme-color);
|
||||
}
|
||||
.docsify-dark-mode .sidebar ul li a, .docsify-dark-mode .markdown-section strong {
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
.docsify-dark-mode .markdown-section tr:nth-child(2n) {
|
||||
background-color: #3b3b3b;
|
||||
}
|
||||
@media screen and (min-width:769px) {
|
||||
.docsify-dark-mode .sidebar-toggle {
|
||||
background: rgb(0 0 0 / .6);
|
||||
}
|
||||
}
|
||||
`;
|
||||
styleInject(css);
|
||||
|
||||
function install(hook, vm) {
|
||||
hook.afterEach(function (html) {
|
||||
var docsifyDarkSwitcherButton = '<button onclick="docsifyDarkSwitcher()" aria-label="Toggle dark mode" title="Toggle dark mode"></button>';
|
||||
return docsifyDarkSwitcherButton + html;
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
1
static/docsify-pagination.min.js
vendored
Normal file
1
static/docsify-pagination.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/docsify-sidebar-collapse.min.js
vendored
Normal file
1
static/docsify-sidebar-collapse.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e){("object"!=typeof exports||"undefined"==typeof module)&&"function"==typeof define&&define.amd?define(e):e()}(function(){"use strict";function e(e,n){var t,a=(n=void 0===n?{}:n).insertAt;e&&"undefined"!=typeof document&&(t=document.head||document.getElementsByTagName("head")[0],(n=document.createElement("style")).type="text/css","top"===a&&t.firstChild?t.insertBefore(n,t.firstChild):t.appendChild(n),n.styleSheet?n.styleSheet.cssText=e:n.appendChild(document.createTextNode(e)))}var t;function a(e){e&&null!=t&&(e=e.getBoundingClientRect().top,document.querySelector(".sidebar").scrollBy(0,e-t))}function n(){requestAnimationFrame(function(){var e=document.querySelector(".app-sub-sidebar > .active");if(e)for(e.parentNode.parentNode.querySelectorAll(".app-sub-sidebar").forEach(function(e){return e.classList.remove("open")});e.parentNode.classList.contains("app-sub-sidebar")&&!e.parentNode.classList.contains("open");)e.parentNode.classList.add("open"),e=e.parentNode})}function o(e){t=e.target.getBoundingClientRect().top;var n=d(e.target,"LI",2);n&&(n.classList.contains("open")?(n.classList.remove("open"),setTimeout(function(){n.classList.add("collapse")},0)):(function(e){if(e)for(e.classList.remove("open","active");e&&"sidebar-nav"!==e.className&&e.parentNode;)"LI"!==e.parentNode.tagName&&"app-sub-sidebar"!==e.parentNode.className||e.parentNode.classList.remove("open"),e=e.parentNode}(s()),i(n),setTimeout(function(){n.classList.remove("collapse")},0)),a(n))}function s(){var e=document.querySelector(".sidebar-nav .active");return e||(e=d(document.querySelector('.sidebar-nav a[href="'.concat(decodeURIComponent(location.hash).replace(/ /gi,"%20"),'"]')),"LI",2))&&e.classList.add("active"),e}function i(e){if(e)for(e.classList.add("open","active");e&&"sidebar-nav"!==e.className&&e.parentNode;)"LI"!==e.parentNode.tagName&&"app-sub-sidebar"!==e.parentNode.className||e.parentNode.classList.add("open"),e=e.parentNode}function d(e,n,t){if(e&&e.tagName===n)return e;for(var a=0;e;){if(t<++a)return;if(e.parentNode.tagName===n)return e.parentNode;e=e.parentNode}}e(".sidebar-nav > ul > li ul {\n display: none;\n}\n\n.app-sub-sidebar {\n display: none;\n}\n\n.app-sub-sidebar.open {\n display: block;\n}\n\n.sidebar-nav .open > ul:not(.app-sub-sidebar),\n.sidebar-nav .active:not(.collapse) > ul {\n display: block;\n}\n\n/* 抖动 */\n.sidebar-nav li.open:not(.collapse) > ul {\n display: block;\n}\n\n.active + ul.app-sub-sidebar {\n display: block;\n}\n"),document.addEventListener("scroll",n);e("@media screen and (max-width: 768px) {\n /* 移动端适配 */\n .markdown-section {\n max-width: none;\n padding: 16px;\n }\n /* 改变原来按钮热区大小 */\n .sidebar-toggle {\n padding: 0 0 10px 10px;\n }\n /* my pin */\n .sidebar-pin {\n appearance: none;\n outline: none;\n position: fixed;\n bottom: 0;\n border: none;\n width: 40px;\n height: 40px;\n background: transparent;\n }\n}\n");var r,c="DOCSIFY_SIDEBAR_PIN_FLAG";function l(){var e="true"===(e=localStorage.getItem(c));localStorage.setItem(c,!e),e?(document.querySelector(".sidebar").style.transform="translateX(0)",document.querySelector(".content").style.transform="translateX(0)"):(document.querySelector(".sidebar").style.transform="translateX(300px)",document.querySelector(".content").style.transform="translateX(300px)")}768<document.documentElement.clientWidth||(localStorage.setItem(c,!1),(r=document.createElement("button")).classList.add("sidebar-pin"),r.onclick=l,document.body.append(r),window.addEventListener("load",function(){var n=document.querySelector(".content");document.body.onclick=n.onclick=function(e){e.target!==document.body&&e.currentTarget!==n||"true"===localStorage.getItem(c)&&l()}})),function(){if(window.$docsify){for(var e=arguments.length,n=new Array(e),t=0;t<e;t++)n[t]=arguments[t];$docsify.plugins=n.concat($docsify.plugins||[])}else console.error("这是一个docsify插件,请先引用docsify库!")}(function(e,n){e.doneEach(function(e,n){var t=s();i(t),document.querySelectorAll(".sidebar-nav li").forEach(function(e){e.querySelector("ul:not(.app-sub-sidebar)")?e.classList.add("folder"):e.classList.add("file")}),function n(e,t){e&&e.childNodes&&e.childNodes.forEach(function(e){e.classList&&e.classList.contains("folder")&&(e.classList.add("level-".concat(t)),window.$docsify&&window.$docsify.sidebarDisplayLevel&&"number"==typeof window.$docsify.sidebarDisplayLevel&&t<=window.$docsify.sidebarDisplayLevel&&e.classList.add("open"),e&&1<e.childNodes.length&&n(e.childNodes[1],t+1))})}(document.querySelector(".sidebar-nav > ul"),1),a(t),n(e)}),e.ready(function(){document.querySelector(".sidebar-nav").addEventListener("click",o)})})});
|
||||
100
static/docsify-vite-coverpage.css
Normal file
100
static/docsify-vite-coverpage.css
Normal file
@ -0,0 +1,100 @@
|
||||
.cover .mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
section.cover img:first-child {
|
||||
filter: drop-shadow(5px 5px 100px var(--theme-color, #42b983));
|
||||
}
|
||||
|
||||
section.cover .cover-main > p:last-child a {
|
||||
letter-spacing: -.1px;
|
||||
padding: 12px 24px;
|
||||
background-color: #ebebef;
|
||||
border: none;
|
||||
color: #000000;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin: 5px 8px;
|
||||
}
|
||||
|
||||
section.cover .cover-main > p:last-child a:last-child:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
section.cover h1 span {
|
||||
color: var(--theme-color, #42b983);
|
||||
}
|
||||
|
||||
section.cover h1,
|
||||
section.cover blockquote {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
section.cover p:nth-last-child(2),
|
||||
section.cover ul {
|
||||
line-height: 1.5;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 960px) {
|
||||
section.cover .cover-main {
|
||||
margin: 0 72px;
|
||||
}
|
||||
|
||||
section.cover .cover-main,
|
||||
section.cover h1,
|
||||
section.cover blockquote {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
section.cover h1,
|
||||
section.cover blockquote {
|
||||
font-size: 56px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
section.cover p:nth-last-child(2),
|
||||
section.cover ul {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
section.cover p {
|
||||
max-width: 576px;
|
||||
}
|
||||
|
||||
section.cover .cover-main > p:last-child {
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
section.cover blockquote {
|
||||
margin-top: -52px;
|
||||
line-height: -1px;
|
||||
}
|
||||
|
||||
section.cover p:nth-last-child(2),
|
||||
section.cover ul {
|
||||
margin-top: -32px;
|
||||
}
|
||||
|
||||
section.cover p {
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
section.cover ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
section.cover img:first-child {
|
||||
float: right;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 75%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 540px;
|
||||
}
|
||||
}
|
||||
1
static/docsify@4.js
Normal file
1
static/docsify@4.js
Normal file
File diff suppressed because one or more lines are too long
164
static/fontsize.js
Normal file
164
static/fontsize.js
Normal file
@ -0,0 +1,164 @@
|
||||
function adjustFontSize(action) {
|
||||
const markdownSection = document.querySelector('.markdown-section#main');
|
||||
let currentSize = parseFloat(window.getComputedStyle(markdownSection).fontSize);
|
||||
|
||||
if (action === 'increase') {
|
||||
currentSize += 1;
|
||||
} else if (action === 'decrease') {
|
||||
currentSize -= 1;
|
||||
}
|
||||
|
||||
markdownSection.style.setProperty('--font-size', `${currentSize}px`);
|
||||
updateFontSizeDisplay(currentSize);
|
||||
localStorage.setItem('font-size', currentSize);
|
||||
}
|
||||
|
||||
function applyInitialStyles() {
|
||||
const savedSize = localStorage.getItem('font-size');
|
||||
if (savedSize) {
|
||||
const markdownSection = document.querySelector('.markdown-section#main');
|
||||
markdownSection.style.setProperty('--font-size', `${savedSize}px`);
|
||||
}
|
||||
}
|
||||
|
||||
function updateFontSizeDisplay(fontSize) {
|
||||
const fontSizeDisplay = document.querySelector('.font-size-display');
|
||||
const lang = document.documentElement.lang;
|
||||
if (fontSizeDisplay) {
|
||||
if (lang === 'zh') {
|
||||
fontSizeDisplay.textContent = `当前字体大小: ${fontSize}px`;
|
||||
} else {
|
||||
fontSizeDisplay.textContent = `Font size: ${fontSize}px`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', applyInitialStyles);
|
||||
|
||||
function styleInject(css, ref) {
|
||||
if (ref === void 0) ref = {};
|
||||
var insertAt = ref.insertAt;
|
||||
|
||||
if (!css || typeof document === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var head = document.head || document.getElementsByTagName('head')[0];
|
||||
var style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
|
||||
if (insertAt === 'top') {
|
||||
if (head.firstChild) {
|
||||
head.insertBefore(style, head.firstChild);
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
} else {
|
||||
head.appendChild(style);
|
||||
}
|
||||
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = css;
|
||||
} else {
|
||||
style.appendChild(document.createTextNode(css));
|
||||
}
|
||||
}
|
||||
|
||||
var css = `
|
||||
.markdown-section {
|
||||
--font-size: 15px;
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.markdown-section code {
|
||||
font-size: calc(var(--font-size) - 2px) !important;
|
||||
}
|
||||
|
||||
.markdown-section ol, .markdown-section p, .markdown-section ul {
|
||||
line-height: calc(var(--font-size) * 2);
|
||||
}
|
||||
|
||||
.markdown-section h1 {
|
||||
font-size: calc(var(--font-size) * 2.3);
|
||||
}
|
||||
|
||||
.markdown-section h2 {
|
||||
font-size: calc(var(--font-size) * 2.1);
|
||||
}
|
||||
|
||||
.markdown-section h3 {
|
||||
font-size: calc(var(--font-size) * 1.8);
|
||||
}
|
||||
|
||||
.markdown-section h4 {
|
||||
font-size: calc(var(--font-size) * 1.5);
|
||||
}
|
||||
|
||||
.markdown-section h5 {
|
||||
font-size: calc(var(--font-size) * 1.3);
|
||||
}
|
||||
|
||||
.markdown-section h6 {
|
||||
font-size: calc(var(--font-size) * 1.1);
|
||||
}
|
||||
|
||||
button.font-size-button {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 55px;
|
||||
padding: 6px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
z-index: 1000;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
button.font-size-button[onclick="adjustFontSize('decrease')"] {
|
||||
left: 100px;
|
||||
}
|
||||
|
||||
.docsify-dark-mode button.font-size-button {
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
|
||||
.font-size-display {
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
left: 139px;
|
||||
background: transparent;
|
||||
font-size: 16px !important;
|
||||
z-index: 1000;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.font-size-display {
|
||||
top: 40px;
|
||||
left:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.docsify-dark-mode .font-size-display{
|
||||
color: var(--dark-base-color);
|
||||
}
|
||||
`;
|
||||
|
||||
styleInject(css);
|
||||
|
||||
function install(hook, vm) {
|
||||
hook.afterEach(function (html) {
|
||||
const savedSize = localStorage.getItem('font-size') || 15;
|
||||
const lang = document.documentElement.lang;
|
||||
const fontSizeText = lang === 'zh' ? `当前字体大小: ${savedSize}px` : `Font size: ${savedSize}px`;
|
||||
var fontSizeButtons = `
|
||||
<button onclick="adjustFontSize('increase')" class="font-size-button" aria-label="Increase font size" title="Increase font size">A+</button>
|
||||
<button onclick="adjustFontSize('decrease')" class="font-size-button" aria-label="Decrease font size" title="Decrease font size">A-</button>
|
||||
<div class="font-size-display">${fontSizeText}</div>
|
||||
`;
|
||||
return fontSizeButtons + html;
|
||||
});
|
||||
}
|
||||
|
||||
$docsify.plugins = [].concat(install, $docsify.plugins);
|
||||
BIN
static/logo.png
Normal file
BIN
static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 323 KiB |
BIN
static/logo1.png
Executable file
BIN
static/logo1.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
1
static/sidebar.min.css
vendored
Normal file
1
static/sidebar.min.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.sidebar-nav li{position:relative;margin:0;cursor:pointer}.sidebar-nav ul:not(.app-sub-sidebar)>li:not(.file)::before{content:'';display:block;position:absolute;top:11px;left:-12px;height:6px;width:6px;border-right:1px solid #505d6b;border-bottom:1px solid #505d6b;transform:rotate(-45deg);transition:transform .1s}.sidebar-nav ul:not(.app-sub-sidebar)>li.open::before{transform:rotate(45deg)}.sidebar-nav ul:not(.app-sub-sidebar)>li.collapse::before{transform:rotate(-45deg)}
|
||||
104
static/toc.css
Normal file
104
static/toc.css
Normal file
@ -0,0 +1,104 @@
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: center;
|
||||
}
|
||||
.markdown-section {
|
||||
flex: 1 1 0%;
|
||||
margin: 0 48px;
|
||||
}
|
||||
.nav {
|
||||
width: var(--toc-width, 200px);
|
||||
align-self: flex-start;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
aside.nav.nothing {
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.page_toc {
|
||||
position: fixed;
|
||||
border-left-style: solid;
|
||||
border-left-width: 1px;
|
||||
border-left-color: rgba(0, 0, 0, 0.07);
|
||||
border-image-slice: 1;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.page_toc code {
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 2px;
|
||||
color: #e96900;
|
||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
||||
font-size: 0.8rem;
|
||||
margin: 0 2px;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.page_toc p.title {
|
||||
margin: 0px 0 0px 9px;
|
||||
padding-bottom: 5px;
|
||||
font-weight: 600;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
.page_toc .anchor:hover:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
.page_toc ul {
|
||||
list-style-type: none;
|
||||
margin-top: 0px;
|
||||
padding-left: 10px;
|
||||
color: var(--text-color-base, black);
|
||||
text-decoration: none;
|
||||
font-weight: 300;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.page_toc ul a:hover span {
|
||||
color: var(--text-color-tertiary, #42b983);
|
||||
border-bottom: none !important;
|
||||
text-decoration:none !important;
|
||||
}
|
||||
|
||||
.page_toc ul a {
|
||||
color: var(--text-color-base, black);
|
||||
text-decoration: none;
|
||||
font-weight: 300;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1300px) {
|
||||
.page_toc {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: -20px;
|
||||
padding: 10px 0;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-size: 1.0em;
|
||||
}
|
||||
.page_toc a:before {
|
||||
content: "- ";
|
||||
}
|
||||
.nav {
|
||||
margin: 0 auto;
|
||||
width: 800px;
|
||||
}
|
||||
.page_toc p.title {
|
||||
font-weight: 300;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
.content {
|
||||
display: block;
|
||||
}
|
||||
.markdown-section {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.page_toc .active {
|
||||
border-left: 5px solid;
|
||||
color: var(--theme-color, #42b983);
|
||||
padding-left: 10px;
|
||||
}
|
||||
170
static/toc.js
Normal file
170
static/toc.js
Normal file
@ -0,0 +1,170 @@
|
||||
var defaultOptions = {
|
||||
headings: 'h1, h2',
|
||||
scope: '.markdown-section',
|
||||
|
||||
// To make work
|
||||
title: 'Contents',
|
||||
listType: 'ul',
|
||||
}
|
||||
|
||||
// Element builders
|
||||
var tocHeading = function(Title) {
|
||||
return document.createElement('h2').appendChild(
|
||||
document.createTextNode(Title)
|
||||
)
|
||||
}
|
||||
|
||||
var aTag = function(src) {
|
||||
var a = document.createElement('a');
|
||||
var content = src.firstChild.innerHTML;
|
||||
|
||||
// Use this to clip text w/ HTML in it.
|
||||
// https://github.com/arendjr/text-clipper
|
||||
a.innerHTML = content;
|
||||
a.href = src.firstChild.href;
|
||||
a.onclick = tocClick
|
||||
|
||||
// In order to remove this gotta fix the styles.
|
||||
a.setAttribute('class', 'anchor');
|
||||
|
||||
return a
|
||||
};
|
||||
|
||||
var tocClick = function(e) {
|
||||
var divs = document.querySelectorAll('.page_toc .active');
|
||||
|
||||
// Remove the previous classes
|
||||
[].forEach.call(divs, function(div) {
|
||||
div.setAttribute('class', 'anchor')
|
||||
});
|
||||
|
||||
// Make sure this is attached to the parent not itself
|
||||
e.target.parentNode.setAttribute('class', 'active')
|
||||
};
|
||||
|
||||
var createList = function(wrapper, count) {
|
||||
while (count--) {
|
||||
wrapper = wrapper.appendChild(
|
||||
document.createElement('ul')
|
||||
);
|
||||
|
||||
if (count) {
|
||||
wrapper = wrapper.appendChild(
|
||||
document.createElement('li')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
var getHeaders = function(selector) {
|
||||
var headings2 = document.querySelectorAll(selector);
|
||||
var ret = [];
|
||||
|
||||
[].forEach.call(headings2, function(heading) {
|
||||
ret = ret.concat(heading);
|
||||
});
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
var getLevel = function(header) {
|
||||
var decs = header.match(/\d/g);
|
||||
|
||||
return decs ? Math.min.apply(null, decs) : 1;
|
||||
};
|
||||
|
||||
var jumpBack = function(currentWrapper, offset) {
|
||||
while (offset--) {
|
||||
currentWrapper = currentWrapper.parentElement;
|
||||
}
|
||||
|
||||
return currentWrapper;
|
||||
};
|
||||
|
||||
var buildTOC = function(options) {
|
||||
var ret = document.createElement('ul');
|
||||
var wrapper = ret;
|
||||
var lastLi = null;
|
||||
var selector = options.scope + ' ' + options.headings
|
||||
var headers = getHeaders(selector)
|
||||
|
||||
headers.reduce(function(prev, curr, index) {
|
||||
var currentLevel = getLevel(curr.tagName);
|
||||
var offset = currentLevel - prev;
|
||||
|
||||
wrapper = (offset > 0)
|
||||
? createList(lastLi, offset)
|
||||
: jumpBack(wrapper, -offset * 2)
|
||||
|
||||
wrapper = wrapper || ret;
|
||||
|
||||
var li = document.createElement('li');
|
||||
|
||||
wrapper.appendChild(li).appendChild(aTag(curr));
|
||||
|
||||
lastLi = li;
|
||||
|
||||
return currentLevel;
|
||||
}, getLevel(options.headings));
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
// Docsify plugin functions
|
||||
function plugin(hook, vm) {
|
||||
var userOptions = vm.config.toc;
|
||||
|
||||
hook.mounted(function () {
|
||||
var content = window.Docsify.dom.find(".content");
|
||||
if (content) {
|
||||
var nav = window.Docsify.dom.create("aside", "");
|
||||
window.Docsify.dom.toggleClass(nav, "add", "nav");
|
||||
window.Docsify.dom.before(content, nav);
|
||||
}
|
||||
});
|
||||
|
||||
hook.doneEach(function () {
|
||||
var nav = document.querySelectorAll('.nav')[0]
|
||||
var t = Array.from(document.querySelectorAll('.nav'))
|
||||
|
||||
if (!nav) {
|
||||
return;
|
||||
}
|
||||
|
||||
const toc = buildTOC(userOptions);
|
||||
|
||||
// Just unset it for now.
|
||||
if (!toc.innerHTML) {
|
||||
nav.innerHTML = null
|
||||
return;
|
||||
}
|
||||
|
||||
// Fix me in the future
|
||||
var title = document.createElement('p');
|
||||
title.innerHTML = userOptions.title;
|
||||
title.setAttribute('class', 'title');
|
||||
|
||||
var container = document.createElement('div');
|
||||
container.setAttribute('class', 'page_toc');
|
||||
|
||||
container.appendChild(title);
|
||||
container.appendChild(toc);
|
||||
|
||||
// Existing TOC
|
||||
var tocChild = document.querySelectorAll('.nav .page_toc');
|
||||
|
||||
if (tocChild.length > 0) {
|
||||
tocChild[0].parentNode.removeChild(tocChild[0]);
|
||||
}
|
||||
|
||||
nav.appendChild(container);
|
||||
});
|
||||
}
|
||||
|
||||
// Docsify plugin options
|
||||
window.$docsify['toc'] = Object.assign(defaultOptions, window.$docsify['toc']);
|
||||
window.$docsify.plugins = [].concat(plugin, window.$docsify.plugins);
|
||||
1
static/vue.css
Normal file
1
static/vue.css
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user