普通视图

发现新文章,点击刷新页面。
昨天以前首页
  • ✇ZERO开发
  • 如何在Unity3D导入Spine动画北桥苏
    一、前言《如何在Unity3D项目中导入Spine动画》,虽然在网上有很多这种文章,直接将问题交给DeepSeek也能得到具体的操作流程,但是照着他们提供的方法还是能遇到几个问题,比如:AI回答没有提到Unity无法识别.altas,要修改动画文件后缀部分;导入到游戏场景中,动画总是被Canvas的背景图或元素挡住,层级低;所以针对这几点问题和操作流程,再带上Spine的基本操作,我整理成文章,那么,下面先参照一下我的工具版本开始。 二、工具Unity3D 2020.3Spine 3.8.75spine-unity-3.8-2021-11-102D场景游戏三、Spine操作因为练习时,多数动画文件是直接下载的别人制作好的json导出文件(非工程)。所以如果要在游戏场景前看效果,可以先导进Spine工具中查看一下。json导出文件目录123fileName.altas // 图集描述文件fileName.json // 骨骼动画数据fileName.png // 纹理图集导入文件1.导入数据>选择“JSON或二进制文件”>文件选“json”格式文件>导入2.保存更
     

如何在Unity3D导入Spine动画

作者 北桥苏
2025年2月26日 10:13

一、前言

《如何在Unity3D项目中导入Spine动画》,虽然在网上有很多这种文章,直接将问题交给DeepSeek也能得到具体的操作流程,但是照着他们提供的方法还是能遇到几个问题,比如:

  1. AI回答没有提到Unity无法识别.altas,要修改动画文件后缀部分;
  2. 导入到游戏场景中,动画总是被Canvas的背景图或元素挡住,层级低;

所以针对这几点问题和操作流程,再带上Spine的基本操作,我整理成文章,那么,下面先参照一下我的工具版本开始。

img

二、工具

  • Unity3D 2020.3
  • Spine 3.8.75
  • spine-unity-3.8-2021-11-10
  • 2D场景游戏

三、Spine操作

因为练习时,多数动画文件是直接下载的别人制作好的json导出文件(非工程)。所以如果要在游戏场景前看效果,可以先导进Spine工具中查看一下。

json导出文件目录

1
2
3
fileName.altas // 图集描述文件
fileName.json // 骨骼动画数据
fileName.png // 纹理图集

导入文件

1.导入数据>选择“JSON或二进制文件”>文件选“json”格式文件>导入

2.保存更改>浏览>自定义名称的“spine”格式文件

img

展示纹理

1.纹理解包器>图集文件选择“.atlas”格式文件>输出文件夹随便指定即可>解开

2.Hierarchy>图片>图片文件>路径,找到纹理解包后的输出文件夹

img

其他

通常一个json导出文件里可以包含很多个动画,可以看到预览右边的列表,每一个选项就是一个动画,选中可以预览,左边的工程窗的设置可以进入K帧窗。

更多的比如骨骼绑定,蒙皮刷权重,K帧,我后面再出一个单独的文章说明,下面就进入正题到Unity的导入了。

img

四、导入Unity3D

要在Unity3D导入前需要先下载Spine Unity运行库,可以网上找Spine官方下载页;第二个是前面提到的Unity不识别.atlas文件,将动画放到Unity项目的资源文件夹下需要将.atlas改成.txt后缀的文件。

Spine Unity运行库安装

在Unity中,点击菜单栏 Assets > Import Package > Custom Package,选择下载的.unitypackage文件,导入全部内容。

最后在工具栏的GameObject下,查看是否有Spine选项,就可以验证安装成功与否。

Spine数据资源生成

前面提到的Spine动画的三个文件,再放入游戏资产文件夹中修改了图片描述文件格式后,打开项目后,Unity会自动生成一个.meta和两个.asset文件。

1
2
3
_Atlas.asset             与之前的atlas对应的图集描述文件
_Material.mat 与之前的png对应的素材纹理
_SkeletonData.asset 与之前的json对应的骨骼数据文件

创建动画对象

因为游戏是2D的,我主体场景用的是Canvas,开头也提到过的导入后总是显示在Canvas背景图的下层,所以第一步就从设置画面开始。

1.选中Canvas后,Render Mode选择 “Screen Space-Camera”,Hierachy中的Main Camera拖入Render Camera中。

img

2.在场景中创建空对象(如右键Hierarchy > Create Empty),命名为 SpineCharacter

3.添加组件:点击 Add Component,搜索并添加 Skeleton Animation

4.配置组件:

  • Skeleton Data Asset:拖入前面“Spine数据资源”生成的_SkeletonData.asset文件。
  • Animation Name:输入默认播放的动画名称(如idle)。
  • Loop:勾选以循环播放。
  • Scale:调整 Rect Transform 的 Scale,大小自行尝试。

5.Shader设置 UI/Default,默认的Spine Skeleton素材拼接得有点锯齿,详细的可以自行选择尝试。

img

脚本控制动画

创建C#脚本(如SpineController.cs)并附加到角色对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using Spine.Unity;
public class SpineController : MonoBehaviour {
public SkeletonAnimation skeletonAnim;
public string runAnimation = "run";

void Start() {
skeletonAnim.AnimationState.SetAnimation(0, runAnimation, true);
}

// 切换动画
public void PlayAnimation(string animName) {
skeletonAnim.AnimationState.SetAnimation(0, animName, true);
}
}

写在后面

为什么我做小游戏从CocosCreator切到了Unity3D,原因是这次尝试的是抖音直播小玩法,也就是弹幕小游戏。

前期为了跑通流程,所以我要避开所有要用到服务端的产品开发,从而采用指令直推方式,但官网只有Unity SDK的案例,最后有了这篇文章,当然后续还有更多。

当然CocosCreator制作普通单机小游戏我也会继续,不过当前以2D为主,毕竟现在用AI抽卡来生成游戏资产太方便了,等图生3D模型较完善的时候,以后再用AI制作3D小游戏。

  • ✇ZERO开发
  • 个人开发者,还能入局抖音直播小玩法吗?北桥苏
    前言前段时间,我在微信问一问里回答了一个关于 “一天赚几十块钱副业有哪些?”的问题。主要推荐的是直播小玩法的副业,截至目前收获了官方1万的推流和超5千人的围观。由此我认为,当前开发直播小玩法还是比较小众,竞争小,个人开发者入局应该能躺赚一笔,真的很适合参考以前的回合制游戏。简介直播小玩法是抖音里的一种统称,其他平台有叫直播弹幕小游戏,而抖音里的直播小玩法包括两种,弹幕小游戏和互动插件。个人主体开发者申请软著后,符合平台规范都能上架。上架后,只要有主播用了你的开播,就能享受直播间的礼物分成,分成比例见下图。比例看着确实比较低,但他也有一个很符合被动收益的优势:一经开发,多端部署,多人开播,无需直接面向观众。就是我们开发后,其实是可以发布到多个平台的,已知对个人开发者开发弹幕游戏上架的平台有:抖音哔哩哔哩虎牙同一平台可以让多个主播同时开播,看似一场直播分百分之八,但如果一天有100个主播,就可以从100个直播间分走百分点的收入。现状上架直播小玩法虽然是小众行业,但也同样有二八效应,据业内人士说,弹幕游戏有榜单,如果上架后能冲进前30,那每月被动收入十几W很常见。比如2023年的两款,《兵临
     

个人开发者,还能入局抖音直播小玩法吗?

作者 北桥苏
2024年12月21日 17:13

前言

前段时间,我在微信问一问里回答了一个关于 “一天赚几十块钱副业有哪些?”的问题。主要推荐的是直播小玩法的副业,截至目前收获了官方1万的推流和超5千人的围观。由此我认为,当前开发直播小玩法还是比较小众,竞争小,个人开发者入局应该能躺赚一笔,真的很适合参考以前的回合制游戏。

img

简介

直播小玩法是抖音里的一种统称,其他平台有叫直播弹幕小游戏,而抖音里的直播小玩法包括两种,弹幕小游戏和互动插件。个人主体开发者申请软著后,符合平台规范都能上架。上架后,只要有主播用了你的开播,就能享受直播间的礼物分成,分成比例见下图。

img

比例看着确实比较低,但他也有一个很符合被动收益的优势:一经开发,多端部署,多人开播,无需直接面向观众。就是我们开发后,其实是可以发布到多个平台的,已知对个人开发者开发弹幕游戏上架的平台有:

  1. 抖音

  2. 哔哩哔哩

  3. 虎牙

同一平台可以让多个主播同时开播,看似一场直播分百分之八,但如果一天有100个主播,就可以从100个直播间分走百分点的收入。

img

现状

上架直播小玩法虽然是小众行业,但也同样有二八效应,据业内人士说,弹幕游戏有榜单,如果上架后能冲进前30,那每月被动收入十几W很常见。比如2023年的两款,《兵临城下》这款游戏全平台月流水超过6000万,《星辰无双》日均流水突破150万元。

这些头部爆款多数是开发团队完成的,个人开发者前期不试水,上架后可能就是主播一日游,然后还要承担服务器的费用。当然前面的优势和收益也是很可观的,这里只是在入局前给个预期中和一下,防止后期沉默成本过高。

img

开发

根据官方开发文档介绍,互动插件和弹幕小游戏都支持单价版开发,也就是无需购买服务器,通过客户端接收推送完成交互。互动插件这里就不详细介绍了,类似直播里的点歌,点击屏幕上一个按钮,下拉出一些歌曲列表,选中后可以发送到直播间,这种的交互性更似小程序,可专门为开课,舞蹈博客定制相应的业务型互动插件。

而弹幕小游戏的开发,主要的是通过接收直播间的弹幕、礼物数据后,在游戏中显示对应的增益效果,比如送出仙女棒触发什么,阵营能提升什么。大部分是大同小异,更多的是主题和效果的设计,哪些更能迎合主播和观众,下面就用服务器+文档API,介绍一下大致的开发过程。

流程

  1. 用直播伴侣打开后获取Token请求服务器接口

  2. 服务端根据Token获取房间ID并返回到小玩法

  3. 服务端将监听的房间数据通过长链接推送到小玩法

  4. 小玩法根据礼物、弹幕等数据展示buff效果

  5. 时间结束后根据业务数值判断阵营输赢并排名

img

服务端接口

下面就从官方文档里列出一些服务端业务中需要用的请求接口,详细可见开放平台的小玩法文档的服务端API介绍。

接口调用凭证

access_token 是服务端接口的全局唯一调用凭据,如下面直播信息里的 “X-Token”,任务启动的 “access-token”传递的请求头参数用的都是这个。access_token 的有效期为 2 个小时,需要定时刷新 access_token。

直播信息

主播使用直播伴侣或移动端云启动玩法后,直播伴侣/移动端云启动会传入 token 到玩法中,当玩法获取 token 后,传递给玩法的服务端。玩法服务端通过该接口,使用 token 获取直播间信息,在返回到客户端前,服务端还需要调用 “任务启动”、“礼物置顶”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"data": {
"ack_cfg": [ // 预留信息,sdk接入使用,开发者不用感知
],
"linker_info": { // 连屏数据预留信息,开发者目前不用感知
"linker_id": 0,
"linker_status": 0,
"master_status": 0
},
"info": {
"room_id": 7214015683695250235,
"anchor_open_id": "_000oJIu6APhomK7KIBGqSYm5XYPxCJB_xxx",
"avatar_url": "https://p11.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-avt-0015_973c31e8055f78a41d3f7de3def9821d.jpeg?from=3067671334",
"nick_name": "xxx"
}
}
}

任务启动

调用任务启动后,直播间数据才会同步推送给开发者服务器,注意:不同类型的数据需要启动不同的任务单独监听,比如礼物数据单独启动一个,评论数据单独启动一个,见文档的数据开发。

礼物置顶

为什么还要调这个接口,因为置顶的礼物被送出,才会有礼物数据推送(后期会废用不需要这一步),实现时可以在获取房间ID后异步调用。然后直播挂载小玩法后,开发者根据玩法场景自主控制当前场景需要置顶的礼物,前提是置顶的礼物在玩法维度礼物配置中。调用置顶礼物接口的条件:

  • 已开通“获取礼物互动数据能力”。
  • 置顶的礼物数量不能超过6个,且必须为礼物配置列表中已勾选的礼物。

分页查询推送失败数据

可以用定时任务对已经开播的RoomId请求 api 分页查询推送失败的数据,返回空代表全部推送成功,否则可以根据业务需求记录失败的数据和重新推送到小玩法客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{ 
"err_no": 0,
"err_msg": "ok",
"logid": "20220927122238291",
"data": {
"page_num": 1,
"total_count": 100,
"data_list": [
// 当页的数据列表
{
"roomid": "12345", // string类型,消息的房间id
"msg_type": "live_gift", // string类型,表示消息类型
"payload": "[...]" // string类型, 对应推送协议中的payload字符串,需要unmarshal
}
]
}
}

其他接口

弹幕数据上报、用户战绩与排行榜看自身业务使用,而小玩法客户端主要就和服务端保持长链接,接收直播间互动数据,以及三个Http业务接口。

  • 开启,获取roomId
  • 结算,传递比赛结果
  • 获取排行榜单

img

写在后面

上面的是官方玩法,其实还有第三方,而且抖音推出抖音小玩法可能也是打不过就加入的策略。因为以前盛行一时的无人直播,像修狗云蹦迪、挤地铁、马保国格斗等,都是别人用技术手段实现弹幕礼物接收实现的小游戏。

因为没有人出境和抓取数据等原因,开播的房间经常被封,虽然被封,但收益不错也屡禁不止,所以抖音干脆开放小玩法模块(个人猜想),更大程度实现主播、开发者、观众双收。我已知第三方平台有:咩播、阿比整蛊、青播,有机会我再聊聊关于这些平台软件的内部概况。

img

  • ✇ZERO开发
  • QQ小程序互帮互助北桥苏
    个人主体的 QQ 小程序,到底是哪些人开通了流量主在玩啊?从微信端移植并修改了一个工具类的 QQ 小程序,然后备案审核上架后,自然流量没有一点,你说尴不尴尬!还有一点呢,QQ 小程序开通流量主的条件还是很高的,相比微信小程序。要求连续 7 天内,每天的访问 UV 都不能低于 100,也就是在一个连续周期内要完成 700UV。于是,我就去某宝找找有没有做流量主开通的,我先是输入 “QQ 小程序流量主开通”,根本就没有。然后就只搜小程序流量主开通,清一色微信小程序的,没辙,随便找几家问问有没有能做 QQ 小程序的。结果就是,根本没人做这玩意的流量主开通业务,不过也意外地知道了他们做一个微信小程序地普遍报价 150 上下,同样也是刷访问,10 天完成 500UV。最后我就找群找论坛,QQ 小程序互助,也没有,不知道有没有和我一样的,有的话,我建了一个扣扣群,或加我 QQ:2652364582,互帮互助。
     

QQ小程序互帮互助

作者 北桥苏
2024年12月20日 14:51

个人主体的 QQ 小程序,到底是哪些人开通了流量主在玩啊?

从微信端移植并修改了一个工具类的 QQ 小程序,然后备案审核上架后,自然流量没有一点,你说尴不尴尬!

img

还有一点呢,QQ 小程序开通流量主的条件还是很高的,相比微信小程序。

要求连续 7 天内,每天的访问 UV 都不能低于 100,也就是在一个连续周期内要完成 700UV。

于是,我就去某宝找找有没有做流量主开通的,我先是输入 “QQ 小程序流量主开通”,根本就没有。

然后就只搜小程序流量主开通,清一色微信小程序的,没辙,随便找几家问问有没有能做 QQ 小程序的。

img

结果就是,根本没人做这玩意的流量主开通业务,不过也意外地知道了他们做一个微信小程序地普遍报价 150 上下,同样也是刷访问,10 天完成 500UV。

最后我就找群找论坛,QQ 小程序互助,也没有,不知道有没有和我一样的,有的话,我建了一个扣扣群,或加我 QQ:2652364582,互帮互助。

img

  • ✇ZERO开发
  • 2024年,个人申请小游戏软著速通指南北桥苏
    前言2024年6月26号,我申请的小游戏软著通过了。由于等待时间太长,所以就总结了一下整个申请过程踩过的坑。帮助未了解或即将申请个人软著的同学绕过下面三点,可以节省至少三分之一的时间(小游戏类目)。当然,这里也会围绕大家关心的几个问题展开,比如:软著申请的费用、软著申请到底要多久以及整个申请的流程。最后再给大家两份我自己的申请模板,软件源程序文档和软件说明书文档。费用2024年申请软著不用钱,如果说一分钱不用也说不过去,因为在申请时的签章页要打印签字,所以整个过程的花费就是一张纸的打印钱。要是你找的第三方代办收取高费用,并且说要打印这打印那的就自己弄吧。因为现在关于软著的登记都是采用电子版形式了。之前既要打印源码文档和软件说明书,还要寄过去,然后才能收到纸张版软著。时间我从申请到通过一共是三个月时间,但是在过程中有三次补正,也就是提交的信息和资料不符和要求。而每次补正再审核大概在8-15天(个人观察),错三次也就要多一个月时间,按正常填写一遍过的话应该两个月以内就能获取。流程注册与开始申请进入“国家版权保护中心官网”,选择个人身份,填写手机邮箱等信息后注册成功后登陆。然后回到官网首页导
     

2024年,个人申请小游戏软著速通指南

作者 北桥苏
2024年12月10日 16:13

前言

2024年6月26号,我申请的小游戏软著通过了。由于等待时间太长,所以就总结了一下整个申请过程踩过的坑。帮助未了解或即将申请个人软著的同学绕过下面三点,可以节省至少三分之一的时间(小游戏类目)。

当然,这里也会围绕大家关心的几个问题展开,比如:软著申请的费用、软著申请到底要多久以及整个申请的流程。最后再给大家两份我自己的申请模板,软件源程序文档和软件说明书文档。

img

费用

2024年申请软著不用钱,如果说一分钱不用也说不过去,因为在申请时的签章页要打印签字,所以整个过程的花费就是一张纸的打印钱。要是你找的第三方代办收取高费用,并且说要打印这打印那的就自己弄吧。因为现在关于软著的登记都是采用电子版形式了。之前既要打印源码文档和软件说明书,还要寄过去,然后才能收到纸张版软著。

时间

我从申请到通过一共是三个月时间,但是在过程中有三次补正,也就是提交的信息和资料不符和要求。而每次补正再审核大概在8-15天(个人观察),错三次也就要多一个月时间,按正常填写一遍过的话应该两个月以内就能获取。

流程

注册与开始申请

进入“国家版权保护中心官网”,选择个人身份,填写手机邮箱等信息后注册成功后登陆。然后回到官网首页导航栏选择 “版权登记” -> “软件登记” -> ”计算机软件著作权登记申请(R11)“, 然后进入到办理身份,是自己就选 ”我是申请人“。

img

软件申请信息

这是第一步要填写的表单,其中权利取得方式、软件全称、版本号、权利范围为必填,权利取得方式按默认原始取得,权利范围按默认全部权利,其他的可以参考我下面截图。而 ”软件全称“ 一定要注意,因为我其中一项补正就是软件全称和后面的软件说明、源码文档里的页眉软件名称不一致。

img

软件开发信息

软件开发信息都为必填,软件分类选择 ”应用软件“,软件说明 ”原创“,开发方式 ”单独开发“,开发完成日期自己选择,发表状态 ”未发表“。

img

软件功能与特点

img

img

鉴别材料

鉴别材料有两份,分别是程序鉴别材料和文档鉴别材料,两个都选择一般交存。其中程序鉴别材料是代码清除空行注释整理后转PDF提交,前后各连续30页可以按开发时间排序,也可以按功能主次等自定义排序,每页不少于50行,若源程序整体不到60页,应提交全部源程序。

而文档鉴别材料是用来描述程序的内容、组成、设计、功能、开发情况、测试结果及使用方法的文字资料和图表,如程序设计说明书、流程图、用户手册等,同样文档要求是连续的前30页和后30页,每页不少于30行,如果整个文档不到60页,就提交整个说明文档,这个我会在下面列出我的那两个模板。

img

确认信息

填完上面的信息后,提交身份证正反面,最后就会列出提交材料的清单确认信息。

img

签章页提交

签章页其实也是材料清单确认书,下载打印后签字拍照完再上传。软著的状态就会由 “待提交” 转 “待受理” 了,接着就等待审核发放了。

img

模板参考

以下两份就是我的程序鉴别材料和文档鉴别材料模板,这里要注意一点的是,游戏类的文档说明一定要加上 “游戏健康忠告” 页面的介绍。(可以扫描下面公众号二维码找到文章或留言)

img

img

写在后面

软著下来后就准备上架到小游戏或快游戏平台了,可能是近年来的净网相关政策,有些平台对于小游戏或快游戏对个人身份的提交通道已经关闭了。不光如此,我最近做了一个工具类的小程序也卡在提交,因为我是要改名称和类目,现在还需要备案和认证,就不知道到时候我上架的时候,以前积累的UV会不会被清掉。

img

  • ✇ZERO开发
  • 个人开发者,还能入局抖音直播小玩法吗?北桥苏
    前言前段时间,我在微信问一问里回答了一个关于 “一天赚几十块钱副业有哪些?”的问题。主要推荐的是直播小玩法的副业,截至目前收获了官方1万的推流和超5千人的围观。由此我认为,当前开发直播小玩法还是比较小众,竞争小,个人开发者入局应该能躺赚一笔,真的很适合参考以前的回合制游戏。简介直播小玩法是抖音里的一种统称,其他平台有叫直播弹幕小游戏,而抖音里的直播小玩法包括两种,弹幕小游戏和互动插件。个人主体开发者申请软著后,符合平台规范都能上架。上架后,只要有主播用了你的开播,就能享受直播间的礼物分成,分成比例见下图。比例看着确实比较低,但他也有一个很符合被动收益的优势:一经开发,多端部署,多人开播,无需直接面向观众。就是我们开发后,其实是可以发布到多个平台的,已知对个人开发者开发弹幕游戏上架的平台有:抖音哔哩哔哩虎牙同一平台可以让多个主播同时开播,看似一场直播分百分之八,但如果一天有100个主播,就可以从100个直播间分走百分点的收入。现状上架直播小玩法虽然是小众行业,但也同样有二八效应,据业内人士说,弹幕游戏有榜单,如果上架后能冲进前30,那每月被动收入十几W很常见。比如2023年的两款,《兵临
     

个人开发者,还能入局抖音直播小玩法吗?

作者 北桥苏
2024年11月27日 17:13

前言

前段时间,我在微信问一问里回答了一个关于 “一天赚几十块钱副业有哪些?”的问题。主要推荐的是直播小玩法的副业,截至目前收获了官方1万的推流和超5千人的围观。由此我认为,当前开发直播小玩法还是比较小众,竞争小,个人开发者入局应该能躺赚一笔,真的很适合参考以前的回合制游戏。

img

简介

直播小玩法是抖音里的一种统称,其他平台有叫直播弹幕小游戏,而抖音里的直播小玩法包括两种,弹幕小游戏和互动插件。个人主体开发者申请软著后,符合平台规范都能上架。上架后,只要有主播用了你的开播,就能享受直播间的礼物分成,分成比例见下图。

img

比例看着确实比较低,但他也有一个很符合被动收益的优势:一经开发,多端部署,多人开播,无需直接面向观众。就是我们开发后,其实是可以发布到多个平台的,已知对个人开发者开发弹幕游戏上架的平台有:

  1. 抖音

  2. 哔哩哔哩

  3. 虎牙

同一平台可以让多个主播同时开播,看似一场直播分百分之八,但如果一天有100个主播,就可以从100个直播间分走百分点的收入。

img

现状

上架直播小玩法虽然是小众行业,但也同样有二八效应,据业内人士说,弹幕游戏有榜单,如果上架后能冲进前30,那每月被动收入十几W很常见。比如2023年的两款,《兵临城下》这款游戏全平台月流水超过6000万,《星辰无双》日均流水突破150万元。

这些头部爆款多数是开发团队完成的,个人开发者前期不试水,上架后可能就是主播一日游,然后还要承担服务器的费用。当然前面的优势和收益也是很可观的,这里只是在入局前给个预期中和一下,防止后期沉默成本过高。

img

开发

根据官方开发文档介绍,互动插件和弹幕小游戏都支持单价版开发,也就是无需购买服务器,通过客户端接收推送完成交互。互动插件这里就不详细介绍了,类似直播里的点歌,点击屏幕上一个按钮,下拉出一些歌曲列表,选中后可以发送到直播间,这种的交互性更似小程序,可专门为开课,舞蹈博客定制相应的业务型互动插件。

而弹幕小游戏的开发,主要的是通过接收直播间的弹幕、礼物数据后,在游戏中显示对应的增益效果,比如送出仙女棒触发什么,阵营能提升什么。大部分是大同小异,更多的是主题和效果的设计,哪些更能迎合主播和观众,下面就用服务器+文档API,介绍一下大致的开发过程。

流程

  1. 用直播伴侣打开后获取Token请求服务器接口

  2. 服务端根据Token获取房间ID并返回到小玩法

  3. 服务端将监听的房间数据通过长链接推送到小玩法

  4. 小玩法根据礼物、弹幕等数据展示buff效果

  5. 时间结束后根据业务数值判断阵营输赢并排名

img

服务端接口

下面就从官方文档里列出一些服务端业务中需要用的请求接口,详细可见开放平台的小玩法文档的服务端API介绍。

接口调用凭证

access_token 是服务端接口的全局唯一调用凭据,如下面直播信息里的 “X-Token”,任务启动的 “access-token”传递的请求头参数用的都是这个。access_token 的有效期为 2 个小时,需要定时刷新 access_token。

直播信息

主播使用直播伴侣或移动端云启动玩法后,直播伴侣/移动端云启动会传入 token 到玩法中,当玩法获取 token 后,传递给玩法的服务端。玩法服务端通过该接口,使用 token 获取直播间信息,在返回到客户端前,服务端还需要调用 “任务启动”、“礼物置顶”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"data": {
"ack_cfg": [ // 预留信息,sdk接入使用,开发者不用感知
],
"linker_info": { // 连屏数据预留信息,开发者目前不用感知
"linker_id": 0,
"linker_status": 0,
"master_status": 0
},
"info": {
"room_id": 7214015683695250235,
"anchor_open_id": "_000oJIu6APhomK7KIBGqSYm5XYPxCJB_xxx",
"avatar_url": "https://p11.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-avt-0015_973c31e8055f78a41d3f7de3def9821d.jpeg?from=3067671334",
"nick_name": "xxx"
}
}
}

任务启动

调用任务启动后,直播间数据才会同步推送给开发者服务器,注意:不同类型的数据需要启动不同的任务单独监听,比如礼物数据单独启动一个,评论数据单独启动一个,见文档的数据开发。

礼物置顶

为什么还要调这个接口,因为置顶的礼物被送出,才会有礼物数据推送(后期会废用不需要这一步),实现时可以在获取房间ID后异步调用。然后直播挂载小玩法后,开发者根据玩法场景自主控制当前场景需要置顶的礼物,前提是置顶的礼物在玩法维度礼物配置中。调用置顶礼物接口的条件:

  • 已开通“获取礼物互动数据能力”。
  • 置顶的礼物数量不能超过6个,且必须为礼物配置列表中已勾选的礼物。

分页查询推送失败数据

可以用定时任务对已经开播的RoomId请求 api 分页查询推送失败的数据,返回空代表全部推送成功,否则可以根据业务需求记录失败的数据和重新推送到小玩法客户端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{ 
"err_no": 0,
"err_msg": "ok",
"logid": "20220927122238291",
"data": {
"page_num": 1,
"total_count": 100,
"data_list": [
// 当页的数据列表
{
"roomid": "12345", // string类型,消息的房间id
"msg_type": "live_gift", // string类型,表示消息类型
"payload": "[...]" // string类型, 对应推送协议中的payload字符串,需要unmarshal
}
]
}
}

其他接口

弹幕数据上报、用户战绩与排行榜看自身业务使用,而小玩法客户端主要就和服务端保持长链接,接收直播间互动数据,以及三个Http业务接口。

  • 开启,获取roomId
  • 结算,传递比赛结果
  • 获取排行榜单

img

写在后面

上面的是官方玩法,其实还有第三方,而且抖音推出抖音小玩法可能也是打不过就加入的策略。因为以前盛行一时的无人直播,像修狗云蹦迪、挤地铁、马保国格斗等,都是别人用技术手段实现弹幕礼物接收实现的小游戏。

因为没有人出境和抓取数据等原因,开播的房间经常被封,虽然被封,但收益不错也屡禁不止,所以抖音干脆开放小玩法模块(个人猜想),更大程度实现主播、开发者、观众双收。我已知第三方平台有:咩播、阿比整蛊、青播,有机会我再聊聊关于这些平台软件的内部概况。

img

  • ✇ZERO开发
  • QQ小程序已发布,但无法被搜索的解决方案北桥苏
    前言我的QQ小程序在2024年8月就已经审核通过,上架后却一直无法被搜索到。打开后,再在QQ上下拉查看 “最近使用”,发现他出现一下又马上消失。上线是按正常流程走的,开发、备案、审核,也没有任何违规,后台也没收到说被封或异常的信息。排查难道是我名字(实用工具箱)问题,当我要去后台修改名字时,提示要重新备案。不过也让我想起之前我搜索的时候,别人也有用这名字,所以根本不是这个原因。会不会是后台哪里设置了,第一次玩QQ小程序后台,搞不好一开始的时候我乱点了什么。最后找啊找,终于在 “关联设置” 中找到了问题所在。解决在QQ后台的设置下的 “关联设置” 里 “QQ频道” 有一个 “仅允许在机器人服务中使用”,这一项给出的解释是 “打开后,QQ小程序推荐页将不会展示此小程序”,没错,我勾选了。尴不尴尬,去掉后什么无法被搜索,什么在最近使用框里马上消失的问题,全部解决。所以我之前刚上架时没有自然流量也是因为这个,那我才放开小程序推荐,官方会不会就给推了啊,这个只能看后面几天的情况才能知道,但现在的我还是急需流量。找流量为什么着急找流量?因为QQ小程序的流量主开通不同于微信小程序,他的要求更高,必须
     

QQ小程序已发布,但无法被搜索的解决方案

作者 北桥苏
2024年11月12日 14:51

前言

我的QQ小程序在2024年8月就已经审核通过,上架后却一直无法被搜索到。打开后,再在QQ上下拉查看 “最近使用”,发现他出现一下又马上消失。

上线是按正常流程走的,开发、备案、审核,也没有任何违规,后台也没收到说被封或异常的信息。

img

排查

难道是我名字(实用工具箱)问题,当我要去后台修改名字时,提示要重新备案。不过也让我想起之前我搜索的时候,别人也有用这名字,所以根本不是这个原因。

会不会是后台哪里设置了,第一次玩QQ小程序后台,搞不好一开始的时候我乱点了什么。最后找啊找,终于在 “关联设置” 中找到了问题所在。

img

解决

在QQ后台的设置下的 “关联设置” 里 “QQ频道” 有一个 “仅允许在机器人服务中使用”,这一项给出的解释是 “打开后,QQ小程序推荐页将不会展示此小程序”,没错,我勾选了。

尴不尴尬,去掉后什么无法被搜索,什么在最近使用框里马上消失的问题,全部解决。所以我之前刚上架时没有自然流量也是因为这个,那我才放开小程序推荐,官方会不会就给推了啊,这个只能看后面几天的情况才能知道,但现在的我还是急需流量。

img

找流量

为什么着急找流量?因为QQ小程序的流量主开通不同于微信小程序,他的要求更高,必须连续7天内,每天的UV不能低于100。

虽然700UV也不多,但他不是累积的,过了7天没达量,前面的UV总数作废。在不清楚明天有没有自然流量的情况,我决定找人友链,就是我们在自己的小程序里互相跳转。

友链之路

小程序友链,也就是小程序跳小程序,由于我的没有做后台管理,界面展示是写死的,加这个要改两个地方,一个是配置,一个是添加点击跳转事件。

配置,只需在app.json中添加

1
2
3
"navigateToMiniProgramAppIdList": [
"appId"
]

添加点击跳转事件

1
2
3
4
5
qq.navigateToMiniProgram({
appId: '1112309851',
success(res) {
// 跳转成功
}

写在后面

其实平台刚上线时,好像是19年还是18年,个人开发者只要一上架自己的小程序就能开通流量主。现在我的心态,借张伟名言:机会像雨点般打来, 而我却一一闪过。

不过QQ小程序的应用场景还是很多元化的,群和频道,机器人里都能绑定,外加互助一下其实也很快,所以,大家要和我一起吗?我建了一个扣扣群,或加我 QQ:2652364582,互帮互助。

img

  • ✇ZERO开发
  • QQ小程序互帮互助北桥苏
    个人主体的 QQ 小程序,到底是哪些人开通了流量主在玩啊?从微信端移植并修改了一个工具类的 QQ 小程序,然后备案审核上架后,自然流量没有一点,你说尴不尴尬!还有一点呢,QQ 小程序开通流量主的条件还是很高的,相比微信小程序。要求连续 7 天内,每天的访问 UV 都不能低于 100,也就是在一个连续周期内要完成 700UV。于是,我就去某宝找找有没有做流量主开通的,我先是输入 “QQ 小程序流量主开通”,根本就没有。然后就只搜小程序流量主开通,清一色微信小程序的,没辙,随便找几家问问有没有能做 QQ 小程序的。结果就是,根本没人做这玩意的流量主开通业务,不过也意外地知道了他们做一个微信小程序地普遍报价 150 上下,同样也是刷访问,10 天完成 500UV。最后我就找群找论坛,QQ 小程序互助,也没有,不知道有没有和我一样的,有的话,我建了一个扣扣群,或加我 QQ:2652364582,互帮互助。
     

QQ小程序互帮互助

作者 北桥苏
2024年10月30日 14:51

个人主体的 QQ 小程序,到底是哪些人开通了流量主在玩啊?

从微信端移植并修改了一个工具类的 QQ 小程序,然后备案审核上架后,自然流量没有一点,你说尴不尴尬!

img

还有一点呢,QQ 小程序开通流量主的条件还是很高的,相比微信小程序。

要求连续 7 天内,每天的访问 UV 都不能低于 100,也就是在一个连续周期内要完成 700UV。

于是,我就去某宝找找有没有做流量主开通的,我先是输入 “QQ 小程序流量主开通”,根本就没有。

然后就只搜小程序流量主开通,清一色微信小程序的,没辙,随便找几家问问有没有能做 QQ 小程序的。

img

结果就是,根本没人做这玩意的流量主开通业务,不过也意外地知道了他们做一个微信小程序地普遍报价 150 上下,同样也是刷访问,10 天完成 500UV。

最后我就找群找论坛,QQ 小程序互助,也没有,不知道有没有和我一样的,有的话,我建了一个扣扣群,或加我 QQ:2652364582,互帮互助。

img

  • ✇ZERO开发
  • 鸿蒙Next实战:烟花模拟器北桥苏
    前言通过上一篇文章可以看出,要在鸿蒙应用中实现特别炫的特效还是比较复杂。动画固然重要,但如果在赶工期的情况下,大家都会优先业务,那有没有简单快速的方法呢?有的,也用像 Android 和 iOS 里 WebView 的方式,h5 的特效现在是应有尽有,把他嵌入鸿蒙 Next 应用里就可以,那如何在鸿蒙 Next 中使用 WebView 来实现电子烟花?实现要点组件拆解资源引入页面路由WebView开始实践因为前面的木鱼和现在的烟花都是同一个小工具应用,公用组件的拆分、页面跳转和资源的引入全有涉及,所以就连同 WebView 一起总结一下。组件拆解在 ArkUI 中,UI 显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。这里我们将所有页面的导航拆分成一个公用组件,并定义为 HdNav.ets。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869impor
     

鸿蒙Next实战:烟花模拟器

作者 北桥苏
2024年10月7日 08:00

前言

通过上一篇文章可以看出,要在鸿蒙应用中实现特别炫的特效还是比较复杂。动画固然重要,但如果在赶工期的情况下,大家都会优先业务,那有没有简单快速的方法呢?

有的,也用像 Android 和 iOS 里 WebView 的方式,h5 的特效现在是应有尽有,把他嵌入鸿蒙 Next 应用里就可以,那如何在鸿蒙 Next 中使用 WebView 来实现电子烟花?

img

实现要点

  1. 组件拆解
  2. 资源引入
  3. 页面路由
  4. WebView

img

开始实践

因为前面的木鱼和现在的烟花都是同一个小工具应用,公用组件的拆分、页面跳转和资源的引入全有涉及,所以就连同 WebView 一起总结一下。

组件拆解

在 ArkUI 中,UI 显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。这里我们将所有页面的导航拆分成一个公用组件,并定义为 HdNav.ets。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { router } from '@kit.ArkUI'

@Component
export struct HdNav {
@StorageProp('topHeight')
topHeight: number = 0
@Prop
title: string = 'hello world'
@Prop
hasBorder: boolean = false
@Prop
leftIcon: ResourceStr = $r('app.media.ic_common_back')
@Prop
rightIcon: ResourceStr = $r('sys.media.ohos_ic_public_more')
@Prop
showRightIcon: boolean = true
@Prop
iconColor: ResourceStr = $r('app.color.black')
@Prop
titleColor: string = '#131313'
@BuilderParam
menuBuilder: () => void = this.defaultMenu

@Builder
defaultMenu() {

}

build() {
Row({ space: 16 }) {
Image(this.leftIcon)
.size({ width: 24, height: 24 })
.onClick(() => router.back())
.fillColor(this.iconColor)
Row() {
if (this.title) {
Text(this.title)
.fontWeight(600)
.fontColor(this.titleColor)
.layoutWeight(1)
.textAlign(TextAlign.Center)
.fontSize(18)
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
}
}
.height(56)
.layoutWeight(1)

if (this.showRightIcon) {
Image(this.rightIcon)
.size({ width: 24, height: 24 })
.objectFit(ImageFit.Contain)
.bindMenu(this.menuBuilder)
} else {
Blank()
.width(24)
}
}

.padding({ left: 16, right: 16, top: this.topHeight })
.height(56 + this.topHeight)
.width('100%')
.border({
width: { bottom: this.hasBorder ? $r('app.float.common_border_width') : 0 },
color: $r('app.color.common_gray_bg')
})
}
}

资源引入

应用开发过程中,经常需要用到颜色、字体、间距、图片等资源,在不同的设备或配置中,这些资源的值可能不同。

  • 应用资源:借助资源文件能力,开发者在应用中自定义资源,自行管理这些资源在不同的设备或配置中的表现。
  • 系统资源:开发者直接使用系统预置的资源定义。
1
2
3
4
5
6
7
8
# 引入resouces/base/media下的home_selected的图片
$r('app.media.home_selected')

# 导入resources/rawfile下的index.html文件
$rawfile("index.html")

# 获取resources/rawfile下的audio.mp3音频
await getContext(this).resourceManager.getRawFd("audio.mp3")

页面路由

页面路由 router 根据页面的 uri 找到目标页面,从而实现跳转。以最基础的两个页面之间的跳转为例,具体实现步骤如下:

  1. 在 “Project“窗口,打开 src> main >ets,右键点击 pages 文件夹,创建一个页面。
  2. 在 resources/base/profile 下的 main_pages.json,新建一个 pages 中创建页面的文件名(注意大小写)。
  3. 调用 router.push () 路由到指定页面。
  4. 调用 router.back () 回到首页。

img

WebView

页面加载是 Web 组件的基本功能。根据页面加载数据来源可以分为三种常用场景,包括加载网络页面、加载本地页面、加载 HTML 格式的富文本数据。

页面加载过程中,若涉及网络资源获取,需要配置 ohos.permission.INTERNET 网络访问权限,下面以本地静态文件的方法举例。

  • 将资源文件放置在应用的 resources/rawfile 目录下。

img

  • 鸿蒙 Next 应用代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import web_webview from '@ohos.web.webview';
import { HdNav } from '@mygames/basic';

@Entry
@Component
struct WebComponent {
controller: web_webview.WebviewController = new web_webview.WebviewController();

build() {
Column() {
HdNav({ title: '看烟花秀', showRightIcon: false, iconColor: $r('app.color.black') })

Button('loadData')
.onClick(() => {
try {
this.controller.loadUrl($rawfile("index.html"));

} catch (error) {
console.error(`ErrorCode: ${error.code}, Message: ${error.message}`);
}

})
// 组件创建时,加载www.example.com
Web({ src: $rawfile("index.html"), controller: this.controller })
}
}
}
  • 烟花代码

img

写在后面

到这里鸿蒙 Next 应用实战暂告一段落了。但是鸿蒙系统提供了开箱即用的原生 AI 能力,更方便了我们开发者实现应用的快速智能化,所以,鸿蒙 Next 智能应用实战,待续~

  • ✇ZERO开发
  • 鸿蒙Next实战:电子木鱼北桥苏
    前言正所谓:Hello Word 是程序员学任何一门语言的第一个程序实践。这其实也是一个不错的正反馈,那如何让学习鸿蒙 Next 更有成就感呢?下面就演示一下从零开发一个鸿蒙 Next 版的电子木鱼,主打就是一个抽象!实现要点页面布局木鱼点击木鱼音效动画特效自定义弹窗开始实践页面布局ArkTS 定义了声明式 UI 描述、自定义组件和动态扩展 UI 元素的能力,配合 ArkUI 开发框架中的系统组件及其相关的事件方法、属性方法等共同构成 UI 开发的主体。我们下面要完成的主要是一个木鱼和设置按钮、自动按钮。12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364build() {Column() { HdNav({ title: '电子木鱼', showRightIcon: false, iconColor: $r('app.color.white'), titleColor: '#ffffff' })
     

鸿蒙Next实战:电子木鱼

作者 北桥苏
2024年10月6日 08:00

前言

正所谓:Hello Word 是程序员学任何一门语言的第一个程序实践。这其实也是一个不错的正反馈,那如何让学习鸿蒙 Next 更有成就感呢?下面就演示一下从零开发一个鸿蒙 Next 版的电子木鱼,主打就是一个抽象!

img

实现要点

  1. 页面布局
  2. 木鱼点击
  3. 木鱼音效
  4. 动画特效
  5. 自定义弹窗

img

开始实践

页面布局

ArkTS 定义了声明式 UI 描述、自定义组件和动态扩展 UI 元素的能力,配合 ArkUI 开发框架中的系统组件及其相关的事件方法、属性方法等共同构成 UI 开发的主体。我们下面要完成的主要是一个木鱼和设置按钮、自动按钮。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
build() {

Column() {
HdNav({ title: '电子木鱼', showRightIcon: false, iconColor: $r('app.color.white'), titleColor: '#ffffff' })

Row() {
Text(this.woodenType[this.type] + ':'+ this.score).fontSize(22).fontColor("#ffffff").width('100%').textAlign(TextAlign.Center)
}.width("100%").height("8%")

Row() {
Image($r('app.media.setting')).width(25).height(25).margin(16).onClick(() => {
if (this.dialogController != null) {
this.dialogController.open()
}
})
}.width('100%')

Row() {
Image($r('app.media.foreground')).width(40).height(40).margin({left:8,top:5})
}.width('100%')
.onClick(() => {
this.handlePopup = !this.handlePopup
})
.bindPopup(this.handlePopup, {
message: '数据统计功能,正在完善中~',
})

Row() {
if (this.isPresent) {
Text(this.woodenType[this.type] + ': ' + this.woodenFishNum).fontSize(16).fontColor("#ffffff").width('100%').textAlign(TextAlign.Center)
.transition(this.effect)
}
}.width('100%').height('25%')
.alignItems(VerticalAlign.Top)

Row() {
Image($r('app.media.muyu'))
.width(this.isZoomed == true ? this.targetWidth * 1.2 : this.targetWidth * 1)
.height(this.isZoomed == true ? this.targetHeight * 1.2 : this.targetHeight * 1)
}
.width('100%')
.height('25%')
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)

Row() {
Toggle({ type: ToggleType.Switch })
.onChange((isOn: boolean) => {
if(isOn) {
promptAction.showToast({ message: 'auto is on.' })
} else {
promptAction.showToast({ message: 'auto is off.' })
}
})

Text('自动' + this.woodenType[this.type]).fontSize(18).fontColor('#ffffff').height(40).margin({left: 10})

}.width('100%').height('10%').justifyContent(FlexAlign.Center)

}
.height("100%")
.backgroundColor('rgba(0, 0, 0, 1.00)')

}

木鱼点击

木鱼是一张图片,也就是给该图绑定一个点击事件,点击一次有三个动作需要执行:

  • 木鱼有放大的效果
  • 有类似功德文字的飘动
  • 功德数值的累加

而点击的时候要看到实时的效果,所以可以声明三个状态,通过 State 的修改,从而驱动 UI 更新,以下的 animateTo 是给域名的放大添加的一个平滑效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 积分
@State score: number = 0
// 积分文字
@State isPresent: boolean = false
// 木鱼是否放大
@State isZoomed: boolean = false


// 木鱼UI
Image($r('app.media.muyu'))
.width(this.isZoomed == true ? this.targetWidth * 1.2 : this.targetWidth * 1)
.height(this.isZoomed == true ? this.targetHeight * 1.2 : this.targetHeight * 1)
.onClick((event) => {
animateTo({ curve: curves.springMotion() }, () => {
this.isZoomed = !this.isZoomed;

if (this.isZoomed == true) {
this.isPresent = true;
this.score += this.woodenFishNum;
this.onClickPlay();
}
})

// 定时缩小/定时文字消失
setTimeout(() => {this.isZoomed = false;}, 50);
setTimeout(() => {this.isPresent = false}, 600);
})

木鱼音效

木鱼音效是点击时的咚咚的声音,这里就要使用到 HarmonyOS Next 的音频服务。这里需要注意一点,项目运行预览无法播放,一定要模拟器或真机才可以调试音频的播放效果。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 销毁音效工具
onClickDestroy= ()=>{
AudioMgr.Ins().destroy();
console.log('audio', 'destroy');
}

// 初始化音效工具
onClickInit = ()=>{
AudioMgr.Ins().init();
console.log('audio', 'init');
}

// 播放指定音效
onClickPlay = ()=>{
AudioMgr.Ins().play();
console.log('audio', 'playing');
}

img

动画特效

这里的动画效果主要是点击木鱼,从下网上飘出一个文字然后消失的特效。在鸿蒙中可以通过 TransitionEffect 方法添加效果,首先创建特效,然后再文字上挂载。

1
2
3
4
5
6
7
8
9
// 上移入场特效
private effect: object =
TransitionEffect.OPACITY
// 初始正常大小// 假设动画持续时间为500ms
.combine(TransitionEffect.scale({ x: 1, y: 1 }).animation({ curve: curves.springMotion(0.6, 1.2), duration: 0 }))
// 向上平移150单位// 与上一步同时开始
.combine(TransitionEffect.translate({ x: 0, y: 400 }).animation({ curve: curves.springMotion(0.6, 1.2), duration: 10000, delay: 50 }))
// 淡出至完全透明// 在平移结束后开始淡出
.combine(TransitionEffect.opacity(0).animation({ curve: curves.springMotion(0.6, 1.2), duration: 1000, delay: 0 }));

img

自定义弹窗

经过前面布局,事件绑定,音效播放,一个简单的电子木鱼其实已经完成了。但是为了增添趣味和后期扩展,这里再加一个设置功能,通过按钮打开配置项弹窗,设置包括:

  • 类型选项 (功德、财运、桃花运等)
  • 音效选项 (各种解压的音效素材)
  • 皮肤管理 (木鱼的 UI 界面设置)
  • 数值修改 (对展示的累加数值做任意修改)
  • 其他 (是否关闭音效,是否自动点击等)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// 弹窗层(UI开发-组件-自定义弹窗)
@CustomDialog
struct SettingDialog {
controller?: CustomDialogController

// 父子组件双向同步,文档见 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-link-V5
@Link woodenFishType: number

// 木鱼敲击的数值
@Link woodenFishNum: number

build() {
Column() {

Row() {
Text('愿望:').fontSize(17).fontWeight(600)
Radio({ value: '功德', group: 'word' }).checked(true).onChange((isChecked: boolean) => {
if(isChecked) {
this.woodenFishType = 0
}
})
Text('功德').fontSize(15)
Radio({ value: '财富', group: 'word' }).onChange((isChecked: boolean) => {
if(isChecked) {
this.woodenFishType = 1
}
})
Text('财富').fontSize(15)
Radio({ value: '桃花运', group: 'word' }).onChange((isChecked: boolean) => {
if(isChecked) {
this.woodenFishType = 2
}
})
Text('桃花运').fontSize(15)
}
.width('100%')
.margin({bottom: 12})
.justifyContent(FlexAlign.Start)

Row() {
Text('数值:').fontSize(16).fontWeight(600)
TextInput({text:'1'}).type(InputType.Number).width(180).onChange((value: string) => {
this.woodenFishNum = parseInt(value)
})
}
.width('100%')
.margin({bottom: 12})
.justifyContent(FlexAlign.Start)

Row() {
Text('音效:').fontSize(16).fontWeight(600)
Toggle({ type: ToggleType.Switch })
}
.width('100%')
.margin({bottom: 12})
.justifyContent(FlexAlign.Start)

Row() {
Text('皮肤:').fontSize(16).fontWeight(600)
Radio({ value: '默认', group: 'skin' }).checked(true)
Text('木鱼').fontSize(15)
Radio({ value: '悟空', group: 'skin' })
Text('黑悟空').fontSize(15)
Radio({ value: '典韦', group: 'skin' })
Text('典韦').fontSize(15)
}
.width('100%')
.margin({bottom: 12})
.justifyContent(FlexAlign.Start)

}.padding({top: 28, left: 15})

}
}

这里需要注意的是:父子组件的数据传递。因为自定义弹窗和木鱼是两个不同的组件,而点击弹窗中的比如类型切换或修改的数值,全部要更新到木鱼组件的展示当中。

当然鸿蒙也提供了 @Link 装饰器,用于与其父组件中的数据源共享相同的值,可以结合上面代码和下方截图参考其用法。

img

写在后面

到这里,一个通用型的鸿蒙 Next 版电子木鱼就完成了。不管是组件交互还是布局都还好,唯一让我觉得不适应的是动画特效。

如果用这种方式实现电子烟花肯定不行,所以下次将换一种方法快速实现烟花秀,以及页面间的跳转,待更新~

  • ✇ZERO开发
  • 鸿蒙Next实战:环境搭建北桥苏
    前言作为独立开发者,如果我们错过了传统移动 App,和后起小程序的红利,那万物互联 + AI 的应用开发就得抓住了。虽然个人上架应用平台难易都差不多,但是鸿蒙生态当前正需要广大开发者参与,一旦上架,相比其他平台,流量扶持力度更大,变现能力也更容易。所以,我们可以先开发一些应用占个位置,后面再逐渐迭代完善;那么,第一步就先从搭建开发环境开始吧。鸿蒙 Next 简介鸿蒙 Next,英文 HarmoneyOS Next,又叫纯血版鸿蒙,2023 年 8 月 4 日开发者预览版,2024 年 6 月正式对外公布。鸿蒙 NEXT 采用了全鸿蒙内核,完成了对 Linux 内核的全面替换,并去掉了安卓开放源代码项目(AOSP)等代码,实现了真正的自主可控,他能支持华为及合作厂商的多种智能终端设备,包括手机、平板、智慧屏等等。运行环境要求针对开发 HarmonyOS 应用及元服务,华为基于 IntelliJ IDEA Community 开源版本打造了一个集成开发环境(IDE)——DevEco Studio,能将开发的应用和服务同时运行在 HarmonyOS 和 OpenHarmony 系统上,为保证
     

鸿蒙Next实战:环境搭建

作者 北桥苏
2024年10月5日 08:00

前言

作为独立开发者,如果我们错过了传统移动 App,和后起小程序的红利,那万物互联 + AI 的应用开发就得抓住了。

虽然个人上架应用平台难易都差不多,但是鸿蒙生态当前正需要广大开发者参与,一旦上架,相比其他平台,流量扶持力度更大,变现能力也更容易。

所以,我们可以先开发一些应用占个位置,后面再逐渐迭代完善;那么,第一步就先从搭建开发环境开始吧。

img

鸿蒙 Next 简介

鸿蒙 Next,英文 HarmoneyOS Next,又叫纯血版鸿蒙,2023 年 8 月 4 日开发者预览版,2024 年 6 月正式对外公布。鸿蒙 NEXT 采用了全鸿蒙内核,完成了对 Linux 内核的全面替换,并去掉了安卓开放源代码项目(AOSP)等代码,实现了真正的自主可控,他能支持华为及合作厂商的多种智能终端设备,包括手机、平板、智慧屏等等。

img

运行环境要求

针对开发 HarmonyOS 应用及元服务,华为基于 IntelliJ IDEA Community 开源版本打造了一个集成开发环境(IDE)——DevEco Studio,能将开发的应用和服务同时运行在 HarmonyOS 和 OpenHarmony 系统上,为保证 DevEco Studio 正常运行,建议您的电脑配置满足如下要求:

  • 操作系统:Windows10 64 位,内部版号大于 18363
  • 内存:8GB 及以上
  • 硬盘:100GB 及以上
  • 分辨率:1280*800 像素及以上
  • 其他: 开启了 Hyper-V 虚拟化

img

DevEco Studio

下载

进入 huawei 开发者平台下载,最好找 5.0 以上又不是最新版本就行。还有 DevEco Studio 支持 Windows 和 macOS 系统,但我本人用的是 Windows,所以就以 win 系统演示。

img

安装

下载完成后,双击下载的 “deveco-studio-xxxx.exe”,进入 DevEco Studio 安装向导。因为 DevEco Studio 提供开箱即用的开发体验,将 HarmonyOS SDK、Node.js、Hvigor、OHPM、模拟器平台等进行合一打包,几乎无需额外下载配置就能马上跑项目,但是要运行模拟器需要一点配置,比如 Windows 版本要大于 18363。

img

模拟器设置

DevEco Studio 提供预览、模拟器、真机三种方式查看项目的运行效果,但是给予的测试权限不一。最高的真机,目前需要搭载了鸿蒙 Next 的手机才行,且鸿蒙无法自己升级到 Next,所以折中的方法就是用模拟器。官方现在要求使用模拟器需申请,而且本地电脑开始了虚拟化技术 Hyper-V。

img

img

img

项目运行

DevEco Studio 安装完成后,可以通过运行 Hello World 工程来验证环境设置是否正确。接下来以创建一个支持 Phone 设备的工程为例进行介绍。

img

项目结构

可能当时为了适应主流开发语言,加上自己新出的 ArkTS 有三种工程类型可供选择,而我就是为 ArkTS 而来,所以以下和后面要做的应用也都是 ArkTS。

  • ArkTS 工程目录结构(Stage 模型)
  • C++ 工程目录结构(Stage 模型)
  • JS 工程目录结构(FA 模型)

img

项目创建后,结构就是上图,而关于每个目录或文件的用法,就要去官方文档查看 “工程目录结构”,这里就略过进入到简单例子的演示。

img

第一个 Hello World

创建页面

在 “Project” 窗口,点击 “entry > src > main > ets > pages”,打开 “Index.ets” 文件,进行页面的编写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Index.ets
@Entry
@Component
struct Index {
@State message: string = 'Hello World'

build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}

预览效果

在编辑窗口右上角的侧边工具栏,点击 Previewer,打开预览器。

img

写在后面

如果你有应用端相关的开发经验,上手鸿蒙应用还是比较容易的。而如果你像我一样是做后端的,或很少接触前端,那也可以跟着我一起代码实战,简单实现一个鸿蒙 Next 的电子木鱼和电子烟花秀,文章待更新~

  • ✇爱吃猫的鱼BLOG
  • 正则表达式的基本介绍与正则大全M.Talen
    正则表达式(Regular Expression)又称规则表达式,在代码中常简写为Regex、Regexp或RE,它是一种文本模式,包括普通字符(例如a到z之间的字母)和特殊字符(称为"元字符")。作用文本验证:用于检查输入的文本是否符合特定的格式要求,如验证电子邮件、电话号码等。文本搜索和替换:可以在文本中查找特定模式的内容,并进行替换操作。数据提取:从文本中提取出符合特定模式的部分内容。语法分析:在某些编程领域中,用于分析和理解代码的结构。1 语法一个正则表达式是一种从左到右匹配主体字符串的模式,它可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等。1.1 基本匹配由一些字符(如字母、数字或符号)组成的最简单的正则表达式。实例1my1.2 元字符正则表达式主要依赖于元字符。 元字符不代表他们本身的字面意思而是有有特殊的含义。元字符描述.匹配除换行符以外的任意字符[ ]字符类。匹配方括号内的任意字符[^ ]否定的字符种类。匹配除了方括号里的任意字符*匹配前面的子表达式零次或多次+匹配前面的子表达式一次或多次?匹配前面的子表达式零次或一次{n,m}匹配
     

正则表达式的基本介绍与正则大全

作者 M.Talen
2024年5月14日 00:27

正则表达式(Regular Expression)又称规则表达式,在代码中常简写为RegexRegexpRE,它是一种文本模式,包括普通字符(例如a到z之间的字母)和特殊字符(称为"元字符")。

作用

  1. 文本验证:用于检查输入的文本是否符合特定的格式要求,如验证电子邮件、电话号码等。
  2. 文本搜索和替换:可以在文本中查找特定模式的内容,并进行替换操作。
  3. 数据提取:从文本中提取出符合特定模式的部分内容。
  4. 语法分析:在某些编程领域中,用于分析和理解代码的结构。

1 语法

一个正则表达式是一种从左到右匹配主体字符串的模式,它可以从一个基础字符串中根据一定的匹配模式替换文本中的字符串、验证表单、提取字符串等等。

1.1 基本匹配

由一些字符(如字母、数字或符号)组成的最简单的正则表达式。

实例

1
my

image-20240511224117653

1.2 元字符

正则表达式主要依赖于元字符。 元字符不代表他们本身的字面意思而是有有特殊的含义。

元字符描述
.匹配除换行符以外的任意字符
[ ]字符类。匹配方括号内的任意字符
[^ ]否定的字符种类。匹配除了方括号里的任意字符
*匹配前面的子表达式零次或多次
+匹配前面的子表达式一次或多次
?匹配前面的子表达式零次或一次
{n,m}匹配前面的子表达式最少n次最多m次
( )匹配分组。组合一个子表达式
|或运算符,匹配符号前或后的字符
\转义字符,用于匹配一些保留的字符
^从开头进行匹配
$从末端进行匹配

1.2.1 点 .

.匹配任意单个字符,但不匹配换行符。

示例1

1
.

image-20240512143846833

示例2

1
.n

image-20240512143933842

1.2.2 字符类

方括号[]用来指定一个字符类,在方括号中的字符都将被匹配。字符类不会被顺序影响,还可以使用连字符-来指定范围。

示例1

1
[aeiou]

image-20240512144913169

示例2

1
[a-m]

image-20240512145419367

否定字符类

当符号^用在方括号[]内表示这个字符类是否定的。

示例1

1
[^aeiou]

image-20240512145928931

示例2

1
[^a-m]

image-20240512150004372

1.2.3 重复

当一个子表达式后面跟着字符+ * ?,是用来指定匹配该子表达式的次数。

1.2.3.1 星号 *

*匹配在*之前的字符出现大于等于0次。

示例1

1
e*

需要注意的是,e 出现0次的地方也会被标记

image-20240512151436387

示例2

匹配所有字符

1
.*

image-20240512152644347

1.2.3.2 加号 +

+匹配+之前的字符出现大于等于1次。

示例1

1
e+

image-20240512153536137

示例2

匹配以 e 开头,以 u 结尾的内容

1
e.+u

image-20240512153839436

1.2.3.3 问号 ?

匹配之前的字符出现0或者1次,即表示前面的字符是可选的。

示例

1
ou?n

image-20240512154651440

1.2.3.4 花括号 {}

{}常用来限定子表达式可以出现的次数。比如{n,m}表示出现最少 n 次最多 m 次,{n,}表示出现最少 n 次,{,m}表示出现最多 m 次,{n}表示固定出现 n 次。

示例1

1
e{2,3}

image-20240512155501711

示例2

1
e{2,}

image-20240512160016217

示例3

1
e{3}

image-20240512160051826

1.2.4 匹配分组

括号()用来指定一个子表达式,在括号中的内容会被看作一个整体。比如 (xy)* 匹配连续出现零个或多个的 xy,而 xy* 则匹配连续出现零个或多个的 y

示例1

1
(love)+

image-20240512162059930

示例2

1
([at])r

image-20240512164518517

1.2.5 或运算符 |

|用于判断条件,表示或者。

示例

1
a|t|es

image-20240512165004816

1.2.6 转义

反斜线\用于将特殊字符转义为原义字符,特殊字符如{ } [ ] / \ + * . $ ^ | ?

示例

1
y\.

image-20240512165940893

1.2.7 锚点

锚点可以匹配指定开头或结尾的字符串。^ 指定开头,$ 指定结尾。

示例1

1
^Regular

image-20240512172014524

示例2

1
Expression$

image-20240512172057858

1.3 简写字符集

简写描述
\w匹配所有字母数字,等同 [a-zA-Z0-9_]
\W匹配所有非字母数字,等同 [^\w]
\d匹配数字,等同 [0-9]
\D匹配非数字,等同 [^\d]
\s匹配所有空格字符,等同 [\t\n\f\r\p{Z}]
\S匹配所有非空格字符: [^\s]
\f匹配一个换页符
\n匹配一个换行符
\r匹配一个回车符
\t匹配一个制表符
\v匹配一个垂直制表符
\p匹配 CR/LF,等同 \r\n

需要注意的是,\s \S \f \n \r \t \v \p 所匹配的字符均为非打印字符

1.4 断言

断言分为先行断言和后发断言,它们都属于非捕获组(用于匹配模式,但不包括在匹配列表中)。用来筛选指定条件的匹配结果。

需要注意的是,断言必须包含在分组()

符号描述
?=正先行断言-存在
?!负先行断言-排除
?<=正后发断言-存在
?<!负后发断言-排除

1.4.1 正先行断言 ?=

正先行断言的筛选条件为匹配字符其后跟随断言中定义的格式。

示例

1
my(?=\shometown)

image-20240512181224256

1.4.2 负先行断言 ?!

负先行断言的筛选条件为匹配字符其后不跟随断言中定义的格式。

示例

1
my(?!\shometown)

image-20240512231317412

1.4.3 正后发断言 ?<=

正后发断言的筛选条件为匹配字符其前跟随断言中定义的格式。

1
(?<=my)self

image-20240512232345325

1.4.4 负后发断言 ?<!

负后发断言的筛选条件为匹配字符其前不跟随断言中定义的格式。

1
(?<!my)self

image-20240512232406235

2 标记

标记也称为修饰符,作为额外的匹配策略用于修改表达式的搜索结果。标志可以任意组合使用,它也是正则表达式中的一部分。

标志描述
g全局搜索
i忽略大小写
m多行匹配

2.1 全局搜索

标记 g 用于全局搜索。即不仅返回第一个匹配结果,而是全部匹配结果。在语法章节中所有的示例均使用全局搜索。

示例

1
/r/g

image-20240513000657127

2.1 忽略大小写

标记 i 用于忽略大小写。匹配的字符可以是大写或者小写。

示例

1
/r/gi

image-20240513000706053

2.3 多行匹配

标记 m 用于多行匹配。比如前面说到的锚点^ $,如果想在每行的开头结尾生效,就需要使用标记 m

示例

1
/^Regular/gm

image-20240513002324588

3 常用正则

火车车次

1
/^[GCDZTSPKXLY1-9]\d{1,4}$/

手机机身码(IMEI)

1
/^\d{15,17}$/

必须带端口号的网址(或ip)

1
/^((ht|f)tps?:\/\/)?[\w-]+(\.[\w-]+)+:\d{1,5}\/?$/

网址(URL)

1
/^(((ht|f)tps?):\/\/)?([^!@#$%^&*?.\s-]([^!@#$%^&*?.\s]{0,63}[^!@#$%^&*?.\s])?\.)+[a-z]{2,6}\/?/

统一社会信用代码

1
/^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/

统一社会信用代码(宽松匹配)(15位/18位/20位数字/字母)

1
/^(([0-9A-Za-z]{15})|([0-9A-Za-z]{18})|([0-9A-Za-z]{20}))$/

迅雷链接

1
/^thunderx?:\/\/[a-zA-Z\d]+=$/

ed2k链接(宽松匹配)

1
/^ed2k:\/\/\|file\|.+\|\/$/

磁力链接(宽松匹配)

1
/^magnet:\?xt=urn:btih:[0-9a-fA-F]{40,}.*$/

子网掩码(不包含 0.0.0.0)

1
/^(254|252|248|240|224|192|128)\.0\.0\.0|255\.(254|252|248|240|224|192|128|0)\.0\.0|255\.255\.(254|252|248|240|224|192|128|0)\.0|255\.255\.255\.(255|254|252|248|240|224|192|128|0)$/

linux"隐藏文件"路径

1
/^\/(?:[^/]+\/)*\.[^/]*/

linux文件夹路径

1
/^\/(?:[^/]+\/)*$/

linux文件路径

1
/^\/(?:[^/]+\/)*[^/]+$/

window"文件夹"路径

1
/^[a-zA-Z]:\\(?:\w+\\?)*$/

window下"文件"路径

1
/^[a-zA-Z]:\\(?:\w+\\)*\w+\.\w+$/

股票代码(A股)

1
/^(s[hz]|S[HZ])(000[\d]{3}|002[\d]{3}|300[\d]{3}|600[\d]{3}|60[\d]{4})$/

大于等于0,小于等于150,支持小数位出现5,如145.5,用于判断考卷分数

1
/^150$|^(?:\d|[1-9]\d|1[0-4]\d)(?:\.5)?$/

html注释

1
/<!--[\s\S]*?-->/g

md5格式(32位)

1
/^[a-fA-F0-9]{32}$/

GUID/UUID

1
/^[a-f\d]{4}(?:[a-f\d]{4}-){4}[a-f\d]{12}$/i

版本号(version)格式必须为X.Y.Z

1
/^\d+(?:\.\d+){2}$/

视频(video)链接地址(视频格式可按需增删)

1
/^https?:\/\/(.+\/)+.+(\.(swf|avi|flv|mpg|rm|mov|wav|asf|3gp|mkv|rmvb|mp4))$/i

图片(image)链接地址(图片格式可按需增删)

1
/^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i

24小时制时间(HH:mm:ss)

1
/^(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/

12小时制时间(hh:mm:ss)

1
/^(?:1[0-2]|0?[1-9]):[0-5]\d:[0-5]\d$/

base64格式

1
/^\s*data:(?:[a-z]+\/[a-z0-9-+.]+(?:;[a-z-]+=[a-z0-9-]+)?)?(?:;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*?)\s*$/i

数字/货币金额(支持负数、千分位分隔符)

1
/^-?\d{1,3}(,\d{3})*(\.\d{1,2})?$/

银行卡号(10到30位,覆盖对公/私账户,参考微信支付

1
/^[1-9]\d{9,29}$/

中文姓名

1
/^(?:[\u4e00-\u9fa5·]{2,16})$/

英文姓名

1
/(^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$)/

车牌号(新能源)

1
/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z](([DF]((?![IO])[a-zA-Z0-9](?![IO]))[0-9]{4})|([0-9]{5}[DF]))$/

车牌号(非新能源)

1
/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]$/

车牌号(新能源+非新能源)

1
/^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-HJ-NP-Z][A-HJ-NP-Z0-9]{4,5}[A-HJ-NP-Z0-9挂学警港澳]$/

手机号(mobile phone)中国(严谨),根据工信部2019年最新公布的手机号段

1
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[01256789]))\d{8}$/

手机号(mobile phone)中国(宽松),只要是13、14、15、16、17、18、19开头即可

1
/^(?:(?:\+|00)86)?1[3-9]\d{9}$/

手机号(mobile phone)中国(最宽松),只要是1开头即可,如果你的手机号是用来接收短信,优先建议选择这一条

1
/^(?:(?:\+|00)86)?1\d{10}$/

日期(宽松)

1
/^\d{1,4}(-)(1[0-2]|0?[1-9])\1(0?[1-9]|[1-2]\d|30|31)$/

日期(严谨,支持闰年判断)

1
/^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)$/

中国省

1
/^浙江|上海|北京|天津|重庆|黑龙江|吉林|辽宁|内蒙古|河北|新疆|甘肃|青海|陕西|宁夏|河南|山东|山西|安徽|湖北|湖南|江苏|四川|贵州|云南|广西|西藏|江西|广东|福建|台湾|海南|香港|澳门$/

可以被moment转化成功的时间 YYYYMMDD HH:mm:ss

1
/^\d{4}([/:-\S])(1[0-2]|0?[1-9])\1(0?[1-9]|[1-2]\d|30|31) (?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d$/

email(邮箱)

1
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

座机(tel phone)电话(国内),如: 0341-86091234

1
/^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/

身份证号(1代、15位数字)

1
/^[1-9]\d{7}(?:0\d|10|11|12)(?:0[1-9]|[1-2][\d]|30|31)\d{3}$/

身份证号(2代、18位数字),最后一位是校验位,可能为数字或字符X

1
/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/

身份证号,支持1/2代(15位/18位数字)

1
/^\d{6}((((((19|20)\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(((19|20)\d{2})(0[13578]|1[02])31)|((19|20)\d{2})02(0[1-9]|1\d|2[0-8])|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))0229))\d{3})|((((\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|((\d{2})(0[13578]|1[02])31)|((\d{2})02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[048])0229))\d{2}))(\d|X|x)$/

护照(包含香港、澳门)

1
/(^[EeKkGgDdSsPpHh]\d{8}$)|(^(([Ee][a-fA-F])|([DdSsPp][Ee])|([Kk][Jj])|([Mm][Aa])|(1[45]))\d{7}$)/

帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线组合

1
/^[a-zA-Z]\w{4,15}$/

中文/汉字

1
/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/

小数(支持科学计数)

1
/^[+-]?(\d+([.]\d*)?([eE][+-]?\d+)?|[.]\d+([eE][+-]?\d+)?)$/

只包含数字

1
/^\d+$/

html标签(宽松匹配)

1
/<(\w+)[^>]*>(.*?<\/\1>)?/

匹配中文汉字和中文标点

1
/[\u4e00-\u9fa5|\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5]/

qq号格式正确

1
/^[1-9][0-9]{4,10}$/

数字和字母组成

1
/^[A-Za-z0-9]+$/

英文字母

1
/^[a-zA-Z]+$/

小写英文字母组成

1
/^[a-z]+$/

大写英文字母

1
/^[A-Z]+$/

密码强度校验,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符

1
/^\S*(?=\S{6,})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/

用户名校验,4到16位(字母,数字,下划线,减号)

1
/^[\w-]{4,16}$/

ip-v4[:端口]

1
/^((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])(?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$/

ip-v6[:端口]

1
/(^(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$)|(^\[(?:(?:(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))\](?::(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$)/i

16进制颜色

1
/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}|[a-fA-F0-9]{8}|[a-fA-F0-9]{4})$/

微信号(wx),6至20位,以字母开头,字母,数字,减号,下划线

1
/^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/

邮政编码(中国)

1
/^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\d{4}$/

中文和数字

1
/^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$/

不能包含字母

1
/^[^A-Za-z]*$/

java包名

1
/^([a-zA-Z_]\w*)+([.][a-zA-Z_]\w*)+$/

mac地址

1
/^(([a-f0-9][0,2,4,6,8,a,c,e]:([a-f0-9]{2}:){4})|([a-f0-9][0,2,4,6,8,a,c,e]-([a-f0-9]{2}-){4}))[a-f0-9]{2}$/i

匹配连续重复的字符

1
/(.)\1+/

数字和英文字母组成,并且同时含有数字和英文字母

1
/^(?=.*[a-zA-Z])(?=.*\d).+$/

香港身份证

1
/^[a-zA-Z]\d{6}\([\dA]\)$/

澳门身份证

1
/^[1|5|7]\d{6}\(\d\)$/

台湾身份证

1
/^[a-zA-Z][0-9]{9}$/

大写字母,小写字母,数字,特殊符号 @#$%^&*~()-+=` 中任意3项密码

1
/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]/

ASCII码表中的全部的特殊字符

1
/[\x21-\x2F\x3A-\x40\x5B-\x60\x7B-\x7E]+/

正整数,不包含0

1
/^\+?[1-9]\d*$/

负整数,不包含0

1
/^-[1-9]\d*$/

整数

1
/^(?:0|(?:-?[1-9]\d*))$/

浮点数

1
/^(-?[1-9]\d*\.\d+|-?0\.\d*[1-9]\d*|0\.0+)$/

浮点数(严格)

1
/^(-?[1-9]\d*\.\d+|-?0\.\d*[1-9])$/

email(支持中文邮箱)

1
/^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/

域名(非网址,不包含协议)

1
/^([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})$/

军官/士兵证

1
/^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/

户口薄

1
/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/

4 备注

4.1 Regex101

地址:regex101.com

正则表达式测试器,具有语法突出显示、解释、备忘单等功能,适用于 PHP-PCRE、Python、GO、JavaScript、Java、C#-.NET、Rust 等语言。

image-20240513233300327

4.2 RegExr

地址:regexr-cn.com

带有语法高亮、支持 PHP/PCRE 和 JS 语言、上下文解释、备忘单、参考和正则表达式社区的正则表达式测试工具。

image-20240513233809937

4.3 GoRegex

地址:goregex.cn

提供PHP、PCRE、Python、Go、JavaScript等语言的正则表达式在线测试、生成,解析工具服务。其中的正则库及正则教程可以帮助快速方便的获取正则表达式。

image-20240513234042057

4.4 RegexLearn

地址:regexlearn.com/zh-cn

交互式学习正则表达式,在所处的阶段练习、测试和分享自己的正则表达式。

image-20240513234207157

  • ✇爱吃猫的鱼BLOG
  • 玩转npm:从基础到实践的全面指南M.Talen
    1 简介npm(Node Package Manager)是Node.js生态系统中的默认包管理器,它提供了一系列的命令行工具,使得开发者能够方便地进行包的管理操作。这些操作包括但不限于下载、安装、升级、删除包,以及发布和维护自己的包。以下是npm的一些主要功能:包管理:通过npm install命令安装项目所需的包,并将其添加到项目的依赖中,减少重复劳动。版本管理:指定项目依赖项的版本,确保项目不受不兼容版本的影响。脚本执行:在package.json文件中定义脚本,使用npm run命令执行。包发布和分享:开发者可以将自己编写的包发布到NPM的公共仓库中,供其他开发者使用。依赖解析:递归地解析和安装其依赖项,确保项目中的所有依赖都得到满足。包搜索和浏览:在NPM网站上搜索、浏览和发现其他人创建的包。2 安装NPMnpm不需要单独的安装,在安装Node.js的时候会相应的安装npm。前往Node.js官网下载并安装最新版本Node.js验证npm是否安装成功12npm -v # 查看npm版本,若输出版本号,即为安装成功# 10.5.13 基本使用初次运行npm时,可以使用np
     

玩转npm:从基础到实践的全面指南

作者 M.Talen
2024年5月8日 12:38

1 简介

npm(Node Package Manager)是Node.js生态系统中的默认包管理器,它提供了一系列的命令行工具,使得开发者能够方便地进行包的管理操作。这些操作包括但不限于下载、安装、升级、删除包,以及发布和维护自己的包。

以下是npm的一些主要功能:

  • 包管理:通过npm install命令安装项目所需的包,并将其添加到项目的依赖中,减少重复劳动。
  • 版本管理:指定项目依赖项的版本,确保项目不受不兼容版本的影响。
  • 脚本执行:在package.json文件中定义脚本,使用npm run命令执行。
  • 包发布和分享:开发者可以将自己编写的包发布到NPM的公共仓库中,供其他开发者使用。
  • 依赖解析:递归地解析和安装其依赖项,确保项目中的所有依赖都得到满足。
  • 包搜索和浏览:在NPM网站上搜索、浏览和发现其他人创建的包。

2 安装NPM

npm不需要单独的安装,在安装Node.js的时候会相应的安装npm。

  1. 前往Node.js官网下载并安装最新版本Node.js

image-20240425225114401

  1. 验证npm是否安装成功
1
2
npm -v    # 查看npm版本,若输出版本号,即为安装成功
# 10.5.1

3 基本使用

初次运行npm时,可以使用npm init命令进行初始化操作,它会引导填写一些基本信息(如版本号、描述等)

image-20240425230442939

初始化项目后创建package.json文件

package.json文件

package.json文件通常用来描述项目和软件包信息。

  • name:项目或库的名称
  • version:项目的版本
  • author:项目作者
  • description:项目的描述
  • license:项目的许可证

scripts

scripts字段用于定义项目中的各种脚本命令。可以在其中指定一些常用的操作,比如启动项目、执行测试、构建等,并且可以通过命令行工具来执行这些脚本。

例如,假设想在每次提交代码前运行测试,可以创建一个名为precommit的脚本:

1
2
3
4
5
6
{
"scripts": {
"prestart": "npm install",
"start": "node index.js"
}
}

在命令行使用npm run prestart等同于执行npm install

每个script都是一个命令行指令,后面跟着要执行的具体命令。当开发者克隆一个仓库并在自己的机器上运行npm installyarn安装依赖后,可以通过npm run <scriptName>yarn <scriptName>来执行这些预设的任务。这样的自动化大大提高了开发效率,减少了重复劳动,并且确保所有开发者和CI/CD流水线都能以相同的方式执行相同的步骤。

dependencies和devDependencies

dependencies和devDependencies是项目配置文件中的两个重要部分,它们用于分别列出项目运行时和开发时所需的外部模块或库。

  • dependencies:项目在实际运行时所依赖的模块或库。这些依赖项是在生产环境中必须安装和包含的包,因为它们包含了项目功能实现的核心代码或是该应用程序直接使用的库。当用户全局安装该应用程序或在系统上运行它时,npm会自动将这些依赖项下载并安装到node_modules目录中。
  • devDependencies:项目在开发过程中所需要的工具、测试框架、构建工具等,它们通常不参与项目的实际运行。这包括测试库、构建脚本、代码格式化工具等。当发布应用程序时这些依赖项不会被包含在内,但是其他开发者如果要在本地开发或测试代码,则需要安装这些依赖项。

在package.json中明确指定这些依赖项,可以确保任何人在新的环境中克隆和设置项目时都能够获得正确的版本,并且能够重现构建过程。这对于团队协作和持续集成/持续部署(CI/CD)流程至关重要。

4 常用命令

npm提供了许多有用的命令来帮助管理项目的依赖项和其他相关任务。下面是一些最常用的npm命令:

  1. npm init:初始化一个新的Node.js项目,创建一个package.json文件。
  2. npm install:安装所有依赖项以及未列出的新依赖项。
    • npm install :安装一个新依赖项到你的项目。
    • npm install --save:安装一个依赖项,并将其添加到dependencies中。
    • npm install --save-dev:安装一个开发依赖项,并将其添加到devDependencies中。
  3. npm uninstall :卸载一个依赖项。
  4. npm update:更新所有过期的依赖项到最新版本。
  5. npm outdated:列出所有过期的依赖项。
  6. npm ls:显示已安装的包及其版本信息。
  7. npm publish:发布你的包到npm仓库。

更多npm命令可参阅CLI 命令 | npm 中文网 (nodejs.cn)

5 全局安装与本地安装

在 npm 中,可以选择全局安装或本地安装包。这两种方式各有用途:

  • 全局安装 (npm install -g):全局安装的包对所有项目都可用。这意味着无论在哪里,都可以在命令行中访问这些包。这适用于那些不打算在单个项目中使用,而是希望在整个系统范围内使用的工具或命令行程序。例如,如果你经常需要使用某个代码格式化工具或构建脚本,全局安装可以让它在任何地方都可以使用。
  • 本地安装 (npm install):本地安装的包仅限于当前项目的node_modules目录。这意味着其他项目不能访问这些包,除非也为它们安装了同样的依赖项。这适用于那些项目直接依赖的库或工具。例如,如果你的项目需要一个特定版本的jQuery,你应该本地安装它,因为它只对你当前的项目有用。

image-20240428000553721

一般来说,建议尽可能使用本地安装,因为它允许精确控制每个项目的依赖关系,并且避免不同项目之间的冲突。全局安装主要用于那些你需要在多个项目间共享的工具或命令行实用程序。

6 版本管理和兼容性策略

npm版本管理和兼容性策略是确保项目顺利运行的关键部分。以下是一些建议:

  1. 使用语义化版本控制:遵循语义化版本控制规则,即主版本号.次版本号.修订号。当发布新功能时,增加次版本号;当修复 bug 时,增加修订号;当做出破坏性更改时,增加主版本号。这有助于开发者了解他们是否需要升级他们的代码以适应新版本。
  2. 锁定文件:使用package-lock.json或yarn.lock文件来锁定依赖项的具体版本。这可以防止因不同版本而导致的问题,并确保在不同环境中具有相同的一致性和可预测性。
  3. 定期更新:定期运行npm update来更新依赖项到最新版本,以利用最新的改进和安全修复。但请小心重大更新,因为它们可能会引入不兼容的变化。
  4. 依赖项兼容性:当添加新依赖项时,尽量选择广泛支持和积极维护的包。
  5. 测试:在更新依赖项之前,最好在一个隔离的环境中测试它们,比如使用Docker或虚拟机,以确保它们不会破坏现有的功能。
  6. 回退计划:如果更新导致问题,确保有一个回退计划。这可能意味着保留旧版本的代码或依赖项,直到问题解决。
  7. 监控:监控项目以识别潜在的安全漏洞和性能问题。有许多工具和服务可以帮助做到这一点,包括Snyk、Greenkeeper等。
  8. 文档:及时更新README.md或其他文档,说明项目依赖哪些版本的包,以及如何安装和配置它们。

通过遵循这些实践,可以最大限度地减少因依赖项更新而引起的问题,并确保项目稳定可靠。

package-lock.json文件:

package-lock.json文件是npm在执行npm install命令后自动生成的一个锁文件,其目的是确保在不同环境下能够一致地安装相同版本的依赖项。这个文件描述了项目所需的每个依赖的确切版本号以及解析后的实际下载地址。

7 案例分析:创建一个简单的npm模块并发布

  1. 确定模块名称

在GitHub或其他代码托管服务上检查模块名称是否可用,确保该名称没有被其他npm包占用。

  1. 初始化模块

在开发目录中创建一个新的文件夹作为模块项目,在该文件夹内运行npm init命令初始化package.json文件,它会引导填写一些基本信息(如版本号、描述等),或者使用npm init -y命令快速初始化。

image-20240427230309324

  1. 编写代码

在项目目录中创建一个JavaScript文件,通常命名为index.js,在其中编写模块代码,并且确保它能作为一个Node.js模块正确导出功能或类。

  1. 编辑package.json文件

添加必要的元数据,包括模块的名称、版本号、描述、作者、许可证等,如果需要,还可以添加 scripts 部分来自定义命令,例如启动脚本或测试脚本。

  1. 发布模块

第一次发布需要先注册一个npm账户

1
2
# 注册账户
npm adduser

image-20240428001100253

如果有npm账户则直接登录

1
2
# 登录账户
npm login

最后使用npm publish命令将模块发布到npm仓库

  1. 后期维护

对于每次更新,需要先递增版本号,然后再次运行npm publish来更新已发布的模块版本。

8 总结

总的来说,npm不仅是Node.js的核心组成部分,也是现代前端工程化的基石。掌握npm意味着掌握了JavaScript开发的未来趋势,它是每个前端工程师必备的基本功。随着Node.js及JavaScript技术的不断演进,相信npm将继续发挥其重要作用,引领着Web开发的新潮流。

  • ✇爱吃猫的鱼BLOG
  • GitHub Desktop:让代码托管不再高深莫测M.Talen
    简介使用 GitHub Desktop 可以使用一个直观、可视化的界面而不是命令行或 Web 浏览器与 GitHub 交互。可以使用它从桌面完成大多数 Git 命令,使用户可以更容易地进行代码的版本控制、代码的提交、分支的管理、拉取请求的处理等操作。软件特色界面设计:简洁直观的用户界面,即使是 Git 新手也能轻松上手。它提供了清晰的仓库列表、变更摘要和历史记录视图,使用户能够快速理解项目的当前状态。基本 Git 操作:支持所有基本的 Git 操作,如克隆、提交、拉取和推送。这些操作都通过可视化界面进行,降低了学习成本。分支管理:分支创建、切换和合并的流程非常直观。提供了一个易于理解的分支视图,使得分支管理变得更加容易。冲突解决:当合并代码时发生冲突,提供了一个基本的冲突解决界面,帮助用户理解并解决冲突。集成 GitHub 功能:它与 GitHub 的特性紧密集成,比如拉取请求和代码审查,提高了代码的管理和协作效率。扩展性:虽然 GitHub Desktop 专注于基本功能,但它也支持高级用户通过命令行工具执行更复杂的 Git 操作。软件截图特别提醒GitHub Desktop 的默认
     

GitHub Desktop:让代码托管不再高深莫测

作者 M.Talen
2024年4月24日 17:41

简介

使用 GitHub Desktop 可以使用一个直观、可视化的界面而不是命令行或 Web 浏览器与 GitHub 交互。可以使用它从桌面完成大多数 Git 命令,使用户可以更容易地进行代码的版本控制、代码的提交、分支的管理、拉取请求的处理等操作。

image-20240321223318134

软件特色

界面设计:简洁直观的用户界面,即使是 Git 新手也能轻松上手。它提供了清晰的仓库列表、变更摘要和历史记录视图,使用户能够快速理解项目的当前状态。

基本 Git 操作:支持所有基本的 Git 操作,如克隆、提交、拉取和推送。这些操作都通过可视化界面进行,降低了学习成本。

分支管理:分支创建、切换和合并的流程非常直观。提供了一个易于理解的分支视图,使得分支管理变得更加容易。

冲突解决:当合并代码时发生冲突,提供了一个基本的冲突解决界面,帮助用户理解并解决冲突。

集成 GitHub 功能:它与 GitHub 的特性紧密集成,比如拉取请求和代码审查,提高了代码的管理和协作效率。

扩展性:虽然 GitHub Desktop 专注于基本功能,但它也支持高级用户通过命令行工具执行更复杂的 Git 操作。

软件截图

image-20240321230856865

image-20240321231027497

image-20240321231647969

image-20240321231725323

特别提醒

GitHub Desktop 的默认语言为英文,如果希望使用中文界面,可以通过安装汉化包来实现,汉化版本需与 GitHub Desktop 版本一致,本文提供汉化教程。

安装教程

选择合适的版本进行下载,较新的版本可能无汉化,部分版本提供两种安装程序,不了解区别则选择.exe

汉化工具来源:Github Desktop 汉化工具

image-20240322011517641

下载完成后双击运行安装程序进行安装

image-20240424133833716

随后在软件关闭的前提下运行对应版本的汉化工具,即GithubDesktopZhTool.exe文件,汉化完成后汉化工具可删除

image-20240424134314706

使用教程

打开软件后登录GitHub账号自动获取账号信息和存储库,可以连接自己的存储库、克隆其他用户的存储库,或者在本地初始化一个新存储库

image-20240424140838763

然后就可以使用图形化来执行各种git命令,在本地创建的存储库也可以快速在GitHub中创建远程存储库

下载地址

官网下载:https://desktop.github.com/

爱吃猫的鱼CLOUD下载:https://cloud.talen.top/s/14uY

  • ✇ZERO开发
  • 如何用CocosCreator对接抖音小游戏的侧边栏复访北桥苏
    前言最近小游戏的软著下来了,用 CocosCreator 做的游戏也完成了 1.0 版本。而当我打包成抖音小游戏进行提交时,还没到初审就给拒了,因为还有一个机审,机器检测到代码中没有接入 “侧边栏复访功能”。这个我还真不知道,那只能去官方看文档了,位置是小游戏开发文档 -> 指南 -> 开放能力 -> 侧边栏能力。简介侧边栏复访能力是在「2023 年 11 月 24 日」起就开启了「必接审核」,为什么要这样做呢?原来是随着抖音首页侧边栏的日活不断增高,平台也积极引导用户养成从首页侧边栏进入游戏的习惯而做的要求。这样可以大幅提升次留、7 留,反正就是你好我好大家好的局面,接就对了。文档我也大概看了,大概的流程就是打开游戏后,判断是不是侧边栏进来,是的话就相当老用户给他一些奖励,不是的话给一些引导弹窗,让用户触发打开侧边栏。而文档里的方案示例大部分也都有奖励领取环节,但是我这个目前是单机,奖励肯定是没有的,那怎么办,于是我就做了一些简化。流程创建去侧边栏按钮和引导层对接抖音提供的方法检测和跳转打包后去抖音开发工具调测操作创建去侧边栏按钮打开游戏场景画布,找到主界面面板,分
     

如何用CocosCreator对接抖音小游戏的侧边栏复访

作者 北桥苏
2024年8月4日 16:13

前言

最近小游戏的软著下来了,用 CocosCreator 做的游戏也完成了 1.0 版本。而当我打包成抖音小游戏进行提交时,还没到初审就给拒了,因为还有一个机审,机器检测到代码中没有接入 “侧边栏复访功能”。这个我还真不知道,那只能去官方看文档了,位置是小游戏开发文档 -> 指南 -> 开放能力 -> 侧边栏能力

Snipaste_2024-08-05_20-01-47

简介

侧边栏复访能力是在「2023 年 11 月 24 日」起就开启了「必接审核」,为什么要这样做呢?原来是随着抖音首页侧边栏的日活不断增高,平台也积极引导用户养成从首页侧边栏进入游戏的习惯而做的要求。这样可以大幅提升次留、7 留,反正就是你好我好大家好的局面,接就对了。

文档我也大概看了,大概的流程就是打开游戏后,判断是不是侧边栏进来,是的话就相当老用户给他一些奖励,不是的话给一些引导弹窗,让用户触发打开侧边栏。而文档里的方案示例大部分也都有奖励领取环节,但是我这个目前是单机,奖励肯定是没有的,那怎么办,于是我就做了一些简化。

flow_path

流程

  • 创建去侧边栏按钮和引导层
  • 对接抖音提供的方法检测和跳转
  • 打包后去抖音开发工具调测

操作

创建去侧边栏按钮

打开游戏场景画布,找到主界面面板,分别添加 “去侧边栏按钮节点” ,添加图文素材。

Snipaste_2024-08-05_20-05-36

创建引导层节点

继续在主界面下添加引导层空白节点,就是展示一个遮罩,一个引导图片和跳转侧边栏和关闭按钮。遮罩层的添加方式是给节点新增 sprint 组件,组件的 sprite Frame 选择 ”internal”->”image”->”default_btn_disabled”,其他的按钮就是自己的 UI 图标了。

image-20240805200657891

在主界面脚本中挂载节点

就是将去侧边栏和引导图层,跳转复访等绑定触发事件。

image-20240805200735109

主要代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import gameManager from "./gameManager";

const {ccclass, property} = cc._decorator;

@ccclass
export default class startPanel extends cc.Component {

// 抖音侧边栏复访
private isFromSidebar = false //状态,表示是否从侧边栏进入

@property(cc.Node)
public btnSidebar: cc.Node | null = null; // 入口有礼按钮

@property(cc.Node)
public ndSidebar: cc.Node | null = null; // 侧边栏引导对话框

@property(cc.Node)
public btnGotoSidebar: cc.Node | null = null; //去侧边栏按钮

@property(cc.Node)
public btnCloseSidebar: cc.Node | null = null; // 关闭侧边栏引导对话框

private game:gameManager = null;

init(game:gameManager) {
this.game = game
}

onLoad() {
this.game.startAudio();
}

// 弹出侧边栏引导框
private showDialogBox() {
// 显示引导层,隐藏开始按钮
this.ndSidebar.active = true;
this.startBtn.active = false;
}

// 关闭侧边栏对话框
private closeSidebar() {
this.ndSidebar.active = false;
this.startBtn.active = true;
}

// 自动跳转侧边栏
private gotoSidebar() {
this.ndSidebar.active = false;
this.startBtn.active = true;

// 抖音小游戏侧边栏跳转逻辑
tt.navigateToScene({
scene: "sidebar",
success: (res) => {
console.log("navigate to scene success");
// 跳转成功回调逻辑
},
fail: (res) => {
console.log("navigate to scene fail: ", res);
// 跳转失败回调逻辑
},
});
}

start() {
// --侧边栏按钮判断--//
tt.onShow((res) => {
//判断用户是否是从侧边栏进来的
this.isFromSidebar = (res.launch_from == 'homepage' && res.location == 'sidebar_card')

if (this.isFromSidebar) {
//如果是从侧边栏进来的,隐藏“去侧边栏”
this.btnSidebar.active = false
}
else {
//否则 显示“去侧边栏”按钮
this.btnSidebar.active = true
}
});

//判断用户是否支持侧边栏进入功能,有些旧版的抖音没有侧边栏,这种情况就把入口有礼那个按钮给隐藏掉
// 因为我引导层默认就是隐藏,所以这部分可以不用判断
/*tt.checkScene({
scene: "sidebar",
success: (res) => {
this.btnSidebar.node.active = true
},
fail: (res) => {
this.btnSidebar.node.active = false
}
});*/
// --侧边栏按钮判断--//

// 显示侧边栏引导框
this.btnSidebar.on('touchstart', this.showDialogBox, this);

// 关闭侧边栏引导对话框
this.btnCloseSidebar.on('touchstart', this.closeSidebar, this);

// 点击进入抖音侧边栏
this.btnGotoSidebar.on('touchstart', this.gotoSidebar, this);
}
}

写在后面

这样操作下来,你会发现接入这个侧边栏功能并不复杂,其实就相当于做了一个弹窗效果。麻烦的是在 CocosCreator 中添加抖音里内部方法不能马上调试,而是要打完包再放到抖音开发者工具中测试,遇到报错又改打包测试再改。还有一个是官方的文档的举例是用了一个最复杂的方式,其实对于我们单机的小游戏就只是引导一下,没有复访奖励什么的!

image-20240805201033707

  • ✇ZERO开发
  • 个人最新微信小程序——有用工具盒,上架了!北桥苏
    简介“有用工具盒”是一款强大且实用的工具类小程序,提供包括图片处理、信息查询、测算,娱乐等常用工具。如:文本加密解密、二维码生成与识别、九宫格切图、图片拼接、国旗头像生成、房贷和BMI计算器等,如同瑞士军刀一样方便好用。功能介绍国旗头像只需要上传一张图片,就会免费生成一张带国旗的头像九宫格切图只需上传一张图片,工具会自动将他分成九宫格的切图,保存后就可以发朋友圈了。房贷计算器目前贷款利率还没调整,其他的基本功能都没有问题。色盲测试通过不停的切换颜色矩阵,你可以点击其中不同的色块,类似于颜色找茬,来测试你的色盲程度。手持弹幕手持弹幕,是一个可以自定义文字样式的滚动大字报,可以用于像粉丝给爱豆接机用的欢迎词。节日倒计时节日倒计时,是一个在本地存储日期进行倒计时的工具,样式温馨多样。由于没有远程存储,如果对微信进行了清理缓存,节日倒计时也会消失需要重新创建。随机数随机数,是一个可以用于朋友间抽签的小工具,给定两个区间,工具自动产生一个数值。大转盘大转盘是一个随机定义的事件扇叶,抽中哪个就中哪个。二维码生成二维码生成工具,你只需要提供链接或文本,工具会将其生成一个可识别的二维码。二维码识别二维
     

个人最新微信小程序——有用工具盒,上架了!

作者 北桥苏
2024年7月11日 14:13

简介

“有用工具盒”是一款强大且实用的工具类小程序,提供包括图片处理、信息查询、测算,娱乐等常用工具。如:文本加密解密、二维码生成与识别、九宫格切图、图片拼接、国旗头像生成、房贷和BMI计算器等,如同瑞士军刀一样方便好用。

mmexport1720348679200

功能介绍

国旗头像

只需要上传一张图片,就会免费生成一张带国旗的头像

九宫格切图

只需上传一张图片,工具会自动将他分成九宫格的切图,保存后就可以发朋友圈了。

房贷计算器

目前贷款利率还没调整,其他的基本功能都没有问题。

色盲测试

通过不停的切换颜色矩阵,你可以点击其中不同的色块,类似于颜色找茬,来测试你的色盲程度。

image-20240711154242511

手持弹幕

手持弹幕,是一个可以自定义文字样式的滚动大字报,可以用于像粉丝给爱豆接机用的欢迎词。

节日倒计时

节日倒计时,是一个在本地存储日期进行倒计时的工具,样式温馨多样。由于没有远程存储,如果对微信进行了清理缓存,节日倒计时也会消失需要重新创建。

随机数

随机数,是一个可以用于朋友间抽签的小工具,给定两个区间,工具自动产生一个数值。

大转盘

大转盘是一个随机定义的事件扇叶,抽中哪个就中哪个。

image-20240711154305686

二维码生成

二维码生成工具,你只需要提供链接或文本,工具会将其生成一个可识别的二维码。

二维码识别

二维码识别,一个通用型二维码识别器,不管是这里生成的还是其他地方的都可以识别。

全息时钟

全息时钟,一个可以用来拍摄自习课视频的时钟展示,省掉了专门安装全息时钟的APP。

常用号码

常用号码罗列了日常生活中紧急需要的号码,点击后就可以拨打,比如报警,住院等等号码。

image-20240711154336615

恶搞理发器

纯娱乐性的小工具,就好比周星驰的,你看这个是部手机,其实是个理发器。

数钱

数钱也是一个娱乐性工具,看你自己的手速,滑动地越快数的钱越多。

更多

目前这个小程序集成了31个小工具,其他诸如尺子、量角器、计算器、亲戚计算器、粤语翻译等等,更多的你可以自己体验了。后续还会迭代一些AI之类的小工具,如果有体验有问题的,也可以在下方公众号给我留言哈~

gzh_qrcode

  • ✇ZERO开发
  • 2024年,个人申请小游戏软著速通指南北桥苏
    前言2024年6月26号,我申请的小游戏软著通过了。由于等待时间太长,所以就总结了一下整个申请过程踩过的坑。帮助未了解或即将申请个人软著的同学绕过下面三点,可以节省至少三分之一的时间(小游戏类目)。当然,这里也会围绕大家关心的几个问题展开,比如:软著申请的费用、软著申请到底要多久以及整个申请的流程。最后再给大家两份我自己的申请模板,软件源程序文档和软件说明书文档。费用2024年申请软著不用钱,如果说一分钱不用也说不过去,因为在申请时的签章页要打印签字,所以整个过程的花费就是一张纸的打印钱。要是你找的第三方代办收取高费用,并且说要打印这打印那的就自己弄吧。因为现在关于软著的登记都是采用电子版形式了。之前既要打印源码文档和软件说明书,还要寄过去,然后才能收到纸张版软著。时间我从申请到通过一共是三个月时间,但是在过程中有三次补正,也就是提交的信息和资料不符和要求。而每次补正再审核大概在8-15天(个人观察),错三次也就要多一个月时间,按正常填写一遍过的话应该两个月以内就能获取。流程注册与开始申请进入“国家版权保护中心官网”,选择个人身份,填写手机邮箱等信息后注册成功后登陆。然后回到官网首页导
     

2024年,个人申请小游戏软著速通指南

作者 北桥苏
2024年6月27日 16:13

前言

2024年6月26号,我申请的小游戏软著通过了。由于等待时间太长,所以就总结了一下整个申请过程踩过的坑。帮助未了解或即将申请个人软著的同学绕过下面三点,可以节省至少三分之一的时间(小游戏类目)。

当然,这里也会围绕大家关心的几个问题展开,比如:软著申请的费用、软著申请到底要多久以及整个申请的流程。最后再给大家两份我自己的申请模板,软件源程序文档和软件说明书文档。

img

费用

2024年申请软著不用钱,如果说一分钱不用也说不过去,因为在申请时的签章页要打印签字,所以整个过程的花费就是一张纸的打印钱。要是你找的第三方代办收取高费用,并且说要打印这打印那的就自己弄吧。因为现在关于软著的登记都是采用电子版形式了。之前既要打印源码文档和软件说明书,还要寄过去,然后才能收到纸张版软著。

时间

我从申请到通过一共是三个月时间,但是在过程中有三次补正,也就是提交的信息和资料不符和要求。而每次补正再审核大概在8-15天(个人观察),错三次也就要多一个月时间,按正常填写一遍过的话应该两个月以内就能获取。

流程

注册与开始申请

进入“国家版权保护中心官网”,选择个人身份,填写手机邮箱等信息后注册成功后登陆。然后回到官网首页导航栏选择 “版权登记” -> “软件登记” -> ”计算机软件著作权登记申请(R11)“, 然后进入到办理身份,是自己就选 ”我是申请人“。

img

软件申请信息

这是第一步要填写的表单,其中权利取得方式、软件全称、版本号、权利范围为必填,权利取得方式按默认原始取得,权利范围按默认全部权利,其他的可以参考我下面截图。而 ”软件全称“ 一定要注意,因为我其中一项补正就是软件全称和后面的软件说明、源码文档里的页眉软件名称不一致。

img

软件开发信息

软件开发信息都为必填,软件分类选择 ”应用软件“,软件说明 ”原创“,开发方式 ”单独开发“,开发完成日期自己选择,发表状态 ”未发表“。

img

软件功能与特点

img

img

鉴别材料

鉴别材料有两份,分别是程序鉴别材料和文档鉴别材料,两个都选择一般交存。其中程序鉴别材料是代码清除空行注释整理后转PDF提交,前后各连续30页可以按开发时间排序,也可以按功能主次等自定义排序,每页不少于50行,若源程序整体不到60页,应提交全部源程序。

而文档鉴别材料是用来描述程序的内容、组成、设计、功能、开发情况、测试结果及使用方法的文字资料和图表,如程序设计说明书、流程图、用户手册等,同样文档要求是连续的前30页和后30页,每页不少于30行,如果整个文档不到60页,就提交整个说明文档,这个我会在下面列出我的那两个模板。

img

确认信息

填完上面的信息后,提交身份证正反面,最后就会列出提交材料的清单确认信息。

img

签章页提交

签章页其实也是材料清单确认书,下载打印后签字拍照完再上传。软著的状态就会由 “待提交” 转 “待受理” 了,接着就等待审核发放了。

img

模板参考

以下两份就是我的程序鉴别材料和文档鉴别材料模板,这里要注意一点的是,游戏类的文档说明一定要加上 “游戏健康忠告” 页面的介绍。(可以扫描下面公众号二维码找到文章或留言)

img

img

写在后面

软著下来后就准备上架到小游戏或快游戏平台了,可能是近年来的净网相关政策,有些平台对于小游戏或快游戏对个人身份的提交通道已经关闭了。不光如此,我最近做了一个工具类的小程序也卡在提交,因为我是要改名称和类目,现在还需要备案和认证,就不知道到时候我上架的时候,以前积累的UV会不会被清掉。

img

  • ✇ZERO开发
  • 工具类uniapp源码免费开源啦!北桥苏
    简介一个基于uniapp开发的强大且实用的工具类APP,提供了包括图片处理、测算,信息查询和娱乐等常用的工具。如:文本加密解密、二维码生成与识别、九宫格切图、图片拼接、国旗头像、房贷和BMI计算器等,如同瑞士军刀一样方便好用~1🕙 项目基本保持每日更新,右上随手点个 🌟 Star 关注,这样才有持续下去的动力,谢谢~项目展示码云: https://gitee.com/gaoxingqufuhchao/bqs-toolsbox-uniapp落地: https://www.zerofc.cn/market/下载:https://www.zerofc.cn/market/land_pages/bqs_toolsbox/index.html项目截图项目说明项目灵感来源于 前端铺子 ,前台基于Vue-uniApp,使用colorUi与uview框架,部分Demo参考uniApp插件市场等,感谢各位作者~特别声明本软件属于技术开源软件, 任何使用本源码从事商业活动,对别人和自己造成损失的,本人概不负责!功能规划2024-08 : 增加2048小游戏、小霸王游戏机等经典小游戏2024-09 : 增加
     

工具类uniapp源码免费开源啦!

作者 北桥苏
2024年6月11日 14:13

简介

一个基于uniapp开发的强大且实用的工具类APP,提供了包括图片处理、测算,信息查询和娱乐等常用的工具。如:文本加密解密、二维码生成与识别、九宫格切图、图片拼接、国旗头像、房贷和BMI计算器等,如同瑞士军刀一样方便好用~

1
🕙 项目基本保持每日更新,右上随手点个 🌟 Star 关注,这样才有持续下去的动力,谢谢~

项目展示

码云: https://gitee.com/gaoxingqufuhchao/bqs-toolsbox-uniapp

落地: https://www.zerofc.cn/market/

下载:https://www.zerofc.cn/market/land_pages/bqs_toolsbox/index.html

项目截图

img

img

img

img

img

img

img

项目说明

项目灵感来源于 前端铺子 ,前台基于Vue-uniApp,使用colorUi与uview框架,部分Demo参考uniApp插件市场等,感谢各位作者~

特别声明

本软件属于技术开源软件, 任何使用本源码从事商业活动,对别人和自己造成损失的,本人概不负责!

功能规划

2024-08 : 增加2048小游戏、小霸王游戏机等经典小游戏
2024-09 : 增加木鱼、摸鱼等娱乐性小工具
2024-10: 增加编程博文和视频,代码资源等等

安装教程

  1. 下载安装:「HBuildX」、「微信开发者工具」
  2. 扫码登录微信开发者工具
  3. 将项目拖进【HBuildX】- 运行 - 微信小程序 - 完成

其他说明

由于很多年没碰uniapp了,这次我想试一下uniapp统计,因为数据绝对了我更新的频率,而再次玩得时候却差点翻车!

其实主要是Hbuild版本和官方策略原因,以前的时候app打包默认会勾选uni统计。而现在不但出了两个版本(1.0和2.0),而且默认是不勾选的,需要自己挑选。重点是选择哪一个就会在对应版本的统计系统生效,也就是如果选了2.0再打开1.0的后台是看不到数据的,最后我看了文档才了解清楚。

img

写在后面

做这个工具箱app主要有两个原因,一个是我做的一个微信小游戏还在备案中,目前是空档没啥事情;第二个是借机重新捡一下uniapp的内容,很多都已经忘了,所以工具箱app的更新迭代会慢一点。

  • ✇ZERO开发
  • 如何将 Python 项目打包成 exe,另带卸载功能!北桥苏
    前言虽然我是做 web 的,但是对 Python 的众多开源项目一直都很关注。像之前的 stable diffusion 的 AI 绘画,和 so-vits-svc 音色替换等源码的部署文档都很完善了。尽管如此,对于刚入门的和本地环境搭建各种踩坑的同学,又急于一试就显得不太友好了。针对这一现象,网上早有了各种大佬做了一键部署的解决方案,不用安装 Python 环境,不用下载各种依赖包,点一下 exe 就可以用了。 那他们是怎么做的呢,到这里应该已经很多人会说用 pyinstaller。是的这个确实可以解决整体环境打包,但是有时候一些图标和依赖文件要放在一起才能正常使用,类似于绿色桌面工具。那有没有方法对这个进一步封装,就是点击 exe 后需要安装,然后安装后才是项目的文件,还可以卸载,答案就是用 Inno Setup Compiler。那么,接下来我就用一个 GUI 的小 demo 完成 exe 打包和进一步安装打包。环境Python 3.8Tkinter (自带)pyinstaller 6.3.0Inno Setup Compiler 基本流程用 conda 单独创建一虚拟环境
     

如何将 Python 项目打包成 exe,另带卸载功能!

作者 北桥苏
2024年5月30日 19:13

前言

虽然我是做 web 的,但是对 Python 的众多开源项目一直都很关注。像之前的 stable diffusion 的 AI 绘画,和 so-vits-svc 音色替换等源码的部署文档都很完善了。尽管如此,对于刚入门的和本地环境搭建各种踩坑的同学,又急于一试就显得不太友好了。针对这一现象,网上早有了各种大佬做了一键部署的解决方案,不用安装 Python 环境,不用下载各种依赖包,点一下 exe 就可以用了。

那他们是怎么做的呢,到这里应该已经很多人会说用 pyinstaller。是的这个确实可以解决整体环境打包,但是有时候一些图标和依赖文件要放在一起才能正常使用,类似于绿色桌面工具。那有没有方法对这个进一步封装,就是点击 exe 后需要安装,然后安装后才是项目的文件,还可以卸载,答案就是用 Inno Setup Compiler。那么,接下来我就用一个 GUI 的小 demo 完成 exe 打包和进一步安装打包。
图片

环境

Python 3.8
Tkinter (自带)
pyinstaller 6.3.0
Inno Setup Compiler

基本流程

用 conda 单独创建一虚拟环境,比如写一个 tkinter 应用,对了为了好看,我们可以设置以下 icon,尺寸 32x32,大图标 64x64 准备一下即可。然后用 pyinstaller 将应用达成文件包 (含 exe),最后用 Inno Setup Compiler 达成安装包,里面就是各种文件关联,图标和信息的设置了。
图片

开始操作

环境创建

1
2
3
4
5
6
7
8
# 1. 创建环境
conda create -n tools_env python=3.8

# 2. 进入环境
conda activate tools_env

# 3. 安装 pyinstaller
pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple

编码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from ToolTip import ToolTip
import os
import time


class Application(tk.Tk):

def __init__(self):
super().__init__()
self.title("公众号:ZERO开发")
self.iconbitmap('logo.ico')
self.geometry("600x370") # 设置固定的窗口大小
self.resizable(False, False) # 禁止调整窗口大小
self.style = ttk.Style(self)
self.main_color = self.cget("bg")

self.style.configure("TEntry",
padding=6,
relief="flat",
background="#0078d7",
foreground="black",
font=("Arial", 12, "bold"))

self.style.configure("TLabel",
font=("Arial", 12, "bold"))

self.style.configure("TButton",
padding=6,
font=("Arial", 12))

self.create_widgets()

def create_widgets(self):
self.path_label = ttk.Label(self, text='绝对路径:')
self.path_label.grid(row=0, sticky=tk.W, pady=30, padx=20)

self.path = tk.StringVar()
self.path_entry = ttk.Entry(self, width=60, textvariable=self.path)
self.path_entry.grid(row=0, column=1, sticky=tk.E, pady=5)
ToolTip(self.path_entry, "电脑里的目录路径,如 D:\\3code\\6pytorch\pytorch_ai_demo")

self.rename_label = ttk.Label(self, text='修改名称:')
self.rename_label.grid(row=1, sticky=tk.W, pady=5, padx=20)

self.rename = tk.StringVar()
self.rename_entry = ttk.Entry(self, width=60, textvariable=self.rename)
self.rename_entry.grid(row=1, column=1, sticky=tk.E, pady=5)

self.msg_text = tk.Text(self, height=2, width=60, wrap='none') # 添加一个列表框来显示文件名
self.msg_text.grid(row=2, column=1, sticky=tk.W, pady=15)
self.msg_text.configure(bd=0, relief="solid", bg=self.main_color)
# self.msg_text.insert(tk.END, "这是要显示的文本。")

ttk.Button(self, text='确认修改', command=self.start_program).grid(row=3, column=1, sticky=tk.W, pady=20, padx=120)
ttk.Button(self, text='关于作者', command=self.about).grid(row=4, column=1, sticky=tk.W, padx=120)

def start_program(self):
print("绝对路径:{}, 重命名:{}". format(self.path.get(), self.rename.get()))

path = self.path.get()
rename = self.rename.get()

if path == "" or rename == "":
messagebox.showwarning("警告", "输入框不能为空!")
return

if os.path.isdir(path) == False:
messagebox.showwarning("警告", "绝对路径不正确!")
return

i = 0
# '该文件夹下所有的文件(包括文件夹)'
FileList = os.listdir(path)

# '遍历所有文件'
for files in FileList:
oldDirPath = os.path.join(path, files)

self.msg_text.delete(1.0, tk.END)
self.msg_text.insert(tk.END, oldDirPath)

# '如果是文件夹则递归调用'
if os.path.isdir(oldDirPath):
self.start_program(oldDirPath)

# '文件名'
fileName = os.path.splitext(files)[0]
# '文件扩展名'
fileType = os.path.splitext(files)[1]
fileType = fileType.lower()

newDirPath = os.path.join(path, rename + "_" + str(i) + fileType)

# '重命名'
os.rename(oldDirPath, newDirPath)
i += 1

messagebox.showinfo("信息", "操作完成!")

def about(self):
messagebox.showinfo("关于", "微信公众号:ZERO开发\r\n\r\n工具:批量修改文件1.0")

def quit_program(self):
self.destroy()


if __name__ == "__main__":
app = Application()
app.mainloop()

开始打包

pyinstaller -F -w Application.py -–icon=logo.ico
图片
这里我们希望打包是自己的图标就带上 icon,而且打开时不要出现黑色闪框就带上 w,当然后面打开 exe 要把 icon 放到与他同一级的目录中,尺寸上面已经说了,下面是参数说明。

1
2
3
4
5
6
参数说明:    
-–icon=图标路径
-F 打包成一个exe文件
-w 使用窗口,无控制台
-c 使用控制台,无窗口
-D 创建一个目录,里面包含exe以及其他一些依赖性文件

还有一个问题是,如果是修改了代码,需要反复多次打包,可以把项目前一次打包生成的生成的 spec 后缀文件删除即可。打包成功后,控制面包会显示 Building EXE from EXE-00.toc completed successfully,然后根目录的 dist 就是打包后的文件包,里面需要的文件图片等都在里面,后面用 Inno Setup Compiler 也就是对这个文件夹打包。
图片
图片

Inno Setup Compiler 操作

新建脚本,填写信息

图片

选择主程序和需要的文件

图片

设置名称和 icon

图片

选择导出位置 (前面还有协议等设置)

图片

运行脚本开始生成

图片

安装打开,安装目录里有自带卸载程序

图片

  • ✇ZERO开发
  • 如何用 Python 实现一个 “系统声音” 的实时律动挂件北桥苏
    前言应该是三年前,我用 Esp8266 和 ws2812 实现了一个音乐律动灯带。就是电脑播放音乐时,灯带会随着系统内部音乐播放的频率而闪动不同色彩的灯珠。而当时用来监听系统声音的工具是一个博主提供的,除了实时采集声音外还通过 UDP 传递数据到 Esp8266 上。而这次,我就自己用 Python 实现一下,不过不传数据,就采集后直接实时地在电脑上绘制波形动画,主要是用来作为 FL Studio 播放时的一个桌面小挂件。环境python3.8pyaudio0.2.14matplotlibpyaudio 简介pyaudio 是一个跨平台地音频 I/O 库,使用他可以在 Python 程序中进行播放,录音和生成 wav 文件等。需要注意的是,如果要使用 pyaudio 时,python 的版本最好在 3.7 以上,不然 pip 安装会报错。因为以下例子是获取系统内部声音,而 pyaudio 读取的音频流默认是麦克风,所以接下来介绍一下关于获取的设备列表信息。代码获取设备列表12345678# pyaudio实例audio = pyaudio.PyAudio()# 获取设备总数device
     

如何用 Python 实现一个 “系统声音” 的实时律动挂件

作者 北桥苏
2024年5月30日 18:13

前言

应该是三年前,我用 Esp8266 和 ws2812 实现了一个音乐律动灯带。就是电脑播放音乐时,灯带会随着系统内部音乐播放的频率而闪动不同色彩的灯珠。而当时用来监听系统声音的工具是一个博主提供的,除了实时采集声音外还通过 UDP 传递数据到 Esp8266 上。

而这次,我就自己用 Python 实现一下,不过不传数据,就采集后直接实时地在电脑上绘制波形动画,主要是用来作为 FL Studio 播放时的一个桌面小挂件。
图片

环境

  • python3.8

  • pyaudio0.2.14

  • matplotlib
    图片

    pyaudio 简介

    pyaudio 是一个跨平台地音频 I/O 库,使用他可以在 Python 程序中进行播放,录音和生成 wav 文件等。需要注意的是,如果要使用 pyaudio 时,python 的版本最好在 3.7 以上,不然 pip 安装会报错。因为以下例子是获取系统内部声音,而 pyaudio 读取的音频流默认是麦克风,所以接下来介绍一下关于获取的设备列表信息。

    代码获取设备列表

    1
    2
    3
    4
    5
    6
    7
    8
    # pyaudio实例
    audio = pyaudio.PyAudio()
    # 获取设备总数
    device_count = audio.get_device_count()
    # 根据设备索引获取设备详细信息
    for i in range(p.get_device_count()):
    devInfo = p.get_device_info_by_index(i)
    print(devInfo)

    图片

    设备信息参数介绍

  • index: 设备的索引号,通常用于标识系统中的设备顺序。

  • structVersion: 结构版本号,用于表示这个数据结构的版本。

  • name: 设备的名称,这里是 “Microsoft 声音映射器 - Input”。

  • hostApi: 主 API 的标识符,通常用于表示该设备属于哪个 API 或系统。

  • maxInputChannels: 设备支持的最大输入通道数,这里是 2,表示设备支持 2 个输入通道。

  • maxOutputChannels: 设备支持的最大输出通道数,这里为 0,表示该设备没有输出通道。

  • defaultLowInputLatency: 默认的低输入延迟,以秒为单位,这里是 0.09 秒。

  • defaultLowOutputLatency: 默认的低输出延迟,这里是 0.09 秒。

  • defaultHighInputLatency: 默认的高输入延迟,这里是 0.18 秒。

  • defaultHighOutputLatency: 默认的高输出延迟,这里是 0.18 秒。

  • defaultSampleRate: 默认的采样率,这里是 44100.0 赫兹,这是 CD 质量的音频标准采样率。
    图片

    开始操作

    开启立体声混音权限

    打开电脑设置 - 系统 - 声音 - 管理声音设备 - 立体声混响,点击启用。
    图片
    图片

    设置设备索引号

    打开立体声混音后,通过 pyaudio 获取设备列表,找到带有 “立体声混音” 的名称,和 hostApi 为 0 的,hostAPI = 0 表明是 MME 设备。然后拿到该设备索引号,打开音频流时指定该内录设备序号。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def findInternalRecordingDevice(p):
    # 要找查的设备名称中的关键字
    target = '立体声混音'
    # 逐一查找声音设备
    for i in range(p.get_device_count()):
    devInfo = p.get_device_info_by_index(i)
    print(devInfo)
    if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
    # print('已找到内录设备,序号是 ',i)
    return i
    print('无法找到内录设备!')
    return -1

    全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import pyaudio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import wave

FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
CHUNK = 4096
# CHUNK = 1024
WAVE_OUTPUT_FILENAME = 'audio_output.wav'

# 获取内录设备序号,在windows操作系统上测试通过,hostAPI = 0 表明是MME设备
def findInternalRecordingDevice(p):
# 要找查的设备名称中的关键字
target = '立体声混音'
# 逐一查找声音设备
for i in range(p.get_device_count()):
devInfo = p.get_device_info_by_index(i)
print(devInfo)
if devInfo['name'].find(target) >= 0 and devInfo['hostApi'] == 0:
# print('已找到内录设备,序号是 ',i)
return i
print('无法找到内录设备!')
return -1
  • ✇ZERO开发
  • 后端搞 Cocos 小游戏开发的三点避坑指北北桥苏
    前言先说一下我为什么要弄小游戏吧,首先无关工作,也无关兴趣,就只是想在副业里探索一下。没错就是做一个单机的小游戏上架到平台试一下水(薅广告费),不过说实话入局有点晚。 早在 2019 年的时候,我也折腾过白鹭引擎还弄过小 demo,当时上架平台也简单。但是不知道为什么那时不顺手发布一下,录了个视频就没再管了(还是太年轻)。现在好了白鹭引擎倒了,而我也才意识到写文章做视频并不是我的强项。 尽管现在大佬们都在 All in AI,但我还是把一个方向定在了小游戏上。选引擎二选一,挑了 Cocos Creator,之所以有下面的几个坑点,其根本原因是我没有系统性看他们的文档,所以记录一下以便后期捡起。坑点脚本引入方式这个问题是我在 Cocos Creator 资源管理器里,创建脚本时选的 js,而代码里却用了 import 的语法导致还排查了一段时间(离大谱),但下面的花括号还是要值得注意。12import {util} from "./util";import startPanel from "./startPanel";使用 {} 的 import 允许你导入模块中的特定导出项
     

后端搞 Cocos 小游戏开发的三点避坑指北

作者 北桥苏
2024年5月30日 17:30

前言

先说一下我为什么要弄小游戏吧,首先无关工作,也无关兴趣,就只是想在副业里探索一下。没错就是做一个单机的小游戏上架到平台试一下水(薅广告费),不过说实话入局有点晚。

早在 2019 年的时候,我也折腾过白鹭引擎还弄过小 demo,当时上架平台也简单。但是不知道为什么那时不顺手发布一下,录了个视频就没再管了(还是太年轻)。现在好了白鹭引擎倒了,而我也才意识到写文章做视频并不是我的强项。

尽管现在大佬们都在 All in AI,但我还是把一个方向定在了小游戏上。选引擎二选一,挑了 Cocos Creator,之所以有下面的几个坑点,其根本原因是我没有系统性看他们的文档,所以记录一下以便后期捡起。

图片

坑点

脚本引入方式

这个问题是我在 Cocos Creator 资源管理器里,创建脚本时选的 js,而代码里却用了 import 的语法导致还排查了一段时间(离大谱),但下面的花括号还是要值得注意。

1
2
import {util} from "./util";
import startPanel from "./startPanel";
  • 使用 {} 的 import 允许你导入模块中的特定导出项,在这里是具体实例。

  • 不使用 {} 的 import 允许你导入模块的默认导出,在这里只是类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import gameManager from "./gameManager";
    import { util } from "./util";

    const {ccclass, property} = cc._decorator;

    @ccclass
    export default class uiManager extends cc.Component {

    private game: gameManager = null;

    @property(cc.Node)
    ninja: cc.Node = null;

    // 这里gameManager只是类型约束
    init(game: gameManager) {
    this.game = game
    }

    onLoad() {
    // 这里直接使用util的静态方法
    util.resize();
    }

    }

    组件的相关设置

    大部分组件的设置可以从文档里看到,如碰撞组件 BoxCollider,渲染组件里 Sprite(精灵组件设置图片等参数),但是如何要用到其自带滑块,并也用他的精灵图,位置在 internal 里(当时我找了老半天)。internal>image>default_progressbar_bg (进度条举例)
    图片

    音乐和音效

    添加背景音乐

    在 Main Camera 下添加一个空白节点,在该节点中添加 AudioSource 组件,Clip 就是从 assets 里拖入的 mp3 文件。最后将节点拖入脚本中(作为组件操作播放 / 停止)

    1
    2
    3
    4
    @property(cc.AudioSource)
    bgAudio: cc.AudioSource = null;

    this.bgAudio.play();

    图片
    图片

    添加操作音效

    在脚本中定义 AudioClip 属性,然后在 assets 中拖入 mp3 文件,最后在脚本中操作音效的播放与停止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    @property({
    type: cc.AudioClip
    })
    audioWin: cc.AudioClip = null;

    @property({
    type: cc.AudioClip
    })
    audioLose: cc.AudioClip = null;

    playSound(sName){
    switch(sName){
    case "click":
    // cc.audioEngine.play(this.audioClick, false, 1);
    case "win":
    cc.audioEngine.play(this.audioWin, false, 1);
    case "lose":
    cc.audioEngine.play(this.audioLose, false, 1);
    break;
    }
    }

    报错问题

    给游戏加了开始的背景音乐和操作音效后,用编辑器运行一切正常。但是当打包成某节小游戏或某信小游戏后,发现声音直接出不来,在我不断调试也依次报了下面一堆错误。

cocos2d-js-min.js:1 Uncaught TypeError: this.bgAudio.play is not a function

Uncaught TypeError: this.bgAudio.play is not a functionUncaught TypeError: Cannot read properties of undefined (reading ‘playMusic’)

Uncaught TypeError: Cannot read properties of null (reading ‘play’)

cc.audioEngine 为 undefined

图片
一开始我以为是引擎版本原因,切换几次后发现根本不是,因为把代码放到相同版本下的其他项目下是正常的。最主要的是打包后报的错误真不好排查,导致在这个问题上花了很多时间。最后在比较打包后的 js 文件,才怀疑是不是有些引擎里的模块没搭建来,顺着这个思路果真是音乐音效的模块被我关了,前面我还一直以为是 this 指向那里的代码有问题。
图片
解决方法就是在构造发布下面的 “项目设置”,勾选 Audio 和 AudioSource 然后再打包就可以了。其实创建项目时,默认是全选的,但可能是我前期乱折腾去掉了几项。

写在后面

后续可能还有一些关于小游戏或 Unity 游戏制作踩坑内容,包括小游戏的证书申请和上架流程等等,如果你也玩 Cocos Creator 和 Unity3D,欢迎一起交流谈论。

  • ✇ZERO开发
  • 三种方式,浅谈 Cocos Creator 的动画添加北桥苏
    前言虽然 Cocos 的官方文档对动画系统做了较详细的介绍,但是对于刚接触的同学(比如我)来说还是不太友好。尽管如此,我就按文档加社区帖子一起实践了一下。为了方便忘记后能快速捡起,所以就用我的方式结合使用场景,简单介绍一下 Cocos Creator 动画添加的三种方式。属性动画这个是 Cocos Creator 动画系统自带的一种对节点进行标准位移、旋转、缩放动画操作。可以用来制作一些按钮加亮,引导之类的业务型动画。创建节点并挂载 “Animation” 组件添加组件 > 其他组件 > Animation,然后打开动画编辑器,再点击 “新建 Clip 文件”,保存后放在 “assets” 下 “animations”,后缀为.anim 的文件。动画编辑进入编辑后,找到属性列表,点击 “Add Property”,选择列表的 “position,width,coclor” 等属性,点击右侧菜单按钮,可以插入关键帧,删除关键帧,清空关键帧等,添加一帧就可以在属性检查器对应节点的属性进行调节。挂载动画剪辑将已经编辑好的动画剪辑文件 (.anim 后缀),拖入到节点动画组件的 a
     

三种方式,浅谈 Cocos Creator 的动画添加

作者 北桥苏
2024年5月30日 17:13

前言

虽然 Cocos 的官方文档对动画系统做了较详细的介绍,但是对于刚接触的同学(比如我)来说还是不太友好。尽管如此,我就按文档加社区帖子一起实践了一下。为了方便忘记后能快速捡起,所以就用我的方式结合使用场景,简单介绍一下 Cocos Creator 动画添加的三种方式。

图片

属性动画

这个是 Cocos Creator 动画系统自带的一种对节点进行标准位移、旋转、缩放动画操作。可以用来制作一些按钮加亮,引导之类的业务型动画。

图片

创建节点并挂载 “Animation” 组件

添加组件 > 其他组件 > Animation,然后打开动画编辑器,再点击 “新建 Clip 文件”,保存后放在 “assets” 下 “animations”,后缀为.anim 的文件。
图片

动画编辑

进入编辑后,找到属性列表,点击 “Add Property”,选择列表的 “position,width,coclor” 等属性,点击右侧菜单按钮,可以插入关键帧,删除关键帧,清空关键帧等,添加一帧就可以在属性检查器对应节点的属性进行调节。
图片

图片

挂载动画剪辑

将已经编辑好的动画剪辑文件 (.anim 后缀),拖入到节点动画组件的 animation-clip 或 Default Clip 中。4. 脚本控制创建 ts 文件,将以下代码的脚本挂载到与动画相同的节点上(当然也可以制作预设体)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

onLoad () {
var anim = this.getComponent(cc.Animation);
// start_btn_dance 动画剪辑名称
anim.play('start_btn_dance');
}

start () {

}

// update (dt) {}
}

序列帧动画

帧动画也是 Cocos Creator 自带的编辑功能,就是在指定时间内循环各种动作或样式的图片,当然前期要准备好序列帧图片放到 assets 下。

创建 Animation 组件和动画剪辑

这部分和上面的属性动画操作一样
图片

动画编辑

这里在属性列表 Add Property 要选择 “cc.Sprite.spriteFrame”,然后将资源里的序列图片一张一张放入关键帧里。
图片

脚本控制

如果只是用于播放动画的和上面的也一样,但是动画事件需要分开说一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

onLoad () {
// 获取当前节点动画组件
var anim = this.getComponent(cc.Animation);
// 播放指定动画剪辑
anim.play('monster');

//this.node.on('onAnimCompleted', this.onAnimCompleted, this);
}

// 动画事件,接收两个参数
onAnimCompleted(num, str) {
console.log("start anim completed end~");
console.log(num);
console.log(str);
//console.log('onAnimCompleted: param1[%s], param2[%s]', num, string);
//console.log('onAnimCompleted: this is a test event12345' + num);
}
}

动画事件

确切的说应该是动画帧事件,就是在指定帧上添加一个事件(可以预留参数),当播放到该帧时触发。当前触发是在脚本里控制,这种一般用来做比如一个角色击杀时,要触发一个大招特效动画等。
图片

第三方工具动画

通过第三方的工具制作动画后导入到 Cocos Creator, 官方提供对 Spine 和 DragonBones 的支持。下面以 Spine 为例,从工具内导出,到 Cocos 脚本控制进行演示。

Spine 导出

可以直接用工具提供的示例,然后选择导出,注意是 json 格式文件。
图片

图片

Cocos Creator 导入

将上面从 Spine 导出的三个文件整成一文件夹放入 cocos 项目下 assets 的资源下,然后找到后缀 json 文件拖入层级管理器中。
图片

脚本控制

因为在 Spine 已经做好了动画,皮肤和帧事件,所以脚本也就是对动画的播放,操作换肤和事件回调等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const {ccclass, property} = cc._decorator;

@ccclass
export default class NewClass extends cc.Component {

onLoad () {
var anim = this.getComponent(sp.Skeleton);

// 清空动画管道
//anim.clearTracks();

// 添加动作
anim.addAnimation(0, 'run', true, 0);
/*anim.addAnimation(0, 'walk', false, 0);
anim.addAnimation(0, 'jump', false, 0);
anim.addAnimation(0, 'idle', false, 0);
anim.addAnimation(0, 'head-turn', false, 0);
anim.addAnimation(0, 'fall', false, 0);
anim.addAnimation(0, 'crouch', false, 0);
anim.addAnimation(0, 'attack', false, 0);*/

// 停止动画
/*let SpEnt: sp.spine.TrackEntry = anim.setAnimation(0, 'run', false);
SpEnt.animationStart = SpEnt.animationEnd;*/

// 换肤
//anim.setSkin("default");

// 监听动画开始
anim.setStartListener(function () {
console.log("animate start~");
}.bind(this));

// 监听动画结束
anim.setCompleteListener(function () {
console.log('animater end~');
}.bind(this));

}

}

图片

  • ✇ZERO开发
  • 初探 Cocos Creator: 碰撞与物理系统北桥苏
    前言不知道你刚开始玩碰撞时,会不会遇到始终无法触发碰撞事件?玩物理系统时,自由落体的刚体会穿过 “地面” 刚体等情况?没错我全都遇到过,那么下面我就用红蓝色方块,简单实战一下 Cocos Creator 的碰撞与物理系统。场景创建场景很简单,一个白色背景,两个红蓝色玩家,和一个绿色大草地。创建的方式也很简单,全部采用 Sprite 单色。节点创建层级管理器 ->Canvas 右键 -> 创建节点 -> 创建渲染节点 ->Sprite(单色)。颜色填充在属性检查器,找到 Node 下的 Color,选择色盘里的一颜色即可。分组由于物理和碰撞中都要用到,这里就提前给两个玩家和绿草地创建分组并分配好。在属性检查器的 Node 中,找到 Group 点击编辑再添加,如下图。碰撞匹对将三个分组进行碰撞的匹对,一定要勾选这个,不然后面测试碰撞无法触发回调,而是直接穿过另一个物体。碰撞系统测试碰撞组件添加碰撞组件有三种,Box(盒状)、Circle(圆形)、Polygon(多边形),可以根据不同的物体形状选择对应组件类型,比如像赛车的就可以选盒状,合成西瓜的那种就可以选圆形。
     

初探 Cocos Creator: 碰撞与物理系统

作者 北桥苏
2024年5月30日 16:40

前言

不知道你刚开始玩碰撞时,会不会遇到始终无法触发碰撞事件?玩物理系统时,自由落体的刚体会穿过 “地面” 刚体等情况?没错我全都遇到过,那么下面我就用红蓝色方块,简单实战一下 Cocos Creator 的碰撞与物理系统。
图片

场景创建

场景很简单,一个白色背景,两个红蓝色玩家,和一个绿色大草地。创建的方式也很简单,全部采用 Sprite 单色。节点创建层级管理器 ->Canvas 右键 -> 创建节点 -> 创建渲染节点 ->Sprite(单色)。
图片

颜色填充

在属性检查器,找到 Node 下的 Color,选择色盘里的一颜色即可。分组由于物理和碰撞中都要用到,这里就提前给两个玩家和绿草地创建分组并分配好。在属性检查器的 Node 中,找到 Group 点击编辑再添加,如下图。
图片

碰撞匹对

将三个分组进行碰撞的匹对,一定要勾选这个,不然后面测试碰撞无法触发回调,而是直接穿过另一个物体。
图片

碰撞系统测试

碰撞组件添加

碰撞组件有三种,Box(盒状)、Circle(圆形)、Polygon(多边形),可以根据不同的物体形状选择对应组件类型,比如像赛车的就可以选盒状,合成西瓜的那种就可以选圆形。在层级管理器中选中节点,进入属性检查器,添加组件,选择碰撞组件,Box Collider。
图片

参数介绍(Box)

  • Tag: 用于给在同一节点下,标识不同碰撞组件的

  • Offset: 碰撞的中心点位置,用于给碰撞范围定位

  • Size: 默认是物品节点的大小,其实是物体碰撞的范围大小
    图片
    脚本测试创建脚本,开启碰撞监听和碰撞范围绘制 Debug,update 中添加红色方块向右移动,设置碰撞产生的回调。最后拖入节点的属性面板中,前提相关物品都添加了碰撞组件,并且也勾选了碰撞匹对。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    const {ccclass, property} = cc._decorator;

    @ccclass
    export default class NewClass extends cc.Component {

    onLoad() {

    }

    start() {
    // 碰撞系统(绘制和监听开启)
    var manager = cc.director.getCollisionManager();
    manager.enabled = true;
    manager.enabledDebugDraw = true;
    manager.enabledDrawBoundingBox = true;
    }

    update(dt) {
    this.node.x += dt * 50;
    }

    /**
    * 当碰撞产生的时候调用
    * param {Collider} other 产生碰撞的另一个碰撞组件
    * param {Collider} self 产生碰撞的自身的碰撞组件
    */
    onCollisionEnter(other, self) {
    console.log("red_collision_enter_1");
    }

    /**
    * 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用
    * @param {Collider} other 产生碰撞的另一个碰撞组件
    * @param {Collider} self 产生碰撞的自身的碰撞组件
    */
    onCollisionStay(other, self) {
    console.log("red_collision_stay_2");
    }

    /**
    * 当碰撞结束后调用
    * @param {Collider} other 产生碰撞的另一个碰撞组件
    * @param {Collider} self 产生碰撞的自身的碰撞组件
    */
    onCollisionExit(other, self) {
    console.log("red_collision_exit_3");
    }

    }

    物理系统测试

    物理碰撞组件添加

    选择物理组件下的 Box(添加组件 -> 物理组件 ->Collider->Box),碰撞 + 刚体。参数就不介绍了,在编辑器里悬浮文字就可以看到用法描述,不过 刚体(RigidBody)的 “Type” 需要注意一下。
    图片

    脚本测试

    脚本中开启物理系统才可以看到自由落体效果,而碰撞监听需要在属性检查器的刚体中 “Enabled Contact Listen” 开启。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    const {ccclass, property} = cc._decorator;

    @ccclass
    export default class NewClass extends cc.Component {

    onLoad() {
    // 开启物理系统
    cc.director.getPhysicsManager().enabled = true;
    // 物理物品绘制
    /*cc.director.getPhysicsManager().debugDrawFlags = cc.PhysicsManager.DrawBits.e_aabbBit |
    cc.PhysicsManager.DrawBits.e_pairBit |
    cc.PhysicsManager.DrawBits.e_centerOfMassBit |
    cc.PhysicsManager.DrawBits.e_jointBit |
    cc.PhysicsManager.DrawBits.e_shapeBit;*/
    }

    start() {}

    update(dt) { }


    /**刚体的属性Enabled Contact Listen必须开启**/
    // 只在两个碰撞体开始接触时被调用一次
    onBeginContact(contact, selfCollider, otherCollider) {
    console.log("~collider start1111111111111111111111~");
    }

    // 只在两个碰撞体结束接触时被调用一次
    onEndContact(contact, selfCollider, otherCollider) {
    console.log("~collider end2222222222222222222222222~");
    }

    // 每次将要处理碰撞体接触逻辑时被调用
    onPreSolve(contact, selfCollider, otherCollider) {
    console.log("~pre collider3333333333333333333333333~");
    }

    // 每次处理完碰撞体接触逻辑时被调用
    onPostSolve(contact, selfCollider, otherCollider) {
    console.log("~solve44444444444444444444444444444444~");
    }

    }

图片

  • ✇ZERO开发
  • hexo实战:(一)零成本搭建个人独立博客北桥苏
    前言很多平台都能写博客还有创作激励,为什么我又要搭一个?为什么这次要选择用Hexo框架?对应的原因是流量自由和省钱,第一个,很多平台能写但不是都有收益,而且平台有自身的规则,比如会屏蔽一些推广类信息。如果我哪天做了一产品,是没办法直接用平台博客的方式硬推的,至少放码和链接不行。第二个用Hexo搭到GitHub上,我可以不用买服务器,毕竟现在也还没有想法要做一个什么样的东西。总之,有个独立博客,相比平台博客在内容约束上更自由。有想法了就发出来,做了游戏什么的就放出来,md的文章以后要存储备份可以转word,更方便在副业的路上轻装探索。Hexo介绍Hexo是一款基于Node.js的开源静态博客框架,用于快速、简单且高效地搭建个人或团队的静态博客网站。说白了他是一个静态网站生成器,我们新增文章只需要编辑md文件,通过运行命令再生成像html的静态文件。其实我挺早听过Hexo,但一直没用,直到我cms搭的博客别人挂马后。我关闭网站全面使用平台博客,但经种种原因,我又萌生了建独立博客的想法,并且这次打算走长期路线,第一步先记录上次Hexo搭建过程仅供参考。流程本地构建Hexo配置 GitHub代
     

hexo实战:(一)零成本搭建个人独立博客

作者 北桥苏
2024年5月30日 16:13

前言

很多平台都能写博客还有创作激励,为什么我又要搭一个?为什么这次要选择用Hexo框架?

对应的原因是流量自由和省钱,第一个,很多平台能写但不是都有收益,而且平台有自身的规则,比如会屏蔽一些推广类信息。如果我哪天做了一产品,是没办法直接用平台博客的方式硬推的,至少放码和链接不行。第二个用Hexo搭到GitHub上,我可以不用买服务器,毕竟现在也还没有想法要做一个什么样的东西。

总之,有个独立博客,相比平台博客在内容约束上更自由。有想法了就发出来,做了游戏什么的就放出来,md的文章以后要存储备份可以转word,更方便在副业的路上轻装探索。

Hexo介绍

Hexo是一款基于Node.js的开源静态博客框架,用于快速、简单且高效地搭建个人或团队的静态博客网站。说白了他是一个静态网站生成器,我们新增文章只需要编辑md文件,通过运行命令再生成像html的静态文件。其实我挺早听过Hexo,但一直没用,直到我cms搭的博客别人挂马后。我关闭网站全面使用平台博客,但经种种原因,我又萌生了建独立博客的想法,并且这次打算走长期路线,第一步先记录上次Hexo搭建过程仅供参考。

流程

  • 本地构建Hexo
  • 配置 GitHub
  • 代码上传与备份
  • 个性化域名绑定

环境搭建

Hexo的博客,不管是页面的添加还是构建都是通过npm命令,所以最基本要把Node安装了。项目部署和部署的地方又在GitHub,所以Git也要提前装好。这里强调一下,运行Hexo命令最好在Git的GUI窗口里,不要用Windows的cmd,坑多,关于Node和Git环境安装就跳过了。

构建Hexo

安装Hexo

1
npm install -g hexo

检验Hexo是否安装

1
hexo -v

项目构建

1
2
3
4
5
6
7
8
# 创建一blog项目
hexo init blog

# 进入项目
cd blog

# 安装依赖包
npm install

其他操作

1
2
3
4
5
#右键 Git Bush,用户项目自动化部署
npm install hexo-deployer-git --save

hexo _config.yml中文乱码问题
用Notepad++等编辑器打开,选择 “编码” -> “转为UTF-8编码”

安装项目开发者操作包.jpg

项目预览

1
2
3
4
5
6
7
8
# 清理旧的静态文件
hexo clean

# 生成静态文件
hexo g

# 运行预览项目
hexo s

Snipaste_2024-05-23_19-55-21.jpg
Snipaste_2024-05-23_19-57-44.jpg

配置 GitHub

这里虽然只是写的配置GitHub,其实包含了本地用Git生成SSH密钥对,和GitHub上公钥添加,提交Token的获取,以及Pages服务的开启。还有仓库名的建立也有讲究,下面就从这些点开始逐一展开。

建立仓库

仓库名是个什么讲究法呢?就是格式要保持 “github账号名.github.io”, 比如我的账户名是“z11r00”,那么仓库就要建成 “z11r00.github.io”。如果不这样,最后等用Hexo部署完毕后,初始的域名可能就是 “github账号名.github.io/仓库名”,会在后面多了一个路径,而且hexo的config没有设置好连css都加载不出来。
image.png

设置SSH

GitHub 的 SSH(Secure Shell)主要用于安全地连接到 GitHub 服务器,其实就是平时Git常用的克隆、拉取、提交、推送等操作。而好处除了安全外,就是提交代码不用每次都要输入账号密码。如果安装了hexo-deployer-git的话,只需一个命令就可以完成项目从静态构建到自动部署。

生成SSH密钥对

打开Git面板,输入 “ssh-keygen -t rsa -C GitHub账户”, 这里的GitHUb账户是你登陆GitHub的邮箱等方式。生成后找到目录下的id_rsa.pub(公钥),用编辑器打开并复制。

实际生成id_rsa文件.jpg

GitHub中添加SSH公钥

登陆GitHub网站,点击个人头像,找到 “Settings”->”SSH and GPG keys”后,点击 “New SSH keys”,最后将前面复制的很长的公钥字符串粘贴到Key文本框中。

github添加ssh.jpg
github添加ssh key.jpg
github粘贴ssh.jpg

验证设备是否可连接

通过 “ssh -T git@github.com” 命令,验证当前的设备是否可以连接。
校验ssh是否绑定.jpg

获取提交的token

虽然说SSH连接不用一直登陆,但是初次还要要的。而且不光要输入账号密码还需要一个提交用的Token,没有这个,运行hexo d一直提示Logon failed, 这个后面会集中列出报错事故的。

获取token,还是进入“Settins”,找到 “Developer settings”->“Personal access tokens”->“Tokens(classic)”, 然后设置备注和过期时间。最主要的权限要勾选 “workflow”、“gist”、“user”,点击 “Generate”按钮,生成的”ghp_”为前缀的就是token了,复制并保存下来。

提交仓库失败1.jpg
提交仓库失败3.jpg
提交仓库失败4.jpg
提交仓库失败5.jpg

项目部署

项目部署的其实是将Hexo生成的静态文件提交到github上,后期添加文章也就是markdown文件,继续重新生成,重新部署。而项目的代码却在本地,虽然代码量不多,但是里面的package.json和_config.yml,以及用到的主题包,还是有必要保存一下。所以我这里的方法是,静态部署项目放在一个公有仓库,而项目源代码单独提交到一私有仓库下。

修改配置

打开项目根目录下的_config.yml,主要添加仓库的地址,其他的配置下篇再介绍。因为hexo很多玩法更多的是配置和各种依赖,比如可以添加统计、留言、修改主题、站内搜索、甚至广告位等等。
image.png

静态文件生成

通过 “hexo clean” 先清理,然后执行 “hexo g” 重新生成。

将博客编译为静态文件项目.jpg

开始部署

通过命令 “hexo d”,开始部署项目,如果第一次运行,就需要前面提到的输入github账号密码。确认Login后会再次弹一个窗口就是输入Token了,最后完成部署。这里需要注意一下的是,最好用Git面板运行命令,如果是cmd很有可能第二次的窗无法弹出,亲测坑点。

页面上传.jpg
image.png

访问测试

部署完成就进入仓库下,除了查看提交的代码外,打开仓库下的 “Settings”,找到 “Pages”。

提交仓库失败6.jpg

个性化域名绑定

有一个git域名其实也不错,为什么还要买一个去绑定呢?一个是我本身这域名就空在这里,第二个是可以给博客增加一点IP点,第三个是更利于某度的爬取。我看其他博主说国内一些搜索引擎屏蔽了github的pages博客,当然我没有验证过,下次也要做SEO相关的时候可以测试一下。

获取IP地址

要想知道当前项目部署的独立IP地址,只需要ping一下github分配的域名,比如我直接 “ping z11r00.github.io”就可以看到了。

IP获取.jpg

域名解析

进入购买的域名控制台,给自己的域名添加两个解析,一个指向旧域名,一个解析到前面获取到的IP地址。

域名解析.jpg

项目绑定域名

进入仓库的“Settings”下,点击 “Pages”,找到 “Custom domain”,将自己的域名粘贴进文本框保存。然后在项目的“source” 新建CNAME(没有后缀), 打开文件粘贴域名,比如我的zerofc.cn,最后再重新部署项目访问。

image.png

报错汇总

1.extends includes/layout.pug block content include ./includes/mixins/post-ui.pug #recent-posts.recent-posts +postUI include includes/pagination.pug
项目启动后报的这个,是因为缺失了一些依赖包,上面的是没有 pug 以及 stylus 的渲染器,解决方法就是安装对应的依赖。

1
npm install hexo-renderer-pug hexo-renderer-stylus --save

2.运行后打开hexo博客上的中文乱码
解决方法是用Notepad++等编辑器打开,选择 “编码” -> “转为UTF-8编码”。

3.unable to access ‘https://github.com/z11r00/z11r00.github.io.git/‘: Empty reply from server
出现这个报错的是项目初次部署时,原因就是没有设置Token,解决方法就是前面“配置 GitHub”的“提交Token获取”部分。

4.unable to access ‘https://github.com/z11r00/z11r00.github.io.git/‘: The requested URL returned error: 403
出现这个一般就是间接性打开GitHub网站,毕竟是国外网站,多刷新几下,多请求几下就可以了。

写在后面

既然博客已经搭起来了,后面还有分两步走,凑成三部曲。第一个是Hexo的各种配置和插件的玩法,第二个是Hexo博客SEO相关的内容,如果我那个小游戏软著下来了,可能博客的事情就会延后一点。

  • ✇ZERO开发
  • hexo实战:(三)独立博客运营总结北桥苏
    前言通过前面两个步骤,完成了静态博客从搭建到基本功能添加和界面优化。那么,这次就要介绍一下搭在GitHub上的静态博客如何运营推广。也就是如何让网站被各大搜索引擎收录?如何提高网站权重,提高收录量?网站收录平台选择站长相关的平台有:某度站长工具、360站长平台、搜狗资源平台、必应网站管理员工具、谷歌站长工具等。列出的五个平台,可以按自身情况提交,提交方法也大同小异,以下以某度为例。添加网站添加某度、360、某狗等引擎收录,进入某度的站长工具,点击添加网站。流程就三步,输入网站,设置站点属性,最后验证网站。而验证网站又有三种方式,分别是文件验证、HTML标签验证、CNAME验证,我这里选择文件验证。选择文件验证后,下载baidu_verify_xxxx.html文件,然后将该文件放入theme/主题包名/source/根目录下。重新编译生成静态文件,而验证文件会被原封不动地复制到编译后博客根目录地public下,最后部署就完成验证了。链接提交进入站长工具的 “普通收录”,这里我们可以向搜索引擎主动提交网站的链接地址。其中提交的方式有三种,分别是API提交、sitemap、手动提交,而最方
     

hexo实战:(三)独立博客运营总结

作者 北桥苏
2024年5月30日 16:13

前言

通过前面两个步骤,完成了静态博客从搭建到基本功能添加和界面优化。那么,这次就要介绍一下搭在GitHub上的静态博客如何运营推广。也就是如何让网站被各大搜索引擎收录?如何提高网站权重,提高收录量?

网站收录

平台选择

站长相关的平台有:某度站长工具、360站长平台、搜狗资源平台、必应网站管理员工具、谷歌站长工具等。列出的五个平台,可以按自身情况提交,提交方法也大同小异,以下以某度为例。

添加网站

添加某度、360、某狗等引擎收录,进入某度的站长工具,点击添加网站。流程就三步,输入网站,设置站点属性,最后验证网站。而验证网站又有三种方式,分别是文件验证、HTML标签验证、CNAME验证,我这里选择文件验证。

选择文件验证后,下载baidu_verify_xxxx.html文件,然后将该文件放入theme/主题包名/source/根目录下。重新编译生成静态文件,而验证文件会被原封不动地复制到编译后博客根目录地public下,最后部署就完成验证了。

image-20240606113057594

image-20240606135833994

链接提交

进入站长工具的 “普通收录”,这里我们可以向搜索引擎主动提交网站的链接地址。其中提交的方式有三种,分别是API提交、sitemap、手动提交,而最方便快捷的就是给引擎提供sitemap,也就是网站地图,里面按固定格式放满网站上需要被收录的链接。但是某度对于这种方式有限制,需要站点达到一定量才可以使用sitemap,当然也不妨碍我们先做出地图。

image-20240607091525644

安装地图生成插件

以下两个插件都可以生成sitemap,但是generator-sitemap相比另一个多了一种txt格式。

1
2
npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save
配置url

设置这个可以在sitemap中指定网站的地址,如果绑定了个性化域名就填写改域名。不然放入github自带域名,可能被国内引擎屏蔽,也可能由自带域名重定向个性化域名,同样都影响网站的收录。

1
2
3
4
url: https://www.zerofc.cn
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:

image-20240607105629724

配置地图插件

打开hexo的_config.yml添加下面对应插件的参数,用于配置sitemap文件的保存位置。其中上面的插件可通过txt和xml决定需要的格式。

1
2
3
4
5
6
7
8
# generator-sitemap插件
sitemap:
#path: sitemap.txt
path: sitemap.xml

# hexo sitemap百度网站地图
baidusitemap:
path: baidusitemap.xml
清理与生成

插件完毕后再重新编译打包的同时,在public下就会生成sitemap的xml文件了。

1
hexo clean && hexo g

image-20240606133915299

创建robots文件

robots.txt 文件是一个简单的文本文件,用于指示搜索引擎爬虫如何访问和索引您的网站。创建后放入hexo主题包下的source,这样每次打包后都会在静态项目的根目录下,以下是一个简单的robots.txt文件配置。

1
2
3
User-agent: *  
Disallow: /video/
Disallow: /archives/

上述示例告诉所有搜索引擎爬虫(User-agent: *)不要索引 /video//archives/ 目录下的内容。

image-20240607145358947

错误合集

1
2
The file will have its original line endings in your working directory.
On branch master

原因

windows下的换行符是CRLF而Unix的换行符格式是LF。git默认支持LF。

解决方法

1
2
3
git rm -r --cached .

git config --global core.autocrlf false

抱团友情链接

最好是有收录或网站权重高的,欢迎大家找我互链!

添加广告联盟

这个后续等流量上来了再更新。

其他优化

markdown中插入视频

启动源代码模式,输入下面代码后再切回。

image-20240606204325844

1
2
3
4
<video width="320" height="240" controls>  
<source src="https://www.zerofc.cn/zd_image_bed/img/11.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
  • ✇ZERO开发
  • hexo实战:(二)个人独立博客豪华装修合集北桥苏
    前言上次介绍了使用Hexo+GitHub Pages,零成本搭建一个专属自己的独立博客网站。我觉得那篇文章是没有入门门槛的,不管你是什么行业,只要想打造个人IP,又不太想受博客平台约束,那么读完后动手操作一下也能轻松完成。而这次呢,上篇也说了Hexo会出三篇内容,这里就要在前者基础上做进一步升级,将完成下面七个主要的博客常用功能。指标Hexo如何安装Butterfly主题并配置?Hexo如何创建页面和添加文章?Hexo如何添加第三方评论系统?Butterfly主题如何添加站内搜索?Butterfly主题如何添加百度统计?Butterfly主题如何添加文章置顶功能?Butterfly主题如何配置RSS和404页面?如何配合Typora完成md的同步与本地备份?主题添加与配置Hexo官网专门有一个栏目的主题列表,这里我选的 “butterfly”,首先拉取主题代码到themes目录下,然后在Hexo的配置中启动主题。拉取主题包1git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/b
     

hexo实战:(二)个人独立博客豪华装修合集

作者 北桥苏
2024年5月30日 16:13

前言

上次介绍了使用Hexo+GitHub Pages,零成本搭建一个专属自己的独立博客网站。我觉得那篇文章是没有入门门槛的,不管你是什么行业,只要想打造个人IP,又不太想受博客平台约束,那么读完后动手操作一下也能轻松完成。而这次呢,上篇也说了Hexo会出三篇内容,这里就要在前者基础上做进一步升级,将完成下面七个主要的博客常用功能。

指标

  • Hexo如何安装Butterfly主题并配置?
  • Hexo如何创建页面和添加文章?
  • Hexo如何添加第三方评论系统?
  • Butterfly主题如何添加站内搜索?
  • Butterfly主题如何添加百度统计?
  • Butterfly主题如何添加文章置顶功能?
  • Butterfly主题如何配置RSS和404页面?
  • 如何配合Typora完成md的同步与本地备份?

主题添加与配置

Hexo官网专门有一个栏目的主题列表,这里我选的 “butterfly”,首先拉取主题代码到themes目录下,然后在Hexo的配置中启动主题。

拉取主题包

1
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly

启动主题

1
theme: butterfly

image-20240601204144917

基础配置

基础配置主要是设置网站的标题、描述、SEO、菜单等项,下面我就列出hexo的config(根目录下_config.yml),和主题Butterfly的config(themes的Butterfly下_config.yml),并注释相关项的简介仅供参考。

hexo_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
title: ZERO开发                           #网站标题
subtitle: 一个独立开发者的博客 #网站副标题
description: 公众号:ZERO开发 #网站描述
keywords: 技术博客、独立开发者、PHP开发、Pthon开发、人工智能、物联网、游戏开发
author: 北桥苏 #您的名字
language: zh-CN #网站使用的语言
timezone: #网站时区。Hexo 默认使用您电脑的时区

# URL 网址
## 如果您的网站存放在子目录中,
## 例如 http://yoursite.com/blog,则请将您的 url
## 设为 http://yoursite.com/blog 并把 root 设为 /blog/。
url: http://z11r00.github.io
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:

# Directory 目录配置
source_dir: source #源文件夹,这个文件夹用来存放内容。
public_dir: public #公共文件夹,这个文件夹用于存放生成的站点文件。
tag_dir: tags #标签文件夹
archive_dir: archives #归档文件夹
category_dir: categories #分类文件夹
code_dir: downloads/code #nclude code 文件夹
i18n_dir: :lang #国际化(i18n)文件夹
skip_render: #跳过指定文件的渲染,您可使用 glob 表达式来匹配路径。

# Writing 文章
new_post_name: :title.md # 新建文章默认文件名
default_layout: post # 默认布局
titlecase: false # Transform title into titlecase
external_link: true # 在新标签中打开一个外部链接,默认为true
filename_case: 0 #转换文件名,1代表小写;2代表大写;默认为0,意思就是创建文章的时候,是否自动帮你转换文件名,默认就行,意义不大。
render_drafts: false #是否渲染_drafts目录下的文章,默认为false
post_asset_folder: false #启动 Asset 文件夹
relative_link: false #把链接改为与根目录的相对位址,默认false
future: true #显示未来的文章,默认false
syntax_highlighter: highlight.js
highlight: #代码块的设置
enable: true
line_number: true
auto_detect: false
tab_replace:
prismjs:
preprocess: true
line_number: true
tab_replace: ''

# Category & Tag 分类和标签的设置
default_category: uncategorized #默认分类
category_map: #分类别名
tag_map: #标签别名

# 全局日期格式化
date_format: YYYY-MM-DD
time_format: HH:mm:ss
updated_option: 'mtime'
pagination_dir: page #分页目录

## 插件index,用于显示分页和排序配置
index_generator:
path: ''
per_page: 5# 0.关闭分页功能 >0.每页条数
order_by:
top: -1# 置顶排序: -1.倒序 1.正序
date: -1# 日期排序: -1.倒序 1.正序

# 主题启动配置
theme: butterfly

# Deployment github部署配置
deploy:
type: git
repository: https://github.com/z11r00/z11r00.github.io
branch: main

##hexo-generator-search搜索插件配置
search:
path: search.xml
field: post
format: html
limit: 10000

## rss配置
feed:
type: atom
path: atom.xml
limit: 20

## rss位置
rss: /atom.xml

hexo_butterfly_config.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
nav:
logo: /img/logo.png # 导航栏左侧LOGO
display_title: true
fixed: true # 是否置顶导航栏

## 菜单图标配置
Home: / || fas fa-home
Archives: /archives/ || fas fa-archive
Tags: /tags/ || fas fa-tags
Categories: /categories/ || fas fa-folder-open
List||fas fa-list:
Music: /music/ || fas fa-music
Movie: /movies/ || fas fa-video
Link: /link/ || fas fa-link
About: /about/ || fas fa-heart

# Menu 菜单跳转配置
menu:
首页: / || fas fa-home
时间轴: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open
#清单||fa fa-heartbeat:
#音乐: /music/ || fas fa-music
#照片: /Gallery/ || fas fa-images
#电影: /movies/ || fas fa-video
友链: /link/ || fas fa-link
关于: /about/ || fas fa-heart

# Code Blocks (代碼相關)
# --------------------------------------
highlight_theme: light # darker / pale night / light / ocean / mac / mac light / false
highlight_copy: true # copy button
highlight_lang: true # show the code language
highlight_shrink: false # true: shrink the code blocks / false: expand the code blocks | none: expand code blocks and hide the button
highlight_height_limit: false # unit: px
code_word_wrap: false # 代码是否自动换行

# Social Settings (社交圖標設置)
social:
fab fa-github: https://github.com/z11r00 || Github || '#24292e'
fas fa-envelope: 2652364582@qq.com || Email || '#4a7dbe'
fas fa-rss: /atom.xml || RSS


# Image (圖片設置)
# --------------------------------------

# Favicon(網站圖標)
favicon: /img/favicon.png

# Avatar (頭像)
avatar:
img: /img/avatar.png
effect: false

# 是否禁用所有跳转页的顶部图片
disable_top_img: true

# 首页图
index_img: /img/index_img.jpg

# 所有页面的默认顶部图
default_top_img: /img/default_top_img.jpeg

# 归档(时间线)页面顶部图
archive_img: /img/archive_img.jpg

# 标签页面顶部图
tag_img:

# The banner image of tag page
# format:
# - tag name: xxxxx
tag_per_img:

# 分类页面顶部图
category_img:

# The banner image of category page
# format:
# - category name: xxxxx
category_per_img:

## 封面配置
cover:
# display the cover or not (是否顯示文章封面)
index_enable: true
aside_enable: true
archives_enable: true
# the position of cover in home page (封面顯示的位置)
# left/right/both
position: both
(當沒有設置cover時,默認的封面顯示)
default_cover:
- https://i.loli.net/2020/05/01/gkihqEjXxJ5UZ1C.jpg

# Replace Broken Images (替換無法顯示的圖片)
error_img:
flink: /img/friend_404.gif
post_page: /img/404.jpg

# 404 页面配置
error_404:
enable: true
subtitle: 'Page Not Found'
background: /img/404.jpg

## 文章配置
post_meta:
page: # Home Page
date_type: created # created or updated or both 主頁文章日期是創建日或者更新日或都顯示
date_format: date # date/relative 顯示日期還是相對日期
categories: true # true or false 主頁是否顯示分類
tags: false # true or false 主頁是否顯示標籤
label: true # true or false 顯示描述性文字
post:
date_type: both # created or updated or both 文章頁日期是創建日或者更新日或都顯示
date_format: date # date/relative 顯示日期還是相對日期
categories: true # true or false 文章頁是否顯示分類
tags: true # true or false 文章頁是否顯示標籤
label: true # true or false 顯示描述性文字

# 锚点配置
anchor:
# when you scroll, the URL will update according to header id.
auto_update: false
# Click the headline to scroll and update the anchor
click_to_scroll: false

# figcaption (圖片描述文字)
photofigcaption: false

# 复制功能的配置
# copyright: Add the copyright information after copied content (複製的內容後面加上版權信息)
copy:
enable: true # 是否开启网站复制权限
copyright:
enable: false # 是否开启复制版权信息添加
limit_count: 50 # 字数限制,当复制文字大于这个字数限制时,将在复制的内容后面加上版权信息

# Post
# --------------------------------------

# toc (文章的目錄配置)
toc:
post: true
page: false
number: true
expand: false
style_simple: false
scroll_percent: true

# 文章版权设置
post_copyright:
enable: true
decode: false
author_href:
license: CC BY-NC-SA 4.0
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/

# Sponsor/reward 文章打赏
reward:
enable: true
text: 打赏一下~
QR_code:
- img: /img/qrcode/wechat_trade.jpg
link:
text: 微信
- img: /img/qrcode/alipay_trade.jpg
link:
text: 支付宝

# 文章编辑器配置
# Easily browse and edit blog source code online.
post_edit:
enable: false
# url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/
# For example: https://github.com/jerryc127/butterfly.js.org/edit/main/source/
url:

# 文章推荐配置
related_post:
enable: true
limit: 6 # Number of posts displayed
date_type: created # or created or updated 文章日期顯示創建日或者更新日

# post_pagination (分頁)
# value: 1 || 2 || false
# 1: The 'next post' will link to old post
# 2: The 'next post' will link to new post
# false: disable pagination
post_pagination: 1

# Displays outdated notice for a post (文章過期提醒)
noticeOutdate:
enable: false
style: flat # style: simple/flat
limit_day: 500 # When will it be shown
position: top # position: top/bottom
message_prev: It has been
message_next: days since the last update, the content of the article may be outdated.

# Footer Settings(页尾设置)
# --------------------------------------
footer:
owner:
enable: true
since: 2017
custom_text: Copyright© ZERO开发-独立开发者的日常总结<br/><a href="https://beian.miit.gov.cn/" target="_blank">赣ICP备16002525号-1</a>
# copyright: true # Copyright of theme and framework
copyright: false


# aside (側邊欄)
# --------------------------------------

aside:
enable: true
hide: false
button: true
mobile: true # display on mobile
position: left # left or right
display:
archive: true
tag: true
category: true
card_author:
enable: true
description:
button:
enable: true
icon: fas fa-video
text: 关注我
link: https://space.bilibili.com/286666708/
card_announcement:
enable: true
content: 微信公众号:ZERO开发,致力于为猿友们提供有价值的内容
card_recent_post:
enable: true
limit: 5 # if set 0 will show all
sort: date # date or updated
sort_order: # Don't modify the setting unless you know how it works
card_categories:
enable: true
limit: 8 # if set 0 will show all
expand: none # none/true/false
sort_order: # Don't modify the setting unless you know how it works
card_tags:
enable: true
limit: 40 # if set 0 will show all
color: false
orderby: random # Order of tags, random/name/length
order: 1 # Sort of order. 1, asc for ascending; -1, desc for descending
sort_order: # Don't modify the setting unless you know how it works
card_archives:
enable: true
type: monthly # yearly or monthly
format: MMMM YYYY # eg: YYYY年MM月
order: -1 # Sort of order. 1, asc for ascending; -1, desc for descending
limit: 8 # if set 0 will show all
sort_order: # Don't modify the setting unless you know how it works
card_webinfo:
enable: true
post_count: true
last_push_date: true
sort_order: # Don't modify the setting unless you know how it works
card_post_series:
enable: true
series_title: false # The title shows the series name
orderBy: 'date' # Order by title or date
order: -1 # Sort of order. 1, asc for ascending; -1, desc for descending

# busuanzi count for PV / UV in site
# 訪問人數
busuanzi:
site_uv: true
site_pv: true
page_pv: true

# Time difference between publish date and now (網頁運行時間)
# Formal: Month/Day/Year Time or Year/Month/Day Time
runtimeshow:
enable: false
publish_date:

# Aside widget - 最新评论
newest_comments:
enable: true
sort_order: # Don't modify the setting unless you know how it works
limit: 6
storage: 10 # unit: mins, save data to localStorage
avatar: true

# Bottom right button (右下角按鈕)
# --------------------------------------

# Conversion between Traditional and Simplified Chinese (簡繁轉換)
translate:
enable: false
# The text of a button
default: 繁
# the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese)
defaultEncoding: 2
# Time delay
translateDelay: 0
# The text of the button when the language is Simplified Chinese
msgToTraditionalChinese: '繁'
# The text of the button when the language is Traditional Chinese
msgToSimplifiedChinese: '簡'

# Read Mode (閲讀模式)
readmode: true

# Local search (hexo-generator-search创建搜索)
local_search:
enable: true
# Preload the search data when the page loads.
preload: false
# Show top n results per article, show all results by setting to -1
top_n_per_article: 1
# Unescape html strings to the readable one.
unescape: false
CDN:

# Docsearch
docsearch:
enable: false
appId:
apiKey:
indexName:
option:

# Share System (分享)
# --------------------------------------
# Share.js
# https://github.com/overtrue/share.js
sharejs:
enable: true
sites: weibo,wechat,qq,facebook,twitter

# AddToAny
# https://www.addtoany.com/
addtoany:
enable: false
item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link

# Comments System (评论系统)
# --------------------------------------
# 评论配置
comments:
# Up to two comments system, the first will be shown as default
# Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk
use: gitalk # Valine,Disqus
text: true # Display the comment name next to the button
# lazyload: The comment system will be load when comment element enters the browser's viewport.
# If you set it to true, the comment count will be invalid
lazyload: true
count: false # Display comment count in post's top_img
card_post_count: false # Display comment count in Home Page

# disqus
# https://disqus.com/
disqus:
shortname:
apikey: # For newest comments widget

# Alternative Disqus - Render comments with Disqus API
# DisqusJS 評論系統,可以實現在網路審查地區載入 Disqus 評論列表,兼容原版
# https://github.com/SukkaW/DisqusJS
disqusjs:
shortname:
apikey:
option:

# livere (來必力)
# https://www.livere.com/
livere:
uid:

# gitalk
# https://github.com/gitalk/gitalk
gitalk:
client_id: Ov23…………1C6fM
client_secret: 4304…………44433f77352
repo: z11r00.github.io
owner: z11r00
admin: z11r00
option:

# Analysis (第三方统计配置)
# --------------------------------------

# Baidu Analytics
# https://tongji.baidu.com/web/welcome/login
baidu_analytics: 74270…………………………………………

# Advertisement
# --------------------------------------

# Google Adsense (谷歌廣告)
google_adsense:
enable: false
auto_ads: true
js: https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js
client:
enable_page_level_ads: true

# Verification (站長驗證)
# --------------------------------------

site_verification:
# - name: google-site-verification
# content: xxxxxx
# - name: baidu-site-verification
# content: xxxxxxx

创建菜单页面

页面包括标签页(tags)、分类页(categories)、友链页(link)、关于页(about),当然也可以自行添加,比如音乐电影之类。不过添加这种页面方式都大同小异,以下以标签页举例。

运行命令

1
hexo new page tags

编辑MD

运行命令后,会在source下根据butterfly模板生成对应的md文件,tags就是tags,不过要将md文件的type修改为对应的类型,类型见上。

1
2
3
title: 标签页
date: 2024-05-02 21:01:24
type: "tags"

image-20240601173015639

Page(页面)front-matter

1
2
3
4
5
6
7
8
title: 页面名称
date: 创建日期
type: (tags,link,categories这三个页面需要配置)
comments: (是否需要显示评论,默认true)
description: 用于SEO优化
top_img: (设置顶部图)
mathjax: (数学公式显示是否支持)
katex: (Tex公式显示是否支持)

创建文章

写文章,可以通过命令创建,也可以在source/_posts目录下,自行新建markedown文件,因为命令也是在_posts文件夹下新建。

运行命令

1
hexo new "文章的大标题"

Post(文章)front-matter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
title: CentOS7下Tomcat启动慢的原因及解决方案
date: 2017-12-02 21:01:24
description:文章描述,用于做SEO优化的
keywords: 文章SEO关键词
top_img: 文章顶部图
cover: 文章缩略图(封面图)
toc: true (是否显示文章目录)
toc_number: true (是否显示文章目录的标识数字)
copyright: true (是否显示版权)
mathjax: (数学公式显示是否支持)
katex: (Tex公式显示是否支持)
hide: false (是否隐藏当前文章)
comments: true #是否可评论
toc: true #是否显示文章目录
categories: "云服务器" #分类
tags: #标签
- centOS
- tomcat

站内搜索添加

站内搜索,我是采用的hexo-generator-search插件解决方案,安装完插件,然后配置一下,最后用hexo清理再生成一下全站静态,同时在根目录也会生成一个search.xml,用于做字符串模糊匹配的。

插件安装

1
npm install hexo-generator-search --save

添加或配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-config(hexo配置)

search:
path: search.xml
field: post
format: html
limit: 10000

-butterfly-config(butterfly主题配置)

local_search:
enable: true
preload: false
CDN:

清理与生成

1
hexo clean && hexo g

image-20240601175004305

评论系统添加

第三方评论系统我这里使用的是Gitalk ,Gitalk 是一个基于 GitHub Issue 和 Preact 开发的评论插件。使用GitHub登陆,能支持多国语言,至于他的原理,其他博主有介绍。这里就不展开了,如果有时间以后可能会整体介绍一下常用的第三方评论系统,因为我还是希望评论能支持多种方式登陆的,目前没有找到合适的就先选择Gitalk。

注册应用账号

地址:https://github.com/settings/applications/new

1

获取参数

注册成功后拿到 “Client ID” 和 “Client secrets”(点击生成再复制),其中注意的是Homepage URL 要设置为 用户名.github.io精确到https的地址。Authorization callback URL 填写注册的域名,如果绑定了个性化域名就填自己的域名,也是要精确到https的位置。

2

修改Butterfly配置

打开butterfly主题的配置文件,第一个找到 “gitalk” 项,将上面复制的client id 和 client secrets粘贴。

第二个找到 “comments”,将use配置为 “gitalk”,当然也可以用valine、Disqus之类的第三方评论系统。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
comments:
use: # 使用的第三方评论系统名称
text: true # 是否在按钮旁显示评论名称
# If you set it to true, the comment count will be invalid
lazyload: false # 是否设置评论窗为懒加载
count: true # 是否设置评论数统计
card_post_count: true # 是否将评论数显示到首页

gitalk:
client_id: # github应用ID
client_secret: # github应用密钥
repo: 用户名.github.io
owner: 用户名
admin: 用户名

3

博客仓库设置

进入仓库,点击 “Settings”,找到 “Features”, 将 “Issues” 勾选。

4

文章置顶功能添加

打开hexo配置文件 _config.yml,如果前面有per_page的关闭,使用的是hexo-generator-index插件排序,可以自定义序号和日期排序。

如何要置顶文章,只需在文章md的front-matter里添加一个top参数,数值自定。文章列表会出现一个钉子图标,要看到效果则要hexo先清理再生成。

添加配置

1
2
3
4
5
6
index_generator:
path: ''
per_page: 5 # 每页条数
order_by:
top: -1 # 置顶: -1.倒序 1.顺序
date: -1 # 日期: -1.倒序 1.顺序

md文章设置

image-20240601193026538

清理与生成

1
hexo clean && hexo g

image-20240601192658429

RSS配置

对于RSS输出功能,需要安装 hexo-generator-feed 插件。最后使用hexo清理再生成,博客根目录就会生成atom.xml

插件安装

1
npm install hexo-generator-feed --save

添加配置

1
2
3
4
feed:
type: atom
path: atom.xml
limit: 20

设置RSS地址

1
rss: /atom.xml

设置404页面

在hexo的_config.yml找到或添加error_404,设置开启,分别添加标题和背景图。

1
2
3
4
error_404:
enable: true
subtitle: 'Page Not Found'
background: /img/404.jpg

image-20240601193726689

添加百度统计

先登陆或注册百度统计平台,找到 “使用设置” -> “代码获取” -> “新版统计代码获取”,然后会看到一段js代码,只需要复制如下的一个32位长度的字符串。最后将该字符串粘贴到butterfly的config.yml中的baidu_analytics中,部署后一天就可以在后台查看统计报表了。

image-20240601194438994

MarketDown用法

关于新建的文章,我希望本地能备份一份,有md文件和图片,方便上传到其他平台博客。那要怎么做呢,这里我用一个免费的md工具——Typora为例。

创建文件和文件夹

创建一个以文章标题的文件夹,里面再分别创建一img文件夹和同文章标题的md文件,img下再创建一个与文章标题同名的文件夹。

image-20240601194438994

Typora设置

依次找到 “文件” -> “偏好设置” -> “图像” , 将插入图片时的下拉选中 “复制到指定路径”,填入下面的值。

1
./img/${filename}/

image-20240601194438994

第二步找到 “格式” -> “图像” -> “设置图片根目录”,选择markdown文件同级的目录,最后复制图片时就会复制到img下的文章同名目录下。

image-20240601194438994

为什么要这样设置?因为Hexo的图片在打包前都是在主题包/source/img里,而为了方便本地能按文章存储,也方便将本地的文章图片直接丢到img下,然后md文件放到_post中。打包之后就能以仓库图片展示,而且按文章分类存储,以后删除起来也一目了然。

image-20240601194438994

写在最后

这次的优化看起来好像是面面俱到了,但其实关于Hexo主题还有更细节的处理。比如可以添加博客看板精灵,酷炫的动态大背景,还有鼠标跟随或点击特效等等。但是我这博客目前定位主要以内容为主,所以暂时就就演示了,当然,如果有用户喜欢也可以马上加上去的。

最后呢,就是三部曲的第二篇结束了,那下次就自然地要开始进入Hexo章最后一篇。现在是计划介绍一下怎么让博客被各大搜索引擎收录,以及一些推广心得等等。具体的详细内容未定,更新时间也还不知道,因为在等我那个小游戏的软著下来,下来后我一定要好好写一篇软著申请避坑的文章,可实在是太难等了!

(我是一个持续摸索个人副业的普通程序员,关注我,和你一起探索更多可能。——ZERO开发)

  • ✇ZERO开发
  • 谈后端人眼里的nvm、yarn、pnpm……北桥苏
    前言虽然我是做后端的,但也时常关注前端,只是最近觉得前端的各种工具名称太眼花缭乱了,nvm、yarn、pnpm、taro……不要说具体使用,就连他们到底是工具还是新框架我都搞混。所以,我就用一篇文章简要记录他们到底是什么,怎么区别以及简易的搭建过程。nvmnvm(Node Version Manager),顾名思义,他是Node.js的版本管理工具。主要用来在单个操作系统下安装或管理多版本Node,常用于解决项目中不同版本依赖问题。下载github搜作者coreybutler,项目nvm-windows。安装安装前如果电脑已经有了Node.js,最好卸载以防后面冲突。然后点击exe文件下一步下一步完成后,nvm会自动在电脑的用户变量中添加NVM_HOME和NVM_SYMLINK,最后cmd输入nvm -v,显示nvm版本号表示已经成功。使用1234nvm install 6.2.0 安装指定版本nvm uninstall 6.2.0 卸载指定版本nvm list 查看安装列表nvm use 6.2.0 使用指定版本pnpmpnpm(Performant npm),是一个
     

谈后端人眼里的nvm、yarn、pnpm……

作者 北桥苏
2024年5月4日 16:13

前言

虽然我是做后端的,但也时常关注前端,只是最近觉得前端的各种工具名称太眼花缭乱了,nvm、yarn、pnpm、taro……

不要说具体使用,就连他们到底是工具还是新框架我都搞混。所以,我就用一篇文章简要记录他们到底是什么,怎么区别以及简易的搭建过程。

nvm

nvm(Node Version Manager),顾名思义,他是Node.js的版本管理工具。主要用来在单个操作系统下安装或管理多版本Node,常用于解决项目中不同版本依赖问题。

下载

github搜作者coreybutler,项目nvm-windows。

img

安装

安装前如果电脑已经有了Node.js,最好卸载以防后面冲突。然后点击exe文件下一步下一步完成后,nvm会自动在电脑的用户变量中添加NVM_HOME和NVM_SYMLINK,最后cmd输入nvm -v,显示nvm版本号表示已经成功。

img

使用

1
2
3
4
nvm install 6.2.0     安装指定版本
nvm uninstall 6.2.0 卸载指定版本
nvm list 查看安装列表
nvm use 6.2.0 使用指定版本

img

pnpm

pnpm(Performant npm),是一个快速、磁盘空间友好的包管理工具,和npm类似,可以简单理解为npm的优化加强版,适合于较大的前端项目,具体的特征可以看其他博主的介绍。因为npm是Node自带,所以有Node即可有pnpm。

下载安装

npm install pnpm -g

使用

1
2
3
4
5
pnpm install 包  // 
pnpm i 包
pnpm add 包 // -S 默认写入dependencies
pnpm add -D // -D devDependencies
pnpm add -g // 全局安装

yarn

yarn 是 Facebook 开发的一个 JavaScript 包管理工具,yarn 使用与 npm 不同的锁定文件格式,但是仍然可以兼容 npm 的包管理规范。

下载安装

npm install -g yarn

使用

1
2
3
4
yarn --version // 查看版本
yarn init // 同npm init,执行输入信息后,会生成package.json文件
yarn install // 安装package.json里所有包,并将包及它的所有依赖项保存进yarn.lock
yarn run // 用来执行在 package.json 中 scripts 属性下定义的脚本

写在后面

写这篇文章的最主要原因,其实还是因为平时独立开发中的项目有用到。比如,我放在独立博客里的在线工具(各种集成编程小工具),和项目中心(带摸鱼小游戏)都有使用pnpm和yarn,大家感兴趣的话可以看看。

img

❌
❌