使用 Service Worker 创建动态图像
Service Workers 是一项非常棒的技术。您可能知道它们与术语渐进式 Web 应用程序 (PWA) 相关,因此通常在浏览器上可见的内容可以“安装”在操作系统中,并且可以像本机应用程序一样打开,并像本机应用程序一样卸载,看起来就像一个本机应用程序。但服务人员能做的远不止这些。
有关可访问性和解释,请查看此处。
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)); } });
但是其他类型的动态响应呢?喜欢图片吗?
生成图像:“简单”的方式。
生成动态图像的最简单方法是创建 SVG,它基本上是一个 XML 文档。意思是,它是文本。这是一项完全可行的任务,您可以使用 D3.js 等库为您生成 SVG 元素和路径:像 line() 和其他工厂这样的工厂返回函数,这些函数返回您需要放入
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。 “生成”是指使用编辑工具来改变图片或从头开始创建它。在这些情况下我们通常做的是使用
问题是,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 方法在上下文中绘制图片,例如获取它来自现成的 元素。
问题再次出现,我们无法访问 DOM,因此无法引用 元素。相反,我们可以做的是,它获取我们需要作为背景的图片,获取其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中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

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

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

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

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

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

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

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

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

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