首页 > 其他分享 >canvas实现场景移动效果

canvas实现场景移动效果

时间:2024-12-06 20:29:11浏览次数:5  
标签:canvas 场景 const ctx 圆形 dx circle 移动 Math

实现步骤

1. 中心圆形与随机圆形

  • 在 Canvas 中心绘制一个固定圆形。
  • 在画布其他地方随机生成 5 个圆形,记录每个圆形的初始位置。

2. 鼠标点击事件

  • 获取鼠标点击坐标,并计算与中心圆形之间的距离和角度。

3. 圆形反向移动

  • 5 个随机圆形根据中心点为参考,向反方向移动。
  • 使用 Math.atan2 计算移动的角度,并用 Math.cosMath.sin 更新圆形的位置。

4. 动画与停止

  • 使用 requestAnimationFrame 实现动画,逐帧更新圆的位置。
  • 当所有圆形的移动距离达到目标值时,停止动画。

案例代码实现

<canvas id="myCanvas" width="600" height="400" style="border:1px solid #000;"></canvas>
<script>
    const canvas = document.getElementById("myCanvas");
    const ctx = canvas.getContext("2d");

    // 初始化画布中心坐标
    const canvasWidth = canvas.width;
    const canvasHeight = canvas.height;
    const centerX = canvasWidth / 2;
    const centerY = canvasHeight / 2;

    // 定义中心圆形
    const centerCircle = {
        x: centerX,
        y: centerY,
        radius: 20,
        color: "blue",
    };

    // 场景中随机生成 5 个圆形
    const sceneCircles = [];
    for (let i = 0; i < 5; i++) {
        sceneCircles.push({
            x: Math.random() * canvasWidth, // 随机 x 坐标
            y: Math.random() * canvasHeight, // 随机 y 坐标
            radius: 15,
            color: "red",
            speed: 3, // 移动速度
            targetX: null, // 目标 x 坐标
            targetY: null, // 目标 y 坐标
            moving: false, // 是否在移动
        });
    }

    // 绘制中心圆形
    function drawCenterCircle() {
        ctx.beginPath();
        ctx.arc(centerCircle.x, centerCircle.y, centerCircle.radius, 0, 2 * Math.PI);
        ctx.fillStyle = centerCircle.color;
        ctx.fill();
    }

    // 绘制场景圆形
    function drawSceneCircles() {
        sceneCircles.forEach((circle) => {
            ctx.beginPath();
            ctx.arc(circle.x, circle.y, circle.radius, 0, 2 * Math.PI);
            ctx.fillStyle = circle.color;
            ctx.fill();
        });
    }

    // 更新圆形的位置
    function moveSceneCircles() {
        sceneCircles.forEach((circle) => {
            if (!circle.moving) return;

            // 计算剩余距离
            const dx = circle.targetX - circle.x;
            const dy = circle.targetY - circle.y;
            const distance = Math.sqrt(dx * dx + dy * dy);

            // 如果距离小于速度,直接停止
            if (distance < circle.speed) {
                circle.x = circle.targetX;
                circle.y = circle.targetY;
                circle.moving = false;
                return;
            }

            // 根据角度计算下一步移动
            const angle = Math.atan2(dy, dx);
            circle.x += circle.speed * Math.cos(angle);
            circle.y += circle.speed * Math.sin(angle);
        });
    }

    // 动画循环
    function animate() {
        ctx.clearRect(0, 0, canvasWidth, canvasHeight); // 清除画布
        drawCenterCircle();
        drawSceneCircles();
        moveSceneCircles();
        requestAnimationFrame(animate);
    }

    // 鼠标点击事件
    canvas.addEventListener("click", (event) => {
        // 获取鼠标点击的坐标
        const rect = canvas.getBoundingClientRect();
        const mouseX = event.clientX - rect.left;
        const mouseY = event.clientY - rect.top;

        // 计算点击位置与中心圆的距离和角度
        const dx = mouseX - centerCircle.x;
        const dy = mouseY - centerCircle.y;
        const distance = Math.sqrt(dx * dx + dy * dy);
        const angle = Math.atan2(dy, dx);

        // 为每个场景圆形设置目标点(反方向)
        sceneCircles.forEach((circle) => {
            circle.targetX = circle.x - distance * Math.cos(angle);
            circle.targetY = circle.y - distance * Math.sin(angle);
            circle.moving = true; // 开启移动
        });
    });

    // 初始绘制并启动动画
    drawCenterCircle();
    drawSceneCircles();
    animate();
</script>

 

 

 

标签:canvas,场景,const,ctx,圆形,dx,circle,移动,Math
From: https://blog.csdn.net/lixin5456985/article/details/144298497

相关文章

  • canvas根据鼠标点击平滑移动案例
    1.圆形绘制在画布中心绘制一个圆形,并初始化圆形的坐标和半径。2.鼠标点击事件为Canvas添加鼠标点击事件,记录点击的目标坐标。3.移动逻辑使用Math.atan2计算从圆心到点击位置的角度。通过三角函数(Math.cos和Math.sin)逐帧更新圆的坐标,使其沿直线平滑移动。4.动画......
  • 基于手机移动端的自驾游汽车租赁租车系统 微信小程序-
    文章目录项目介绍具体实现截图技术介绍uniapp+hbuilderx小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示源码获取/详细视频演示项目介绍自驾游微信小程序通过提供便捷的信息查询、用户互动和管理功能,为自驾游爱好者提供了一个全面的服务平台。......
  • OpenResty + Lua 进行后端开发的可行性与应用场景
    OpenResty+Lua进行后端开发的可行性探究OpenResty+Lua进行后端开发是非常可行的,并且在某些场景下具有显著优势。下面我将从可行性、优缺点、适用场景以及一些实践建议等方面进行详细探讨。一、可行性分析OpenResty本质上是一个高性能的Web服务器和应用服务器,它基于Ngi......
  • OpenResty + Lua 进行后端开发的可行性与应用场景
    OpenResty+Lua进行后端开发的可行性探究OpenResty+Lua进行后端开发是非常可行的,并且在某些场景下具有显著优势。下面我将从可行性、优缺点、适用场景以及一些实践建议等方面进行详细探讨。一、可行性分析OpenResty本质上是一个高性能的Web服务器和应用服务器,它基于Ngi......
  • OpenResty + Lua 进行后端开发的可行性与应用场景
    OpenResty+Lua进行后端开发的可行性探究OpenResty+Lua进行后端开发是非常可行的,并且在某些场景下具有显著优势。下面我将从可行性、优缺点、适用场景以及一些实践建议等方面进行详细探讨。一、可行性分析OpenResty本质上是一个高性能的Web服务器和应用服务器,它基于Ngi......
  • moviepy字幕移动
    moviepy==1.0.2整块字幕移动#字幕整块平移......
  • C# 23种模式具体应用场景
    23种模式具体应用场景整理23种设计模式的应用场景并提供完整具体的Demo是一个相当庞大的任务。为了确保每个模式的解释和示例都清晰易懂,我将逐步介绍每个设计模式,并提供相应的C#代码示例和中文注释。1.单例模式(SingletonPattern)应用场景在一个Web应用中,我们可能需要一个全局......
  • 智慧园区算法视频分析服务器垃圾桶溢满检测算法:DDNS动态域名解析在安防场景中有哪些应
    随着互联网技术的不断进步,动态域名解析(DDNS)曾经是安防视频监控领域中一个不可或缺的技术。尽管在今天,DDNS的使用频率有所下降,尤其是在P2P技术逐渐普及的背景下,但它仍然在某些场景下发挥着重要作用。本文将带您回顾DDNS的定义、原理以及它在安防领域的应用,帮助您理解这项技术如何......
  • UE5 自转+移动靶的实现
    A、实现思路1、自转tick事件,设置本地旋转,速度由变量决定。2、自动移动自定义事件,设置时间轴,N秒内三个关键帧(如00-01-00),映射一个数值范围,以此设置相对位置。移动距离上限由变量决定。3、多靶子的不同效果在场景里复制多个靶子实例,每个靶子通过两个变量来设置不同数值......
  • 移动端设备上稀奇古怪的前端问题收集(一)
    作者:京东物流陈雨作为一名开发者,bug往往是我们最怕遇见的东西;而比遇到bug更可怕的事情,是定位不到bug。作为一名前端开发者,与业务逻辑相关的bug还相对好定位、好解决一些;而一些与语法特性、平台与设备差异相关的bug则更令人头疼一些。这里记录下我在工作中遇到过的稀奇古......