# CSS魔术师Houdini

这一块写的有点简陋了,有时间再补一补 demo1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .el{
            --elUnit:500px;
            height:var(--elUnit);
            width: var(--elUnit);
            --arcColor:yellowgreen;
            --background-canvas: (ctx,geom)=>{
                ctx.strokeStyle = `var(--arcColor)`;
                ctx.lineWidth = 4;
                ctx.beginPath();
                ctx.arc(200,200,50,0,2*Math.PI);
                ctx.stroke();
                ctx.closePath();
            };
            background: paint(background-canvas);
        }
    </style>
</head>
<body>
<div class="el"></div>
    <script>
        if (CSS in window || !CSS.paintWorklet) {
            console.error('您的浏览器不支持houdini');
        } else {
            CSS.paintWorklet.addModule('./arc.js');
        }
        
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

art.js

registerPaint('background-canvas',class {
    static get inputProperties() {
        return ['--background-canvas'];
    }
    paint(ctx,geom,properties) {
        eval(properties.get('--background-canvas').toString())(ctx,geom,properties)
    }
})
1
2
3
4
5
6
7
8

demo2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body{
            background: #000;
            color:#fff;
        }
        body::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            --star-density:1;
            --star-opacity:1;
            background-image:paint(yd-sky);
            animation: shine 1s linear alternate infinite;
        }
        @keyframes shine {
            from{
                opacity: 1;
            }
            to{
                opacity: 0.2;
            }
        }
    </style>
</head>
<body>
    <script>
        if (CSS in window || !CSS.paintWorklet) {
            console.error('您的浏览器不支持houdini');
        } else {
            CSS.paintWorklet.addModule('./sky.js');
        }
        
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

sky.js

registerPaint('yd-sky',class {
    constructor() {
        this.stars = [];
    }
    static get inputProperties() {
        return ['--star-density','--star-opacity'];
    }
    addStars(xMax, yMax, starDensity) {
        let starsNum = Math.round((xMax + yMax) * starDensity);
        for( let i = 0; i <= starsNum; i++) {
            const x = Math.floor(Math.random()*xMax + 1);
            const y = Math.floor(Math.random()*xMax + 1);
            const hue = Math.floor(Math.random()*360 + 1);
            const opacityOne = Math.floor(Math.random()*9 + 1);
            const opacityTwo = Math.floor(Math.random()*9 + 1);
            const size = Math.floor(Math.random()*2 + 1);
            this.stars.push(
                {x,y,hue,opacityOne,opacityTwo,size}
            )
        }
    }
    paint(ctx,geom,properties) {
        let xMax = geom.width;
        let yMax = geom.height;
        let starDensity = properties.get('--star-density');
        let starOpacity = properties.get('--star-opacity');
        ctx.fillRect(0,0,xMax,yMax);
        this.addStars(xMax, yMax, starDensity);
        const stars = this.stars;
        for(let star of stars) {
            const opacity = ('.' + (star.opacityOne + star.opacityTwo))*starOpacity
            ctx.fillStyle = `hsla(${star.hue},30%,80%,${opacity})`;
            ctx.fillRect(star.x, star.y, star.size, star.size);
        }
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36