猿问

如何更改 Javascript 对象的不透明度

在这里找到使用普通 JavaScript 的元球代码。有什么方法可以改变元球的不透明度吗?我认为这应该是一个快速解决方案,但我不太确定。我尝试更改为 CSS 类气泡,但这不起作用,所以我假设需要在 Javascript 中。有什么帮助,谢谢。

在这里找到使用普通 JavaScript 的元球代码。有什么方法可以改变元球的不透明度吗?我认为这应该是一个快速解决方案,但我不太确定。我尝试更改为 CSS 类气泡,但这不起作用,所以我假设需要在 Javascript 中。有什么帮助,谢谢。

body {

  margin: 0;

}


.wrap {

  overflow: hidden;

  position: relative;

  height: 100vh;

}


canvas {

  width: 100%;

  height: 100%;

}

<div class="wrap">

  <canvas id="bubble"></canvas>

</div>


慕虎7371278
浏览 152回答 2
2回答

当年话下

您可以通过使用 RGBA 更改上下文 alpha 通道来实现此目的(请参阅最底部ctx.fillStyle = 'rgba(0, 0, 255, 0.5)' // NEW!,其中 0.5 是不透明度级别 - 请参阅):;(function() {&nbsp; 'use strict'&nbsp; var lava0&nbsp; var ge1doot = {&nbsp; &nbsp; screen: {&nbsp; &nbsp; &nbsp; elem: null,&nbsp; &nbsp; &nbsp; callback: null,&nbsp; &nbsp; &nbsp; ctx: null,&nbsp; &nbsp; &nbsp; width: 0,&nbsp; &nbsp; &nbsp; height: 0,&nbsp; &nbsp; &nbsp; left: 0,&nbsp; &nbsp; &nbsp; top: 0,&nbsp; &nbsp; &nbsp; init: function(id, callback, initRes) {&nbsp; &nbsp; &nbsp; &nbsp; this.elem = document.getElementById(id)&nbsp; &nbsp; &nbsp; &nbsp; this.callback = callback || null&nbsp; &nbsp; &nbsp; &nbsp; if (this.elem.tagName == 'CANVAS') this.ctx = this.elem.getContext('2d')&nbsp; &nbsp; &nbsp; &nbsp; window.addEventListener(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'resize',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.resize()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }.bind(this),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; false&nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; this.elem.onselectstart = function() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; this.elem.ondrag = function() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; initRes && this.resize()&nbsp; &nbsp; &nbsp; &nbsp; return this&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; resize: function() {&nbsp; &nbsp; &nbsp; &nbsp; var o = this.elem&nbsp; &nbsp; &nbsp; &nbsp; this.width = o.offsetWidth&nbsp; &nbsp; &nbsp; &nbsp; this.height = o.offsetHeight&nbsp; &nbsp; &nbsp; &nbsp; for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.left += o.offsetLeft&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.top += o.offsetTop&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (this.ctx) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.elem.width = this.width&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.elem.height = this.height&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; this.callback && this.callback()&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; },&nbsp; }&nbsp; // Point constructor&nbsp; var Point = function(x, y) {&nbsp; &nbsp; this.x = x&nbsp; &nbsp; this.y = y&nbsp; &nbsp; this.magnitude = x * x + y * y&nbsp; &nbsp; this.computed = 0&nbsp; &nbsp; this.force = 0&nbsp; }&nbsp; Point.prototype.add = function(p) {&nbsp; &nbsp; return new Point(this.x + p.x, this.y + p.y)&nbsp; }&nbsp; // Ball constructor&nbsp; var Ball = function(parent) {&nbsp; &nbsp; var min = 0.1&nbsp; &nbsp; var max = 1.5&nbsp; &nbsp; this.vel = new Point(&nbsp; &nbsp; &nbsp; (Math.random() > 0.5 ? 1 : -1) * (0.2 + Math.random() * 0.25),&nbsp; &nbsp; &nbsp; (Math.random() > 0.5 ? 1 : -1) * (0.2 + Math.random())&nbsp; &nbsp; )&nbsp; &nbsp; this.pos = new Point(&nbsp; &nbsp; &nbsp; parent.width * 0.2 + Math.random() * parent.width * 0.6,&nbsp; &nbsp; &nbsp; parent.height * 0.2 + Math.random() * parent.height * 0.6&nbsp; &nbsp; )&nbsp; &nbsp; this.size = parent.wh / 15 + (Math.random() * (max - min) + min) * (parent.wh / 15)&nbsp; &nbsp; this.width = parent.width&nbsp; &nbsp; this.height = parent.height&nbsp; }&nbsp; // move balls&nbsp; Ball.prototype.move = function() {&nbsp; &nbsp; // bounce borders&nbsp; &nbsp; if (this.pos.x >= this.width - this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.x > 0) this.vel.x = -this.vel.x&nbsp; &nbsp; &nbsp; this.pos.x = this.width - this.size&nbsp; &nbsp; } else if (this.pos.x <= this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.x < 0) this.vel.x = -this.vel.x&nbsp; &nbsp; &nbsp; this.pos.x = this.size&nbsp; &nbsp; }&nbsp; &nbsp; if (this.pos.y >= this.height - this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.y > 0) this.vel.y = -this.vel.y&nbsp; &nbsp; &nbsp; this.pos.y = this.height - this.size&nbsp; &nbsp; } else if (this.pos.y <= this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.y < 0) this.vel.y = -this.vel.y&nbsp; &nbsp; &nbsp; this.pos.y = this.size&nbsp; &nbsp; }&nbsp; &nbsp; // velocity&nbsp; &nbsp; this.pos = this.pos.add(this.vel)&nbsp; }&nbsp; // lavalamp constructor&nbsp; var LavaLamp = function(width, height, numBalls, c0, c1) {&nbsp; &nbsp; this.step = 5&nbsp; &nbsp; this.width = width&nbsp; &nbsp; this.height = height&nbsp; &nbsp; this.wh = Math.min(width, height)&nbsp; &nbsp; this.sx = Math.floor(this.width / this.step)&nbsp; &nbsp; this.sy = Math.floor(this.height / this.step)&nbsp; &nbsp; this.paint = false&nbsp; &nbsp; this.metaFill = createRadialGradient(width, height, width, c0, c1)&nbsp; &nbsp; this.plx = [0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0]&nbsp; &nbsp; this.ply = [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1]&nbsp; &nbsp; this.mscases = [0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 0, 2, 1, 1, 0]&nbsp; &nbsp; this.ix = [1, 0, -1, 0, 0, 1, 0, -1, -1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1]&nbsp; &nbsp; this.grid = []&nbsp; &nbsp; this.balls = []&nbsp; &nbsp; this.iter = 0&nbsp; &nbsp; this.sign = 1&nbsp; &nbsp; // init grid&nbsp; &nbsp; for (var i = 0; i < (this.sx + 2) * (this.sy + 2); i++) {&nbsp; &nbsp; &nbsp; this.grid[i] = new Point((i % (this.sx + 2)) * this.step, Math.floor(i / (this.sx + 2)) * this.step)&nbsp; &nbsp; }&nbsp; &nbsp; // create metaballs&nbsp; &nbsp; for (var k = 0; k < numBalls; k++) {&nbsp; &nbsp; &nbsp; this.balls[k] = new Ball(this)&nbsp; &nbsp; }&nbsp; }&nbsp; // compute cell force&nbsp; LavaLamp.prototype.computeForce = function(x, y, idx) {&nbsp; &nbsp; var force&nbsp; &nbsp; var id = idx || x + y * (this.sx + 2)&nbsp; &nbsp; if (x === 0 || y === 0 || x === this.sx || y === this.sy) {&nbsp; &nbsp; &nbsp; force = 0.6 * this.sign&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; force = 0&nbsp; &nbsp; &nbsp; var cell = this.grid[id]&nbsp; &nbsp; &nbsp; var i = 0&nbsp; &nbsp; &nbsp; var ball&nbsp; &nbsp; &nbsp; while ((ball = this.balls[i++])) {&nbsp; &nbsp; &nbsp; &nbsp; force +=&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (ball.size * ball.size) /&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (-2 * cell.x * ball.pos.x - 2 * cell.y * ball.pos.y + ball.pos.magnitude + cell.magnitude)&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; force *= this.sign&nbsp; &nbsp; }&nbsp; &nbsp; this.grid[id].force = force&nbsp; &nbsp; return force&nbsp; }&nbsp; // compute cell&nbsp; LavaLamp.prototype.marchingSquares = function(next) {&nbsp; &nbsp; var x = next[0]&nbsp; &nbsp; var y = next[1]&nbsp; &nbsp; var pdir = next[2]&nbsp; &nbsp; var id = x + y * (this.sx + 2)&nbsp; &nbsp; if (this.grid[id].computed === this.iter) {&nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; var dir,&nbsp; &nbsp; &nbsp; mscase = 0&nbsp; &nbsp; // neighbors force&nbsp; &nbsp; for (var i = 0; i < 4; i++) {&nbsp; &nbsp; &nbsp; var idn = x + this.ix[i + 12] + (y + this.ix[i + 16]) * (this.sx + 2)&nbsp; &nbsp; &nbsp; var force = this.grid[idn].force&nbsp; &nbsp; &nbsp; if ((force > 0 && this.sign < 0) || (force < 0 && this.sign > 0) || !force) {&nbsp; &nbsp; &nbsp; &nbsp; // compute force if not in buffer&nbsp; &nbsp; &nbsp; &nbsp; force = this.computeForce(x + this.ix[i + 12], y + this.ix[i + 16], idn)&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; if (Math.abs(force) > 1) mscase += Math.pow(2, i)&nbsp; &nbsp; }&nbsp; &nbsp; if (mscase === 15) {&nbsp; &nbsp; &nbsp; // inside&nbsp; &nbsp; &nbsp; return [x, y - 1, false]&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; // ambiguous cases&nbsp; &nbsp; &nbsp; if (mscase === 5) dir = pdir === 2 ? 3 : 1&nbsp; &nbsp; &nbsp; else if (mscase === 10) dir = pdir === 3 ? 0 : 2&nbsp; &nbsp; &nbsp; else {&nbsp; &nbsp; &nbsp; &nbsp; // lookup&nbsp; &nbsp; &nbsp; &nbsp; dir = this.mscases[mscase]&nbsp; &nbsp; &nbsp; &nbsp; this.grid[id].computed = this.iter&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; // draw line&nbsp; &nbsp; &nbsp; var ix =&nbsp; &nbsp; &nbsp; &nbsp; this.step /&nbsp; &nbsp; &nbsp; &nbsp; (Math.abs(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.abs(this.grid[x + this.plx[4 * dir + 2] + (y + this.ply[4 * dir + 2]) * (this.sx + 2)].force) - 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) /&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.abs(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.abs(this.grid[x + this.plx[4 * dir + 3] + (y + this.ply[4 * dir + 3]) * (this.sx + 2)].force) - 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ) +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1)&nbsp; &nbsp; &nbsp; ctx.lineTo(&nbsp; &nbsp; &nbsp; &nbsp; this.grid[x + this.plx[4 * dir] + (y + this.ply[4 * dir]) * (this.sx + 2)].x + this.ix[dir] * ix,&nbsp; &nbsp; &nbsp; &nbsp; this.grid[x + this.plx[4 * dir + 1] + (y + this.ply[4 * dir + 1]) * (this.sx + 2)].y + this.ix[dir + 4] * ix&nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; this.paint = true&nbsp; &nbsp; &nbsp; // next&nbsp; &nbsp; &nbsp; return [x + this.ix[dir + 4], y + this.ix[dir + 8], dir]&nbsp; &nbsp; }&nbsp; }&nbsp; LavaLamp.prototype.renderMetaballs = function() {&nbsp; &nbsp; var i = 0,&nbsp; &nbsp; &nbsp; ball&nbsp; &nbsp; while ((ball = this.balls[i++])) ball.move()&nbsp; &nbsp; // reset grid&nbsp; &nbsp; this.iter++&nbsp; &nbsp; &nbsp; this.sign = -this.sign&nbsp; &nbsp; this.paint = false&nbsp; &nbsp; ctx.fillStyle = this.metaFill&nbsp; &nbsp; ctx.beginPath()&nbsp; &nbsp; // compute metaballs&nbsp; &nbsp; i = 0&nbsp; &nbsp; //ctx.shadowBlur = 50;&nbsp; &nbsp; //ctx.shadowColor = "green";&nbsp; &nbsp; while ((ball = this.balls[i++])) {&nbsp; &nbsp; &nbsp; // first cell&nbsp; &nbsp; &nbsp; var next = [Math.round(ball.pos.x / this.step), Math.round(ball.pos.y / this.step), false]&nbsp; &nbsp; &nbsp; // marching squares&nbsp; &nbsp; &nbsp; do {&nbsp; &nbsp; &nbsp; &nbsp; next = this.marchingSquares(next)&nbsp; &nbsp; &nbsp; } while (next)&nbsp; &nbsp; &nbsp; // fill and close path&nbsp; &nbsp; &nbsp; if (this.paint) {&nbsp; &nbsp; &nbsp; &nbsp; ctx.fill()&nbsp; &nbsp; &nbsp; &nbsp; ctx.closePath()&nbsp; &nbsp; &nbsp; &nbsp; ctx.beginPath()&nbsp; &nbsp; &nbsp; &nbsp; this.paint = false&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; // gradients&nbsp; var createRadialGradient = function(w, h, r, c0, c1) {&nbsp; &nbsp; var gradient = ctx.createRadialGradient(w / 1, h / 1, 0, w / 1, h / 1, r)&nbsp; &nbsp; gradient.addColorStop(0, c0)&nbsp; &nbsp; gradient.addColorStop(1, c1)&nbsp; }&nbsp; // main loop&nbsp; var run = function() {&nbsp; &nbsp; requestAnimationFrame(run)&nbsp; &nbsp; ctx.clearRect(0, 0, screen.width, screen.height)&nbsp; &nbsp; ctx.fillStyle = 'rgba(0, 0, 255, 0.5)' // NEW!&nbsp; &nbsp; lava0.renderMetaballs()&nbsp; }&nbsp; // canvas&nbsp; var screen = ge1doot.screen.init('bubble', null, true),&nbsp; &nbsp; ctx = screen.ctx&nbsp; screen.resize()&nbsp; // create LavaLamps&nbsp; lava0 = new LavaLamp(screen.width, screen.height, 6, '#FF9298', '#E4008E')&nbsp; run()})()body {&nbsp; margin: 0;}.wrap {&nbsp; overflow: hidden;&nbsp; position: relative;&nbsp; height: 100vh;}canvas {&nbsp; width: 100%;&nbsp; height: 100%;}<div class="wrap">&nbsp; <canvas id="bubble"></canvas></div>

冉冉说

您的 Lava 构造函数采用两种颜色,可以修改这些颜色以满足您的颜色需求。通过使用rgba()颜色版本,您可以设置 alpha(即不透明度)或气泡/肉丸。但是,在执行此操作之前,您需要返回gradient创建的 颜色createRadialGradient,以便可以使用颜色:var createRadialGradient = function(w, h, r, c0, c1) {&nbsp; // ... code ...&nbsp; return gradient; // add this line};现在您可以修改调用构造函数的方式:// rgba versions of your colors -----------------------\/lava0 = new LavaLamp(screen.width, screen.height, 6, "rgba(255, 146, 152, 0.5)", "rgba(228, 0, 142, 0.5)");;(function() {&nbsp; "use strict";&nbsp; var lava0;&nbsp; var ge1doot = {&nbsp; &nbsp; screen: {&nbsp; &nbsp; &nbsp; elem:&nbsp; &nbsp; &nbsp;null,&nbsp; &nbsp; &nbsp; callback: null,&nbsp; &nbsp; &nbsp; ctx:&nbsp; &nbsp; &nbsp; null,&nbsp; &nbsp; &nbsp; width:&nbsp; &nbsp; 0,&nbsp; &nbsp; &nbsp; height:&nbsp; &nbsp;0,&nbsp; &nbsp; &nbsp; left:&nbsp; &nbsp; &nbsp;0,&nbsp; &nbsp; &nbsp; top:&nbsp; &nbsp; &nbsp; 0,&nbsp; &nbsp; &nbsp; init: function (id, callback, initRes) {&nbsp; &nbsp; &nbsp; &nbsp; this.elem = document.getElementById(id);&nbsp; &nbsp; &nbsp; &nbsp; this.callback = callback || null;&nbsp; &nbsp; &nbsp; &nbsp; if (this.elem.tagName == "CANVAS") this.ctx = this.elem.getContext("2d");&nbsp; &nbsp; &nbsp; &nbsp; window.addEventListener('resize', function () {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.resize();&nbsp; &nbsp; &nbsp; &nbsp; }.bind(this), false);&nbsp; &nbsp; &nbsp; &nbsp; this.elem.onselectstart = function () { return false; }&nbsp; &nbsp; &nbsp; &nbsp; this.elem.ondrag&nbsp; &nbsp; &nbsp; &nbsp; = function () { return false; }&nbsp; &nbsp; &nbsp; &nbsp; initRes && this.resize();&nbsp; &nbsp; &nbsp; &nbsp; return this;&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; resize: function () {&nbsp; &nbsp; &nbsp; &nbsp; var o = this.elem;&nbsp; &nbsp; &nbsp; &nbsp; this.width&nbsp; = o.offsetWidth;&nbsp; &nbsp; &nbsp; &nbsp; this.height = o.offsetHeight;&nbsp; &nbsp; &nbsp; &nbsp; for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.left += o.offsetLeft;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.top&nbsp; += o.offsetTop;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (this.ctx) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.elem.width&nbsp; = this.width;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.elem.height = this.height;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; this.callback && this.callback();&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; // Point constructor&nbsp; var Point = function(x, y) {&nbsp; &nbsp; this.x = x;&nbsp; &nbsp; this.y = y;&nbsp; &nbsp; this.magnitude = x * x + y * y;&nbsp; &nbsp; this.computed = 0;&nbsp; &nbsp; this.force = 0;&nbsp; };&nbsp; Point.prototype.add = function(p) {&nbsp; &nbsp; return new Point(this.x + p.x, this.y + p.y);&nbsp; };&nbsp; // Ball constructor&nbsp; var Ball = function(parent) {&nbsp; &nbsp; var min = .1;&nbsp; &nbsp; var max = 1.5;&nbsp; &nbsp; this.vel = new Point(&nbsp; &nbsp; &nbsp; (Math.random() > 0.5 ? 1 : -1) * (0.2 + Math.random() * 0.25), (Math.random() > 0.5 ? 1 : -1) * (0.2 + Math.random())&nbsp; &nbsp; );&nbsp; &nbsp; this.pos = new Point(&nbsp; &nbsp; &nbsp; parent.width * 0.2 + Math.random() * parent.width * 0.6,&nbsp; &nbsp; &nbsp; parent.height * 0.2 + Math.random() * parent.height * 0.6&nbsp; &nbsp; );&nbsp; &nbsp; this.size = (parent.wh / 15) + ( Math.random() * (max - min) + min ) * (parent.wh / 15);&nbsp; &nbsp; this.width = parent.width;&nbsp; &nbsp; this.height = parent.height;&nbsp; };&nbsp; // move balls&nbsp; Ball.prototype.move = function() {&nbsp; &nbsp; // bounce borders&nbsp; &nbsp; if (this.pos.x >= this.width - this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.x > 0) this.vel.x = -this.vel.x;&nbsp; &nbsp; &nbsp; this.pos.x = this.width - this.size;&nbsp; &nbsp; } else if (this.pos.x <= this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.x < 0) this.vel.x = -this.vel.x;&nbsp; &nbsp; &nbsp; this.pos.x = this.size;&nbsp; &nbsp; }&nbsp; &nbsp; if (this.pos.y >= this.height - this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.y > 0) this.vel.y = -this.vel.y;&nbsp; &nbsp; &nbsp; this.pos.y = this.height - this.size;&nbsp; &nbsp; } else if (this.pos.y <= this.size) {&nbsp; &nbsp; &nbsp; if (this.vel.y < 0) this.vel.y = -this.vel.y;&nbsp; &nbsp; &nbsp; this.pos.y = this.size;&nbsp; &nbsp; }&nbsp; &nbsp; // velocity&nbsp; &nbsp; this.pos = this.pos.add(this.vel);&nbsp; };&nbsp; // lavalamp constructor&nbsp; var LavaLamp = function(width, height, numBalls, c0, c1) {&nbsp; &nbsp; this.step = 5;&nbsp; &nbsp; this.width = width;&nbsp; &nbsp; this.height = height;&nbsp; &nbsp; this.wh = Math.min(width, height);&nbsp; &nbsp; this.sx = Math.floor(this.width / this.step);&nbsp; &nbsp; this.sy = Math.floor(this.height / this.step);&nbsp; &nbsp; this.paint = false;&nbsp; &nbsp; this.metaFill = createRadialGradient(width, height, width, c0, c1);&nbsp; &nbsp; this.plx = [0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0];&nbsp; &nbsp; this.ply = [0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1];&nbsp; &nbsp; this.mscases = [0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 0, 2, 1, 1, 0];&nbsp; &nbsp; this.ix = [1, 0, -1, 0, 0, 1, 0, -1, -1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1];&nbsp; &nbsp; this.grid = [];&nbsp; &nbsp; this.balls = [];&nbsp; &nbsp; this.iter = 0;&nbsp; &nbsp; this.sign = 1;&nbsp; &nbsp; // init grid&nbsp; &nbsp; for (var i = 0; i < (this.sx + 2) * (this.sy + 2); i++) {&nbsp; &nbsp; &nbsp; this.grid[i] = new Point(&nbsp; &nbsp; &nbsp; &nbsp; (i % (this.sx + 2)) * this.step, (Math.floor(i / (this.sx + 2))) * this.step&nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; }&nbsp; &nbsp; // create metaballs&nbsp; &nbsp; for (var k = 0; k < numBalls; k++) {&nbsp; &nbsp; &nbsp; this.balls[k] = new Ball(this);&nbsp; &nbsp; }&nbsp; };&nbsp; // compute cell force&nbsp; LavaLamp.prototype.computeForce = function(x, y, idx) {&nbsp; &nbsp; var force;&nbsp; &nbsp; var id = idx || x + y * (this.sx + 2);&nbsp; &nbsp; if (x === 0 || y === 0 || x === this.sx || y === this.sy) {&nbsp; &nbsp; &nbsp; force = 0.6 * this.sign;&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; force = 0;&nbsp; &nbsp; &nbsp; var cell = this.grid[id];&nbsp; &nbsp; &nbsp; var i = 0;&nbsp; &nbsp; &nbsp; var ball;&nbsp; &nbsp; &nbsp; while (ball = this.balls[i++]) {&nbsp; &nbsp; &nbsp; &nbsp; force += ball.size * ball.size / (-2 * cell.x * ball.pos.x - 2 * cell.y * ball.pos.y + ball.pos.magnitude + cell.magnitude);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; force *= this.sign&nbsp; &nbsp; }&nbsp; &nbsp; this.grid[id].force = force;&nbsp; &nbsp; return force;&nbsp; };&nbsp; // compute cell&nbsp; LavaLamp.prototype.marchingSquares = function(next) {&nbsp; &nbsp; var x = next[0];&nbsp; &nbsp; var y = next[1];&nbsp; &nbsp; var pdir = next[2];&nbsp; &nbsp; var id = x + y * (this.sx + 2);&nbsp; &nbsp; if (this.grid[id].computed === this.iter) {&nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; var dir, mscase = 0;&nbsp; &nbsp; // neighbors force&nbsp; &nbsp; for (var i = 0; i < 4; i++) {&nbsp; &nbsp; &nbsp; var idn = (x + this.ix[i + 12]) + (y + this.ix[i + 16]) * (this.sx + 2);&nbsp; &nbsp; &nbsp; var force = this.grid[idn].force;&nbsp; &nbsp; &nbsp; if ((force > 0 && this.sign < 0) || (force < 0 && this.sign > 0) || !force) {&nbsp; &nbsp; &nbsp; &nbsp; // compute force if not in buffer&nbsp; &nbsp; &nbsp; &nbsp; force = this.computeForce(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; x + this.ix[i + 12],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; y + this.ix[i + 16],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idn&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; if (Math.abs(force) > 1) mscase += Math.pow(2, i);&nbsp; &nbsp; }&nbsp; &nbsp; if (mscase === 15) {&nbsp; &nbsp; &nbsp; // inside&nbsp; &nbsp; &nbsp; return [x, y - 1, false];&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; // ambiguous cases&nbsp; &nbsp; &nbsp; if (mscase === 5) dir = (pdir === 2) ? 3 : 1;&nbsp; &nbsp; &nbsp; else if (mscase === 10) dir = (pdir === 3) ? 0 : 2;&nbsp; &nbsp; &nbsp; else {&nbsp; &nbsp; &nbsp; &nbsp; // lookup&nbsp; &nbsp; &nbsp; &nbsp; dir = this.mscases[mscase];&nbsp; &nbsp; &nbsp; &nbsp; this.grid[id].computed = this.iter;&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; // draw line&nbsp; &nbsp; &nbsp; var ix = this.step / (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.abs(Math.abs(this.grid[(x + this.plx[4 * dir + 2]) + (y + this.ply[4 * dir + 2]) * (this.sx + 2)].force) - 1) /&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Math.abs(Math.abs(this.grid[(x + this.plx[4 * dir + 3]) + (y + this.ply[4 * dir + 3]) * (this.sx + 2)].force) - 1) + 1&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; ctx.lineTo(&nbsp; &nbsp; &nbsp; &nbsp; this.grid[(x + this.plx[4 * dir]) + (y + this.ply[4 * dir]) * (this.sx + 2)].x + this.ix[dir] * ix,&nbsp; &nbsp; &nbsp; &nbsp; this.grid[(x + this.plx[4 * dir + 1]) + (y + this.ply[4 * dir + 1]) * (this.sx + 2)].y + this.ix[dir + 4] * ix&nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; this.paint = true;&nbsp; &nbsp; &nbsp; // next&nbsp; &nbsp; &nbsp; return [&nbsp; &nbsp; &nbsp; &nbsp; x + this.ix[dir + 4],&nbsp; &nbsp; &nbsp; &nbsp; y + this.ix[dir + 8],&nbsp; &nbsp; &nbsp; &nbsp; dir&nbsp; &nbsp; &nbsp; ];&nbsp; &nbsp; }&nbsp; };&nbsp; LavaLamp.prototype.renderMetaballs = function() {&nbsp; &nbsp; var i = 0, ball;&nbsp; &nbsp; while (ball = this.balls[i++]) ball.move();&nbsp; &nbsp; // reset grid&nbsp; &nbsp; this.iter++;&nbsp; &nbsp; this.sign = -this.sign;&nbsp; &nbsp; this.paint = false;&nbsp; &nbsp; ctx.fillStyle = this.metaFill;&nbsp; &nbsp; ctx.beginPath();&nbsp; &nbsp; // compute metaballs&nbsp; &nbsp; i = 0;&nbsp; &nbsp; //ctx.shadowBlur = 50;&nbsp; &nbsp; //ctx.shadowColor = "green";&nbsp; &nbsp; while (ball = this.balls[i++]) {&nbsp; &nbsp; &nbsp; // first cell&nbsp; &nbsp; &nbsp; var next = [&nbsp; &nbsp; &nbsp; &nbsp; Math.round(ball.pos.x / this.step),&nbsp; &nbsp; &nbsp; &nbsp; Math.round(ball.pos.y / this.step), false&nbsp; &nbsp; &nbsp; ];&nbsp; &nbsp; &nbsp; // marching squares&nbsp; &nbsp; &nbsp; do {&nbsp; &nbsp; &nbsp; &nbsp; next = this.marchingSquares(next);&nbsp; &nbsp; &nbsp; } while (next);&nbsp; &nbsp; &nbsp; // fill and close path&nbsp; &nbsp; &nbsp; if (this.paint) {&nbsp; &nbsp; &nbsp; &nbsp; ctx.fill();&nbsp; &nbsp; &nbsp; &nbsp; ctx.closePath();&nbsp; &nbsp; &nbsp; &nbsp; ctx.beginPath();&nbsp; &nbsp; &nbsp; &nbsp; this.paint = false;&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; };&nbsp; // gradients&nbsp; var createRadialGradient = function(w, h, r, c0, c1) {&nbsp; &nbsp; var gradient = ctx.createRadialGradient(&nbsp; &nbsp; &nbsp; w / 1, h / 1, 0,&nbsp; &nbsp; &nbsp; w / 1, h / 1, r&nbsp; &nbsp; );&nbsp; &nbsp; gradient.addColorStop(0, c0);&nbsp; &nbsp; gradient.addColorStop(1, c1);&nbsp; &nbsp; return gradient;&nbsp; };&nbsp; // main loop&nbsp; var run = function() {&nbsp; &nbsp; requestAnimationFrame(run);&nbsp; &nbsp; ctx.clearRect(0, 0, screen.width, screen.height);&nbsp; &nbsp; lava0.renderMetaballs();&nbsp; };&nbsp; // canvas&nbsp; var screen = ge1doot.screen.init("bubble", null, true),&nbsp; &nbsp; &nbsp; ctx = screen.ctx;&nbsp; screen.resize();&nbsp; // create LavaLamps&nbsp; lava0 = new LavaLamp(screen.width, screen.height, 6, "rgba(255, 146, 152, 0.5)", "rgba(228, 0, 142, 0.5)");&nbsp; run();})();body {&nbsp; margin: 0;}.wrap {&nbsp; overflow: hidden;&nbsp; position: relative;&nbsp; height: 100vh;}canvas {&nbsp; width: 100%;&nbsp; height: 100%;}<div class="wrap">&nbsp; <canvas id="bubble"></canvas></div>
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答