繁体   English   中英

如何仅对 html 画布上的某些元素添加淡入淡出效果

[英]How to add a fade effect to only certain elements on a html canvas

我有一个带有多个不同颜色圆圈的画布,我只想为某些圆圈添加淡出效果。 该效果仅适用于红色和绿色。

代码如下

function drawPiece(pieceX, pieceY, color) {

if (color === "rgba(0,0,0,1)" || color === "rgba(255,255,255,1)"){


    ctx.beginPath();
    ctx.fillStyle = color;
    ctx.arc(pieceX, pieceY, 50, 0, 2 * Math.PI, false);
    ctx.fill();
    ctx.lineWidth = "4";
    ctx.strokeStyle = "rgba(0,0,0,1)";
    ctx.stroke();
    ctx.closePath();
}
else {
    ctx.beginPath();
    ctx.fillStyle = color;
    ctx.arc(pieceX, pieceY, 10, 0, 2 * Math.PI, false);
    ctx.fill();
    ctx.lineWidth = "4";
    ctx.strokeStyle = "rgba(0,0,0,1)";
    ctx.stroke();
    ctx.closePath();
    setTimeout(function(){
        var fadeTarget = document.getElementById("canvasGame");
        var fadeEffect = setInterval(function () {
            if (!fadeTarget.style.opacity) {
                fadeTarget.style.opacity = 1;
            }
            if (fadeTarget.style.opacity > 0) {
                fadeTarget.style.opacity -= 0.02;
            } else {
                clearInterval(fadeEffect);
            }
        }, 20);
    },0.5);

}


}

淡入淡出效果有效,但它淡出整个画布而不是单个圆圈。

我怎样才能做到这一点,只有一些元素淡出。

提前致谢

画布是一种绘画表面。 这意味着你不能你画完之后改变它。 您只能清除它,或在其上涂漆。 就像真正的绘画一样,您无法更改已绘制的笔划的颜色。

所以你必须清除画布,然后重新绘制它,除了这次绘制一些具有不同不透明度的圆圈。 只需将这些rgba值的最后一个数字更改为 0 到 1 之间即可更改不透明度。

将不透明度存储在某个变量中:

var circleOpacity = 1;

更改不透明度,然后在间隔函数中重绘:

circleOpactiy -= 0.2;
drawMyCanvas();

现在用fillStyle绘制一些部分,例如:

ctx.fillStyle = shouldBeFaded ? `rgba(0,0,0,${circleOpacity})` : 'rgba(0,0,0,1)'

或者,您可以绝对放置两个画布,使它们彼此重叠,并且您可以像已经在做的那样淡化顶部的画布。 这样你就不必不断地重新渲染画布。 如果您只想淡化一些圆圈,这可能会更容易。 但是如果你想在画布上做任何更复杂的事情(比如渲染某种游戏),你无论如何都要重新绘制画布的每一帧动画。

一个很棒的画布 2d 资源是 MDN 的CanvasRenderingContext2D

使用画布制作动画。

如果要为画布内容设置动画,则需要一个渲染循环。

渲染循环每秒调用 60 次,如果可能,绘制过多并且速率将降至 60fps 以下。

主循环清除画布,然后绘制动画内容,然后请求下一帧。

requestAnimationFrame(mainLoop);  // request the first frame to start the animation
function mainLoop() {
    ctx.globalAlpha = 1; // default to 1 in case there is other content drawn
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);  // clear the canvas
    drawContent(); // render the content.
    requestAnimationFrame(mainLoop);  // request the next frame (in 1/60th second)
}

绘制圆的函数。 您可以从颜色中删除 alpha 并使用globalAlpha设置透明度。

Math.TAU = Math.PI * 2;  // set up 2 PI
function drawCircle(x, y, radius, color, alpha = 1) {
    ctx.globalAlpha = alpha;
    ctx.fillStyle = color;
    ctx.strokeStyle = "#000"; 
    ctx.lineWidth = 4;
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.TAU);
    ctx.fill();
    ctx.stroke();
}

创建一个对象来保存一个圆的描述和一个数组来放置它们

const circles = [];
function circle(x,y,r = 10, col = "#FFF", alpha = 1) {
    return {x, y, r, col, alpha, alphaTarget: alpha};
}

然后在drawContent函数中一次绘制一个圆圈

function drawContent() {
    for (const circle of circles) {
        if(circle.alpha !== circle.alphaTarget) {
           const aStep = circle.alphaTarget - circle.alpha;
           const dir = Math.sign(aStep);
           circle.alpha += Math.min(Math.abs(aStep), dir * 0.02)) * dir;
        }  
        drawCircle(circle.x, circle.y, circle.r, circle.col, circle.alpha);
    }
 }

演示

该演示绘制了 100 个圆圈,每个圆圈都有自己的颜色和 alpha。 随机选择 alpha 淡出然后再回来。

如果要为画布内容设置动画,则需要一个渲染循环。

我移动圆圈,以便如果设备渲染内容变慢,那么更容易看到低帧速率。

 Math.TAU = Math.PI * 2; // set up 2 PI Math.rand = (val) => Math.random() * val; Math.randI = (val) => Math.random() * val | 0; requestAnimationFrame(mainLoop); const ctx = canvas.getContext("2d"); const W = canvas.width = innerWidth; // size canvas to page const H = canvas.height = innerHeight; // size canvas to page const circleCount = 100; const circleFadeRate = 0.01; // per 60th second const circles = []; const circle = (x,y,r = 10, col = "#FFF", alpha = 1) => ({x, y, r, col, alpha, alphaTarget: alpha}); createCircles(); function createCircles() { var i = circleCount; while (i--) { circles.push(circle(Math.rand(W), Math.rand(H), Math.rand(10) + 10, "#" + Math.randI(0xFFF).toString(16).padStart(3,"0"), 1)); } circles.sort((a,b) => ar - br); // big drawn last } function mainLoop() { ctx.globalAlpha = 1; ctx.clearRect(0, 0, W, H); drawContent(); requestAnimationFrame(mainLoop); } function drawCircle(x, y, radius, color, alpha = 1) { ctx.globalAlpha = alpha; ctx.fillStyle = color; ctx.strokeStyle = "#000"; ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.TAU); ctx.fill(); ctx.stroke(); } function drawContent() { for (const circle of circles) { if(circle.alpha !== circle.alphaTarget) { const aStep = circle.alphaTarget - circle.alpha; const dir = Math.sign(aStep); circle.alpha += Math.min(Math.abs(aStep), 0.02) * dir; } else if(Math.random() < 0.01) { circle.alphaTarget = circle.alpha < 0.7 ? 1 : Math.random() * 0.4; } circle.y += (circle.r - 10) / 5; circle.y = circle.y > H + circle.r + 2 ? -(circle.r + 2) : circle.y; drawCircle(circle.x, circle.y, circle.r, circle.col, circle.alpha); } }
 body { padding: 0px; } canvas { position: absolute; top: 0px; left: 0px; }
 <canvas id="canvas"></canvas>

有关 2D 画布 API 的更多信息,请参阅此答案顶部的链接。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM