You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现类似Google Gravity的Canvas文本下落弹跳效果技术咨询

Implement Google-Style Gravity & Bounce Effect for Canvas Text

Great idea to recreate that fun Google Gravity effect! Let's break down how to modify your code so each character from your input falls, bounces, and behaves just like you want. Here's the complete, working solution with explanations:

Step 1: Refactor Your Game Area & Add Animation Loop

First, we need a proper game loop to handle continuous updates—like gravity pulling characters down and collision detection. We'll also track all the text characters we need to animate.

Step 2: Create a Text Class for Individual Characters

Each character gets its own position, velocity, and behavior. This lets them fall independently, just like the Google Gravity effect.

Full Working Code

<!DOCTYPE html>
<html>
<head>
    <style>
        canvas {
            border: 1px solid #d3d3d3;
            background-color: #f1f1f1;
        }
    </style>
</head>
<body onload="startGame()">
    <br>
    <input type="text" name="Box" id="Box" value="" placeholder="Write whatever"/>
    <button onclick="spawnText()">Submit</button>

    <script>
        function startGame() {
            myGameArea.start();
        }

        var myGameArea = {
            canvas: createElementOnDom('CANVAS', 'myCANVAS'),
            texts: [], // Store all individual text characters
            gravity: 0.5, // Adjust for stronger/weaker gravity
            bounceFactor: 0.8, // Retained velocity after bounce (0 = no bounce, 1 = full bounce)
            start: function() {
                this.canvas.width = 500;
                this.canvas.height = 500;
                this.context = this.canvas.getContext("2d");
                document.body.insertBefore(this.canvas, document.body.childNodes[0]);
                this.interval = setInterval(updateGameArea, 20); // Update every 20ms (~50fps)
            },
            clear: function() {
                this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
            }
        };

        function createElementOnDom(type, id) {
            var element = document.createElement(type);
            element.id = id;
            return element;
        }

        // Class for each falling character
        function Text(x, y, text) {
            this.x = x;
            this.y = y;
            this.speedX = Math.random() * 4 - 2; // Random horizontal drift (-2 to 2)
            this.speedY = 0; // Start with no vertical speed
            this.text = text;
            this.font = "20px Arial";

            this.update = function() {
                // Apply gravity
                this.speedY += myGameArea.gravity;
                this.x += this.speedX;
                this.y += this.speedY;

                // Bounce off bottom of canvas
                if (this.y + 20 > myGameArea.canvas.height) { // 20 matches font size
                    this.y = myGameArea.canvas.height - 20;
                    this.speedY = -this.speedY * myGameArea.bounceFactor;
                    this.speedX *= 0.98; // Add friction to slow horizontal movement
                }

                // Bounce off left/right edges
                if (this.x < 0) {
                    this.x = 0;
                    this.speedX = -this.speedX * myGameArea.bounceFactor;
                }
                if (this.x + 15 > myGameArea.canvas.width) { // Approx character width
                    this.x = myGameArea.canvas.width - 15;
                    this.speedX = -this.speedX * myGameArea.bounceFactor;
                }
            };

            this.draw = function() {
                ctx = myGameArea.context;
                ctx.font = this.font;
                ctx.fillText(this.text, this.x, this.y);
            };
        }

        function updateGameArea() {
            myGameArea.clear();
            // Update and draw each text character
            for (let i = 0; i < myGameArea.texts.length; i++) {
                myGameArea.texts[i].update();
                myGameArea.texts[i].draw();
            }
        }

        function spawnText() {
            var inputText = document.getElementById("Box").value.trim();
            if (!inputText) return;

            // Uncomment below to clear existing characters on new submit
            // myGameArea.texts = [];

            // Spawn characters with spacing
            let startX = 10;
            const startY = 50;
            const spacing = 15; // Space between characters

            for (let i = 0; i < inputText.length; i++) {
                let char = inputText[i];
                myGameArea.texts.push(new Text(startX + (i * spacing), startY, char));
            }

            // Optional: Clear input box after submit
            document.getElementById("Box").value = "";
        }
    </script>
</body>
</html>

Key Features Explained

  • Individual Character Animation: Each character from your input acts as a separate object, so they fall and bounce independently (just like Google Gravity).
  • Gravity & Bounce: The gravity property controls fall speed, while bounceFactor adjusts how high characters bounce after hitting edges.
  • Collision Detection: Handles bounces off all canvas edges, plus adds friction so characters eventually settle at the bottom.
  • Natural Drift: A small random horizontal speed gives each character a unique path, making the effect feel more organic.

Customization Tips

  • Tweak myGameArea.gravity to make falls faster or slower.
  • Change bounceFactor to make bounces higher (closer to 1) or lower (closer to 0).
  • Modify the font property in the Text class to use different sizes or typefaces.
  • Uncomment myGameArea.texts = [] in spawnText() to clear old characters when submitting new text.

内容的提问来源于stack exchange,提问作者sosa123

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:25:40