我正在尝试复制这个例子;我有一个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: (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() ];
这个解决方案真正有趣的部分是,您仍然需要实际注册paint函数。
我这样做的方式与我之前的回答类似:https://stackoverflow.com/a/61966697/13175138哪个使用这个https://twitter.com/DasSurma/status/983305990731894785
需要注意的是,该示例中的这个解决方案使用eval
作为其registerPaint函数的一部分,因此从安全角度来看,这可能会有问题,尽管理论上应该从主运行时对paint代码进行沙盒处理。
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>