HTML 5画布覆盖在网页的顶部

HTML 5 Canvas Over-layed on top of a Web Page?

本文关键字:网页 顶部 覆盖 5画 布覆盖 HTML      更新时间:2023-09-26

我们的目标是让烟花出现在现有网页的顶部,这样你就可以同时看到现有网页和烟花在它上面爆炸。我成功地让他们在页面的顶部,然而,现在他们不褪色。我在网页的顶部留下了白色的东西。

我有这个jsfiddle:

http://jsfiddle.net/2EQ2w/1/

var SCREEN_WIDTH = window.innerWidth,
    SCREEN_HEIGHT = window.innerHeight,
    mousePos = {
        x: 400,
        y: 300
    },
    // create canvas
    canvas = document.createElement('canvas'),
    context = canvas.getContext('2d'),
    particles = [],
    rockets = [],
    MAX_PARTICLES = 400,
    colorCode = 0;
// init
$(document).ready(function() {
    document.body.insertBefore(canvas, document.body.firstChild);
    canvas.width = SCREEN_WIDTH;
    canvas.height = SCREEN_HEIGHT;
    setInterval(launch, 800);
    setInterval(loop, 1000 / 50);
});
// update mouse position
$(document).mousemove(function(e) {
    e.preventDefault();
    mousePos = {
        x: e.clientX,
        y: e.clientY
    };
});
// launch more rockets!!!
$(document).mousedown(function(e) {
    for (var i = 0; i < 5; i++) {
        launchFrom(Math.random() * SCREEN_WIDTH * 2 / 3 + SCREEN_WIDTH / 6);
    }
});
function launch() {
    launchFrom(mousePos.x);
}
function launchFrom(x) {
    if (rockets.length < 10) {
        var rocket = new Rocket(x);
        rocket.explosionColor = Math.floor(Math.random() * 360 / 10) * 10;
        rocket.vel.y = Math.random() * -3 - 4;
        rocket.vel.x = Math.random() * 6 - 3;
        rocket.size = 8;
        rocket.shrink = 0.999;
        rocket.gravity = 0.01;
        rockets.push(rocket);
    }
}
function loop() {
    // update screen size
    if (SCREEN_WIDTH != window.innerWidth) {
        canvas.width = SCREEN_WIDTH = window.innerWidth;
    }
    if (SCREEN_HEIGHT != window.innerHeight) {
        canvas.height = SCREEN_HEIGHT = window.innerHeight;
    }
    // clear canvas
    context.fillStyle = "rgba(0, 0, 0, 0.001)";
    context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    var existingRockets = [];
    for (var i = 0; i < rockets.length; i++) {
        // update and render
        rockets[i].update();
        rockets[i].render(context);
        // calculate distance with Pythagoras
        var distance = Math.sqrt(Math.pow(mousePos.x - rockets[i].pos.x, 2) + Math.pow(mousePos.y - rockets[i].pos.y, 2));
        // random chance of 1% if rockets is above the middle
        var randomChance = rockets[i].pos.y < (SCREEN_HEIGHT * 2 / 3) ? (Math.random() * 100 <= 1) : false;
/* Explosion rules
             - 80% of screen
            - going down
            - close to the mouse
            - 1% chance of random explosion
        */
        if (rockets[i].pos.y < SCREEN_HEIGHT / 5 || rockets[i].vel.y >= 0 || distance < 50 || randomChance) {
            rockets[i].explode();
        } else {
            existingRockets.push(rockets[i]);
        }
    }
    rockets = existingRockets;
    var existingParticles = [];
    for (var i = 0; i < particles.length; i++) {
        particles[i].update();
        // render and save particles that can be rendered
        if (particles[i].exists()) {
            particles[i].render(context);
            existingParticles.push(particles[i]);
        }
    }
    // update array with existing particles - old particles should be garbage collected
    particles = existingParticles;
    while (particles.length > MAX_PARTICLES) {
        particles.shift();
    }
}
function Particle(pos) {
    this.pos = {
        x: pos ? pos.x : 0,
        y: pos ? pos.y : 0
    };
    this.vel = {
        x: 0,
        y: 0
    };
    this.shrink = .97;
    this.size = 2;
    this.resistance = 1;
    this.gravity = 0;
    this.flick = false;
    this.alpha = 1;
    this.fade = 0;
    this.color = 0;
}
Particle.prototype.update = function() {
    // apply resistance
    this.vel.x *= this.resistance;
    this.vel.y *= this.resistance;
    // gravity down
    this.vel.y += this.gravity;
    // update position based on speed
    this.pos.x += this.vel.x;
    this.pos.y += this.vel.y;
    // shrink
    this.size *= this.shrink;
    // fade out
    this.alpha -= this.fade;
};
Particle.prototype.render = function(c) {
    if (!this.exists()) {
        return;
    }
    c.save();
    c.globalCompositeOperation = 'lighter';
    var x = this.pos.x,
        y = this.pos.y,
        r = this.size / 2;
    var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
    gradient.addColorStop(0.1, "rgba(255,255,255," + this.alpha + ")");
    gradient.addColorStop(0.8, "hsla(" + this.color + ", 100%, 50%, 0)");
    gradient.addColorStop(1, "hsla(" + this.color + ", 100%, 50%, 0)");
    c.fillStyle = gradient;
    c.beginPath();
    c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size : this.size, 0, Math.PI * 2, true);
    c.closePath();
    c.fill();
    c.restore();
};
Particle.prototype.exists = function() {
    return this.alpha >= 0.1 && this.size >= 1;
};
function Rocket(x) {
    Particle.apply(this, [{
        x: x,
        y: SCREEN_HEIGHT}]);
    this.explosionColor = 0;
}
Rocket.prototype = new Particle();
Rocket.prototype.constructor = Rocket;
Rocket.prototype.explode = function() {
    var count = Math.random() * 10 + 80;
    for (var i = 0; i < count; i++) {
        var particle = new Particle(this.pos);
        var angle = Math.random() * Math.PI * 2;
        // emulate 3D effect by using cosine and put more particles in the middle
        var speed = Math.cos(Math.random() * Math.PI / 2) * 15;
        particle.vel.x = Math.cos(angle) * speed;
        particle.vel.y = Math.sin(angle) * speed;
        particle.size = 10;
        particle.gravity = 0.2;
        particle.resistance = 0.92;
        particle.shrink = Math.random() * 0.05 + 0.93;
        particle.flick = true;
        particle.color = this.explosionColor;
        particles.push(particle);
    }
};
Rocket.prototype.render = function(c) {
    if (!this.exists()) {
        return;
    }
    c.save();
    c.globalCompositeOperation = 'lighter';
    var x = this.pos.x,
        y = this.pos.y,
        r = this.size / 2;
    var gradient = c.createRadialGradient(x, y, 0.1, x, y, r);
    gradient.addColorStop(0.1, "rgba(255, 255, 255 ,255)");
    gradient.addColorStop(0.1, "rgba(0, 0, 0, 0)");
    c.fillStyle = gradient;
    c.beginPath();
    c.arc(this.pos.x, this.pos.y, this.flick ? Math.random() * this.size / 2 + this.size / 2 : this.size, 0, Math.PI * 2, true);
    c.closePath();
    c.fill();
    c.restore();
};

它是建立在这个基础上的:

http://jsfiddle.net/dtrooper/AceJJ/

有谁知道我怎么能让这些烟火消失吗?或者让粒子在几毫秒没有移动后淡出?

你当然可以使用渐隐轨迹:

http://jsfiddle.net/LgjG8/

设置第二个屏幕外画布,其全局alpha值减小:

// create 2nd canvas
var canvas2 = document.createElement('canvas'),
    context2 = canvas2.getContext('2d');
canvas2.width = canvas.width;
canvas2.height = canvas.height;
// reduce alpha of second canvas
context2.globalAlpha = 0.8;

然后,而不是简单地擦拭画布每帧,复制第一个屏幕上的画布到第二个。这将产生一个褪色的可见画布的副本,由于降低全局alpha值。然后擦拭第一张画布,然后再复制褪色的版本。最后,像往常一样更新画布。这将产生一个踪迹。

// produce faded copy of current canvas
context2.clearRect(0, 0, canvas2.width, canvas2.height);
context2.drawImage(canvas, 0, 0);
// redraw faded copy on original canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(canvas2, 0, 0);

我没有仔细看你的代码,所以你可能需要稍微摆弄一下,但是你明白了。

烟花使用低不透明度的fillRect()来清除(淡出)旧烟花。因此,画布后面不会显示任何内容。

然而,你可以使用clearRect()代替,使画布没有坚实的背景。这样做的问题是,烟花不会留下漂亮的痕迹,因为没有低透明度填充来淡化它们。

不是最优的,但至少烟花是在其他页面的内容前面。我希望有一个clearStyle,你可以设置为低不透明度,但遗憾的是,没有。

// clear canvas
//context.fillStyle = "rgba(0, 0, 0, 0.05)";
//context.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
context.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
工作示例

既然你想让内容可见,你可以尝试改变路径生成的方式,并使用clearRect。而不是由c.fill()完成的轨迹,你可以让它由粒子完成,这样你就可以看到它们。

在Rocket.prototype.render中可以这样做:

//c.fill();
var particle = new Particle(this.pos);
particle.shrink = Math.random() * 0.05 + 0.93;
particle.size = 10;
particles.push(particle);

然后这些痕迹就可以看到了。

例子

编辑回答前(未按提问者预期工作):

loop()函数中,你有一个非常小的alpha,使烟火不会褪色。

尝试更改:

context.fillStyle = "rgba(0, 0, 0, 0.001)";

context.fillStyle = "rgba(0, 0, 0, 0.05)";

希望有帮助!