CSS 페인트 API

Chrome 65의 새로운 가능성

CSS 페인트 API('CSS 사용자설정 페인트' 또는 'Houdini의 페인트 워크릿'이라고도 함)는 Chrome 65부터 기본적으로 사용 설정됩니다. 기본 설명 취할 수 있는 조치 사용할 수 있나요? 어떻게 작동하나요? 자, 계속 읽어 볼까요?

CSS Paint API를 사용하면 CSS가 속성에는 이미지가 필요합니다. 속성(예: background-image 또는 border-image) 일반적으로 이미지 파일을 로드할 때 url()와 함께 사용되거나 CSS가 기본 제공되어 사용됩니다. linear-gradient()와 같은 함수가 포함됩니다. 이러한 기능을 사용하는 대신 이제 paint(myPainter): 페인트 Worklet을 참조합니다.

페인트 작업 도구 작성

myPainter라는 페인트 Worklet을 정의하려면 CSS 페인트를 로드해야 합니다. CSS.paintWorklet.addModule('my-paint-worklet.js')을 사용하여 worklet 파일을 만듭니다. 그 안에서 파일에서 registerPaint 함수를 사용하여 페인트 Worklet 클래스를 등록할 수 있습니다.

class MyPainter {
  paint(ctx, geometry, properties) {
    // ...
  }
}

registerPaint('myPainter', MyPainter);

paint() 콜백 내에서 ctx <canvas>에서 가져온 CanvasRenderingContext2D입니다. kubectl 명령어 <canvas>에서 그릴 수 있는 경우 페인트 Worklet에서 그릴 수 있습니다. geometry는 만들 수 있는 캔버스의 너비와 높이입니다. properties 요청사항 이 도움말의 뒷부분에서 설명합니다.

입문 예로, 격자무늬 페인트 워크렛을 작성하여 <textarea>의 배경 이미지로 사용할 수 있습니다. (텍스트 영역을 사용하는 이유는 크기를 조절할 수 있습니다.)

<!-- index.html -->
<!doctype html>
<style>
  textarea {
    background-image: paint(checkerboard);
  }
</style>
<textarea></textarea>
<script>
  CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
  paint(ctx, geom, properties) {
    // Use `ctx` as if it was a normal canvas
    const colors = ['red', 'green', 'blue'];
    const size = 32;
    for(let y = 0; y < geom.height/size; y++) {
      for(let x = 0; x < geom.width/size; x++) {
        const color = colors[(x + y) % colors.length];
        ctx.beginPath();
        ctx.fillStyle = color;
        ctx.rect(x * size, y * size, size, size);
        ctx.fill();
      }
    }
  }
}

// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);

이전에 <canvas>를 사용한 적이 있다면 이 코드가 익숙할 것입니다. 자세한 내용은 라이브 데모 여기에서 확인하세요.

배경 이미지로 격자무늬 패턴이 있는 텍스트 영역
배경 이미지로 격자무늬 패턴이 있는 텍스트 영역

여기서 일반적인 배경 이미지를 사용하는 것과는 다른 점은 패턴이 가 다시 그려집니다. 다시 말해 배경 이미지는 고밀도 디스플레이에 대한 보상이 있습니다.

꽤 멋지지만 상당히 정적이기도 합니다. 새로운 YAML 파일을 동일한 패턴을 원했지만 크기가 다른 Worklet을 반환할 때마다 정사각형 그렇지 않습니다.

Worklet의 매개변수화

다행히 페인트 Worklet은 다른 CSS 속성에 액세스할 수 있습니다. CSS 속성은 추가 매개변수 properties가 사용됩니다. 클래스에 정적 inputProperties 속성이 있는 경우 모든 CSS 속성의 변경사항을 구독할 수 있습니다. 여기에는 맞춤 속성도 포함됩니다. 값은 properties 매개변수

<!-- index.html -->
<!doctype html>
<style>
  textarea {
    /* The paint worklet subscribes to changes of these custom properties. */
    --checkerboard-spacing: 10;
    --checkerboard-size: 32;
    background-image: paint(checkerboard);
  }
</style>
<textarea></textarea>
<script>
  CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
  // inputProperties returns a list of CSS properties that this paint function gets access to
  static get inputProperties() { return ['--checkerboard-spacing', '--checkerboard-size']; }

  paint(ctx, geom, properties) {
    // Paint worklet uses CSS Typed OM to model the input values.
    // As of now, they are mostly wrappers around strings,
    // but will be augmented to hold more accessible data over time.
    const size = parseInt(properties.get('--checkerboard-size').toString());
    const spacing = parseInt(properties.get('--checkerboard-spacing').toString());
    const colors = ['red', 'green', 'blue'];
    for(let y = 0; y < geom.height/size; y++) {
      for(let x = 0; x < geom.width/size; x++) {
        ctx.fillStyle = colors[(x + y) % colors.length];
        ctx.beginPath();
        ctx.rect(x*(size + spacing), y*(size + spacing), size, size);
        ctx.fill();
      }
    }
  }
}

registerPaint('checkerboard', CheckerboardPainter);

이제 서로 다른 모든 종류의 격자무늬에 동일한 코드를 사용할 수 있습니다. 그러나 이제 DevTools로 이동하여 값을 조작할 수 있습니다. 올바른 스타일을 찾을 때까지

페인트 Worklet을 지원하지 않는 브라우저

이 문서 작성 시점에는 Chrome에만 페인트 Worklet이 구현되어 있습니다. 거기에 있는 동안 다른 모든 브라우저 공급업체에서 제공하는 긍정적인 신호이기 때문에 별다른 진전이 없습니다. 최신 정보를 확인하려면 Houdini 준비가 되었나요?를 확인하세요. 정기적으로 개선해야 합니다 그동안에는 프로그레시브를 사용하여 페인트 지원이 없더라도 코드가 계속 실행되도록 Worklet의 일환입니다. 예상대로 작동하도록 하려면 CSS와 JS라는 두 가지 위치가 있습니다.

CSS 객체를 확인하여 JS에서 페인트 Worklet 지원을 감지할 수 있습니다. js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } CSS 측면에서는 두 가지 옵션이 있습니다. 다음과 같이 @supports를 사용할 수 있습니다.

@supports (background: paint(id)) {
  /* ... */
}

더 간단한 요령은 CSS가 무효화되고 이후에 알 수 없는 함수가 있는 경우 전체 속성 선언을 무시합니다. 만약 속성을 두 번 지정합니다. 첫째, 페인트 Worklet을 사용하지 않고, 그 다음 다음과 같이 점진적으로 개선됩니다.

textarea {
  background-image: linear-gradient(0, red, blue);
  background-image: paint(myGradient, red, blue);
}

페인트 Worklet을 지원 있는 브라우저에서는 background-image은(는) 첫 번째 항목을 덮어씁니다. 지원되지 않는 브라우저 페인트 Worklet의 경우 두 번째 선언이 유효하지 않으므로 삭제됩니다. 첫 번째 선언이 적용됩니다

CSS 페인트 폴리필

많은 경우 CSS 페인트 폴리필 는 최신 브라우저에 CSS 맞춤 페인트 및 페인트 Worklet 지원을 추가합니다.

사용 사례

페인트 워크릿의 사용 사례는 많지만 일부는 페인트 워크릿보다 기타 등등 가장 명백한 방법 중 하나는 페인트 Worklet을 사용하여 크기를 줄이는 것입니다. 정의합니다. 요소가 단순히 장식을 만들기 위해서만 추가되는 경우가 많습니다. 있습니다. 예를 들어 Material Design Lite에서는 버튼이 에는 2개의 추가 <span> 요소가 포함되어 물결을 일으킬 수 있습니다. 버튼이 많으면 총 개수가 많아질 수 있음 이로 인해 모바일에서 성능이 저하될 수 있습니다. 만약 페인트 Worklet을 사용해 물결 효과 구현 0개의 추가 요소와 하나의 페인트 Worklet만 남게 됩니다. 또한 훨씬 더 쉽게 맞춤설정하고 매개변수를 제공합니다

페인트 워크렛을 사용할 때의 또 다른 이점은 대부분의 시나리오에서 페인트 Worklet을 사용하는 것은 바이트 측면에서 작습니다. 물론 페인트 코드가 캔버스의 크기나 매개변수가 변경됩니다. 코드가 복잡하고 시간이 오래 걸리면 버벅거림. Chrome은 기본 스레드에서 페인트 워크렛을 옮기고 오래 실행되는 페인트 워크렛이라도 기본 작업의 응답성에 스레드가 필요합니다.

제 생각에 가장 흥미로운 전망은 페인트 워크렛을 사용하면 CSS 기능의 폴리필을 사용할 수 있습니다. 한 가지 예는 원뿔 경사를 폴리필해도 Chrome에서 기본적으로 제공됩니다 또 다른 예로, CSS 회의에서 여러 개의 테두리 색상을 가질 수 있다는 결론을 내렸습니다. 회의 중에 동료인 Ian Kilpatrick이 새로운 CSS의 polyfill을 작성했습니다. 사용하여 표현합니다.

'틀을 벗어나 생각하기'

대부분의 사람들은 배경 이미지를 만들 때 배경 이미지와 테두리 이미지를 알아보겠습니다. 페인트 Worklet의 덜 직관적인 사용 사례는 mask-image: DOM 요소에 임의의 모양을 만듭니다. 예를 들어 다이아몬드:

<ph type="x-smartling-placeholder">
</ph> 다이아몬드 모양의 DOM 요소입니다. <ph type="x-smartling-placeholder">
</ph> 다이아몬드 모양의 DOM 요소입니다.

mask-image는 요소의 크기인 이미지를 사용합니다. 마스크 이미지는 투명하고 요소는 투명합니다. 마스크가 적용되는 영역 이미지는 불투명하고 요소는 불투명합니다

지금 Chrome에서 보기

페인트 worklet은 한동안 Chrome Canary에 사용되었습니다. Chrome 65에서는 기본적으로 사용 설정되어 있습니다. 새로운 가능성을 시도해 보세요. 페인트 작업장이 열리고 빌드한 것이 표시됩니다! 더 많은 아이디어를 얻으려면 빈센트 드 올리베이라의 컬렉션을 확인해 보세요.