Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 黑色调整后的画布不会随着时间的推移将图形完全褪色为黑色_Javascript_Html_Canvas_Html5 Canvas - Fatal编程技术网

Javascript 黑色调整后的画布不会随着时间的推移将图形完全褪色为黑色

Javascript 黑色调整后的画布不会随着时间的推移将图形完全褪色为黑色,javascript,html,canvas,html5-canvas,Javascript,Html,Canvas,Html5 Canvas,我有一块黑色的画布,里面画着东西。我希望里面画的东西随着时间的推移,按照画的顺序(FIFO)逐渐变黑。如果我使用未调整大小的画布,则此操作有效。调整画布的大小后,元素将淡入灰白色 问题:画布调整大小后,为什么白色斑点不会完全褪色为黑色?当我没有调整画布的大小时,如何让它们以相同的方式淡入黑色 这里有一些代码可以演示 我不知道我是否理解你,但看着你的小提琴,我认为,对于你所寻找的,你需要在循环的任何迭代中提供画布的大小。如果不是,则只取初始值: 编辑 如果对画布应用阈值过滤器,则可以执行此操作。您

我有一块黑色的画布,里面画着东西。我希望里面画的东西随着时间的推移,按照画的顺序(FIFO)逐渐变黑。如果我使用未调整大小的画布,则此操作有效。调整画布的大小后,元素将淡入灰白色

问题:画布调整大小后,为什么白色斑点不会完全褪色为黑色?当我没有调整画布的大小时,如何让它们以相同的方式淡入黑色

这里有一些代码可以演示


我不知道我是否理解你,但看着你的小提琴,我认为,对于你所寻找的,你需要在循环的任何迭代中提供画布的大小。如果不是,则只取初始值:

编辑

如果对画布应用阈值过滤器,则可以执行此操作。您可以每秒运行一次过滤器,这样预浪漫就不会受到太大的影响

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.fillRect(0,0,300,150);
//context.globalAlpha=1;
//context.globalCompositeOperation = "source-over";


var canvas2 = document.getElementById('canvas2');
var context2 = canvas2.getContext('2d');

canvas2.width=canvas2.height=canvas.width;

window.draw = function(){
    var W = canvas2.width;
    var H = canvas2.height;
    context2.fillStyle='rgba(255,255,255,1)';
    context2.fillRect(
        Math.floor(Math.random()*W),
        Math.floor(Math.random()*H),
        2,2);
    context2.fillStyle='rgba(0,0,0,.02)';
    context2.fillRect(0,0,W,H);

    context.fillStyle='rgba(0,0,0,1)';
    context.fillRect(0,0,300,150);
    context.drawImage(canvas2,0,0,300,150);

    setTimeout('draw()', 1000/20);
}
setTimeout('draw()', 1000/20);

window.thresholdFilter = function () {
    var W = canvas2.width;
    var H = canvas2.height;
    var i, j, threshold = 30, rgb = []
    ,   imgData=context2.getImageData(0,0,W,H), Npixels = imgData.data.length;

    for (i = 0; i < Npixels; i += 4) {
        rgb[0] = imgData.data[i];
        rgb[1] = imgData.data[i+1];
        rgb[2] = imgData.data[i+2];
        if (    rgb[0] < threshold &&
                rgb[1] < threshold &&
                rgb[2] < threshold
        ) {
           imgData.data[i] = 0;
           imgData.data[i+1] = 0;
           imgData.data[i+2] = 0;
        }
    }

    context2.putImageData(imgData,0,0);
};

setInterval("thresholdFilter()", 1000);
var canvas=document.getElementById('canvas');
var context=canvas.getContext('2d');
context.fillRect(0,0300150);
//context.globalAlpha=1;
//context.globalCompositeOperation=“源代码结束”;
var canvas2=document.getElementById('canvas2');
var context2=canvas2.getContext('2d');
canvas2.width=canvas2.height=canvas.width;
window.draw=函数(){
var W=画布宽度2.5毫米;
var H=画布高度2.2;
context2.fillStyle='rgba(255255,1)';
context2.fillRect(
Math.floor(Math.random()*W),
Math.floor(Math.random()*H),
2,2);
context2.fillStyle='rgba(0,0,0,02)';
context2.fillRect(0,0,W,H);
context.fillStyle='rgba(0,0,0,1)';
context.fillRect(0,0300150);
背景.drawImage(canvas2,0,0300150);
setTimeout('draw()',1000/20);
}
setTimeout('draw()',1000/20);
window.thresholdFilter=函数(){
var W=画布宽度2.5毫米;
var H=画布高度2.2;
变量i,j,阈值=30,rgb=[]
,imgData=context2.getImageData(0,0,W,H),Npixels=imgData.data.length;
对于(i=0;i

这是小提琴:

问题分为两部分:

  • 使用低alpha值绘制时存在()舍入错误。浏览器将永远无法获得颜色和alpha通道的结果混合等于0,因为混合的结果浮点值将在绘制时转换为整数,这意味着该值永远不会小于1。下次它混合它(值1,因为alpha内部是一个介于0和255之间的值)时,将再次使用该值,它将再次四舍五入到1,并且永远保持不变

  • 为什么当你有一个调整大小的画布时它会工作?在这种情况下,这是因为你只画了一半的大画布到较小的画布,这导致像素被插值。由于该值非常低,这意味着在这种情况下,像素将变为“黑色”(完全透明),因为周围像素之间的平均值将导致该值四舍五入为0-排序与#1相反

  • 若要绕过此问题,您必须手动清除预计为黑色的等级库。这将涉及自己跟踪每个粒子/等级库,或使用直接像素操作更改alpha

    更新

    关键是使用跟踪。您可以通过将每个等级库创建为一个自我更新点来实现这一点,该点跟踪alpha和清除

    简单的等级库对象可以如下所示:

    function Spec(ctx, speed) {
        
        var me = this;
            
        reset();                             /// initialize object
        
        this.update = function() {
        
            ctx.clearRect(me.x, me.y, 1, 1); /// clear previous drawing
    
            this.alpha -= speed;             /// update alpha
            
            if (this.alpha <= 0) reset();    /// if black then reset again
            
            /// draw the spec
            ctx.fillStyle = 'rgba(255,255,255,' + me.alpha + ')';
            ctx.fillRect(me.x, me.y, 1, 1);
        }
        
        function reset() {
    
            me.x = (ctx.canvas.width * Math.random())|0;  /// random x rounded to int
            me.y = (ctx.canvas.height * Math.random())|0; /// random y rounded to int
    
            if (me.alpha) {                               /// reset alpha
                me.alpha = 1.0;                           /// set to 1 if existed
            } else {
                me.alpha = Math.random();                 /// use random if not
            }
        }
    }
    
    你只需使用速度,就可以根据规格单独设置,而不必与FPS混为一谈

    现在只需更新循环中的每个对象:

    function loop() {
    
        /// iterate each object
        var i = specs.length - 1;    
        while(i--) {
            specs[i].update();        /// update each object
        }
    
        requestAnimationFrame(loop);  /// loop synced to monitor
    }
    

    正如您所看到的,性能不是一个问题,也没有残留。希望这能有所帮助。

    为了避免舍入问题,您可以使用较长的刷新间隔和较大的alpha值,使用自己的计时器将淡入淡出效果提取到单独的函数中

    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    context.fillRect(0, 0, 300, 150);
    
    // Comment this out and it works as intended, why?
    canvas.width = canvas.height = 300;
    
    window.draw = function () {
        context.fillStyle = 'rgba(255,255,255,1)';
        context.fillRect(
            Math.floor(Math.random() * 300),
            Math.floor(Math.random() * 300),
            2, 2);
        setTimeout('draw()', 1000 / 20);
    }
    
    window.fadeToBlack = function () {
        context.fillStyle = 'rgba(0,0,0,.1)';
        context.fillRect(0, 0, 300, 300);
        setTimeout('fadeToBlack()', 1000 / 4);    
    }
    
    draw();
    fadeToBlack();
    

    Fiddle演示了这一点:

    我的问题是白色斑点没有完全消失。他们仍然在屏幕上。我在用Chrome做测试,如果有什么不同的话。谢谢你的回答,我可能会使用这样的阈值过滤器。这是一个相当大的性能消耗,所以我将不得不小心使用它!谢谢你的回答。这实际上是我已经开发的当前解决方法。在这种情况下,这似乎是最好的选择。其他选项对性能影响太大。谢谢。这个答案很有启发性,而且最重要的是,它向我提供了这样一个线索:我对此无能为力。
    function loop() {
    
        /// iterate each object
        var i = specs.length - 1;    
        while(i--) {
            specs[i].update();        /// update each object
        }
    
        requestAnimationFrame(loop);  /// loop synced to monitor
    }
    
    var canvas = document.getElementById('canvas');
    var context = canvas.getContext('2d');
    context.fillRect(0, 0, 300, 150);
    
    // Comment this out and it works as intended, why?
    canvas.width = canvas.height = 300;
    
    window.draw = function () {
        context.fillStyle = 'rgba(255,255,255,1)';
        context.fillRect(
            Math.floor(Math.random() * 300),
            Math.floor(Math.random() * 300),
            2, 2);
        setTimeout('draw()', 1000 / 20);
    }
    
    window.fadeToBlack = function () {
        context.fillStyle = 'rgba(0,0,0,.1)';
        context.fillRect(0, 0, 300, 300);
        setTimeout('fadeToBlack()', 1000 / 4);    
    }
    
    draw();
    fadeToBlack();