three.js和画布实现信号光圈动画
实现效果
信号光圈由中心向外发散,并逐渐消失。
实现思路
使用画布制作光圈,以画布作为纹理,在循环渲染函数中改变mesh的尺寸和透明度。
具体实现
1、画布制作光圈
//创建画布
var canvas = document.createElement('canvas');
//设置画布大小
canvas.width = 300;
canvas.height=300;
//2.获取在 canvas 上绘图的 canvasRenderingContent2D 对象。这两行是必不可少的哦
var ctx=canvas.getContext("2d");
//3.绘制
//第一圈
ctx.beginPath();//开始绘制
ctx.lineWidth = 2;//线的宽度
ctx.arc(150,150,1,0,2*Math.PI);//arc 的意思是“弧”
ctx.fillStyle = 'rgba(255, 255, 255, 0)';//画布背景
ctx.strokeStyle="#00ff00";//将线条颜色设置为蓝色
ctx.stroke();//stroke() 方法默认颜色是黑色(如果没有上面一行,则会是黑色)。
ctx.closePath();//结束绘制
//第二圈
ctx.beginPath();//开始绘制
ctx.lineWidth = 2;//线的宽度
ctx.arc(150,150,30,0,2*Math.PI);//arc 的意思是“弧”
ctx.fillStyle = 'rgba(255, 255, 255, 0)';//画布背景
ctx.strokeStyle="#5CFF5C";//将线条颜色设置为蓝色
ctx.stroke();//stroke() 方法默认颜色是黑色(如果没有上面一行,则会是黑色)。
ctx.closePath();//结束绘制
//第三圈
ctx.beginPath();//开始绘制
ctx.lineWidth = 2;//线的宽度
ctx.arc(150,150,60,0,2*Math.PI);//arc 的意思是“弧”
ctx.fillStyle = 'rgba(255, 255, 255, 0)';//画布背景
ctx.strokeStyle="#97FF97";//将线条颜色设置为蓝色
ctx.stroke();//stroke() 方法默认颜色是黑色(如果没有上面一行,则会是黑色)。
ctx.closePath();//结束绘制
//第四圈
ctx.beginPath();//开始绘制
ctx.lineWidth = 2;//线的宽度
ctx.arc(150,150,90,0,2*Math.PI);//arc 的意思是“弧”
ctx.fillStyle = 'rgba(255, 255, 255, 0)';//画布背景
ctx.strokeStyle="#BDFFBD";//将线条颜色设置为蓝色
ctx.stroke();//stroke() 方法默认颜色是黑色(如果没有上面一行,则会是黑色)。
ctx.closePath();//结束绘制
2、动画光圈实现(主要代码)
/**
* 发送信号光圈
*/
var mesh;
function signalLightCanvas(){
//创建画布
var canvas = document.createElement('canvas');
.....(实现画布看`画布制作多圆嵌套`)
//画布作为纹理
var canvas_texture = new THREE.CanvasTexture(canvas);
canvas_texture.needsUpdate = true;
var canvas_geometry = new THREE.PlaneBufferGeometry (10,10);
var canvas_material = new THREE.MeshBasicMaterial({
map:canvas_texture,
transparent:true,
side:THREE.DoubleSide,
depthWrite:false
});
mesh = new THREE.Mesh(canvas_geometry,canvas_material);
mesh.position.set(posArr[i].x,posArr[i].y,posArr[i].z);
scene.add(mesh);
}
}
//渲染函数中:改变mesh的尺寸和透明度
function animate() {
window.requestAnimationFrame(() => {
//光圈动画
var size = 0.03;//可自行更改
if (mesh) {
mesh._s += 0.007;
mesh.scale.set( size* mesh._s, size * mesh._s,size * mesh._s );
if (mesh._s <= 1.5) {
//mesh._s=1,透明度=0 mesh._s=1.5,透明度=1
mesh.material.opacity = ( mesh._s - 1 ) * 2;
} else if (mesh._s > 1.5 && mesh._s <= 2) {
//mesh._s=1.5,透明度=1 mesh._s=2,透明度=0
mesh.material.opacity = 1 - ( mesh._s - 1.5 ) * 2;
} else {
mesh._s = 1.0;
}
}
renderer.clear();
renderer.render( scene, camera );
animate();
});
}