|
|
请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 马黑黑 于 2022-8-8 23:04 编辑
本帖不仅仅讨论标题提出的命题,因为这个命题太简单了。怎么个简单法?重绘背景之时,将 fillStyle 设置为透明色,比如针对画笔 ctx :
ctx.fillStyle = 'transparent';
或者:
ctx.fillStyle = 'rgba(0,0,0,0)';
然后重绘背景(参数 width 和 height 是事先获得赋值的变量):
ctx.fillRect(0,0,width,height);
如此,画布的背景色就是全透明的,而画布上绘制的元素是可见的,帖子之上,就好像没有画布一样。
还有一种方法,假如画布和帖子一样大小,则帖子父框不需要设置背景图片,直接用 drawImage 方法将已经预加载的图片标签(<img id="mypic" ... />)写入画布背景,取代上面的矩形填充(不需要设置 fillStyle):
ctx.drawImage(mpic, 0, 0, width, height);
本帖标题提出的命题已完成。下面讲重点:通过对象实现canvas画布动画并令动画融入帖子。
首先需要准备CSS和HTML层面的东东。我们的预设是这样:画布只是帖子的一个组成部分,它以 400*400 的尺寸出现在帖子的正中央。CSS和HTML代码如下:
<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>
这是三层的DOM结构:父元素 papa、子元素 mama、孙元素 canv(不要纠结mama为什么是papa的儿子哈)。
下面是重点中的重点:JS作画。为了将来便于扩展,我们需要创建一个绘制对象,本例的绘制对象是球球,我们用函数构建方法创建一个球球对象,使用构建函数创建对象的方法惯例上要求对象名称头一个字母大写:
function Ball(x, y, r, vx, vy, color) {
this.x = x; //圆心X坐标
this.y = y; //圆心Y坐标
this.r = r; //半径
this.vx = vx; //横向偏移量
this.vy = vy; //纵向偏移量
this.color = color; //球体颜色
}
对象的好处在于,它可以集合我们所需要的无序化的属性,还有方法,将来需要的时候还可以随意增减。这里,Ball 对象我们定义了6个属性,这些属性在对象实例化时再进行赋值,例如,在我们创建一个新的 Ball 对象的时候:
let myball = new Ball (60,60,20,0.5,1,'tan');
myball 通过 new Ball() 变成了一个 Ball 对象的实例,它的6个属性齐刷刷给了出来:X坐标60、Y坐标60、半径20、横向偏移量0.5、纵向偏移量1,颜色是棕褐色。myball实例化了Ball对象,它是可以直接被驱动的。当然,要驱动myball,有一些方法是Ball 对象通用的,就是说,Ball 对象应当创建有通用于所有实例化的类似于上面的 myball 的对象方法,我们可以使用 prototype 原型链属性来构建 Ball 的通用方法,例如,绘制球形:
Ball.prototype.draw = function() {
ctx.beginPath(); //画笔路径启动
ctx.fillStyle = this.color; //画笔填充色
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI); //绘制圆形
ctx.fill(); //上色
}
这个实际上是一个名叫 draw 的函数,不过它专属于 Ball 对象的一个通用函数(或方法),提供给 Ball 的实例化对象使用:
myball.draw();
这就画出了一个球形,球形的样式是按照 myball 提供的参数绘制的。
要使得球球运动,我们需要在画布上不停地擦除、重绘,球球的运动在画布上的体现是,擦除后在新的不远处重绘球球,就是说,arc() 画圆方法要改变圆心xy坐标进行重绘,达到圆从这个位置挪到了那个位置的效果。为此,我们需要为 Ball 对象创建一个改变 xy坐标的通用函数:
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;
}
两个 if 语句分别处理横纵两个方向的变化,我们以横向变化为例加以说明:如果圆的X坐标+圆半径大于等于画布宽度,或者(||表示或者),如果圆的X坐标-半径小于等于0,则令圆的横向偏移量变为自己的负数。
为什么要这么做?看看后两句,圆的xy坐标依次加上 vx 或 vy 偏移量,加加加的结果是圆的位置会突破画布尺寸,圆心坐标加半径大于等于画布宽度后如果不做干预球球就不可见,所以令偏移量变为其负数,它就会往回走,走走走又走到左边和上边,突破了左边线或上边线的标志是 圆心坐标减去半径小于等于0,我们就干预它,再令其偏移量等于自己的负数,负负得正原理知道吧?如此反复,圆永远画地为牢,好可怜的圆圆。
那么,怎样才能让上面 Ball 对象不停地运行起来?嗯,我们还得为实例化的 Ball 对象 myball 建立一个永动机制:
//动画渲染函数
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); //递归调用 本函数:永动机制
}
渲染动画函数要手动运行一次,然后就可以喝杯咖啡观赏球球的运动了:
render();
如果需要画多个球,思路是创建多个 Ball 对象实例,用数组来加载这些实例。这是后话,现在的重点问题是要先理解和掌握如何操纵一个球。
本帖所使用的完整代码放在二楼。
|
评分
-
| 参与人数 2 | 威望 +80 |
金钱 +160 |
经验 +80 |
收起
理由
|
加林森
| + 30 |
+ 60 |
+ 30 |
很给力! |
红影
| + 50 |
+ 100 |
+ 50 |
赞一个! |
查看全部评分
|