0

我正在尝试复制此示例;我有一个 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). 演示是什么,我没有做什么?

4

1 回答 1

1

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

- 编辑:我通过: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() ];

这个解决方案真正有趣的部分是您仍然需要实际注册绘制函数。

我这样做的方式与我之前的答案类似:https ://stackoverflow.com/a/61966697/13175138使用此https://twitter.com/DasSurma/status/983305990731894785

请注意,该示例中的此解决方案eval用作其 registerPaint 函数的一部分,因此从安全角度来看这可能是有问题的,尽管理论上应该从主运行时将绘制代码沙箱化。

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>

于 2020-11-08T06:28:18.720 回答