搜索
首页web前端js教程使用 Service Worker 创建动态图像

Service Workers 是一项非常棒的技术。您可能知道它们与术语渐进式 Web 应用程序 (PWA) 相关,因此通常在浏览器上可见的内容可以“安装”在操作系统中,并且可以像本机应用程序一样打开,并像本机应用程序一样卸载,看起来就像一个本机应用程序。但服务人员能做的远不止这些。

Dynamic image creation with service workers

有关可访问性和解释,请查看此处。

Service Worker 基本上是共享的 Web Worker(顺便说一句,它作为一种单独的技术存在),具有拦截浏览器从同一 范围内的 URL 发出的所有 http 请求 的特殊能力(原始路径)worker 已注册。然后,可以指示它使用构造的或缓存的响应进行响应 - 实际上阻止浏览器通过请求访问网络 - 或者正常地将请求传递到网络或通过修改请求(使用 fetch)。

这就是说,很明显为什么 Service Worker 通常与离线时访问网页的能力相关联:第一次可以下载并缓存所有静态资源(基本上是“安装”)页面),然后 Service Worker 可以使用缓存版本响应相同的请求,基本上像本机应用程序一样提供“应用程序资源”。 dev.to 就是一个很好的例子。

这已经是一个简化,谈论缓存清除、更新和其余内容超出了本文的范围,所以我不会沉迷于此。我要讨论的是 Service Worker 提供构建响应的能力。

嘲笑回应

我的团队最近的任务是构建一个“展示”应用程序,即一个基本上不执行任何操作的 Web 应用程序,但目的是展示如何按照设计系统使用我们的 Web 组件 UI 套件以及编码指南。

该应用程序旨在作为纯粹的前端应用程序(意味着我们不应该也开发后端),但应该

看起来像我们的客户维护的众多 B2B 应用程序之一,具有后端和所有功能。这时候 Service Worker 的角色就派上用场了。

现在,通过文字回复非常简单。即使 JSON 基本上也是文本,所以最终我们的 Service Worker 可能是这样的:


self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/hello')) {
    event.respondWith(new Response(
      JSON.stringify({ message: 'Hello!' }),
      { headers: { 'Content-Type': 'application/json' }}
    );
  } else  {
    event.respondWith(fetch(event.request));
  }
});
我不会让你厌倦如何改进这个片段。 URL匹配可以使用URLPattern。您可以使用 fetch 加载静态数据并将其存储在 IndexedDB 上。你可以为此发疯。

但是其他类型的动态响应呢?喜欢图片吗?

生成图像:“简单”的方式。

生成动态图像的最简单方法是创建 SVG,它基本上是一个 XML 文档。意思是,它是文本。这是一项完全可行的任务,您可以使用 D3.js 等库为您生成 SVG 元素和路径:像 line() 和其他工厂这样的工厂返回函数,这些函数返回您需要放入 的 d 属性中的内容。元素:

self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/hello')) {
    event.respondWith(new Response(
      JSON.stringify({ message: 'Hello!' }),
      { headers: { 'Content-Type': 'application/json' }}
    );
  } else  {
    event.respondWith(fetch(event.request));
  }
});

动态生成 SVG 可以很好地让任务脱离主线程 - 而且结果甚至可以被缓存。这对于图表和信息图表来说非常有用,并且足够“简单”地完成。

生成其他图像类型

更棘手的是生成光栅图像,如PNG或JPG。 “生成”是指使用编辑工具来改变图片或从头开始创建它。在这些情况下我们通常做的是使用 。元素,获取其 2d 上下文并开始使用其许多绘图指令在其上绘画。

问题是,Service Worker 无法访问 DOM 元素。那么,我们运气不好吗?

不用担心,我的朋友们!因为所有worker(包括serviceworker)都可以创建OffscreenCanvas对象。为构造器提供以像素为单位的宽度和高度,然后您就可以在 Service Worker 中看到完美的(尽管不可见)画布:

import { pie, arc } from 'd3-shape';

const pieData = pie().sort(null)(data);
const sectorArc = arc().outerRadius(35).innerRadius(20);

const svg = '<svg viewbox="-40 -40 80 80" xmlns="http://www.w3.org/2000/svg">'
  + pieData.map((pie, index) =>
    `<path d="${sectorArc(pie)}" fill="${colors[index]}"></path>`
  ).join('')
  + '</svg>';

event.respondWith(new Response(
  svg, { headers: { 'Content-Type': 'image/svg+xml' }}
));

对于那些想知道的人:是的,您可以获得不同类型的上下文,尽管并非所有浏览器都可用。您可以尝试使用诸如 Three.js 这样的库在 Service Worker 中生成 3D 场景(我想我稍后会尝试)。

现在我们基本上可以做任何事情。绘制直线、弧线、路径等。甚至修改画布的几何形状。这就像在 DOM 画布上下文上绘图一样简单,所以我不会沉迷于这部分。

绘图文字

我们确实也可以写文字。这很重要,因为在其他环境中 - 即 Paint 工作集,我们不能这样做:

注意:PaintRenderingContext2D 实现了 CanvasRenderingContext2D API 的子集。具体来说,它没有实现 CanvasImageData、CanvasUserInterface、CanvasText 或 CanvasTextDrawingStyles API。

但对于 Service Worker 来说,这一切都很好。这意味着我们有一个更强大(尽管性能较差)的环境来生成背景图像。

绘制文本就这么简单:

const canvas = new OffscreenCanvas(800, 600);
const context = canvas.getContext('2d');

可以使用你喜欢的字体,但我发现通常的标准值,如 sans-serif、等宽字体或 system-ui 似乎不起作用,因为它们都会回退到默认衬线字体。但您可以照常使用字体堆栈:

context.fillStyle = '#222';
context.font = '24px serif';
// (x, y) = (50, 90) will be the *bottom left* corner of the text
context.fillText('Hello, world!', 50, 90);

此外,您可以使用字体加载API从外部资源加载字体:

self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/hello')) {
    event.respondWith(new Response(
      JSON.stringify({ message: 'Hello!' }),
      { headers: { 'Content-Type': 'application/json' }}
    );
  } else  {
    event.respondWith(fetch(event.request));
  }
});

发送回应用程序

发回响应就像调用 ConvertToBlob 方法一样简单,该方法返回一个 Blob(你猜对了)的承诺。并且 Blob 可以轻松发送回发件人。

import { pie, arc } from 'd3-shape';

const pieData = pie().sort(null)(data);
const sectorArc = arc().outerRadius(35).innerRadius(20);

const svg = '<svg viewbox="-40 -40 80 80" xmlns="http://www.w3.org/2000/svg">'
  + pieData.map((pie, index) =>
    `<path d="${sectorArc(pie)}" fill="${colors[index]}"></path>`
  ).join('')
  + '</svg>';

event.respondWith(new Response(
  svg, { headers: { 'Content-Type': 'image/svg+xml' }}
));

该方法默认创建一个 PNG 图像,但可以指示创建一个 JPG 文件,如上所示。 “image/webp”是另一种常见格式,但 Safari 不支持它。老实说,这里的选择有点令人印象深刻,因为新可用且功能更强大的图像格式解码器并未反映在其相应的编码器中。但这对于大多数用途来说已经足够了。

有趣的事实:convertToBlob 方法特定于 OffscreenCanvas 类。 HTMLCanvasElements 具有 toBlob,它采用回调作为第一个参数,采用常见的前 Promise 时代异步任务处理风格。

使用模板图像

现在,如果我们想要从头开始创建图片,这一切都有效。但是如果我们想从空白模板开始怎么办?

如果我们要在主线程中工作,我们可以使用 2D 上下文的 drawImage 方法在上下文中绘制图片,例如获取它来自现成的 使用 Service Worker 创建动态图像元素。

问题再次出现,我们无法访问 DOM,因此无法引用 使用 Service Worker 创建动态图像元素。相反,我们可以做的是,它获取我们需要作为背景的图片,获取其Blob,然后将其转换为drawImage可以消化的其他内容。输入 createImageBitmap,这是一个在 Service Worker 中也可用的全局方法。它返回一个 ImageBitmap 实例的承诺,这是前端 Web 开发中许多鲜为人知的类之一。它显然在 WebGL 上下文中使用更广泛,但 drawImage 似乎接受它,所以...

const canvas = new OffscreenCanvas(800, 600);
const context = canvas.getContext('2d');

从现在开始,我们可以继续在其上绘制涂鸦和文本,创建令人满意的同步图像并发回给用户。

注意:使用 SVG 可以更轻松地解决这个问题,因为您可以只使用 元素设置背景图片。但这意味着浏览器必须在发送生成的图像之后加载图片,而使用这种技术,这是在之前完成的。选择字体时也有类似的情况。

将所有内容放在一起

在所有这些示例中,我使用了模块服务工作者(即我使用了从其他ES模块导入)。遗憾的是,Firefox 尚不支持模块服务工作者,但希望很快就会支持。与此同时,您可能需要调整代码以使用旧的 importScripts。

通过 import 或 importScripts 将其他脚本导入服务工作人员时,请记住,当导入的文件发生更改时,浏览器将不会触发 updatefound 事件:它在以下情况下触发Service Worker 入口脚本发生变化。

在像我们这样的情况下,服务工作者只需要模拟后端的存在,它的生命周期可以通过在安装事件触发时立即调用 self.skipWaiting() 来缩短,然后调用 self.在激活事件上调用clients.claim(),以便能够立即响应请求(否则,它只会在下一页刷新时启动)。

self.addEventListener('fetch', event => {
  if (event.request.url.includes('/api/hello')) {
    event.respondWith(new Response(
      JSON.stringify({ message: 'Hello!' }),
      { headers: { 'Content-Type': 'application/json' }}
    );
  } else  {
    event.respondWith(fetch(event.request));
  }
});

这基本上就是一切,所以...和服务人员一起玩吧,伙计们!

以上是使用 Service Worker 创建动态图像的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

node.js流带打字稿node.js流带打字稿Apr 30, 2025 am 08:22 AM

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python vs. JavaScript:性能和效率注意事项Python vs. JavaScript:性能和效率注意事项Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript的起源:探索其实施语言JavaScript的起源:探索其实施语言Apr 29, 2025 am 12:51 AM

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。