无法导入 css houdini paint js 文件

Can't import css houdini paint js file

我有一个 React/Electron 应用程序,我正在尝试使用新的 CSS Houdini paint() 功能(如 in this page 所示)。在我项目的 index.html 文件中,我添加了一个带有 paintWorklet addModule() 函数的脚本标签,如下所示:

<script>
  CSS.paintWorklet.addModule('../src/ResultDisplay/DefaultResultDisplay/testPaint.js');
</script>

然后在该 testPaint.js 文件中,我基本上拥有该博客中显示内容的副本 post:

registerPaint(
  "testPaint",
  class {
    paint(ctx, geom) {
      console.log("painting!!!");
      const circleSize = 10;
      const bodyWidth = geom.width;
      const bodyHeight = geom.height;

      const maxX = Math.floor(bodyWidth / circleSize);
      const maxY = Math.floor(bodyHeight / circleSize);

      for (let y = 0; y < maxY; y++) {
        for (let x = 0; x < maxX; x++) {
          ctx.fillStyle = "blue";
          ctx.beginPath();
          ctx.arc(
            x * circleSize * 2 + circleSize,
            y * circleSize * 2 + circleSize,
            circleSize,
            0,
            2 * Math.PI,
            true
          );
          ctx.closePath();
          ctx.fill();
        }
      }
    }
  }
);

最后是我的 css 文件:

.container {
  background-image: paint(testPaint);
  display: flex;
  margin: 4px;
  border-radius: 12px;
  height: 75px;
}

我应该指出我正在使用 CSS 模块,所以这个文件是 defaultResultStyles.module.scss;不确定这是否会影响任何事情。当我在我的应用程序中调出本应具有这些样式的组件时,它没有样式,尽管检查它,它确实显示 background-image: paint(testPaint). The console.log that I added to the testPaint.js` file is never showed.

我尝试了 addModule 文件路径的多种变体;我试过 testPaint.js,同时使用 ./srcsrc 启动它,但似乎没有任何效果;这在 Electron/React 应用程序中可能吗?

addModule 函数将无法通过 webpack 或其他捆绑器工作,而是通过浏览器的本机模块系统工作。您必须将 testPaint.js 文件放在 public 目录中,否则它将与其他所有内容捆绑在一起。

这是我添加到 index.html 以将其从本地 Create React App 项目的 public 目录添加到 运行 的内容:

    <script>
      CSS.paintWorklet.addModule('%PUBLIC_URL%/testPaint.js');
    </script>

我实际上并没有设置任何标记,只是添加了容器 class 来测试它:


如果你想在不通过 public 文件夹的情况下使用它(因为通常你必须在 index.html 中添加绘画模块,这会改变 public 目录),那么我建议使用 React Helmet 来设置脚本标签。请注意,CRA 的 hot-reload 功能似乎会阻止脚本更新,因此每次更改脚本标签时,您都需要手动刷新页面。

import React from 'react';
import { render } from 'react-dom';
import { Helmet } from 'react-helmet';
import styled from 'styled-components';

// Render these styled components like normal react components.
// They will pass on all props and work
// like normal react components – except they're styled!
const Demo = styled.div`
  background: #1108a0;
  padding: 50px 0;
`;
const Test = styled.div`
  --color: cyan;
  --multiplier: 0.24;
  --pad: 30;
  --slant: 20;
  background: paint(background-canvas);
  transition: --multiplier 0.4s;
  font: bold 6em sans-serif;
  color: yellow;
  text-shadow: 0 3px 1px cyan;
  line-height: 1.5em;
  width: max-content;
  padding-left: 30px;
  padding-right: 50px;
  isolation: isolate;
  &:hover {
    --multiplier: 1;
  }
  & span {
    mix-blend-mode: exclusion;
  }
`;
export const App = () => (
  <Demo>
    <Test className="el" right={'right'}>
      <span>JS-in-CSS</span>
    </Test>
  </Demo>
);
export const Helm = () => (
  <Helmet>
    <script language="javascript+paint">{`
  registerPaint('background-canvas', class {
  static get inputProperties() {
      return ['--multiplier', '--color', '--pad', '--slant'];
  }
  paint(ctx, geom, properties) {
    let multiplier = +properties.get('--multiplier').toString();
    let c = properties.get('--color').toString();
    let pad = +properties.get('--pad').toString();
    let slant = +properties.get('--slant').toString();
    ctx.moveTo(0, 0);
    ctx.lineTo(pad + (geom.width - slant - pad) * multiplier, 0);
    ctx.lineTo(pad + (geom.width - slant - pad) * multiplier + slant, geom.height);
    ctx.lineTo(0, geom.height);
    ctx.fillStyle = c;
    ctx.fill();
  }
})
`}</script>

    <script>{`
  if ("paintWorklet" in CSS) {
  const src = document.querySelector('script[language$="paint"]').innerHTML;
  const blob = new Blob([src], {
    type: 'text/javascript'
  });
  CSS.paintWorklet.addModule(URL.createObjectURL(blob));
}
`}</script>
  </Helmet>
);
render(
  <div>
    <Helm />
    <App />
  </div>,
  document.getElementById('root')
);

如果您希望避免使用 /public,您可以使用像 Yarn Workspaces 这样的 monorepo 管理器将您的工作集保存在一个专用包中。然后,您可以将它导入您的客户端应用程序,就像导入任何其他包依赖项一样。

循序渐进(使用 Yarn Workspaces):

  1. 为您的应用程序(package.json 名称为@packages/myapp)和工作集(@packages/myworklet)创建专用包
  2. 将您的工作集添加为应用程序的依赖项 -- from @packages/myapp 运行 yarn add @packages/myworklet
  3. 从@packages/myworklet导入您的工作集并添加它——参见https://houdini.how/usage/