当前位置:   article > 正文

分享一个CSS的垂帘效果_css卷帘效果

css卷帘效果

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

先上效果图:
在这里插入图片描述
再上代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        html, body, canvas {
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }
        html, body {
            width: 100%;
            height: 100%;
            overflow: hidden;
            margin: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            background: #191919;
        }
        .asset-img {
            display: none;
        }
    </style>
</head>
<body>
<canvas></canvas>
<img class="asset-img" id="light-img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAABGdBTUEA
ALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACnVBMVEUAAAD40ED40D740Dv40En40Dr40FH40Df40D/40D340
Dn40Dz40Dj40AD40Ff40Db40DT40EH40EL40ED40ED40Dv40D/4zz/4zz74zz/4zz/40D74zz/4zz/4zz/40UH40kD40UL40kH4zz/4zz340D34zz740kH41U
T410f410j410j410f40D/40D/4zz/40ED40EH400T410f42Er4103410/411D41UT40kH40D/4z0D4zz/41UX410j42E7411L42Ff42Vv42Vz42En41kb40UH
4zz/40Dz40ED41UT42Ej4107411b42l743WT432r4323432r410/42En4zz340Dn400H410f42mD432v44nf45IP45Yn45IT44nj432r411b400L40D/4zz/4
1UT42Er411P432v44oD46Zv47q/48Lj46Zr432n40UH410f42Ff44nf48r/499T4997499T48r744nf43WP40D741EH42Vv4+O34+PP4+O347q745IL432j40
UD432345Yj48LX49934+PP4+Pj4993477T45Ib432z411D400D40D/40UH432n45IP47a7432j42Vv410/400H40Dr4zz340UD410b410346Zj48r343WP42F
f410f40D/41kT42Er42l744nv46Zf42l3411L410r41kX40ED410f42E7411b421/45IL45Ib432n421740UH40D340Dz4zz741EP410j410743WT432f432v
43mj43GT42Ej41kT4zz740ED41EX411P42Ff42Fv411f410j41kX400P41034107411D42E340D740UH410j41kb41ET400H40D/40ED4z0D4zz74zz340D//
//+WdN8lAAAA3nRSTlMAAAAAAAAAAAAAAAAAAAAAAAAAAgMCBAcJDAkDCA0SFRsbGxMDBQscJSwwMS0SDAUFFyExQExUVyIYDQULJzlOZHeDhDonFwoDASE5V
XGNpbO4tFM5BwEcMJa3zdjb2Mu2cBwDESM+Y7bU4ebo4bUUK3bL6vDy7+rKogIZgPb49ebXsBu02+jx9/jw6Nu0VRsBGbDX5q9/UhkCCRUqS+HqoHMqESI9i9
Thi2E9IhEvTG+V1tq0kxsDAQchN1Ggr7SvoDghChUjYXJ/cjgnIUlSVEkFGi8qIhsFFAcICAaJi/ApAAAAAWJLR0Te6W7imwAAAAd0SU1FB+YMHBEUINvSacM
AAAIKSURBVCjPY2AgBBgZmZiFRYQZgQBVnEVUTFxCUlJSSlxMlAVJjplVWkZWTl5BUUleWVZGhZkZYZKqmpy6hqaWtpaOhrqunj7MREZGA1lDI2MTUzNzM1MT
YwtLK2uIFCOjiI2hrZ29g6OTs5Ojg72Lq5u7Bxs7SMZTXNfL28fXzz8gMMjfzzc4xEI3NIwVrEUyPMLeNzIqOiY2Lj4hMtE+Ikk2mYkRKCOekpqW7peRmZWdk
52bmeeXnqYhJ84BkpHKLzAt9C/KKi4pLSvPragsNNXMl/JkZGCqUqvWMqsJiMkuqa2rL2tobKox06qWTOZg4EiWbNY2d25pbWvv6Ozo6u7pde7T6pf04GTgmG
AzEahn0uSGsvqO+rIpjVOnTdeaoTaTmYGLfdbsOXMLKyvmzS/rKps/r2jBwrmL5KWAfmViEl+8ZGn6srzlK6Z0T1mxPG/lqtVr1oLdxp0sqbRu/YaNeUWbNm8
q2rJ1w/p12yS38wDDh3PHTrldu/dsWLZ33/4DB5dt2HPosO7OMFBwM/KKHjl6bPf64yemOZ88dXz96TPyR6T5+EFByi6ganP07LrV585fmH5x6bqzs21UmZhg
0XDJXe7ykjnrtK5cvXZdzv0GMycs6jiZpXdKLs532+Z2M0VSXAQ5KTAKeorcuu1uc+TO3e07hNDSCCMjNyczKz8nN8FkxgAAgH2hXtQzzA4AAAAldEVYdGRhd
GU6Y3JlYXRlADIwMjItMTItMjhUMTc6MjA6MzIrMDA6MDA1MNVoAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIyLTEyLTI4VDE3OjIwOjMyKzAwOjAwRG1t1AAAAA
BJRU5ErkJggg==" alt="base64">

</body>
<script>
    class Mouse {
        constructor(canvas) {
            this.pos = new Vector(-1000, -1000)
            this.radius = 40

            canvas.onmousemove = e => this.pos.setXY(e.clientX, e.clientY)
            canvas.ontouchmove = e => this.pos.setXY(e.touches[0].clientX, e.touches[0].clientY)
            canvas.ontouchcancel = () => this.pos.setXY(-1000, -1000)
            canvas.ontouchend = () => this.pos.setXY(-1000, -1000)
        }
    }
    class Dot {
        constructor(x, y) {
            this.pos = new Vector(x, y)
            this.oldPos = new Vector(x, y)
            this.friction = 0.97
            this.gravity = new Vector(0, 0.6)
            this.mass = 1
            this.pinned = false
            this.lightImg = document.querySelector('#light-img')
            this.lightSize = 15
        }

        update(mouse) {
            if (this.pinned) return
            let vel = Vector.sub(this.pos, this.oldPos)
            this.oldPos.setXY(this.pos.x, this.pos.y)
            vel.mult(this.friction)
            vel.add(this.gravity)
            let { x: dx, y: dy } = Vector.sub(mouse.pos, this.pos)
            const dist = Math.sqrt(dx * dx + dy * dy)
            const direction = new Vector(dx / dist, dy / dist)
            const force = Math.max((mouse.radius - dist) / mouse.radius, 0)
            if (force > 0.6) this.pos.setXY(mouse.pos.x, mouse.pos.y)
            else {
                this.pos.add(vel)
                this.pos.add(direction.mult(force))
            }
        }

        drawLight(ctx) {
            ctx.drawImage(
                this.lightImg,
                this.pos.x - this.lightSize / 2, this.pos.y - this.lightSize / 2, this.lightSize, this.lightSize
            )
        }

        draw(ctx) {
            ctx.fillStyle = '#aaa'
            ctx.fillRect(this.pos.x - this.mass, this.pos.y - this.mass, this.mass * 2, this.mass * 2)
        }
    }
    class Stick {
        constructor(p1, p2) {
            this.startPoint = p1
            this.endPoint = p2
            this.length = this.startPoint.pos.dist(this.endPoint.pos)
            this.tension = 0.3
        }

        update() {
            const dx = this.endPoint.pos.x - this.startPoint.pos.x
            const dy = this.endPoint.pos.y - this.startPoint.pos.y
            const dist = Math.sqrt(dx * dx + dy * dy)
            const diff = (dist - this.length) / dist
            const offsetX = diff * dx * this.tension
            const offsetY = diff * dy * this.tension
            const m = this.startPoint.mass + this.endPoint.mass
            const m1 = this.endPoint.mass / m
            const m2 = this.startPoint.mass / m
            if (!this.startPoint.pinned) {
                this.startPoint.pos.x += offsetX * m1
                this.startPoint.pos.y += offsetY * m1
            }
            if (!this.endPoint.pinned) {
                this.endPoint.pos.x -= offsetX * m2
                this.endPoint.pos.y -= offsetY * m2
            }
        }

        draw(ctx) {
            ctx.beginPath()
            ctx.strokeStyle = '#999'
            ctx.moveTo(this.startPoint.pos.x, this.startPoint.pos.y)
            ctx.lineTo(this.endPoint.pos.x, this.endPoint.pos.y)
            ctx.stroke()
            ctx.closePath()
        }
    }
    class Rope {
        constructor(config) {
            this.x = config.x
            this.y = config.y
            this.segments = config.segments || 10
            this.gap = config.gap || 15
            this.color = config.color || 'gray'
            this.dots = []
            this.sticks = []
            this.iterations = 10
            this.create()
        }
        pin(index) {
            this.dots[index].pinned = true
        }
        create() {
            for (let i = 0; i < this.segments; i++) {
                this.dots.push(new Dot(this.x, this.y + i * this.gap))
            }
            for (let i = 0; i < this.segments - 1; i++) {
                this.sticks.push(new Stick(this.dots[i], this.dots[i + 1]))
            }
        }
        update(mouse) {
            this.dots.forEach(dot => {
                dot.update(mouse)
            })
            for (let i = 0; i < this.iterations; i++) {
                this.sticks.forEach(stick => {
                    stick.update()
                })
            }
        }
        draw(ctx) {
            this.dots.forEach(dot => {
                dot.draw(ctx)
            })
            this.sticks.forEach(stick => {
                stick.draw(ctx)
            })
            this.dots[this.dots.length - 1].drawLight(ctx)
        }
    }
    class App {
        static width = innerWidth
        static height = innerHeight
        static dpr = devicePixelRatio > 1 ? 2 : 1
        static interval = 1000 / 60
        constructor() {
            this.canvas = document.querySelector('canvas')
            this.ctx = this.canvas.getContext('2d')

            this.mouse = new Mouse(this.canvas)

            this.resize()
            window.addEventListener('resize', this.resize.bind(this))

            this.createRopes()
        }
        createRopes() {
            this.ropes = []

            const TOTAL = App.width * 0.06
            for (let i = 0; i < TOTAL + 1; i++) {
                const x = randomNumBetween(App.width * 0.3, App.width * 0.7)
                const y = 0
                const gap = randomNumBetween(App.height * 0.05, App.height * 0.08)
                const segments = 10
                const rope = new Rope({ x, y, gap, segments })
                rope.pin(0)

                this.ropes.push(rope)
            }
        }
        resize() {
            App.width = innerWidth
            App.height = innerHeight

            this.canvas.style.width = '100%'
            this.canvas.style.height = '100%'
            this.canvas.width = App.width * App.dpr
            this.canvas.height = App.height * App.dpr
            this.ctx.scale(App.dpr, App.dpr)
            this.createRopes()
        }
        render() {
            let now, delta
            let then = Date.now()
            const frame = () => {
                requestAnimationFrame(frame)
                now = Date.now()
                delta = now - then
                if (delta < App.interval) return
                then = now - (delta % App.interval)
                this.ctx.clearRect(0, 0, App.width, App.height)

                // draw here
                this.ropes.forEach(rope => {
                    rope.update(this.mouse)
                    rope.draw(this.ctx)
                })
            }
            requestAnimationFrame(frame)
        }
    }
    function randomNumBetween(min, max) {
        return Math.random() * (max - min) + min
    }
    window.addEventListener('load', () => {
        const app = new App()
        app.render()
    })
    class Vector {
        constructor(x, y) {
            this.x = x || 0
            this.y = y || 0
        }
        static add(v1, v2) {
            return new Vector(v1.x + v2.x, v1.y + v2.y)
        }
        static sub(v1, v2) {
            return new Vector(v1.x - v2.x, v1.y - v2.y)
        }
        add(x, y) {
            if (arguments.length === 1) {
                this.x += x.x
                this.y += x.y
            } else if (arguments.length === 2) {
                this.x += x
                this.y += y
            }
            return this
        }
        sub(x, y) {
            if (arguments.length === 1) {
                this.x -= x.x
                this.y -= x.y
            } else if (arguments.length === 2) {
                this.x -= x
                this.y -= y
            }
            return this
        }
        mult(v) {
            if (typeof v === 'number') {
                this.x *= v
                this.y *= v
            } else {
                this.x *= v.x
                this.y *= v.y
            }
            return this
        }
        setXY(x, y) {
            this.x = x
            this.y = y
            return this
        }
        dist(v) {
            const dx = this.x - v.x
            const dy = this.y - v.y
            return Math.sqrt(dx * dx + dy * dy)
        }
    }
</script>
</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
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307

代码直接粘贴到html页面就能使用,顺滑的不可言说

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/192914
推荐阅读
相关标签
  

闽ICP备14008679号