matlab绘制银河系,利用HTML5 Canvas实现绘制银河系特效

特效描述:利用HTML5 Canvas实现 绘制银河系特效。利用HTML5 Canvas实现绘制银河系特效

代码结构

1. HTML代码

var w = window.innerWidth;

var h = window.innerHeight;

var dustCanvas = document.createElement('canvas');

var dustCtx = dustCanvas.getContext('2d');

var starCanvas = document.createElement('canvas');

var starCtx = starCanvas.getContext('2d');

document.body.appendChild(dustCanvas);

document.body.appendChild(starCanvas);

dustCanvas.width = starCanvas.width = w;

dustCanvas.height = starCanvas.height = h;

dustCtx.globalCompositeOperation = 'lighter';

starCtx.globalCompositeOperation = 'lighter';

var galaxies = [];

var mouse = {

pos: {

x: w * 0.5,

y: h * 0.5

},

speed: 0

};

var randomNumbers = length => Array.from(new Array(length), () => Math.random());

var PI = Math.PI;

var TAU = PI * 2;

var r = () => Math.random();

var angle2 = (p1,p2) => Math.atan2(

p2[1]-p1[1],

p2[0]-p1[0]

);

var distance2 = (p1,p2) => Math.sqrt(

Math.pow(p1[0]-p2[0], 2) +

Math.pow(p1[1]-p2[1], 2)

);

var createDustParticle = (color) => {

var canvas = document.createElement('canvas');

var w = 100;

var h = 100;

var cx = w * 0.5;

var cy = h * 0.5;

canvas.width = w;

canvas.height = h;

var ctx = canvas.getContext('2d');

canvas.ctx = ctx;

var xRand = -5 + (r()*10);

var yRand = -5 + (r()*10);

var xRand2 = 10 + (r()*(cx/2));

var yRand2 = 10 + (r()*(cy/2));

var color = color || {

r: Math.round(150+(r()*100)),

g: Math.round(50+(r()*100)),

b: Math.round(50+(r()*100))

};

ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},.02)`;

Array

.from(new Array(200), () => randomNumbers(3))

.forEach( (p,i,arr) => {

var length = arr.length;

var x = Math.cos( TAU/xRand/length*i ) * p[2]*xRand2 + cx;

var y = Math.sin( TAU/yRand/length*i ) * p[2]*yRand2 + cy;

ctx.beginPath();

ctx.moveTo(x, y);

ctx.arc(x, y, p[2]*4, 0, TAU);

ctx.fill();

});

return canvas;

};

var Galaxy = function(x,y) {

var g = this;

g.x = x;

g.y = y;

g.stars = [];

g.dust = [];

g.drag = r();

g.angleOffsetX = TAU*r();

g.angleOffsetY = TAU*r();

g.realAngleOffsetX = 0;

g.realAngleOffsetY = 0;

g.color = {

r: Math.round(50+(r()*100)),

g: Math.round(50+(r()*100)),

b: Math.round(150+(r()*100))

};

var calculateStarDustParams = o => {

o.angle = angle2([g.x,g.y], [o.x,o.y]);

o.distance = distance2([g.x,g.y], [o.x,o.y]);

o.xAspect = [o.x/o.y];

o.yAspect = [o.y/o.x];

};

g.calculateCenter = () => {

if (!g.stars.length) return;

g.x = g.stars

.map(s => s.x)

.reduce((previous,current) => previous + current)

/ g.stars.length;

g.y = g.stars

.map(s => s.y)

.reduce((previous,current) => previous + current)

/ g.stars.length;

g.stars.forEach(calculateStarDustParams);

g.dust.forEach(calculateStarDustParams);

};

};

var Star = function(x, y, spread) {

var s = this;

s.x = x + Math.cos(TAU*r()) * spread;

s.y = y + Math.sin(TAU*r()) * spread;

s.radius = r()+0.25;

s.speed = r();

};

var Dust = function(x, y, size) {

var d = this;

d.x = x;

d.y = y;

d.size = size;

d.texture = createDustParticle();

d.speed = r();

};

var updateStarDust = (s,g) => {

if (g == currentGalaxy && drawingMode) return;

s.angle += (0.5+(s.speed*0.5))/s.distance;

s.x = g.x + (Math.cos(s.angle+g.realAngleOffsetX)*s.distance);

s.y = g.y + (Math.sin(s.angle+g.realAngleOffsetY)*s.distance);

};

var update = () => {

galaxies.forEach(g => {

if (g != currentGalaxy) {

g.realAngleOffsetX +=

g.realAngleOffsetX < g.angleOffsetX

? (g.angleOffsetX-g.realAngleOffsetX)*0.05 : 0;

g.realAngleOffsetY +=

g.realAngleOffsetY < g.angleOffsetY

? (g.angleOffsetY-g.realAngleOffsetY)*0.05 : 0;

}

g.stars.forEach((s) => {

/*s.distance -= s.distance < 2

? 0

: TAU/s.distance;*/

updateStarDust(s,g);

});

g.dust.forEach((d) => {

/*d.distance -= d.distance < 50

? 0

: TAU/d.distance;*/

updateStarDust(d,g);

});

});

};

var render = () => {

dustCtx.globalCompositeOperation = 'source-over';

dustCtx.fillStyle = 'rgba(0,0,0,.05)';

dustCtx.fillRect(0,0,w,h);

dustCtx.globalCompositeOperation = 'lighter';

starCtx.clearRect(0,0,w,h);

starCtx.fillStyle = '#ffffff';

starCtx.strokeStyle = 'rgba(255,255,255,.05)';

starCtx.beginPath();

if (drawingMode) galaxies.forEach(g => {

starCtx.moveTo(g.x, g.y);

starCtx.arc(g.x,g.y,2,0,TAU);

});

galaxies.forEach(g => {

g.stars.forEach(s => {

starCtx.moveTo(s.x, s.y);

starCtx.arc(s.x,s.y,s.radius,0,TAU);

});

g.dust.forEach(d => {

dustCtx.drawImage(d.texture, d.x-(d.size*0.5), d.y-(d.size*0.5), d.size, d.size)

});

});

dustCtx.fill();

starCtx.fill();

if (drawingMode && currentGalaxy) {

starCtx.beginPath();

currentGalaxy.stars.forEach((s,i) => {

starCtx.moveTo(s.x, s.y);

starCtx.lineTo(currentGalaxy.x, currentGalaxy.y);

});

starCtx.stroke();

}

};

var currentGalaxy = null;

var drawingMode = false;

var activateDraw = e => {

drawingMode = true;

mouse.pos.x = e.layerX;

mouse.pos.y = e.layerY;

currentGalaxy = new Galaxy(e.layerX, e.layerY);

galaxies.push(currentGalaxy);

};

var disableDraw = e => {

drawingMode = false;

currentGalaxy = null;

};

var draw = e => {

if (!drawingMode) return;

currentGalaxy.stars.push(new Star(mouse.pos.x, mouse.pos.y, mouse.speed));

currentGalaxy.stars.push(new Star(mouse.pos.x, mouse.pos.y, mouse.speed));

currentGalaxy.stars.push(new Star(mouse.pos.x, mouse.pos.y, mouse.speed));

if (mouse.speed*1.5 > 13 && mouse.speed < 100) currentGalaxy.dust.push(

new Dust(

(currentGalaxy.x + (Math.cos(TAU*r()) * mouse.speed*0.1)),

(currentGalaxy.y + (Math.sin(TAU*r()) * mouse.speed*0.1)),

mouse.speed*1.5

)

);

currentGalaxy.calculateCenter();

};

var loop = () => {

draw();

update();

render();

window.requestAnimationFrame(loop);

};

loop();

var moveEvent = e => {

mouse.speed = distance2(

[e.layerX,e.layerY],

[mouse.pos.x,mouse.pos.y]

);

mouse.pos.x = e.layerX;

mouse.pos.y = e.layerY;

draw(e);

};

window.addEventListener('mousedown', activateDraw);

window.addEventListener('mousemove', moveEvent);

window.addEventListener('mouseup',disableDraw);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值