Canvas如何绘画出动态星空背景——详解(详细介绍每一步的作用)

本文详细介绍了如何利用HTML5Canvas在网页上创建动态星空背景,包括画布准备、功能函数的实现(如随机数生成、星星移动范围计算、创建星星和调整透明度)以及确保背景随页面缩放而响应式更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分析需要哪些功能

需要的canvas

  1. 需要一个和视图一样大小的画布
  2. 需要一个存放星星的子画布,放在主画布

需要的功能函数

  1. 随机数函数
  2. 星星移动范围函数
  3. 创建星星函数
  4. 将星星放在主画布函数
  5. 调用的主函数(main)

功能实现

1.画布准备

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>星空背景</title>
</head>
<body>
    <div class="container">
        <canvas id="canvas"></canvas>
    </div>
</body>
</html>

2.功能函数

  1. 随机数函数
function random(min, max) {
    if (arguments.length < 2) {
      max = min
      min = 0
    }
    
    if (min > max) {
      var hold = max
      max = min
      min = hold
    }

    return Math.floor(Math.random() * (max - min + 1)) + min
  }
  1. 星星移动范围函数
function maxOrbit(x, y) {
    var max = Math.max(x, y),
      diameter = Math.round(Math.sqrt(max * max + max * max))
    return diameter / 2
    //星星移动范围,值越大范围越小,
  }
  1. 创建星星函数
 let Star = function () {
    // 轨道半径
    this.orbitRadius = random(maxOrbit(w, h))
    // 星星的大小(设置半径)
    this.radius = random(60, this.orbitRadius) / 8
    // 屏幕中心
    this.orbitX = w / 2
    this.orbitY = h / 2
    // 移动速度
    this.timePassed = random(0, maxStars)
    this.speed = random(this.orbitRadius) / 50000
    // 随机透明度
    this.alpha = random(2, 10) / 10
    // 添加星星
    stars.push(this)
  }
  1. 将星星放在主画布函数(直接在Star的原型上绑定方法
 Star.prototype.draw = function () {
    var x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
      y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
      twinkle = random(10)

    if (twinkle === 1 && this.alpha > 0) {
      this.alpha -= 0.05
    } else if (twinkle === 2 && this.alpha < 1) {
      this.alpha += 0.05
    }

    ctx.globalAlpha = this.alpha
    ctx.drawImage(
      canvas2,
      x - this.radius / 2,
      y - this.radius / 2,
      this.radius,
      this.radius
    )
    this.timePassed += this.speed
  }
  1. 调用的主函数(main)
function main() {
    ctx.globalCompositeOperation = 'source-over'
    ctx.globalAlpha = 0.5 //尾巴
    ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)'
    ctx.fillRect(0, 0, w, h)

    ctx.globalCompositeOperation = 'lighter'
    for (var i = 1, l = stars.length; i < l; i++) {
      stars[i].draw()
    }
    requestAnimationFrame(main)
  }

完整案例(注意看注解,便于理解)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>星空背景</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }

    .container {
        overflow: hidden;
        width: 100vw;
        height: 100vh;
    }
</style>

<body>
    <div class="container">
        <canvas id="canvas"></canvas>
    </div>
    <script>
        function random(min, max) {
            if (arguments.length < 2) {
                max = min
                min = 0
            }

            if (min > max) {
                var hold = max
                max = min
                min = hold
            }

            return Math.floor(Math.random() * (max - min + 1)) + min
        }

        function maxOrbit(x, y) {
            var max = Math.max(x, y),
                diameter = Math.round(Math.sqrt(max * max + max * max))
            return diameter / 2
            //星星移动范围,值越大范围越小,
        }
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        // 屏幕的长宽
        const w = (canvas.width = window.innerWidth)
        const h = (canvas.height = window.innerHeight)
        // 色度
        const hue = 217,
        // 星星数量
            maxStars = 2500
        // 存放星星的数组
        let stars = []
        // 创建星星画布
        let canvas2 = document.createElement('canvas')
        let starCtx = canvas2.getContext('2d')
        // 星星画布的大小
        starCtx.width = 100
        starCtx.height = 100
        // 半径
        let r = 50
        // 设置渐变色
        let gradient2 = starCtx.createRadialGradient(r, r, 0, r, r, r)
        gradient2.addColorStop(0.025, '#CCC')
        gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)')
        gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)')
        gradient2.addColorStop(1, 'transparent')
        // 渐变色添加到星星画布
        starCtx.fillStyle = gradient2
        starCtx.beginPath()
        // 绘制圆
        starCtx.arc(r, r, r, 0, Math.PI * 2)
        // 填充
        starCtx.fill()

        // 创建星星
        let Star = function () {
            // 轨道半径
            this.orbitRadius = random(maxOrbit(w, h))
            // 星星的大小(设置半径)
            this.radius = random(60, this.orbitRadius) / 8
            // 屏幕中心
            this.orbitX = w / 2
            this.orbitY = h / 2
            // 初始的随机位置
            this.timePassed = random(0, maxStars)
            // 后续的移动速度
            this.speed = random(this.orbitRadius) / 50000
            // 随机透明度(为了让星星可以明灭不定)
            this.alpha = random(2, 10) / 10
            // 添加星星 this指代本身Star添加到星星数组
            stars.push(this)
        }
        // 将星星放在主画布上,在Star的原型上设置一方法
        // 方便后续调用
        Star.prototype.draw = function () {
            // 为了让星星围绕中心轴旋转
            let x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
                y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
                // 随机一个值,根据这个值改变星星的透明度,可以控制星星闪烁
                twinkle = random(10)
            // 实现星星闪烁的方法,修改透明度
            if (twinkle === 1 && this.alpha > 0) {
                this.alpha -= 0.05
            } else if (twinkle === 2 && this.alpha < 1) {
                this.alpha += 0.05
            }

            // 设置全局的透明度
            ctx.globalAlpha = this.alpha
            // 将子画布星星绘制在主画布上
            ctx.drawImage(
                canvas2,
                x - this.radius / 2,
                y - this.radius / 2,
                this.radius,
                this.radius
            )
            // 不断修改星星的位置形成动态
            this.timePassed += this.speed
        }

        // 创建星星
        for (var i = 0; i < maxStars; i++) {
            new Star()
        }

        function main() {
            ctx.globalCompositeOperation = 'source-over'
            ctx.globalAlpha = 0.5 //尾巴
            // 画布颜色
            ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)'
            // 填充整个画布
            ctx.fillRect(0, 0, w, h)

            ctx.globalCompositeOperation = 'lighter'
            // 调用draw方法,将星星绘制在图片上
            for (var i = 1, l = stars.length; i < l; i++) {
                stars[i].draw()
            }
            // 可以先把这个方法注释掉,可以看到背景上的星星
            // 下面是执行动画的方法S
            window.requestAnimationFrame(main)
        }
        main()
    </script>
</body>

</html>

出现的问题

缩放页面星空图不会跟着缩放,没有响应式更新,星空的大小已经定死了
下面是修改后的代码,缩放页面星空也会跟着变化直至填充满整个屏幕

    function canvasStar() {
            function random(min, max) {
                if (arguments.length < 2) {
                    max = min
                    min = 0
                }

                if (min > max) {
                    var hold = max
                    max = min
                    min = hold
                }

                return Math.floor(Math.random() * (max - min + 1)) + min
            }

            function maxOrbit(x, y) {
                var max = Math.max(x, y),
                    diameter = Math.round(Math.sqrt(max * max + max * max))
                return diameter / 2
                //星星移动范围,值越大范围越小,
            }
            const canvas = document.getElementById('canvas')
            const ctx = canvas.getContext('2d')
            // 屏幕的长宽
            const w = (canvas.width = window.innerWidth)
            const h = (canvas.height = window.innerHeight)
            // 色度
            const hue = 217,
                // 星星数量
                maxStars = 2500
            // 存放星星的数组
            let stars = []
            // 创建星星画布
            let canvas2 = document.createElement('canvas')
            let starCtx = canvas2.getContext('2d')
            // 星星画布的大小
            starCtx.width = 100
            starCtx.height = 100
            // 半径
            let r = 50
            // 设置渐变色
            let gradient2 = starCtx.createRadialGradient(r, r, 0, r, r, r)
            gradient2.addColorStop(0.025, '#CCC')
            gradient2.addColorStop(0.1, 'hsl(' + hue + ', 61%, 33%)')
            gradient2.addColorStop(0.25, 'hsl(' + hue + ', 64%, 6%)')
            gradient2.addColorStop(1, 'transparent')
            // 渐变色添加到星星画布
            starCtx.fillStyle = gradient2
            starCtx.beginPath()
            // 绘制圆
            starCtx.arc(r, r, r, 0, Math.PI * 2)
            // 填充
            starCtx.fill()

            // 创建星星
            let Star = function () {
                // 轨道半径
                this.orbitRadius = random(maxOrbit(w, h))
                // 星星的大小(设置半径)
                this.radius = random(60, this.orbitRadius) / 8
                // 屏幕中心
                this.orbitX = w / 2
                this.orbitY = h / 2
                // 初始的随机位置
                this.timePassed = random(0, maxStars)
                // 后续的移动速度
                this.speed = random(this.orbitRadius) / 50000
                // 随机透明度(为了让星星可以明灭不定)
                this.alpha = random(2, 10) / 10
                // 添加星星 this指代本身Star添加到星星数组
                stars.push(this)
            }
            // 将星星放在主画布上,在Star的原型上设置一方法
            // 方便后续调用
            Star.prototype.draw = function () {
                // 为了让星星围绕中心轴旋转
                let x = Math.sin(this.timePassed) * this.orbitRadius + this.orbitX,
                    y = Math.cos(this.timePassed) * this.orbitRadius + this.orbitY,
                    // 随机一个值,根据这个值改变星星的透明度,可以控制星星闪烁
                    twinkle = random(10)
                // 实现星星闪烁的方法,修改透明度
                if (twinkle === 1 && this.alpha > 0) {
                    this.alpha -= 0.05
                } else if (twinkle === 2 && this.alpha < 1) {
                    this.alpha += 0.05
                }

                // 设置全局的透明度
                ctx.globalAlpha = this.alpha
                // 将子画布星星绘制在主画布上
                ctx.drawImage(
                    canvas2,
                    x - this.radius / 2,
                    y - this.radius / 2,
                    this.radius,
                    this.radius
                )
                // 不断修改星星的位置形成动态
                this.timePassed += this.speed
            }

            // 创建星星
            for (var i = 0; i < maxStars; i++) {
                new Star()
            }

            function main() {
                ctx.globalCompositeOperation = 'source-over'
                ctx.globalAlpha = 0.5 //尾巴
                // 画布颜色
                ctx.fillStyle = 'hsla(' + hue + ', 64%, 6%, 2)'
                // 填充整个画布
                ctx.fillRect(0, 0, w, h)

                ctx.globalCompositeOperation = 'lighter'
                // 调用draw方法,将星星绘制在图片上
                for (var i = 1, l = stars.length; i < l; i++) {
                    stars[i].draw()
                }
                // 可以先把这个方法注释掉,可以看到背景上的星星
                // 下面是执行动画的方法S
                window.requestAnimationFrame(main)

            }
            main()
        }
        canvasStar()
        window.addEventListener('resize', canvasStar)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值