html探照灯效果,HTML5 P5.js二维光线投射球形照明(探照灯)动画

本文介绍了一段使用JavaScript和p5.js库创建的3D光线投射效果代码。通过定义变量、事件监听和数学计算,实现了鼠标交互改变光线投射的方向和颜色,营造出动态的光影效果。代码中涉及的关键技术包括向量运算、圆周率应用、颜色渐变以及光线投射算法。
摘要由CSDN通过智能技术生成

JavaScript

语言:

JaveScriptBabelCoffeeScript

确定

let canvas, ctx;

let mouseIn = false;

function setup() {

canvas = createCanvas(windowWidth, windowHeight);

ctx = canvas.drawingContext;

canvas.canvas.onmouseenter = () => mouseIn = true;

canvas.canvas.onmouseleave = () => mouseIn = false;

}

function draw() {

// ctx.globalAlpha = 1;

blendMode(BLEND);

background(0);

stroke(255);

noFill();

let o = Date.now() / 3000;

// let center = createVector(

// width / 5 * cos(o) + width / 2,

// height / 2

// );

// let center = createVector(cos(o), sin(o))

// .mult(width / 5)

// .add(width / 2, height / 2);

let center = createVector(width / 2, height / 2);

translate(center.x, center.y);

let c = createVector(cos(o * PI), sin(o))

.mult(width / 5);

// .add(width / 2, height / 2);//createVector(0, 0);

let r = 100;

let p = createVector(

sin(o * 2) * 150,

cos(o) * 350

);

let p2;

if(mouseIn) {

p2 = createVector(mouseX, mouseY).sub(center);

}

else {

p2 = createVector(

sin(o * 1.5 + HALF_PI) * 150,

cos(o + HALF_PI + QUARTER_PI) * 350

);

}

blendMode(ADD);

doLight(c.copy(), r, p2.copy(), 1000, '210, 100%, 50%');

// ctx.globalAlpha = 0.75;

doLight(c.copy(), r, p.copy().mult(1.2).rotate(o * 4), 1000, '0, 100%, 50%');

doLight(c.copy(), r, p.copy().mult(1.4).rotate(-o * 5), 1000, '130, 100%, 50%');

}

function doLight(c, r, p, r2, hsl = '0, 0%, 100%') {

let a = p.copy().add(c).div(2);

let d_ = c.copy().sub(p);

let d = d_.mag();

if(d >= r) {

let [ x1, y1, x2, y2 ] = intersection(c.x, c.y, r, a.x, a.y, d / 2);

let va__ = createVector(x1, y1);

let vb__ = createVector(x2, y2);

// let va_ = va__.copy().sub(p);

// let vb_ = vb__.copy().sub(p);

let vac_ = va__.copy().sub(c);

let vbc_ = vb__.copy().sub(c);

// let angle = p5.Vector.angleBetween(va_, vb_);

// let va = va_.copy().setMag(1000).add(p);

// let vb = vb_.copy().setMag(1000).add(p);

// let vac = vac_.copy().setMag(1000).add(c);

// let vbc = vbc_.copy().setMag(1000).add(c);

let a_ = vac_.heading();

let b_ = vbc_.heading();

ctx.fillStyle = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r2);

ctx.fillStyle.addColorStop(0.0, `hsla(${hsl}, 1.0)`);

ctx.fillStyle.addColorStop(0.3, `hsla(${hsl}, 0.7)`);

ctx.fillStyle.addColorStop(1.0, `hsla(${hsl}, 0.0)`);

ctx.beginPath();

ctx.arc(p.x, p.y, r2, a_ + HALF_PI, b_ - HALF_PI, true);

ctx.arc(c.x, c.y, r, b_, a_, false);

ctx.closePath();

ctx.fill();

ctx.beginPath();

ctx.globalAlpha = 0.325;

ctx.arc(p.x, p.y, r2, 0, TAU);

ctx.closePath();

ctx.fill();

ctx.globalAlpha = 1.0;

let d__ = d_.copy().limit(r);

let grad = ctx.createRadialGradient(d__.x + c.x, d__.y + c.y, 0, c.x, c.y, r * 1.1);

grad.addColorStop(0.75, `hsla(${hsl}, 0.0)`);

grad.addColorStop(1.00, `hsla(${hsl}, ${map(d, r, r2, 1, 0)})`);

// Attempting to be more realistic.

// let grad = ctx.createRadialGradient(d__.x + c.x, d__.y + c.y, 0, c.x, c.y, r * 1.1);

// grad.addColorStop(constrain(map(d, r, r2, 0.5, 0.8), 0, 1), `hsla(${hsl}, 0.0)`);

// grad.addColorStop(constrain(map(d, r, r2, 0.6, 0.9), 0, 1), `hsla(${hsl}, ${map(d, r, r2, 0.9, 0)})`);

ctx.fillStyle = grad;

ctx.beginPath();

ctx.arc(c.x, c.y, r, 0, TAU);

ctx.fill();

}

}

function windowResized() {

resizeCanvas(windowWidth, windowHeight);

}

// Circle intersection.

// I took this from somewhere on StackOverflow. ¯\_(ツ)_/¯

function intersection(x0, y0, r0, x1, y1, r1) {

let a, dx, dy, d, h, rx, ry;

let x2, y2, xi, xi_prime, yi, yi_prime;

dx = x1 - x0;

dy = y1 - y0;

d = sqrt((dy * dy) + (dx * dx));

if(d > (r0 + r1) || d < abs(r0 - r1)) {

return false;

}

a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2.0 * d);

x2 = x0 + (dx * a / d);

y2 = y0 + (dy * a / d);

h = sqrt((r0 * r0) - (a * a));

rx = -dy * (h / d);

ry = dx * (h / d);

xi = x2 + rx;

xi_prime = x2 - rx;

yi = y2 + ry;

yi_prime = y2 - ry;

return [xi, yi, xi_prime, yi_prime];

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值