0%

更新于 2025/08/21

保存的文件无法打开、关于自动滚动、console 不显示、滚动视图、流式传输、输入框上移

阅读全文 »

需求

在开发tg miniapp的时候,有一个场景如下:

1
2
1.点击播放声音
2.连续点击,需要重复地从头再次播放。(比如声音是‘噔-噔-咚’,快速连续点击就响起‘噔-噔-噔’)

代码实现

这边给元素绑定了点击事件,当用户触发点击事件,就将音频的当前进度设置为0,并且播放。

1
2
audio.currentTime=0;
audio.play();

适配情况

这个代码在pc的chrome和android的浏览器中都可以正常实现需求。

但是ios中,会出现声音的延迟(比如声音是‘噔-噔-咚’,快速连续点击就响起‘——噔-噔-咚’,稍慢连续点击就响起‘–噔–噔–噔’)

解决方案

调用howler库

相关源码如下(源于howler库)

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
// Call this method on touch start to create and play a buffer,
// then check if the audio actually played to determine if
// audio has now been unlocked on iOS, Android, etc.
var unlock = function(e) {
// Create a pool of unlocked HTML5 Audio objects that can
// be used for playing sounds without user interaction. HTML5
// Audio objects must be individually unlocked, as opposed
// to the WebAudio API which only needs a single activation.
// This must occur before WebAudio setup or the source.onended
// event will not fire.
while (self._html5AudioPool.length < self.html5PoolSize) {
try {
var audioNode = new Audio();

// Mark this Audio object as unlocked to ensure it can get returned
// to the unlocked pool when released.
audioNode._unlocked = true;

// Add the audio node to the pool.
self._releaseHtml5Audio(audioNode);
} catch (e) {
self.noAudio = true;
break;
}
}

// Loop through any assigned audio nodes and unlock them.
for (var i=0; i<self._howls.length; i++) {
if (!self._howls[i]._webAudio) {
// Get all of the sounds in this Howl group.
var ids = self._howls[i]._getSoundIds();

// Loop through all sounds and unlock the audio nodes.
for (var j=0; j<ids.length; j++) {
var sound = self._howls[i]._soundById(ids[j]);

if (sound && sound._node && !sound._node._unlocked) {
sound._node._unlocked = true;
sound._node.load();
}
}
}
}

// Fix Android can not play in suspend state.
self._autoResume();

// Create an empty buffer.
var source = self.ctx.createBufferSource();
source.buffer = self._scratchBuffer;
source.connect(self.ctx.destination);

// Play the empty buffer.
if (typeof source.start === 'undefined') {
source.noteOn(0);
} else {
source.start(0);
}

// Calling resume() on a stack initiated by user gesture is what actually unlocks the audio on Android Chrome >= 55.
if (typeof self.ctx.resume === 'function') {
self.ctx.resume();
}

// Setup a timeout to check that we are unlocked on the next event loop.
source.onended = function() {
source.disconnect(0);

// Update the unlocked state and prevent this check from happening again.
self._audioUnlocked = true;

// Remove the touch start listener.
document.removeEventListener('touchstart', unlock, true);
document.removeEventListener('touchend', unlock, true);
document.removeEventListener('click', unlock, true);
document.removeEventListener('keydown', unlock, true);

// Let all sounds know that audio has been unlocked.
for (var i=0; i<self._howls.length; i++) {
self._howls[i]._emit('unlock');
}
};
};

前言

tg应用开发分为机器人和小程序两部分

tg-bot

首先要在telegram的BotFather申请创建机器人,直接输入/newbot按照命令一步一步来就可以了。

成功后你会获得一串HTTP API,这个要保存下来。后续编程开发需要使用。

tgbot程序编写

bot部分参考了这位的博客

技术栈:grammY+node直接启动。以下是具体代码。

阅读全文 »

搭建个人博客的初衷,是为了不再受制于博客平台(cs*n),同时还要能专注于博客的编写而不用费心思去处理编译部署打包。(要抄配置直接拉到文章底部,我把配置文件放那了)

这里使用的是hexo博客框架next主题,用到的依赖如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"hexo": "^7.3.0",
"hexo-deployer-git": "^4.0.0",
"hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^2.0.0",
"hexo-generator-index": "^4.0.0",
"hexo-generator-search": "^2.4.3",
"hexo-generator-seo-friendly-sitemap": "^0.2.1",
"hexo-generator-tag": "^2.0.0",
"hexo-reading-time": "^1.0.3",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-marked": "^6.3.0",
"hexo-renderer-stylus": "^3.0.1",
"hexo-server": "^3.0.0",
"hexo-theme-landscape": "^1.0.0",
"hexo-theme-next": "^8.21.0",
"hexo-word-counter": "^0.2.0"
阅读全文 »

文中有部分名词可能不准确,见谅

本文主要介绍storybook+shadcn/ui+tailwindcss的storybook代码编写。

阅读全文 »

ps:有个需求是要等待确认交易。写这篇之后,我发现直接用回调函数要等好久好久好久。找到解决方案在这个链接但是有点麻烦。我已经弃用web3,直接使用ethersjs配合infura了,贼快。

本文将介绍如何使用web3js在Sepolia测试网完成一次交易,本文采用两种方式获得钱包,第一种是使用metamask,第二种使用web3创建。(可跳过第一节直接从第二节阅读)
使用的lib版本如下
“web-vitals”: “^2.1.4”,
“web3”: “^4.11.1”

阅读全文 »

图片

1
https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/${pokemon.id}.png

信息

1
https://pokeapi.co/api/v2/pokemon/${pokemon.id | pokemon.name}