> 웹 프론트엔드 > JS 튜토리얼 > 서비스 워커를 사용한 동적 이미지 생성

서비스 워커를 사용한 동적 이미지 생성

Patricia Arquette
풀어 주다: 2024-11-19 18:00:04
원래의
250명이 탐색했습니다.

서비스 직원은 환상적인 기술입니다. PWA(Progressive Web Application)라는 용어와 관련하여 이를 알 수 있으므로 일반적으로 브라우저에 표시되는 항목이 OS에 "설치"될 수 있고 기본 애플리케이션처럼 열릴 수도 있고 기본 애플리케이션처럼 제거될 수도 있습니다. 모든 면에서 기본 애플리케이션처럼 보입니다. 하지만 서비스 작업자는 그 이상을 할 수 있습니다.

Dynamic image creation with service workers

접근성 및 설명은 여기를 참조하세요.

서비스 워커는 기본적으로 동일한 범위에 있는 URL에서 브라우저가 만든 모든 http 요청을 가로채는 특별한 기능을 갖춘 공유 웹 워커(별도의 기술로 존재)입니다. (원본 경로) 작업자가 등록되었습니다. 그런 다음 구성된 응답이나 캐시된 응답으로 응답하도록 지시할 수 있습니다(실제로 브라우저가 요청으로 네트워크에 접속하는 것을 방지함). 또는 요청을 정상적으로 네트워크에 전달하거나 요청을 수정(가져오기 사용)하여.

즉, 서비스 워커가 오프라인일 때 웹 페이지에 액세스하는 기능과 종종 연관되는 이유는 분명합니다. 처음으로 모든 정적 리소스를 다운로드하고 캐시할 수 있습니다(기본적으로 "설치"). 페이지) 그러면 서비스 워커는 캐시된 버전으로 동일한 요청에 응답할 수 있으며 기본적으로 기본 앱인 것처럼 "애플리케이션 리소스"를 제공할 수 있습니다. dev.to가 그 좋은 예입니다.

이미 단순화한 내용이고 캐시 무효화, 업데이트 및 기타 사항에 대한 이야기는 이 기사의 범위를 벗어나므로 이에 대해서는 다루지 않겠습니다. 제가 이야기할 것은 구성된 응답

을 제공하는 서비스 워커의 능력입니다.

조롱 응답

저희 팀은 최근 "쇼케이스" 애플리케이션, 즉 기본적으로 아무 것도 하지 않지만 디자인 시스템에 따라 웹 구성 요소 UI 키트를 사용하는 방법을 보여주는 웹 애플리케이션을 구축하는 임무를 받았습니다. 그리고 코딩 가이드 라인.

이제 텍스트 응답으로 응답하는 것은 매우 간단합니다. JSON도 기본적으로 텍스트이므로 결국 서비스 워커는 다음과 같을 수 있습니다.


이 스니펫이 어떻게 개선될 수 있는지에 대해 지루하게 여기지는 않겠습니다. URL 일치는 URLPattern을 사용할 수 있습니다. 가져오기를 사용하여 정적 데이터를 로드하고 IndexedDB에 저장할 수 있습니다. 그러면 정말 미쳐버릴 것 같아요.

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));
  }
});
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사
그렇다면 다른 종류의 동적 반응은 어떨까요? 이미지가 마음에 드시나요?

이미지 생성: "쉬운" 방법.

동적 이미지를 생성하는 가장 쉬운 방법은 기본적으로 XML 문서인 SVG를 만드는 것입니다. 즉, 텍스트입니다. 이는 완전히 실행 가능한 작업이며 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 컨텍스트를 얻고 다양한 그리기 지시문을 사용하여 그림을 그리기 시작합니다.

문제는 서비스 워커가 DOM 요소에 접근할 수 없다는 것입니다. 그럼 우리는 운이 없는 걸까요?

걱정하지 마세요, 친구들! 모든 작업자(서비스 작업자 포함)가 OffscreenCanvas 개체를 생성할 수 있기 때문입니다. 생성자에게 너비와 높이를 픽셀 단위로 지정하면 서비스 워커에서 완벽하게 미세한(눈에 보이지는 않지만) 캔버스를 얻을 수 있습니다.

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와 같은 라이브러리를 사용하여 서비스 워커에서 3D 장면을 생성해 볼 수 있습니다(나중에 시도해 볼 것 같습니다).

이제 기본적으로... 무엇이든 할 수 있습니다. 선, 호, 경로 등을 그립니다. 캔버스의 형상도 수정합니다. DOM 캔버스 컨텍스트에 그림을 그리는 것만큼 간단하므로 이 부분은 다루지 않겠습니다.

텍스트 그리기

실제로 텍스트도 쓸 수 있습니다. 이는 다른 환경, 즉 Paint worklet에서는 그렇게 할 수 없기 때문에 중요합니다.

참고: PaintRenderingContext2D는 CanvasRenderingContext2D API의 하위 집합을 구현합니다. 특히 CanvasImageData, CanvasUserInterface, CanvasText 또는 CanvasText DrawingStyles API를 구현하지 않습니다.

그러나 서비스 워커에서는 이 모든 것이 괜찮습니다. 이는 배경 이미지를 생성할 수 있는 더 강력한(비록 성능은 떨어지지만) 환경을 갖추고 있음을 의미합니다.

텍스트 그리기는 다음과 같이 쉽습니다.

const canvas = new OffscreenCanvas(800, 600);
const context = canvas.getContext('2d');
로그인 후 복사
로그인 후 복사

여기에서 원하는 글꼴을 사용할 수 있습니다. 하지만 산세리프, 모노스페이스 또는 시스템 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);
로그인 후 복사

또한 Font Loading 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));
  }
});
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

애플리케이션으로 다시 보내기

응답을 다시 보내는 것은 Blob이라는 약속을 반환하는 ConvertToBlob 메서드를 호출하는 것만큼 쉽습니다. 그리고 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에는 비동기 작업 처리의 일반적인 Promise 시대 이전 스타일에서 콜백을 첫 번째 인수로 사용하는 toBlob이 있습니다.

템플릿 이미지 사용

이제 처음부터 그림을 만들고 싶다면 이 모든 것이 가능합니다. 하지만 빈 템플릿에서 시작하고 싶다면 어떻게 해야 할까요?

메인 스레드에서 작업한다면 2D 컨텍스트의 drawImage 메서드를 사용하여 컨텍스트에 그림을 삽입할 수 있습니다. 쉽게 사용할 수 있는 요소.

다시 한 번 문제는 DOM에 액세스할 수 없어서 강요. 우리가 할 수 있는 대신에 필요한 그림을 배경으로 가져와 Blob을 가져온 다음 drawImage가 소화할 수 있는 다른 것으로 변환합니다. 서비스 워커에서도 사용할 수 있는 전역 메서드인 createImageBitmap을 입력합니다. 프런트엔드 웹 개발의 잘 알려지지 않은 클래스 중 하나인 ImageBitmap 인스턴스에 대한 Promise를 반환합니다. 분명히 WebGL 컨텍스트에서 더 널리 사용되지만 drawImage에서는 이를 허용하는 것 같아서...

const canvas = new OffscreenCanvas(800, 600);
const context = canvas.getContext('2d');
로그인 후 복사
로그인 후 복사

이 시점부터 계속해서 낙서와 텍스트를 그려 만족스러운 동적인 이미지를 만들어 사용자에게 다시 보낼 수 있습니다.

참고: 이 문제는 SVG를 사용하면 더 쉽게 해결할 수 있습니다. 배경 그림을 설정하는 요소입니다. 하지만 이는 생성된 이미지가 전송된 브라우저가 사진을 로드해야 함을 의미하는 반면, 이 기술을 사용하면 이 작업이 전에 수행됩니다. 글꼴을 선택할 때도 비슷한 내용이 적용됩니다.

모두 합치기

이러한 모든 예에서는 모듈 서비스 워커를 사용했습니다(즉, 다른 ES 모듈에서 가져오기를 사용했습니다). 아쉽게도 모듈 서비스 워커는 아직 Firefox에서 지원되지 않지만 곧 지원될 예정입니다. 그동안에는 기존 importScript를 대신 사용하도록 코드를 조정해야 할 수도 있습니다.

import 또는 importScripts를 통해 다른 스크립트를 서비스 워커로 가져올 때, 가져온 파일이 변경될 때 브라우저는 updatefound 이벤트를 발생 않습니다. 이 이벤트는 오직 서비스워커 입력 스크립트가 변경됩니다.

우리와 같이 서비스 워커가 백엔드의 존재를 조롱하는 데만 필요한 경우, 설치 이벤트가 시작될 때 self.skipWaiting()을 호출한 다음 self를 호출하여 서비스 워커의 수명 주기를 단축할 수 있습니다. 요청에 즉시 응답할 수 있도록 activate 이벤트에 클라이언트.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));
  }
});
로그인 후 복사
로그인 후 복사
로그인 후 복사
로그인 후 복사

그리고 이것이 기본적으로 전부이므로... 서비스 직원들과 함께 즐거운 시간 보내세요!

위 내용은 서비스 워커를 사용한 동적 이미지 생성의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿