超有用的 Web API.docx - Word

信息来源

清单

相关demo 的源码,可以从 juejinBlogsCodes WebApi 获取。

名称 功能
Screen Wake Lock API 能够防止设备因为闲置而自动调低亮度或锁定屏幕
Cookie Store API 更加便捷获取和设置cookie的信息
Compression Stream API 使用 gzip 或者默认格式压缩和解压缩数据
CSS Custom Highlight API JavaScript 创建范围并使用 CSS 定义样式来设置文档中任意文本范围的样式
EyeDropper 从屏幕上选择颜色
Prioritized Task Scheduling API 对任务优先级进行控制
Trusted Types API 为Web开发者提供了一种锁定DOM(文档对象模型)API中易受攻击部分的方法
CSS Font Loading API 动态加载字体资源的事件和接口
Popover API 内置的弹框能力
URL Pattern API URL匹配器, 类似path-to-regex
Audio Output Devices API 音频输出选择能力
Device Memory API 获取内存信息
Barcode Detection API 用于检测图像中的条形码和二维码

Screen Wake Lock API

Screen Wake Lock API 提供了一种方法,使得当应用程序需要保持运行时,能够防止设备因为闲置而自动调低亮度或锁定屏幕。 这对于诸如视频会议、演示文稿、实时游戏、在线教育等需要用户持续关注且不允许屏幕熄灭的应用场景尤其有用。通过使用这个API,即使在没有用户交互的情况下,开发者也能确保屏幕始终保持开启状态。

简简单单30行代码,就能控制和监听 屏幕唤醒锁。

<button onclick="onLockScreen()">锁屏</button>
    <button onclick="onUnlockScreen()">释放</button>

    <div id="statusElem"></div>
    <script>
        let wakeLock = null;
        async function onLockScreen() {
            // create an async function to request a wake lock
            try {
                wakeLock = await navigator.wakeLock.request("screen");
                statusElem.textContent = "唤醒锁已激活";

                wakeLock.addEventListener("release", () => {
                    // the wake lock has been released
                    statusElem.textContent = "唤醒锁已释放";
                });
            } catch (err) {
                // The Wake Lock request has failed - usually system related, such as battery.
                statusElem.textContent = `${err.name}, ${err.message}`;
            }
        }
        async function onUnlockScreen() {
            if (!wakeLock) return;
            wakeLock.release().then(() => {
                wakeLock = null;
            });
        }
    </script>

Compression Stream API

Compression Stream API 提供了一种 JavaScript API,使用 gzip 或者默认格式压缩和解压缩数据流。 内置的压缩库意味着 JavaScript 应用不再需要包含其它压缩库,这使得应用程序的下载大小更小。

代码嘛,简简单单。

<input type="file" id="file" >
    <script>
        async function compressAndDownload(filename, content) {
            // 创建原始数据流
            const stringStream = new ReadableStream({
                start(controller) {
                    controller.enqueue(new TextEncoder().encode(content));
                    controller.close();
                }
            });

            // 创建压缩流
            const compressionStream = new CompressionStream('gzip');

            // 将原始数据流连接到压缩流
            const compressedStream = stringStream.pipeThrough(compressionStream);

            // 创建ArrayBuffer容器接收压缩数据
            const chunks = [];
            const reader = compressedStream.getReader();
            try {
                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;
                    chunks.push(value);
                }
            } finally {
                reader.releaseLock();
            }

            // 合并压缩数据并创建Blob
            const compressedBlob = new Blob(chunks, { type: 'application/gzip' });

            // 创建下载链接
            const url = URL.createObjectURL(compressedBlob);
            const link = document.createElement('a');
            link.href = url;
            link.download = `${filename}.gz`;
            document.body.appendChild(link);

            // 触发下载
            link.click();

            // 清理
            setTimeout(() => {
                document.body.removeChild(link);
                URL.revokeObjectURL(url);
            }, 0);
        }


        file.addEventListener('change', async (event) => {
            if(event.target.files.length === 0){
                return;
            }
            const file = event.target.files[0];
            const reader = new FileReader();
            reader.readAsText(event.target.files[0]);
            reader.onload = async () => {
                const content = reader.result;
                compressAndDownload(file.name, content);
            }
        })
    </script>

CSS Custom Highlight API

CSS 自定义高亮 API 提供了一种方法,可以通过使用 JavaScript 创建范围并使用 CSS 定义样式来设置文档中任意文本范围的样式。

可以去 MDN 在线的示例 进行实操 CSS Custom Highlight API#Result

其逻辑是就是查找所有文本节点,收集匹配内容的 Range, 最后作为参数构建 HighLight对象, 需要注意的是其 <b>并未产生新的节点</b>

核心逻辑代码如下:

const query = document.getElementById("query");
const article = document.querySelector("article");

// Find all text nodes in the article. We'll search within these text nodes.
const treeWalker = document.createTreeWalker(article, NodeFilter.SHOW_TEXT);
const allTextNodes = [];
let currentNode = treeWalker.nextNode();
while (currentNode) {
  allTextNodes.push(currentNode);
  currentNode = treeWalker.nextNode();
}
// Listen to the input event to run the search.
query.addEventListener("input", () => {
  // If the CSS Custom Highlight API is not supported, display a message and bail-out.
  if (!CSS.highlights) {
    article.textContent = "CSS Custom Highlight API not supported.";
    return;
  }

  // Clear the HighlightRegistry to remove the previous search results.
  CSS.highlights.clear();

  // Clean-up the search query and bail-out if if it's empty.
  const str = query.value.trim().toLowerCase();
  if (!str) {
    return;
  }

  // Iterate over all text nodes and find matches.
  const ranges = allTextNodes
    .map((el) => {
      return { el, text: el.textContent.toLowerCase() };
    })
    .map(({ text, el }) => {
      const indices = [];
      let startPos = 0;
      while (startPos < text.length) {
        const index = text.indexOf(str, startPos);
        if (index === -1) break;
        indices.push(index);
        startPos = index + str.length;
      }

      // Create a range object for each instance of str we found in the text node.
      return indices.map((index) => {
        const range = new Range();
        range.setStart(el, index);
        range.setEnd(el, index + str.length);
        return range;
      });
    });

  // Create a Highlight object for the ranges.
  const searchResultsHighlight = new Highlight(...ranges.flat());

  // Register the Highlight object in the registry.
  CSS.highlights.set("search-results", searchResultsHighlight);
});

EyeDropper

可以打开并使用它从屏幕上选择颜色。

记住了,是从屏幕上拾取颜色

基于这个做个取色插件,是不是分分钟就搞定呢?

代码,简简单单二三十行:

<button id="start-button">打开拾色器</button>
    <img src="https://img.alicdn.com/imgextra/i1/O1CN01CC9kic1ig1r4sAY5d_!!6000000004441-2-tps-880-210.png" />
    <div>
        颜色是:<span id="result"></span>
    </div>
    <script>
        document.getElementById("start-button").addEventListener("click", () => {
            const resultElement = document.getElementById("result");

            if (!window.EyeDropper) {
                resultElement.textContent = "你的浏览器不支持 EyeDropper API";
                return;
            }

            const eyeDropper = new EyeDropper();
            const abortController = new AbortController();

            eyeDropper
                .open({ signal: abortController.signal })
                .then((result) => {
                    resultElement.textContent = result.sRGBHex;
                    resultElement.style.backgroundColor = result.sRGBHex;
                })
                .catch((e) => {
                    resultElement.textContent = e;
                });
        });

    </script>

Prioritized Task Scheduling API

提供了一种标准化的方法,用于对属于应用程序的所有任务进行优先级排序。

优先级任务调度API允许开发者为异步任务分配优先级,这些任务按照以下三种优先级顺序执行:

  1. user-blocking这类任务优先级最高 ,它们直接影响用户的交互体验。这类任务主要包括页面渲染至可交互状态的过程,以及对用户输入的即时响应。例如,页面初次加载的核心内容渲染、按钮点击事件的处理等。
  2. user-visible : 这类任务虽可见于用户界面,但并不阻止用户继续进行其他操作。这类任务包括渲染页面的非关键部分,例如非核心图片加载、非关键动画渲染等。这是默认的优先级等级。
  3. background优先级最低的一类任务 ,它们对时间要求不严苛,可以在不影响用户体验的前提下稍后执行。这类任务包括日志处理、非必需的第三方库初始化以及其他不影响页面即时呈现的工作。这些任务通常在主线程空闲时执行,以避免阻塞用户可见或交互相关的高优先级任务。

欸,这就给高端玩家无限遐想了,只能一个字表达 太牛了

下面一个例子,来看看优先级的输出情况, 可以看到,如你所愿:

<div id="log"></div>
    <script>
        let log = document.getElementById("log");
        function mylog(text) {
            log.innerHTML += `${text}<br/>`;
        }

        // three tasks, in reverse order of priority
        scheduler.postTask(() => mylog("background 1"), { priority: "background" });
        scheduler.postTask(() => mylog("user-visible 1"), { priority: "user-visible" });
        scheduler.postTask(() => mylog("user-blocking 1"), { priority: "user-blocking" });

        // three more tasks, in reverse order of priority
        scheduler.postTask(() => mylog("background 2"), { priority: "background" });
        scheduler.postTask(() => mylog("user-visible 2"), { priority: "user-visible" });
        scheduler.postTask(() => mylog("user-blocking 2"), { priority: "user-blocking" });

        // Task with default priority: user-visible
        scheduler.postTask(() => mylog("user-visible 3 (default)"));

    </script>

Trusted Types API

为Web开发者提供了一种锁定DOM API中不安全部分的方法,目的是防止客户端跨站脚本(Cross-site scripting,XSS)攻击

在下面的例子中,通过 TrustedTypePolicyFactory.createPolicy()方法创建一个策略,通过 TrustedTypePolicy.createHTML方法创建一个安全的HTML字符串插入到文档中。

有很大的灵活性,策略是自己可以定义的。

<div id="myDiv"></div>

    <script>

        var entityMap = {
            "&": "&",
            "<": "<",
            ">": ">",
            '"': '"',
            "'": ''',
            "/": '/'
        };
        // 创建一个策略,该策略将用于将不受信任的输入转换为安全的内容。
        const escapeHTMLPolicy = trustedTypes.createPolicy("myEscapePolicy", {
            createHTML: (string) => string.replace(/[&<>"'/]/g, function (s) {
                return entityMap[s];
            }),
        });

        let el = document.getElementById("myDiv");
        const escaped = escapeHTMLPolicy.createHTML("<img src=x onerror=alert(1)>");
        console.log(escaped instanceof TrustedHTML); // true
        el.innerHTML = escaped;

    </script>

除此之外,还可以用来创建用来检查 ScriptScriptURL的策略。

const policy = trustedTypes.createPolicy("myPolicy", {
  createScriptURL: (s, type, sink) => { //......},
  createScript: (s) => { //......}
});

CSS Font Loading API

CSS 字体加载 API 为你提供了动态加载字体资源的事件和接口。

以往引入字体主要是靠 css 来实现的, 动态引入字体也可以通过动态添加 link节点来实现。

@font-face {
2  font-family: 'MyCustomFont';
3  src: url('fonts/mycustomfont.woff2') format('woff2'),
4       url('fonts/mycustomfont.woff') format('woff');
5  font-weight: normal;
6  font-style: normal;
7}

现在呢, 内置了原生AP, 能动态加载字体,而且能控制加载时机,以及加载的状态。

const font = new FontFace("myfont", "url(myfont.woff)", {
  style: "italic",
  weight: "400",
  stretch: "condensed",
});

// 加载字体
font.load().then(()=>{
    // 加载完毕
},  (err) => {
    // 加载异常
    console.error(err);
},);

// 等待到所有的字体都加载完毕
document.fonts.ready.then(() => {
  // 使用该字体渲染文字(如:在 canvas 中绘制)
});

Audio Output Devices API

音频输出设备API(Audio Output Devices API)赋予了Web应用程序能力,使其能够询问用户希望使用哪个音频输出设备进行声音播放。

欸, 可以选择音频输出设备,还是比较有意思的。协议原文 Audio Output Devices API, 可惜还没有浏览器支持。

document.querySelector("#myButton").addEventListener("click", async () => {
  if (!navigator.mediaDevices.selectAudioOutput) {
    console.log("selectAudioOutput() not supported or not in secure context.");
    return;
  }

  // Display prompt to select device
  const audioDevice = await navigator.mediaDevices.selectAudioOutput();

  // Create an audio element and start playing audio on the default device
  const audio = document.createElement("audio");
  audio.src = "https://example.com/audio.mp3";
  audio.play();

  // Change the sink to the selected audio output device.
  audio.setSinkId(audioDevice.deviceId);
});

Device Memory API

传统上,开发人员评估客户端设备性能时,由于无法直接获取设备的RAM大小信息,他们往往需要采取一些经验法则,或是通过设备基准测试,抑或是根据设备制造商、用户代理(User Agent)字符串等其他因素间接推测设备能力。

但现在,有以下两种方法可以直接或间接确定设备的大致RAM量:

  1. Device Memory JavaScript API : 这个API为开发者提供了一种直接了解设备内存(RAM)容量的方式。通过 navigator.deviceMemory属性,可以获得设备内存级别的大致信息,如0.5表示小于1GB的RAM,1表示1-2GB,以此类推。
  2. 接受Client Hints : 客户端提示(Client Hints)是一种HTTP协议扩展,允许浏览器在HTTP请求中主动发送设备能力相关信息。其中,Device-Memory HTTP请求头就包含了设备的内存类别信息。虽然这不是直接在JavaScript中获取,但服务器可以根据这个头信息动态调整响应内容,帮助开发者根据设备RAM大小优化用户体验。
const RAM = navigator.deviceMemory;  // 8

值是 0.25, 0.5, 1, 2, 48之一,所以机器 16G内存,显示的也是8。

Barcode Detection API

用于检测图像中的条形码和二维码。

欸, 这就很有意思,配和 navigator.mediaDevices.getUserMedia唤起摄像头,定期截图分析,是不是就是一个web版本的扫码能力呢?

if (!("BarcodeDetector" in globalThis)) {
  console.log("此浏览器不支持条形码检测器。");
} else {
  console.log("条形码检测器是支持的!");

  // 创建新检测器
  const barcodeDetector = new BarcodeDetector({
    formats: ["code_39", "codabar", "ean_13"],
  });

    barcodeDetector
      .detect(imageEl)
      .then((barcodes) => {
        barcodes.forEach((barcode) => console.log(barcode.rawValue));
      })
      .catch((err) => {
        console.log(err);
      });

}
第1页,共1页
本文共0个字符
中文(中国)
辅助功能
文档日期2024-03-18 11:32:09