• 【前端】弹球特效(重力模拟)


    在这里插入图片描述
    在这里插入图片描述

    弹球特效

    文章目录


    请添加图片描述

    import React, { useRef, useEffect } from 'react';
    
    const BouncingBallSimulation = () => {
      const canvasRef = useRef(null);
    
      useEffect(() => {
        const canvas = canvasRef.current;
        const ctx = canvas.getContext('2d');
        let animationFrameId;
    
        // Set canvas size
        canvas.width = 900;
        canvas.height = 1600;
    
        // Circle properties
        const centerX = canvas.width / 2;
        const centerY = canvas.height / 2;
        const radius = Math.min(centerX, centerY) * 0.7;
    
        // Ball properties
        const ballRadius = 15;
        let x = centerX;
        let y = centerY - radius + ballRadius;
        let dx = 2;
        let dy = 0;
    
        // Gravity and friction
        const gravity = 0.2;
        const friction = 0.99;
    
        // Matrix rain properties
        const fontSize = 14;
        const columns = canvas.width / fontSize;
        const drops = [];
        for (let i = 0; i < columns; i++) {
          drops[i] = 1;
        }
    
        const drawMatrixRain = () => {
          ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
          ctx.fillRect(0, 0, canvas.width, canvas.height);
    
          ctx.fillStyle = '#0F0';
          ctx.font = `${fontSize}px monospace`;
    
          for (let i = 0; i < drops.length; i++) {
            const text = String.fromCharCode(0x30A0 + Math.random() * 96);
            ctx.fillText(text, i * fontSize, drops[i] * fontSize);
    
            if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
              drops[i] = 0;
            }
            drops[i]++;
          }
        };
    
        const draw = () => {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
    
          // Draw matrix rain
          drawMatrixRain();
    
          // Draw circle
          ctx.beginPath();
          ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
          ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
          ctx.stroke();
    
          // Draw ball
          ctx.beginPath();
          ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
          ctx.fillStyle = 'white';
          ctx.fill();
    
          // Apply gravity
          dy += gravity;
    
          // Ball movement and collision detection
          const nextX = x + dx;
          const nextY = y + dy;
          const distanceFromCenter = Math.sqrt((nextX - centerX) ** 2 + (nextY - centerY) ** 2);
    
          if (distanceFromCenter + ballRadius > radius) {
            // Calculate the normal vector
            const nx = (nextX - centerX) / distanceFromCenter;
            const ny = (nextY - centerY) / distanceFromCenter;
    
            // Calculate the dot product
            const dotProduct = dx * nx + dy * ny;
    
            // Update velocity
            dx = (dx - 2 * dotProduct * nx) * friction;
            dy = (dy - 2 * dotProduct * ny) * friction;
          } else {
            x = nextX;
            y = nextY;
          }
    
          animationFrameId = requestAnimationFrame(draw);
        };
    
        draw();
    
        return () => {
          cancelAnimationFrame(animationFrameId);
        };
      }, []);
    
      return (
        
    {canvasRef} className="border border-gray-300" />
    ); }; export default BouncingBallSimulation;

    在这里插入图片描述

  • 相关阅读:
    MySQL练习题15道
    protobuf的优缺点
    python中的bisect模块与二分查找
    Android 12(S) 图像显示系统 - drm_hwcomposer 简析(上)
    容器化管理k8s部署踩坑记录
    Future与CompletableFuture
    基础排序算法详解与对比分析
    十二、【VUE基础】列表渲染
    【毕业设计】基于大数据的抖音短视频数据分析与可视化 - python 大数据 可视化
    139.深度学习分布式计算框架-2
  • 原文地址:https://blog.csdn.net/m0_74120525/article/details/140461355