canvas动画案例 太阳地球月亮旋转

此项目的效果是太阳保持不动,地球围绕太阳转,月亮围绕地球转,要注意的是有两个原点位置的变换,地球和月亮的旋转点是不同的。如下图:

完整代码:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas {
            background-color: #666;
            display: block;
            margin: auto;
        }
    </style>
</head>

<body>
    <script>
        // 1、准备一个canvas
        const canvas = document.createElement('canvas')
        canvas.width = 800
        canvas.height = 800
        document.body.append(canvas)
        const context = canvas.getContext('2d')

        // 准备一个地球旋转的角度
        let earthAngle = 0

        // 月球旋转的角度
        let moonAngle = 0

        function loop() {
            context.save()
            // 清除之前画在画布上的内容 循环重复的内容
            context.clearRect(0, 0, canvas.width, canvas.height)

            // 画太阳
            context.beginPath()
            context.arc(400, 300, 100, 0, 2 * Math.PI)
            context.fillStyle = '#e3fa14'
            context.shadowColor = '#e3fa14'
            context.shadowBlur = 10
            context.fill()
            context.closePath()

            // 画地球
            context.beginPath()

            // 先把 canvas 原点移动到正中心
            context.translate(400, 300)
            // 然后记画笔旋转角度 围绕太阳中心 原点位置400,300
            context.rotate((earthAngle += 0.3) * Math.PI / 180)

            // 为了后面画月亮的动画,要把原点变成和地球中心完全一致
            context.translate(200,0)

            // 再画地球 原点和地球中心一致 此时原点中心在600,300
            // 此时原点中心已经又移动,为了原点和地球中心一致,所以(0,0)
            context.arc(0, 0, 20, 0, 2 * Math.PI) 
            context.fillStyle = 'blue'
            context.shadowBlur = 0
            context.fill()
            context.closePath()

            // 画月亮
            context.beginPath()
            context.rotate((moonAngle += 2) * Math.PI / 180) // 月亮旋转 围绕地球中心,原点位置600,300

            context.arc(40, 0, 6, 0, 2 * Math.PI) // 此时原点中心在(600,300)
            context.fillStyle = '#fff'
            context.fill()
            context.closePath()

            context.restore()
            requestAnimationFrame(loop)
        }
        requestAnimationFrame(loop)
    </script>
</body>

</html>

画太阳时,太阳的中心点在(400,300) 

画地球时,为了让地球围绕太阳转,所以先把原点移动到了(400,300),然后再旋转

而为了月亮绕着地球转,又把原点移动了(200,0),此时的原点位置就在了(600,300)的位置,但600,300这个数值后面不用,只是为了清楚坐标移动。需要注意的是:第二次移动坐标原点时,此时地球的中心位置变成了(0,0),是为了把原点变成和地球中心完全一致

而此时的原点已经和地球中心一致,所以画月亮时,就要月亮根据地球中心的位置距离来画

注意:移动了两次原点位置,为了保持旋转各自绕着各自的旋转点旋转,要先移动原点,再旋转,最后根据原点来画圆

context.save() 方法会将当前画布(Canvas)的状态压入一个保存状态的栈中。这个状态包括当前的变换矩阵、剪切区域、画笔样式(strokeStyle, fillStyle, lineWidth等)、字体样式(font)、全局透明度(globalAlpha)、全局复合操作(globalCompositeOperation)等。

当你需要改变这些状态进行某些绘制操作,但又不希望这些改变影响到后续绘制时,可以使用 context.save() 来保存当前状态,之后进行的任何状态改变都不会影响到之前保存的状态。

context.restore() 方法会从状态栈中弹出最近保存的状态,并将Canvas的渲染上下文恢复到这个状态。这意味着所有在 context.save() 之后做的状态改变(如变换、设置透明度等)都会被撤销,Canvas的状态会回到 context.save() 被调用时的状态。

这两个方法通常成对使用,在你需要临时改变Canvas状态进行绘制时非常有用。例如,你可能需要在一个特定的透明度下绘制某些图形,但之后又要恢复到原来的透明度进行其他绘制。这时,你可以在改变透明度之前调用 context.save(),绘制完毕后调用 context.restore() 来恢复到原来的透明度设置。

Video_2024-10-14_142041

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值