小天管理 发表的所有内容
-
[Android] Dhizuku,更优雅地免解锁使用第三方安装器
使用了一段时间的 Dhizuku ,在自己的网站写了一篇水文,全文如下,权当抛砖引玉,欢迎大佬们不吝赐教。 如果把 Android 手机比喻为一栋房屋,那么解锁 Bootloader 后,你才真正拥有了这座房屋的“所有权”而非“使用权”;而诸如 Dhizuku / Shizuku 这类免解锁玩机工具则更像是与房东“扯皮”来获得更多对房屋装修的“支配权”,虽然有种戴着脚铐跳舞的妥协感,但是在部分场景下足矣。 解锁玩机已经愈发困难,折腾需求依然存在 由于众所周知的原因,手机厂商对于用户的“折腾”、“玩机”行为不断限制,解锁 Bootloader 的难度与日俱增,就看看小米 BL 解锁答题裸考下面的热门评论吧: KernelSU 作者 weishu 在小米解锁 bootloader 考试中获得了 30 分的好成绩 你也快来试试吧! 小米“高考”果然名不虚传! 当然,忽略“房间里的大象”而直接指责手机厂商固然不妥,但是厂商的一些“流氓行径”着实令人不爽。那么如果跳过成本愈发高昂的解锁,我们是否还能实现一些玩机需求?比如绕过烦人的官方安装器,使用更方便的第三方安装器? Shizuku —— 巧借 adb ,获取更高的权限玩机 根据 Shizuku 官网 和 GitHub 主页 上面的介绍,开发者将其定义为“让你的应用直接使用系统 API”的工具,其最大亮点就在主页上的“支持 adb 使用”,也就是“如果你的「需要 root 的应用」只需要 adb 权限,则可以使用 Shizuku 轻松地扩大用户群体。” 虽然对于大多数玩机发烧友已经是陈词滥调,但是还是援引一下Android 调试桥 (adb) - Android Developers上面的定义:Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作,例如安装和调试应用。adb 提供对 Unix shell (可用来在设备上运行各种命令)的访问权限……简单来说,adb 就是谷歌给予开发者的一个调试工具,其本意是便于开发者调试应用,不过在 Android 11 或更高版本上,您可以直接从您的设备启动无线调试并启动 Shizuku ,而无需连接到计算机。 正因为如此,目前已经有大量玩机应用适配了 Shizuku ,具体可以看 timschneeb/awesome-shizuku 上面整理的列表,其中就有可以包含你正在使用的部分甚至所有玩机应用,在此处不再赘述。 不过,由于对于 adb 的强依赖,虽然理论上 Shizuku 在正常开关机后依然能保持激活状态,其易用性在不同厂商的设备上也因不同厂商的“优化”而不尽相同——某些厂商的“安全管家”会把 “USB 调试”作为风险项目,在扫描时关闭;某些厂商的“USB 调试”被魔改,或在高版本 AOSP 中隐藏“无线调试”选项,或需要手动调整为“生产模式”才能使用 adb 完整权限;更有甚者,在拔掉数据线时会自动禁用 adb 权限……在我的设备上,即使允许 Shizuku 后台运行、自启动并忽略省电优化,其依然会在重新开机(不是重启或者更新)后失去激活状态,这样即使使用 Shizuku 激活第三方安装器,也免不了一遍又一遍的重新激活,外加烦人的 USB 安装风险提示对话框,与预期的流畅优雅的安装器体验相去甚远。 Dhizuku —— 共享 DeviceOwner 权限,更稳定的“旁门左道” 不过,除了方便开发者使用 USB 调试而带来的 adb 权限,Google 为了方便企业进行企业移动管理( EMM )而引入了 DeviceOwner ,相比被频繁“关照”的 adb ,其更为冷门,在部分场景下甚至更为强大。 由于其过于冷门,为了方便后续行文并且让读者不被,还是援引一些资料补充一下背景信息:根据设备管理概览 - Android Developers中的内容,结合Android Device Admin and Device Owner Explained中的内容稍加整理,你会发现 Google: 在 2010 年,Android 在 Android 2.2 ( API 级别 8 )中推出了一项名为“Device Admin”(设备管理员)的功能。它从未真正打算用作企业设备管理解决方案,尽管 Google 确实鼓励使用它; 在 2014 年,Google 在 Android 5.0 Lollipop 中推出了“Device Owner”,这是 Device Admin 的替代品。Device Owner 提供了更多功能、更好的安全性,并为真正的企业设备配置系统铺平了道路; 在 2018 年,Android 9.0 ( API 级别 28 )发布,这是最后一个支持 Device Admin 的 Android 版本; 在 2019 年,Android 10.0 ( API 级别 29 )发布,这是第一个不支持设备管理员的 Android 版本; 在 2022 年(及以后),Device Admin 已经 4+ 年没有得到 Google 的支持。早在 2014 年,Device Owner 就被引入以取代 Device Admin ,但在 2019 年 Android 10.0 推出之前,Android 同时支持这两种功能。 如果你是从 Android 4.4 时代开始玩机的老发烧有,或许对一些应用(安全软件或是恶意软件)请求激活设备管理员权限来进行“加固”,那便是已经在 Android 10.0 中消亡的“Device Admin”(设备管理员);拜“Device Owner”的广泛支持所赐,本文的主角 Dhizuku 也能能够实现 Android 5.0 ~ 14 的广泛且一致的支持。 好的,现在忘掉那些繁琐的概念,根据 Dhizuku 的GitHub 主页 介绍,其“参考 Shizuku 的设计思想,分享 DeviceOwner (设备所有者) 权限给其余应用”。不过由于 Android 的一些奇妙限制,其激活过程略显繁琐。根据激活指南,我使用AndroidAccounts找到了所有创建了账户的应用并且使用雹 Hail进行冻结。不过在我遇到的场景下,“小米账号”和“Google Play 服务”作为系统应用无法使用 Shizuku 模式进行冻结,退出登录,在成功激活后重新登录即可;此外,在 2.8 版本中,通过 Shizuku 激活后会提示“已激活但是权限不完整”,还需要 ADB 运行额外命令才能完成激活,而在最新的 2.9-alpha 版本中,已经无需连接电脑执行额外的命令。 恭喜,现在不出意外的话,你已经完成了 Dhizuku 激活,此时你的手机锁屏页面和通知页面底部会多出一行小字——“此设备归贵单位所有”(英文版系统为“This device belong to your organization”)。此提示无法隐藏(可能是处于安全和隐私考虑),但是可以通过爱玩机工具箱或者OwnDroid自定义“贵单位”/"your organization"的内容。顺带一提,OwnDroid 在最新的 6.0 版已经支持 Dhizuku API 激活,此后便可根据其文档体验 Google 为企业管理提供的细致的权限管理。 Dhizuku 由于起步较晚,现阶段提供支持的应用还相对较少,除了上文提到的 雹 Hail 和 OwnDroid ,目前还有 Amarok 支持借助 Dhizuku 隐藏应用和文件。不过我个人目前认为最好用的应用当 InstallX 莫属,从其Telegram Channel下载最新版后,在“配置”选项卡新建一个配置,授权器选择“Dhizuku”,此后在设置的默认配置选择刚刚的配置,如果单击“锁定为默认安装器”提示“锁定成功”,即可体验优雅丝滑的安装体验。Dhizuku 在 2.9-alpha 也修复了重启后无法自启动的问题,因此无论是开关机、重启还是更新,Dhizuku 的激活状态依然有效。 瑕不掩瑜——免解锁方案的缺陷 如果说此方案有什么瑕疵,那当属在安装应用后会有一条通知——“……已由您的管理员安装”,此通知和提示文字一样为系统级设计,如果介意可以考虑使用第三方通知收纳软件,不属于本文讨论范围;另外根据酷安社区的讨论,尽管 DeviceOwner 冷门且通用,部分厂商还是通过系统自带的不可删除的账户、屏蔽部分 adb 命令等方式限制 Dhizuku ,而且部分厂商的系统安装器是写死在内核中,无法使用 root 以外的方式修改或绕过,本文的方法同样不适用于这类设备。 当然,此方案还有不少值得优化之处,本文就权当抛砖引玉,欢迎大佬们不吝赐教。
-
[问与答] 自己公司的自助设备小程序,被用户投诉要求退款,难道只能认栽吗?
自助设备上已经完成操作,而且数量比较大,接近 100 块钱。 客户投诉要求退款,收到投诉后就及时在投诉单上进行了回复,但是客户留的电话打了一下午也打不通。 然后到傍晚的时候就收到交易体验分扣分通知: 违规类型:拒绝提供服务 备注:因用户投诉并平台审核,你的小程序存在 [拒绝提供服务--和解期超时未回复] 的违规行为。。。。平台将对你的小程序扣减体验分 1 分。
- [问与答] 北京联通 4G 访问 GitHub 飞快,不知道是 DNS 还是链路问题
-
[华硕] Koolcenter 的固件不开源,可以放心用吗?
过去 koolshare 被取缔以后,现在新版的 koolcenter 感觉是被朝廷招安以后的版本了,其发布的固件确定可信吗? 有没有相关消息报道过可信度的?
-
[分享创造] 开学了,分享下之前写的关于大学计算机学习的方法指引
也许对在读大学的朋友会有一定的参考价值,顺手在这里贴一下,有兴趣可以参考。 https://wiki.0xffff.one/getting-started/ 主要是针对我过去学计算机到工作的困惑,与身边人的观念冲突,和身边朋友数年来的摸索之间,一步步想通后的一个方法总结。 形式上是一系列文章,整体比较务实和行动导向。主要讨论大学与中小学学习、以及不同大学之间的异同;在心态上如何平衡学校 title 的落差,从中小学填鸭教育过渡到大学的主动学习的策略;还有 CS 领域入门的一些关注点,关于个人电脑开发环境,知识管理体系的准备,以及最早期 Overview 的搭建等等。 这里也是 0xFFFF CS Wiki 的一部分,Wiki 本身除了这一系列指引外,其他内容目前还及其简陋,所以也希望可以吸纳一些新鲜血液一起来交流,沉淀一些东西。不知不觉我毕业也有好几年,自觉已经很难再从学生的视角去思考一些问题了😄
-
[分享发现] 用 cursor 做网站是真的爽
比如说,我想要个 图片分割并 zip 下载 的功能,但是我又不懂 canvas 也不知道浏览器能不能直接打包 zip 。只要告诉它: 生成一个 image splitter 组件,用户上传一张照片,选择行、列数量,点击按钮,就会自动分割,并打包成 zip 格式自动下载。 就会生成一个功能完整的组件: 'use client' import React, { useState } from 'react'; import JSZip from 'jszip'; import { saveAs } from 'file-saver'; const ImageSplitter = () => { const [image, setImage] = useState<File | null>(null); const [rows, setRows] = useState(3); const [cols, setCols] = useState(3); const handleImageUpload = (e: React.ChangeEvent<HTMLInputElement>) => { if (e.target.files && e.target.files[0]) { setImage(e.target.files[0]); } }; const handleSplitImage = async () => { if (!image) return; const img = new Image(); img.src = URL.createObjectURL(image); img.onload = async () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); if (!ctx) return; const zip = new JSZip(); const { width, height } = img; const pieceWidth = width / cols; const pieceHeight = height / rows; for (let r = 0; r < rows; r++) { for (let c = 0; c < cols; c++) { canvas.width = pieceWidth; canvas.height = pieceHeight; ctx.drawImage( img, c * pieceWidth, r * pieceHeight, pieceWidth, pieceHeight, 0, 0, pieceWidth, pieceHeight ); const dataUrl = canvas.toDataURL('image/png'); const base64Data = dataUrl.split(',')[1]; zip.file(`piece_${r}_${c}.png`, base64Data, { base64: true }); } } const content = await zip.generateAsync({ type: 'blob' }); saveAs(content, 'image_pieces.zip'); }; }; return ( <div className="flex flex-col items-center justify-center p-4"> <div className="bg-white shadow-md rounded-lg p-6 w-full max-w-md"> <label className="block mb-2"> Upload an image: <input type="file" accept="image/*" onChange={handleImageUpload} className="mb-4 w-full p-2 border border-gray-300 rounded" /> </label> <label className="block mb-2"> Enter number of rows: <input type="number" value={rows} onChange={(e) => setRows(parseInt(e.target.value))} min="1" className="mb-4 w-full p-2 border border-gray-300 rounded" /> </label> <label className="block mb-2"> Enter number of columns: <input type="number" value={cols} onChange={(e) => setCols(parseInt(e.target.value))} min="1" className="mb-4 w-full p-2 border border-gray-300 rounded" /> </label> <button onClick={handleSplitImage} className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 transition" > Split Image </button> </div> </div> ); }; export default ImageSplitter; 当然一开始样式有点丑,我补充了一句:使用 tailwind 优化一下样式,要现代感,柔色调 大体效果就出来了: https://imagesplitter.org/
-
[分享发现] 草草体验了下飞牛私有云 fnOS,只能说是大失所望。
这两天忽然出来个免费 nas 系统,尤其是我在的几个 qq 群基本是在同一两天内出现说免费 nas 系统好牛掰,尤其是影音多么多么牛掰之类的,体验吊打黑裙之类的,架不住都说的天花乱坠,虚拟机装了下体验了下,登录后的第一感觉是 好快,第二感觉是 就这?说好的吊打呢?说好的影音牛掰呢? 1 说应用:少,总共 25 个应用,11 个是矿神 SPK7 的,玩群晖的都懂。 [img][/img] [img][/img] 2 说备份:有点意思,差点意思。 [img][/img] 3 说设置:好听叫功能简洁,对小白友好。 [img][/img] 4 说 docker: 内置加速,其他没啥可说。 [img][/img] AdGuard Home fnOS 查询日志 [img][/img] 5 说远程访问:用他家的得注册懒得试,ddns 就 4 个。 [img][/img] [img][/img] 6 说影音:刮削挺快,但是你为啥要请求百度的域名?另外上传了个.wmv 的视频,无法播放,没然后了。 [img][/img] 自家服务器刮削就是快 [img][/img] [img][/img] 7 说系统:是 debian12 没错,还是清华源,虽然 fnOS 应用少,但是有 docker 啊,你甚至还可以 apt install. [img][/img] [img][/img] [img][/img] 因为是草草体验,找了半天没找到 demo,只能虚拟机体验下,加上本人很业余,也就用过群晖和 Pve ,所以上面所说都是非常片面小白的,很多方面理解不到位,还望担待。 截至现在,还有人在群里说:“fnOS 挺不错的” 我只能说:啊 对对对。
-
[OpenWrt] 局域网内无线连接的设备之间无法互相访问,但无线和有线连接设备之间却可以
用 R2S Plus 做的主路由,用的是友善定制的 FriendlyWrt ,但其实就是 OpenWRT 。 下面是我用 iperf3 测出来的情况: 第一次用 OpenWRT ,不太懂怎么设置,不过可以确定的是无线设置没开客户端隔离。 网上搜不到相关问题,问客服也不知道怎么解决,所以来万能的 V2 问问。 因为不知道到底是什么问题也不懂,如果需要更多的信息还望老哥们提出来。
-
[问与答] 怎么样用一年的时间达到三年的水平,比如前端领域,一年时间可以达到三年的水平吗?现在招聘都要 3 年 plus
- [问与答] 求推荐能稳定运行 SPA Web 应用的 mini 主机
需求: 1. 便宜! 2. 体积小! 3. HDMI 插电视上运行,稳定性强,需要稳定运行 4 年以上。- [程序员] 独立开发周记 81: 8 月数据总结
2024 ,0826-0901 暑假结束了,天气凉快了,孩子终于要开学了。 8 月数据总结 最近一个多月都在全身心在新 App 上,所有的在架 App 都没有任何打理。 总得来看,下载量提升很多,App Store 和 Google Play 的收入没什么变化,但是国内安卓市场的收入大幅减少。 下载量(极简时钟) App Store ,增长 44% Google Play ,增长 19.30% 国内安卓市场,因为上个月的数据不全,就和 6 月份对比,增长了 18.7% 收入变化 App Store ,增长 2.2% Google Play ,增长 9.08% Admob ,增长 0.28% 国内安卓市场,减少 18.92% Ship-A-Ton 第三周 Ship-A-Ton 就剩 18 天了,感觉要砍掉一个大功能才能勉强提交了。 这周严重阻碍开发进度的就是黑神话·悟空!。每天都会玩到后半夜一点多,这就导致睡眠不足,严重影响到了白天的开发效率。 这周的番茄钟数量是 26 ,相比上周多了 4 个, 但也只是 4 个而已。开发速度太慢了,这让我又开始焦虑了。 这周有两个主要的进展,一是完成了第三个功能模块的原型,跑通了整个流程。这个模块经历了两次更名,一开始叫 Wishlist ,再后来叫 Goals ,最后定为 Desires 。 另一个进展就是和设计师顺利达成了合作,App 的 UI 终于有保证了。这一周的绝大部分开发时间都花在了 UI 上,和我之前自己瞎写的 UI 一对比,简直是云泥之别。专业的事情还是要交给专业的人来做。 [Vlog: Week 3 for Shipaton] 本周探索 监测 ScrollView 滚动状态 需要在新 App 里加入对 ScrollView 滚动状态的监测,看完了肘子哥的文章,# 如何判断 ScrollView 、List 是否正在滚动中。因为 App 是 iOS 17+ 的,还不能直接使用 iOS 18 的新 API , 直接就使用了肘子哥的 IsScrolling 。 单复数的文案本地化 App 里需要用的针对单词单复数的不同文案,所以就第一次使用了 SwiftUI 中 Text 对单复数的 API ,不用自己写 if else 判断,很优雅。# Pluralisation made simpler in SwiftUI SVG 转成 SF Symbols 我想要把 MasterGo/Figma 里面的切图导出后,放到 Xcode 中,然后通过 Image 和 foregroundStyle 给切图加上不同的颜色,就像 SF Symbols 那样。导出成 jpg 和 png 都无法做到,尝试导出 SVG 后才发现 SwiftUI 的 Image 还不支持 SVG 。 我就想着怎么能把 SVG 转成 SF Symbols ,找了两个工具 App ,都是收费的,连试用也没有,我就没敢直接付费。于是我就问了下 ChatGPT 怎么将 SVG 转换成 SF Symbols ,AI 的回答如下: 我就在这个回答里找到了解决方案:PDF !将 icon 导出为 PDF ,放到 Xcode 的 Asset 里,然后将图片设置为 Render as Template Image 就可以了。 生活 吃了两顿大餐,还发现了一家不错的面馆。 和许久没见的老同学见面,畅聊一晚。 直面天命,刚过第五回,下周肯定能通关了。 第三回,黄眉差一点初见过,我以为还有一个阶段变身,当时葫芦也没酒了,就摆烂打了。 第四回,晦月魔君确实恶心,我是天命人,不是修脚师傅! 第五回,死的最多次数居然是在铁球山路…… 最近因为玩游戏和写代码,尤克里里都生疏了,每天练习时间大大减少,甚至有一两天都没拿起来。花了将近一个月练习 Em 和弦终于成功了,录了 New Boy 。 [Vlog: Ukulele - New Boy] 视频内容还请移步到公众号文章里查看: https://mp.weixin.qq.com/s/OgBlZGfDmPtq7hFY7XLi9g- [问与答] 有没有这么一款 webssh 管理工具
轻量化,最好开源,能支持私有部署,准备部署到公司内网 支持 webssh 和 文件下载 重点 支持通过按用户组指定登录授权,比如:管理组的用户使用 root 登录, 而程序组的用户使用 programer 用户登录 资产管理及权限控制,即: 特定的用户/用户组只能连接特定的 ssh 主机 jumpserver 太重了,完全不想去用 next-terminal 不支持第 3 条- [OpenAI] 现在 AI 太好了,想实现啥自己提需求让 AI 去实现
一直没找到好用的 goole 居中的插件 让 Claud 实现了一个 几分钟就完事了 https://raw.githubusercontent.com/macong0420/Image/main/202409022058444.png- [分享创造] 开发了一个网页端跨平台传输工具,基于 WebRTC,无需下载软件
https://peer-drop.real-tech.online/ 用聊天框的形式,支持传输文字和文件 目前只支持局域网 只要有浏览器就能互相通信,无论手机平板还是电脑- [问与答] 找 电子书
防止被 pua 找了些电子书 但是 很多好像没有中文版 和 pdf 下载 《精神控制的艺术》( The Art of Manipulation ) – 这本书探讨了操控和影响他人的技巧,虽然不一定是学术性,但提供了关于精神控制的实用见解。 《心理操控:如何识别和抵抗心理操控》( Mind Control: The Ultimate Guide to Understanding and Resisting Mind Control ) – 这本书详细解释了心理操控的机制,并提供了识别和抵抗这些操控的方法。 《社会工程学:黑客如何利用心理学进行攻击》( Social Engineering: The Science of Human Hacking ) – 克里斯·哈德( Chris Hadnagy )的书籍,探讨了如何通过操控人类行为来实现目的,虽然重点是社会工程学,但涵盖了心理操控的许多方面。- [问与答] 为什么 acfun 的网页版登录不上了
- [程序员] 高度配置化的工作流系统有老板需要吗
给大伙推荐一款高度可配置化的工作流系统,非常 nice,具体可以看图片或者访问下面的网址。 访问地址: http://106.54.16.175/ 账号/密码:vistor1/vistor1- [Apple] iPhone 16 可能不支持微信?苹果中国区技术顾问称正与腾讯沟通应用商店抽成事宜
https://www.ithome.com/0/792/961.htm- [Apple] iPhone 16 到底买哪个版本的比较好?
最近一直也有在看 iPhone AI 相关的信息 国内目前看来是没办法用上,最近好像只解锁了港版 然后刚好晚上看到一个老哥在看日版的 自己手上现在是 15pro 春节期间大概率会去日本旅游或者香港旅游 各位大佬有什么建议么- 【安卓软件】七猫免费小说_v7.46-安卓魔改版下载
软件名称】七猫免费小说 【软件语言】中文 【软件大小】100.65MB 【软件版本】7.46 【软件包名】com.kmxs.reader 【开发代号】74600 【系统版本】11 【特殊说明】免广告获得奖励 解锁会员 【软件简介】你在一个完全陌生的地方醒来,没有任何关于自己被敌对士兵包围的记忆。那是什么样的? 男主角得到了一个绰号尼莫,被迫调查一起残忍的罪行,以换取指挥官的赞助。为了破案,他加入了精锐的士兵小队,他需要得到战友的信任才能找到罪魁祸首。然而,如果谋杀案隐藏了更多的秘密,解开的谜团只会引发新的问题呢?他的新战友会成为他的伙伴还是敌人? 特征: ► 军事冲突的两个对立面 尼莫。一个失忆的人。在指挥官的保护下,他加入了一个年轻的士兵小队,进行间谍活动并调查犯罪。 留置权。战争之子。他害怕被黑人叛教者杀害,并渴望为亲人的死报仇雪恨,过着完全不同的生活。 ► 秘密侦查神秘犯罪,寻找线索 寻找线索,做出选择,然后跟随故事寻找罪魁祸首。 ► 两种不同流派的混合:视觉小说和指向与点击 在 Guilty Parade 中,您可以做出重要决定并在营地中独立移动,与物体和角色互动。 ► 有机会与古怪的角色建立牢固的友谊纽带 角色有很多独特的特征(喜剧和戏剧),习惯和他们的行为是不可预测的(角色简介)。 ► 很多有意义的选择会影响你得到的场景 尼莫不仅要调查犯罪,还要学会生活在未知的世界中,并决定他在军事冲突中站在哪一边。 【下载地址】https://pan.quark.cn/s/52199eeff9d0- Cos美图-动漫Coser@溯兮-sukki NIKKE 海伦礼服
- [前端开发] 这可能是见过的最好用的弹幕库 🔥🔥
最近把五年前写的一个弹幕库给重构了一下,本来两年前就想着做这件事,但是其中有一段工作时间压力很大,所以就搁置了,导致没有时间来做这件事情,最近周末 + 晚上花一些时间重构了下,并把文档好好写了一下。言归正传,这篇文章会介绍部分这个弹幕库有的能力,如果正好符合你的需求或者感兴趣,可以帮忙点点 star 来支持一下。 我们有哪些能力 我们提供了灵活调整轨道,自定义弹幕和容器样式,弹幕运动算法等能力,还在提供非常丰富的钩子来让用户处理自定义的行为,只要你想要的,都能做到,本文档会简单介绍一些能力和一些功能的实现。 在线 demo: https://imtaotao.github.io/danmu/ github: https://github.com/imtaotao/danmu?tab=readme-ov-file 官方文档: https://imtaotao.github.io/danmu/document/zh/ 快速开始 对于一个开箱即用的 demo ,可以非常简单的接入,如下所示: import { create } from 'danmu'; const manager = create(); manager.mount('#root'); manager.startPlaying(); // 发送弹幕 manager.push('弹幕内容') 对轨道进行调整 我们对支持类似 CSS calc 表达式的能力,一些位置/宽高等信息都可以用表达式来计算。所以对于轨道来说可以很方便的进行调整。 **number**:默认单位为 px。 **string**:表达式计算。支持(+, -, *, /)数学计算,只支持 % 和 px 两种单位。 // 例如,这里的 100% 是指容器宽度(如果是高度相关的配置 100% 就是容器的高度) manager.setGap('(100% - 10px) / 5'); 限制为顶部 3 条弹幕 // 如果我们希望轨道高度为 50px manager.setTrackHeight('100% / 3'); // 如果不设置渲染区域,轨道的高度会根据默认的 container.height / 3 得到, // 这可能导致轨道高度不是你想要的 manager.setArea({ y: { start: 0, // 3 条轨道的总高度为 150px end: 150, }, }); 限制为中间 3 条弹幕 manager.setTrackHeight('100% / 3'); manager.setArea({ y: { start: `50%`, end: `50% + 150`, }, }); 限制为几条不连续的轨道 限制为几条不连续的轨道,除了要做和连续轨道的操作之外,还需要借助 willRender 这个钩子来实现。 // 如果我们希望轨道高度为 50px ,并渲染 0 ,2 ,4 这几条轨道 manager.setTrackHeight('100% / 6'); // 设置容器的渲染区域 manager.setArea({ y: { start: 0, // 6 条轨道的总高度为 300px end: 300, }, }); manager.use({ willRender(ref) { // 高级弹幕和轨道不强相关,没有 trackIndex 这个属性 if (ref.trackIndex === null) return ref; // 如果为 1 ,3 ,5 这几条轨道就阻止渲染,并重新添加等待下次渲染 if (ref.trackIndex % 2 === 1) { ref.prevent = true; manager.unshift(ref.danmaku); } return ref; }, }); 自定义渲染 弹幕和容器都允许自定义的渲染样式,你可以很方便的做到。 自定义弹幕的样式 1. 通过 manager.setStyle 来设置 import { create } from 'danmu'; // 需要添加的样式 const styles = { color: 'red', fontSize: '15px', // . }; const manager = create(); // 后续渲染的弹幕和当前已经渲染的弹幕会设置上这些样式。 for (const key in styles) { manager.setStyle(key, styles[key]); } 2. 通过 danamaku.setStyle 来设置 import { create } from 'danmu'; // 需要添加的样式 const styles = { color: 'red', fontSize: '15px', // . }; // 初始化的时候添加钩子处理,这样当有新的弹幕渲染时会自动添加上这些样式 const manager = create({ plugin: { $moveStart(danmaku) { for (const key in styles) { danmaku.setStyle(key, styles[key]); } // 你也可以在这里给弹幕 DOM 添加 className danmaku.node.classList.add('className'); }, }, }); // 对当前正在渲染的弹幕添加样式 manager.asyncEach((danmaku) => { for (const key in styles) { danmaku.setStyle(key, styles[key]); } }); 自定义容器样式 import { create } from 'danmu'; // 需要添加的样式 const styles = { background: 'red', // . }; const manager = create({ plugin: { // 你可以在初始化的时候添加钩子处理 init(manager) { for (const key in styles) { manager.container.setStyle(key, styles[key]); } // 你也可以在这里给容器 DOM 添加 className manager.container.node.classList.add('className'); }, }, }); // 或者直接调用 api for (const key in styles) { manager.container.setStyle(key, styles[key]); } 高级弹幕的示例 本章节将介绍如何将弹幕固定在某一位置,以 top 和 left 这两个位置举例。由于我们需要自定义位置,所以我们需要使用高级弹幕的能力。 将弹幕固定在顶部 // 这条弹幕将会居中距离顶部 10px 的位置悬停 5s manager.pushFlexibleDanmaku('弹幕内容', { duration: 5000, direction: 'none', position(danmaku, container) { return { x: `50% - ${danmaku.getWidth() / 2}`, y: 10, // 具体容器顶部的距离为 10px }; }, }); 固定在顶部第 2 条轨道上 // 这条弹幕将会在第二条轨道居中的位置悬停 5s manager.pushFlexibleDanmaku('弹幕内容', { duration: 5000, direction: 'none', position(danmaku, container) { // 渲染在第 3 条轨道中 const { middle } = manager.getTrackLocation(2); return { x: `50% - ${danmaku.getWidth() / 2}`, y: middle - danmaku.getHeight() / 2, }; }, }); 将弹幕固定在左边 // 这条弹幕将会在容器中间距离左边 10px 的地方停留 5s manager.pushFlexibleDanmaku('弹幕内容', { duration: 5000, direction: 'none', position(danmaku, container) { // 渲染在第 3 条轨道中 const { middle } = manager.getTrackLocation(2); return { x: 10, y: `50% - ${danmaku.getHeight() / 2}`, }; }, }); 发送带图片的弹幕 要让弹幕里面能够携带图片,要在弹幕的节点内部添加自定义的内容,实际上不止图片,你可以往弹幕的节点里面添加任何的内容。 本章节的组件以 React 来实现演示。 开发弹幕组件 export function Danmaku({ danmaku }) { return ( <div> <img src="https://abc.jpg" /> {danmaku.data} </div> ); } 渲染弹幕 import ReactDOM from 'react-dom/client'; import { create } from 'danmu'; import { Danmaku } from './Danmaku'; const manager = create<string>({ plugin: { // 将组件渲染到弹幕的内置节点上 $createNode(danmaku) { ReactDOM.createRoot(danmaku.node).render(<Danmaku danmaku={danmaku} />); }, }, }); 编写一个插件 编写一个插件是很简单的,但是借助内核暴露出来的钩子和 API,你可以很轻松的实现强大且定制化的需求。由于内核没有暴露出来根据条件来实现过滤弹幕的功能,原因在于内核不知道弹幕内容的数据结构,这和业务的诉求强相关,所以我们在此通过插件来实现精简弹幕的功能用来演示。 编写一个插件 你编写的插件应当取一个 name,以便于调试定位问题(注意不要和其他插件冲突了)。 插件可以选择性的声明一个 version,这在你的插件作为独立包发到 npm 上时很有用。 export function filter({ userIds, keywords }) { return (manager) => { return { name: 'filter-keywords-or-user', version: '1.0.0', // version 字段不是必须的 willRender(ref) { const { userId, content } = ref.danmaku.data.value; console.log(ref.type); // 可以根据此字段来区分是普通弹幕还是高级弹幕 if (userIds && userIds.includes(userId)) { ref.prevent = true; } else if (keywords) { for (const word of keywords) { if (content.includes(word)) { ref.prevent = true; break; } } } return ref; }, }; }; } 注册插件 你需要通过 mananger.use() 来注册插件。 import { create } from 'danmu'; const manager = create<{ userId: number; content: string; }>(); manager.use( filter({ userIds: [1], keywords: ['菜'], }), ); 发送弹幕 ❌ 会被插件阻止渲染 manager.push({ userId: 1, content: '', }); ❌ 会被插件阻止渲染 manager.push({ userId: 2, content: '你真菜', }); ✔️ 不会被插件阻止渲染 manager.push({ userId: 2, content: '', }); ✔️ 不会被插件阻止渲染 manager.push({ userId: 2, content: '你真棒', }); 总结 本文档只是简单介绍了下现在的部分能力,更详细的文档在官网可以查看,如果对你的业务或者学习有帮助的,给个 star 支持一下作者,也欢迎大家评论探讨(不止弹幕,哈哈)。- Cos美图-动漫Coser@宮本桜 碧蓝航线
- [问与答] 主要工作是处理 Excel 表格+聊天软件, M2 16G Air 是否够用
想趁着这次家电补贴给家里领导换一台电脑,现在的 i7 确实烫手,她的日常工作就是聊天软件和 Excel 表格处理数据,用惯了 MAC 不想换 Windows 想问下 M2 芯片+16G 内存,以上工作是否能够撑个 3-5 年?- [macOS] 微信输入法 mac 端好像无法清空个人词典
- [问与答] 求推荐能稳定运行 SPA Web 应用的 mini 主机