Can't import css houdini paint js file

不羁的心 提交于 2021-01-07 06:59:19

问题


I have a React/Electron app, where I'm trying to use the new CSS Houdini paint() function (as demonstrated in this page). In my project's index.html file I have added a script tag with the paintWorklet addModule() function as shown:

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

Then in that testPaint.js file I have essentially a copy of what's shown in that blog 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();
        }
      }
    }
  }
);

And finally my css file:

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

I should point out I am using CSS Modules, so this file is defaultResultStyles.module.scss; not sure if that affects anything. When I bring up the component that's meant to have these styles in my app, it has no styles, though inspecting it, it does display background-image: paint(testPaint). The console.log that I added to the testPaint.js` file is never shown.

I have tried multiple variations of the filepath for addModule; I've tried just testPaint.js, starting it with ./src and src both, but nothing seems to work; is this possible in an Electron/React app?


回答1:


The addModule function will not work through webpack or other bundlers, it instead works through the native module system of browsers. You have to put the testPaint.js file in the public directory, otherwise it would get bundled with everything else.

Here's what I added to the index.html to get it to run from the public directory on a local Create React App project:

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

I didn't actuallly set up any of the markup and just added the container class to test it out:


If you want to use this without going through the public folder (at all, because normally you'd have to add the paint module in the index.html which is changing the public directory), then I'd suggest using React Helmet to set up the script tags. As a note with this, the hot-reload features of CRA seems to prevent the scripts from updating, so every time you change the script tags, you'll need to refresh the page manually.

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')
);



来源:https://stackoverflow.com/questions/64744884/cant-import-css-houdini-paint-js-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!