在canvas元素

时间:2015-11-13 16:53:43

标签: javascript animation canvas html5-canvas

这是一个关于在我通过javascript试验canvas元素时弹出的东西的查询。我希望有一个点阵列形成一个随时间移动的渐变,它与出现的奇怪图案(仅在第一波或更多波之后)完全不同,它也会根据列和行的数量而变化。画布(改变点的大小只会使图案变大或变小,它总是在相同的像素上。

这里有一个小小的演示,我的意思是你可以随意使用一些界面,更改模式的一个例子是如果行数改变为原始列数的0.75倍(即40列,30行)。

http://codepen.io/zephyr/pen/GpwwWB

使用Javascript:

String.prototype.hexToRGBA = function(a) {
        function cutHex(h) {
                return (h.charAt(0) == "#") ? h.substring(1, 7) : h
        }
        var r = parseInt((cutHex(this)).substring(0, 2), 16);
        var g = parseInt((cutHex(this)).substring(2, 4), 16);
        var b = parseInt((cutHex(this)).substring(4, 6), 16);
        return 'rgba(' + r.toString() + ',' + g.toString() + ',' + b.toString() + ',' + a.toString() + ')';
}

CanvasRenderingContext2D.prototype.clearDrawRect = function(shape) {
        this.clearRect(shape.position.x, shape.position.y, shape.size, shape.size);
        this.fillStyle = shape.color.base;
        this.fillRect(shape.position.x, shape.position.y, shape.size, shape.size);
}

CanvasRenderingContext2D.prototype.render = function(render) {
        (function animate() {
                requestAnimationFrame(animate);
                render();
        })();
}

CanvasRenderingContext2D.prototype.renderAndThrottleFpsAt = function(fps, render) {
        var fpsInterval, startTime, now, then, elapsed;

        fpsInterval = 1000 / fps;
        then = Date.now();
        startTime = then;

        (function animate() {
                requestAnimationFrame(animate);
                now = Date.now();
                elapsed = now - then;
                if (elapsed > fpsInterval) {
                        then = now - (elapsed % fpsInterval);
                        render();
                }
        })();
}

CanvasRenderingContext2D.prototype.pool = {};

CanvasRenderingContext2D.prototype.parsePoint = function(x, y, s, c) {
        return {
                color: c,
                position: {
                        x: x,
                        y: y
                },
                size: s
        }
}

CanvasRenderingContext2D.prototype.fillPointsPool = function(size, cols, rows, color) {
        var i = cols;
        var j = rows;
        while(i--){
            while(j--){
                var x = i * size;
                var y = j * size;
                var a = (i * j) / (cols * rows);
                var c = {
                        hex: color,
                        alpha: a,
                        dir: 1
                };
                if (typeof this.pool.points == 'undefined') {
                        this.pool.points = [this.parsePoint(x, y, size, c)];
                } else {
                        this.pool.points.push(this.parsePoint(x, y, size, c));
                }
            }
            j = rows;
        }
}

CanvasRenderingContext2D.prototype.updatePointsPool = function(size, cols, rows, color) {
        this.pool.points = [];
        this.clearRect(0,0,this.canvas.width,this.canvas.height);
        this.fillPointsPool(size, cols, rows, color);
}

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

// Populate Points
var size = document.getElementById('size');
var cols = document.getElementById('cols');
var rows = document.getElementById('rows');
var color = document.getElementById('color');
ctx.fillPointsPool(size.value, cols.value, rows.value, color.value);

size.oninput = function(){
    ctx.updatePointsPool(this.value, cols.value, rows.value, color.value);
}
cols.oninput = function(){
    ctx.updatePointsPool(size.value, this.value, rows.value, color.value);
}
rows.oninput = function(){
    ctx.updatePointsPool(size.value, cols.value, this.value, color.value);
}
color.oninput = function(){
    ctx.updatePointsPool(size.value, cols.value, rows.value, this.value);
}

ctx.renderAndThrottleFpsAt(60, function(){
        var i = 0;
        var len = ctx.pool.points.length;
        while (i<len) {
                var point = ctx.pool.points[i];

                // Change alpha for wave
                var delta = 0.01;
                point.color.alpha = point.color.alpha + (delta * point.color.dir);
                if (point.color.alpha > 1) {
                        point.color.dir = -1;
                } else if (point.color.alpha <= 0) {
                        point.color.dir = 1;
                }

                // Calculate rgba value with new alpha
                point.color.base = point.color.hex.hexToRGBA(point.color.alpha);
                ctx.clearDrawRect(point);
                i++;
        }
});

你们中是否有人知道导致模式出现的原因,以及有关解决此问题的任何建议?

注意:我将更改updatePointsPool函数

1 个答案:

答案 0 :(得分:1)

更改方向时,您忘记夹住Alpha值。 alpha值中的小误差会缓慢累积,从而产生您在动画进行过程中看到的不需要的伪像。

要在将delta方向添加到alpha后立即在代码中添加alpha的顶部和底部限制。

if (point.color.alpha > 1) {
    point.color.alpha = 1;  // clamp alpha max
    point.color.dir = -1;
} else if (point.color.alpha <= 0) {
    point.color.alpha = 0;  // clamp alpha min
    point.color.dir = 1;
}