如何删除渐变中的间隙

How to remove gaps in gradient

本文关键字:渐变 间隙 删除 何删除      更新时间:2023-09-26

梯度6、7、8和10在其初始颜色之后具有可见间隙。有办法填补这一空白吗?

我假设,一旦对范围进行了分区,如果整数分区不能被画布的宽度整除,那么它们的总和就会小于原始分区。

信息

  • render1()-通过生成两种颜色之间的颜色范围来插值。

  • render2()-JavaScript的createLinearGradient(),具有n个偶数停止。

$(document).ready(function () {
    function addCanvas(ol) {
        var canvas = $('<canvas>', {
            "width": 240,
                "height": 10
        }).addClass('grd')
        .appendTo($('<li>').appendTo(ol));
      return canvas[0];
    }
    var ol = $('<ol>').appendTo($('body'));
    var c1 = '#FF0000';
    var c2 = '#00FF00';
    var canvas;
    for (var i = 1; i <= 30; i+=3) {
        canvas = addCanvas(ol);
        var colors = generateColors(c1, c2, i);
        render(canvas, colors);
    }
    canvas = addCanvas(ol);
    render2(canvas, [c1, c2]);
});
function toHex(c) {
    return (function (hex) {
        return hex.length == 1 ? "0" + hex : hex;
    })(c.toString(16));
}
function hexToRgb(hex) {
    var result = /^#?([a-f'd]{2})([a-f'd]{2})([a-f'd]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null;
}
function rgbToHex(rgb) {
    var r = 0,
        g = 0,
        b = 0;
    if (arguments.length === 1) {
        r = rgb.r || 0;
        g = rgb.g || 0;
        b = rgb.b || 0;
    } else if (arguments.length === 3) {
        r = arguments[0];
        g = arguments[1];
        b = arguments[2];
    }
    return "#" + toHex(r) + toHex(g) + toHex(b);
}
function render(canvas, colors) {
    var ctx = canvas.getContext("2d");
    var n = colors.length;
    var x = 0;
    var subWidth = canvas.width / n;
    for (var i = 0; i < n; i++) {
        var start = i * subWidth;
        var end = start + subWidth;
        ctx.fillStyle = colors[i];
        ctx.fillRect(x + start, 0, x + end, canvas.height);
    }
}
function render2(canvas, colors) {
    var ctx = canvas.getContext("2d");
    var x = canvas.x;
    var y = canvas.y;
    var width = canvas.width;
    var height = canvas.height;
    ctx.fillStyle = createGradient(ctx, colors, x, y, width, height)
    ctx.fillRect(0, 0, width, height);
}
function generateColors(color1, color2, n) {
    function partition(a, b, n) {
        function magnitude(a, b) {
            if (a === b) return 0;
            else if (a > b) return -1 * (a - b);
            else return b - a;
        }
        return magnitude(a, b) / n;
    }
    var c1 = hexToRgb(color1);
    var c2 = hexToRgb(color2);
    var rd = partition(c1.r, c2.r, n);
    var gd = partition(c1.g, c2.g, n);
    var bd = partition(c1.b, c2.b, n);
    var colors = [];
    var i, r, g, b, h = n/2;
    for (i = 0; i < h; i++) {
        r = Math.floor(c1.r + rd * i);
        g = Math.floor(c1.g + gd * i);
        b = Math.floor(c1.b + bd * i);
        colors.push(rgbToHex(r, g, b));
    }
    for (var j = 0; i < n; j++, i++) {
        var k = h-j-1;
        r = Math.floor(c2.r - rd * k);
        g = Math.floor(c2.g - gd * k);
        b = Math.floor(c2.b - bd * k);
        colors.push(rgbToHex(r, g, b));
    }  
    return colors;
}
function createGradient(ctx, colors, x, y, width, height) {
    var h = height / 2;
    var grd = ctx.createLinearGradient(0, h, width, h);
    var n = Math.max(colors.length - 1, 1);
    for (var i = 0; i < colors.length; i++) {
        grd.addColorStop(i / n, colors[i]);
    }
    return grd;
}
canvas.grd {
  display: inline-block;
  margin: 1px 0;
}
ol {
  padding-left: 32px; 
  list-style-type:decimal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

更新的答案:新版本的渲染函数,可以分割多余的像素,并在每侧放置大约一半:

function render(canvas, colors) {
    var ctx = canvas.getContext("2d");
    var n = colors.length;
    var r = canvas.width % n;
    var a = Math.floor(r/2), b = n - r + a;
    var subWidth = Math.floor(canvas.width / n) + 1;
    var start = 0;
    for (var i = 0; i < n; i++) {
        if (i == a) {
            subWidth -= 1;
        }
        if(i == b) {
            subWidth += 1;
        }
        ctx.fillStyle = colors[i];
        ctx.fillRect(start, 0, subWidth, canvas.height);
        start += subWidth;
    }
}

原始答案

几件事:

我认为造成微弱间隙的原因是,一些矩形被绘制成包括分数像素的宽度。你可以做的是把矩形画成精确的像素宽度,有些比另一些宽一个像素。这是对渲染函数的重写(我想。现在已经很晚了:-)

function render(canvas, colors) {
    var ctx = canvas.getContext("2d");
    var n = colors.length;
    var r = canvas.width % n;
    var subWidth = Math.floor(canvas.width / n) + 1;
    var start = 0;
    for (var i = 0; i < n; i++) {
        if (i == r) {
            subWidth -= 1;
        }
        ctx.fillStyle = colors[i];
        ctx.fillRect(start, 0, subWidth, canvas.height);
        start += subWidth;
    }
}

这将计算将适合画布宽度colors.length次的最大整体宽度。然后它计算出还有多少额外的像素(r),然后循环给前r个矩形1个额外的像素宽度。

(此外,请记住fillRect函数的第三个参数是宽度,而不是结束。您的调用正在工作,因为矩形是在彼此的顶部绘制的,并且每个矩形的起始位置是正确的。)

我相信有一个更优雅的解决方案,但这个似乎有效!

此外,当我玩这个的时候,我注意到在javascript中,canvas.width是300,而不是240。这让我四处搜索,我发现了一个很好的解释,说明了它是如何在HTML5中的SO:Canvas宽度和高度上工作的。我认为代码正在渲染到一个300 x 150的画布中,然后缩小到240 x 10。但最终,这并没有造成问题。

希望这能有所帮助!