马黑黑 发表于 2022-8-9 12:58

canvas画布融入帖子续篇:驱动多个运动对象

我们已经介绍了如何在canvas画布里通过创建对象的方式驱动一个球球,该方法的核心是构建一个运动对象,该对象拥有一些通用属性和若干方法,然后以实例化的形式提供属性值、调用通用方法,从而驱动实例对象运动。之前的介绍,我们只创建了一个对象实例,但我们谈到可以扩展实例并将诸多实例放入数组中,然后在渲染动画函数中一一驱动这些对象实例。

要实现对多个运动对象的驱动,我们需要准备一个工具函数,它的作用是获取随机整数,以便我们在创建 Ball 对象实例时随机定义圆球的圆心坐标、半径、横向纵向偏移量和颜色等等。针对偏移量等,我们希望圆球一开始时走向不同,但不能出现0,所以取整数的函数我们要处理一下这个问题:

let num = (min, max) => {
        let number = Math.floor(Math.random() * (max - min + 1)) + min;
        if(number == 0) number = 1;
        return number;
}

这样,我们就可以创建 Ball 对象的多个实例化对象了。首先声明一个数组,用以存储实例化对象:

let ballAr = new Array(20);

ballAr 现在是个空数组,其长度是 20,即它有 20 个空元素。下一步,我们用一个 for 语句充实这些空元素并令其成为 Ball 的实例化对象:

for(let j = 0; j < ballAr.length; j++) { //批量实例化Ball对象
        let item = new Ball(
                num(20, width - 20), // x 坐标
                num(20, height - 20), // y 坐标
                num(5,10), // r 半径
                0.5 * num(-2, 2), // vx 偏移量
                0.5 * num(-2,2), // vy 偏移量
                `rgba(${num(0,255)}, ${num(0,255)}, ${num(0,255)}, 075)` //color 颜色
        );
        ballAr = item; //记入数组内容
}

最后,我们将渲染函数中驱动单个实体化对象换成驱动多个实体化对象即可大功告成(可以比较一下二者的不同):

//渲染函数 :驱动多个对象
function render() {
        ctx.clearRect(0,0,width,height); //清除画布
        ctx.fillStyle = 'transparent'; //画布填充底色
        ctx.fillRect(0,0,width,height); //填充矩形区域
        for(item of ballAr) { //遍历已实体化的 Ball 对象数组
                item.draw(); //对象绘制
                item.move(); //对象数据更新
        }
        requestAnimationFrame(render); //递归调用本函数
}

附:驱动单个对象运动的函数

//渲染函数 :驱动单个对象
function render() {
      ctx.clearRect(0,0,width,height); //清除画布
      ctx.fillStyle = 'transparent'; //'rgba(0,0,0,0)'; //用透明色绘制画布底色
      ctx.fillRect(0,0,width,height); //填充矩形(draw() 函数就在这个矩形区域上作画)
      myball.draw(); //调用 draw 函数作画
      myball.move(); // 变更数据
      requestAnimationFrame(render); //递归调用 本函数:永动机制
}

完整代码请在二楼查阅。

马黑黑 发表于 2022-8-9 12:59

驱动多个对象运动的示例代码:
<style>
#papa { margin: auto; width: 1024px; height: 640px; box-shadow: 3px 3px 20px #000; position: relative; }
#mama { position: absolute; width: 400px; height: 400px; left: calc(50% - 200px); top: calc(50% - 200px); border: 1px solid pink; }
#canv { position: absolute; }
</style>

<div id="papa">
        <div id="mama"><canvas id="canv"></canvas></div>
</div>

<script>

let width = canv.width = mama.offsetWidth, height = canv.height = mama.offsetHeight;
let ctx = canv.getContext('2d');
let ballAr = new Array(20);

let num = (min, max) => {
        let number = Math.floor(Math.random() * (max-min+1)) + min;
        if(number == 0) number = 1;
        return number;
}

for(let j = 0; j < ballAr.length; j++) { //实例化对象
        let item = new Ball(
                num(20, width - 20), // x 坐标
                num(20, height - 20), // y 坐标
                num(5,10), // r 半径
                0.5 * num(-2, 2), // vx 偏移量
                0.5 * num(-2,2), // vy 偏移量
                `rgba(${num(0,255)}, ${num(0,255)}, ${num(0,255)}, 075)` //color 颜色
        );
        ballAr = item;
}
//绘制对象
function Ball(x, y, r, vx, vy, color) {
        this.x = x;
        this.y = y;
        this.r = r;
        this.vx = vx;
        this.vy = vy;
        this.color = color;
}
//绘制函数 :画圆
Ball.prototype.draw = function() {
        ctx.beginPath();
        ctx.fillStyle = this.color
        ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
        ctx.fill();
}
//移动函数 :变换圆心
Ball.prototype.move = function() {
        if (this.x + this.r >= width || this.x - this.r <= 0) this.vx = -this.vx;
        if (this.y + this.r >= height || this.y - this.r <= 0) this.vy = -this.vy;
        this.x += this.vx;
        this.y += this.vy;
}
//渲染函数 :整合绘制、更新函数+递归调用
function render() {
        ctx.clearRect(0,0,width,height);
        ctx.fillStyle = 'transparent';
        ctx.fillRect(0,0,width,height);
        for(item of ballAr) {
                item.draw();
                item.move();
        }
        requestAnimationFrame(render);
}

render();

</script>

加林森 发表于 2022-8-9 14:43

各有自己的运动轨迹,这个方法真好。

红影 发表于 2022-8-9 14:48

其实对于画布的用法还是不熟,正好有黑黑的帖子可以跟着学习,谢谢黑黑{:4_187:}

马黑黑 发表于 2022-8-9 22:30

加林森 发表于 2022-8-9 14:43
各有自己的运动轨迹,这个方法真好。

看懂了

马黑黑 发表于 2022-8-9 22:30

红影 发表于 2022-8-9 14:48
其实对于画布的用法还是不熟,正好有黑黑的帖子可以跟着学习,谢谢黑黑

画布学问很多

加林森 发表于 2022-8-9 22:33

马黑黑 发表于 2022-8-9 22:30
看懂了

基本上看懂了。明天来制作一个试试。

加林森 发表于 2022-8-9 22:33

马黑黑 发表于 2022-8-9 22:30
看懂了

基本上看懂了。明天来制作一个试试。

马黑黑 发表于 2022-8-9 22:39

加林森 发表于 2022-8-9 22:33
基本上看懂了。明天来制作一个试试。

挺好

加林森 发表于 2022-8-9 22:43

马黑黑 发表于 2022-8-9 22:39
挺好

嗯嗯。谢谢你啦!{:4_191:}

加林森 发表于 2022-8-9 22:58

马黑黑 发表于 2022-8-9 22:39
挺好

我有一个构思。父框在外练太极,子框就是八封了,八封是动画的。我该怎么去设置?

马黑黑 发表于 2022-8-9 23:02

加林森 发表于 2022-8-9 22:58
我有一个构思。父框在外练太极,子框就是八封了,八封是动画的。我该怎么去设置?

我不懂太极和八卦

加林森 发表于 2022-8-9 23:13

马黑黑 发表于 2022-8-9 23:02
我不懂太极和八卦

就是八卦图片在动在转啊。

马黑黑 发表于 2022-8-9 23:21

加林森 发表于 2022-8-9 23:13
就是八卦图片在动在转啊。

这个用不着画布。让一个图片转动,用CSS的关键帧动画便可,就像驱动播放器光盘一样。

加林森 发表于 2022-8-9 23:27

马黑黑 发表于 2022-8-9 23:21
这个用不着画布。让一个图片转动,用CSS的关键帧动画便可,就像驱动播放器光盘一样。

哦。明白了。谢谢啦。明天来试一下。谢啦!

马黑黑 发表于 2022-8-9 23:37

加林森 发表于 2022-8-9 23:27
哦。明白了。谢谢啦。明天来试一下。谢啦!

不行的话去补一补CSS关键帧动画,这里有一个很容易上手的基础教程:

https://www.twle.cn/l/yufei/css3/css-css3-animations.html

加林森 发表于 2022-8-9 23:39

马黑黑 发表于 2022-8-9 23:37
不行的话去补一补CSS关键帧动画,这里有一个很容易上手的基础教程:

https://www.twle.cn/l/yufei/css ...

谢啦老黑!明天见!

马黑黑 发表于 2022-8-9 23:46

加林森 发表于 2022-8-9 23:39
谢啦老黑!明天见!

{:4_181:}

加林森 发表于 2022-8-10 08:16

马黑黑 发表于 2022-8-9 23:46


老黑早上好!

红影 发表于 2022-8-10 17:32

马黑黑 发表于 2022-8-9 22:30
画布学问很多

感觉到了{:4_173:}
页: [1] 2
查看完整版本: canvas画布融入帖子续篇:驱动多个运动对象