不能为 css-houdini paint 做 JS-in-CSS?

Can't do JS-in-CSS for css-houdini paint?

我正在尝试复制 this example;我有一个 scss 文件,我在 React/Electron 项目中使用模块化 CSS。我想在同一个文件中定义 paint 使用的函数,例如:

.container {
  --background-canvas: (ctx, geom) => {
    // left blank for minimal example
  };
  background-image: paint(background-canvas);
  display: flex;
  margin: 4px;
  border-radius: 12px;
  height: 75px;
}

但是, CssSyntax error: Expected a pseudo-class or pseudo-element. (2:23) 编译失败。演示是什么我没有做?

好吧,我大部分都在工作。唯一不起作用的部分是过渡,我不确定为什么它不起作用。

-- 编辑:我通过以下方式完成了工作:https://css-houdini.rocks/animating-gradient

  CSS.registerProperty({
    name: '--multiplier',
    syntax: '<number>',
    inherits: false,
    initialValue: 0
  })

我找不到一种方法让 JS 解析器中的 CSS 将 { } 视为字符串的一部分而不是特殊字符,所以我使用了允许我 运行 在 background-canvas 函数中调用相关函数的数组。

  --background-canvas: (ctx, geom) => [ ctx.moveTo(0, 0),
    ctx.lineTo(
      var(--pad) + (geom.width - var(--slant) - var(--pad)) * var(--multiplier),
      0
    ),
    ctx.lineTo(
      var(--pad) + (geom.width - var(--slant) - var(--pad)) * var(--multiplier) +
        var(--slant),
      geom.height
    ),
    ctx.lineTo(0, geom.height), ctx.fillStyle = \`var(--color)\`, ctx.fill() ];

此解决方案真正有趣的部分在于您仍然需要实际注册绘画功能。

我这样做的方式与我之前的答案类似: which uses this https://twitter.com/DasSurma/status/983305990731894785

注意,来自 that example 的这个解决方案使用 eval 作为它的 registerPaint 函数的一部分,所以从安全的角度来看这可能是有问题的,尽管绘制代码理论上应该从主要 运行time.

const Demo = styled.div`
  background: #1108a0;
  padding: 50px 0;
`;
const Test = styled.div`
  --color: cyan;
  --multiplier: 0.24;
  --pad: 30;
  --slant: 20;
  --background-canvas: (ctx, geom) => [ ctx.moveTo(0, 0),
    ctx.lineTo(
      var(--pad) + (geom.width - var(--slant) - var(--pad)) * var(--multiplier),
      0
    ),
    ctx.lineTo(
      var(--pad) + (geom.width - var(--slant) - var(--pad)) * var(--multiplier) +
        var(--slant),
      geom.height
    ),
    ctx.lineTo(0, geom.height), ctx.fillStyle = \`var(--color)\`, ctx.fill() ];
  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;
  }
`;
const App = () => (
  <Demo>
    <Test className="el" right={'right'}>
      <span>JS-in-CSS</span>
    </Test>
  </Demo>
);
ReactDOM.render(<App />, document.getElementById('root'));

/*if ("paintWorklet" in CSS) {
  console.log('here')
  const src = document.querySelector('script[language$="paint"]').innerHTML;
  const blob = new Blob([src], {
    type: 'text/javascript'
  });
  CSS.paintWorklet.addModule(URL.createObjectURL(blob));
}*/
@media (max-width: 900px) {
  .el {
    font-size: 4em;
  }
}
@media (max-width: 500px) {
  .el {
    font-size: 2.4em;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/react-is@17.0.1/umd/react-is.production.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id="root"/>

<script language="javascript+paint">
  registerPaint('background-canvas', class {
  static get inputProperties() {
      return ['--background-canvas'];
  }
  paint(ctx, geom, properties) {
      eval(properties.get('--background-canvas').toString())(ctx, geom, properties);
  }
})
</script>

<script>
  // Register the property so it become animatable
  CSS.registerProperty({
    name: '--multiplier',
    syntax: '<number>',
    inherits: false,
    initialValue: 0
  })
  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>