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

使用 Service Worker 创建动态图像

Nov 19, 2024 pm 06:00 PM

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]}"/>`
  ).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]}"/>`
  ).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

热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

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

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

前端开发中如何实现类似 VSCode 的面板拖拽调整功能? 前端开发中如何实现类似 VSCode 的面板拖拽调整功能? Apr 04, 2025 pm 02:06 PM

探索前端中类似VSCode的面板拖拽调整功能的实现在前端开发中,如何实现类似于VSCode...

See all articles