
Midjourney 创作,未来API
大家好,随着技术的迅速发展,开发者们拥有了越来越多的令人惊叹的新工具和API。但是,我们发现在100多个API中,只有5%的API被开发者们积极地使用。
下面让我们来看看一些有用的Web API,它们可以帮助你将你的网站推向未来的巅峰!
屏幕捕获API,正如其名,允许你捕获屏幕内容,让制作屏幕录像变得轻而易举。你需要一个视频元素来显示捕获的屏幕。点击开始按钮即可开始屏幕捕获。
<video id="preview" autoplay>
Your browser doesn't support HTML5.
</video>
<button id="start" class="btn">Start</button>
// 获取HTML元素
const previewElem = document.getElementById("preview"); // 预览元素
const startBtn = document.getElementById("start"); // 开始按钮元素
// 异步函数,开始录制屏幕和声音
async function startRecording() {
previewElem.srcObject = // 将预览元素的srcObject属性设置为获取到的屏幕和声音媒体流
await navigator.mediaDevices.getDisplayMedia({
video: true, // 录制视频
audio: true, // 录制声音
});
}
// 为开始按钮添加点击事件监听器,点击时调用startRecording函数
startBtn.addEventListener("click", startRecording);
Web Share API 允许你从一个网页分享文本、链接甚至是文件到设备上安装的其他应用程序。
// 异步函数,处理分享事件
async function shareHandler() {
// 调用navigator.share方法进行分享,传入分享内容的相关信息
navigator.share({
title: "Tapajyoti Bose | Portfolio", // 分享标题
text: "Check out my website", // 分享文本
url: "https://tapajyoti-bose.vercel.app/", // 分享链接
});
}
// 给某个元素添加点击事件监听器,点击时调用shareHandler函数
someElement.addEventListener("click", shareHandler);
注意:要使用 Web Share API,你需要从用户那里获得互动,例如按钮点击或触摸事件。
Intersection Observer API 允许你检测元素何时进入或离开视口。这对于实现无限滚动非常有用。
简单的例子
// 创建一个IntersectionObserver实例,观察特定元素
const observer = new IntersectionObserver((entries) => {
// 遍历每个entry,判断是否在视口内
entries.forEach((entry) => {
if (entry.isIntersecting) {
// 元素进入视口,执行相应操作
} else {
// 元素离开视口,执行相应操作
}
});
});
// 将需要观察的元素传递给IntersectionObserver实例
const target = document.querySelector(".target");
observer.observe(target);
一个复杂的分页滚动(React版本)
<div id="root"></div>
/* The entire styling is totally optional */
* {
font-family: Roboto;
}
body {
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
.item {
width: 80vw;
margin: 12px 0;
padding: 32px;
border-radius: 8px;
font-size: larger;
}
.loader {
border: 8px solid #cccccc;
border-top: 8px solid #3498db;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 0.6s linear infinite;
display: inline-block;
margin: 8px auto;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
// 声明常量MAX_PAGES,表示可加载的最大页数
const MAX_PAGES = 5;
// 生成随机颜色的函数
const generateRandomColor = () => {
const characters = "0123456789ABCDEF";
let color = "#";
for (let i = 0; i < 6; i++) {
color += characters[Math.floor(Math.random() * 16)];
}
return color;
};
// 定义Item组件,接受children、color和reference属性,返回带有颜色的div元素
const Item = ({ children, color, reference }) => {
return (
<div className="item" style={{ backgroundColor: color }} ref={reference}>
{children}
</div>
);
};
// 定义App组件
const App = () => {
// 定义状态变量:items-加载的数据数组、isLoading-是否正在加载数据、hasMore-是否还有更多数据可加载、pages-已加载的页数
const [items, setItems] = React.useState([]);
const [isLoading, setIsLoading] = React.useState(false);
const [hasMore, setHasMore] = React.useState(true);
const [pages, setPages] = React.useState(0);
// 定义ref引用observer
const observer = React.useRef();
// 在挂载时更新items数组和pages变量
React.useEffect(() => {
updateItems();
setPages((pages) => pages + 1);
}, []);
// 定义lastItemRef回调函数,用于观察最后一个元素是否进入视口
const lastItemRef = React.useCallback(
(node) => {
if (isLoading) return;
if (observer.current) observer.current.disconnect();
observer.current = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
if (pages < MAX_PAGES) {
updateItems();
setPages((pages) => pages + 1);
} else {
setHasMore(false);
}
}
});
if (node) observer.current.observe(node);
},
[isLoading, hasMore]
);
// 定义updateItems异步函数,更新items数组和isLoading状态变量
const updateItems = async () => {
setIsLoading(true);
await new Promise((resolve) => setTimeout(resolve, 1000));
setItems((currItems) => {
const lastItem = currItems.length;
const updatedItems = [...currItems];
for (let i = 1; i <= 5; i++) {
const item = {
count: lastItem + i,
color: generateRandomColor()
};
updatedItems.push(item);
}
return updatedItems;
});
setIsLoading(false);
};
// 返回页面结构
return (
<React.Fragment>
<h1>Infinite Scroll Demo</h1>
{items.map((item, index) =>
index + 1 === items.length ? (
<Item reference={lastItemRef} key={index} color={item.color}>
{item.count}
</Item>
) : (
<Item key={index} color={item.color}>
{item.count}
</Item>
)
)}
{isLoading && <div className="loader" />}
</React.Fragment>
);
};
// 将App组件渲
注意:此示例使用React,因为这是我个人偏好,但你可以使用任何框架或原生JavaScript。
Clipboard API 允许你读取和写入剪贴板中的数据。这对于实现复制到剪贴板的功能非常有用。
// 定义异步函数copyHandler,将指定文本写入剪贴板
async function copyHandler() {
const text = "https://tapajyoti-bose.vercel.app/";
navigator.clipboard.writeText(text);
}
你是否曾经想过在观看视频时如何防止屏幕关闭?这就是因为使用了 Screen Wake Lock API。
// 声明变量wakeLock
let wakeLock = null;
// 定义异步函数lockHandler,请求屏幕唤醒锁定
async function lockHandler() {
wakeLock = await navigator.wakeLock.request("screen");
}
// 定义异步函数releaseHandler,释放屏幕唤醒锁定
async function releaseHandler() {
await wakeLock.release();
wakeLock = null;
}
// 注意:只有页面已经在屏幕上可见时,才能使用Screen Wake Lock API。否则会抛出错误。
Screen Orientation API 允许你检查屏幕的当前方向,甚至锁定到特定的方向。
// 定义异步函数lockHandler,锁定屏幕方向为竖屏
async function lockHandler() {
await screen.orientation.lock("portrait");
}
// 定义函数releaseHandler,解除屏幕方向锁定
function releaseHandler() {
screen.orientation.unlock();
}
// 定义函数getOrientation,返回屏幕当前的方向
function getOrientation() {
return screen.orientation.type;
}

Fullscreen API 允许你将一个元素或整个页面显示为全屏。
// 定义异步函数enterFullscreen,将整个文档元素进入全屏模式
async function enterFullscreen() {
await document.documentElement.requestFullscreen();
}
// 定义异步函数exitFullscreen,退出全屏模式
async function exitFullscreen() {
await document.exitFullscreen();
}
// 注意:为了使用 Fullscreen API,同样需要用户的交互。
注意:同样需要用户的交互才能使用 Fullscreen API。
这些API,目前在主流浏览器中都得到了很好的支持,包括Google Chrome、Mozilla Firefox、Safari和Microsoft Edge等浏览器。但是,在旧版浏览器中可能会存在一些兼容性问题。因此,在开发使用时,应该考虑到不同浏览器的兼容性问题,并根据实际情况选择是否使用这些API。
非常棒!通过本文的介绍和代码示例,相信大家已经了解了这些有用的Web API,并且知道如何使用它们来提升网站的用户体验和功能。虽然这些API在不同浏览器中的兼容性可能存在一些问题,但我们可以通过适当的兼容性检查和回退方案来确保网站的稳定性和可靠性。总之,Web API为开发者提供了强大的工具和资源,让我们一起探索并不断尝试新的技术和功能,为用户带来更好的体验和价值。
今天的分享就到这里,感谢你的阅读,希望能够帮助到你,文章创作不易,如果你喜欢我的分享,别忘了点赞转发,让更多有需要的人看到,最后别忘记关注「前端达人」,你的支持将是我分享最大的动力,后续我会持续输出更多内容,敬请期待。
原文:
https://tapajyoti-bose.medium.com/7-javascript-web-apis-to-build-futuristic-websites-you-didnt-know-12b737ccf594作者:Tapajyoti Bose
非直接翻译,有自行改编和添加部分,翻译水平有限,难免有疏漏,欢迎指正
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我正在研究使用EventMachine支持的twitter-streamrubygem来跟踪和捕获推文。我对整个事件编程有点陌生。我如何判断我在事件循环中所做的任何处理是否导致我落后?有没有简单的检查方法? 最佳答案 您可以通过使用周期性计时器并打印出耗时来确定延迟。如果您使用的是1秒的计时器,您应该已经过了大约1秒,如果它更长,您就知道您正在减慢react器的速度。@last=Time.now.to_fEM.add_periodic_timer(1)doputs"LATENCY:#{Time.now.to_f-@last}"@
我遇到了ruby正则表达式的问题。我需要找到所有(可能重叠的)匹配项。这是问题的简化:#Simpleexample"Hey".scan(/../)=>["He"]#Actualresults#Withoverlappingmatchestheresultshouldbe=>["He"],["ey"]我尝试执行并获得所有结果的正则表达式如下所示:"aaaaaa".scan(/^(..+)\1+$/)#Thislooksformultiplesof(here)"a"biggerthanonethat"fills"theentirestring."aa"*3=>true,"aaa"*2=
这里还有一个新手问题:require'tasks/rails'我在每个Rails项目的根路径中的Rakefile中看到了这一行。我猜这行用于要求vendor/rails/railties/lib/tasks/rails.rb加载所有rake任务:$VERBOSE=nil#LoadRailsrakefileextensionsDir["#{File.dirname(__FILE__)}/*.rake"].each{|ext|loadext}#LoadanycustomrakefileextensionsDir["#{RAILS_ROOT}/lib/tasks/**/*.rake"].so
在我们的项目中,我们有一些“被遗忘的”类存在了很长一段时间。那些类已被其他类替代,但我们忘记删除它们。是否有一些自动化的方法/工具可以发现Ruby{onRails}应用程序中没有使用哪些类?谢谢! 最佳答案 这个问题已经被提出了很多次,但是最好的答案都在这里:FindunusedcodeinaRailsapp我个人喜欢日志解析:https://stackoverflow.com/a/14161807但在任何情况下,您都可以创建自己的记录器,扩展ActiveRecord::Base以创建一个观察器,该观察器将最常用的模块存储在数据库中
我正在研究Ruby解释器是如何实现的,并且出现了一个问题,但我还没有得到答案。这就是标题中的那个:因为Class(r_cClass)将super设置为自身(忽略元类,因为实际上super是r_cClass的元类),如果我向Class对象发送一个方法,这将在Class的方法表中查找'类(class)。但是Class的类是Class,所以我不应该最终寻找Class的实例方法吗?但事实并非如此,因为在文档中Class类方法和Class实例方法是分开的。在Ruby的eval.c中的search_method中,我没有发现对Class类有什么特别的检查。任何人都可以阐明这一点吗?
我知道我能做到:classParentdefinitialize(args)args.eachdo|k,v|instance_variable_set("@#{k}",v)endendendclassA但我想使用关键字参数来更清楚地说明可以接受哪个散列键方法(并进行验证表明不支持此键)。所以我可以写:classAdefinitialize(param1:3,param2:4)@param1=param1@param2=param2endend但是有没有可能写一些更短的东西而不是@x=x;@y=y;...从传递的关键字参数初始化实例变量?是否可以访问作为哈希传递的关键字参数?
下面的代码通过ftp上传文件并且它有效。require'net/ftp'ftp=Net::FTP.newftp.passive=trueftp.connect("***")ftp.login("***","***")ftp.chdir"claimsecure-xml-files"ftp.putbinaryfile("file.xls",File.basename("file.xls"))ftp.quit但是如何确定上传是否成功呢? 最佳答案 之后ftp.putbinaryfile("file.xls",File.basename("
我有一个模块,其中包含名为String的类(以及其他类。)我需要按名称查找该类,如果没有这样的类,则优雅地回退。moduleMod1moduleStringendendMod1.const_get'String'#⇒Mod1::StringKernel.const_get'::Mod1::String'#⇒Mod1::String到目前为止,还不错。当我尝试查找不存在的类时,我预计会收到NameError,这很好。问题是如果在全局命名空间中存在一个具有给定名称的类,它将被返回:Mod1.const_get'Fixnum'#⇒Fixnum我明白其中的原因,但我的问题是:是否有现成的方法仅
我在尝试从它们的数组中检测某个字符串时遇到了一个奇怪的问题。有人知道这里发生了什么吗?(rdb:1)pmagic_string"TimePeriod"(rdb:1)pmagic_string.classString(rdb:1)pmagic_string=="TimePeriod"false(rdb:1)p"TimePeriod".length11(rdb:1)pmagic_string.length14(rdb:1)pmagic_string[0].chr"\357"(rdb:1)pmagic_string[1].chr"\273"(rdb:1)pmagic_string[2].c