【问题标题】:why is my strokeStyle transparent?为什么我的 strokeStyle 是透明的?
【发布时间】:2014-06-29 23:46:48
【问题描述】:

我正在使用 stroke() 绘制到 HTML5 画布上,无论我如何或何时设置 globalAlpha,都会以一定的透明度绘制笔触。我希望中风完全不透明(globalAlpha=1)。是否还有其他地方正在设置 alpha?

this jsfiddle 中,我在画布上绘制了一个黑色实线网格。对我来说,结果显示交叉点处的点,确认线条是部分透明的。这是它的要点:

context.globalAlpha=1;
context.strokeStyle="#000";
context.beginPath();
/* draw the grid */
context.stroke();
context.closePath;

(对我而言)特别奇怪的是,在我上次重新启动计算机之前,我的代码中没有出现这个问题,所以我猜测缓存中存在一些东西,它使 alpha 保持在我想要的水平。

我显然在这里遗漏了一些东西...感谢您提供的任何帮助。

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    真正的答案:

    • 画布中的每个点的中心在其 (+0.5, +0.5) 坐标中。 因此,为了避免伪影,首先通过 (0.5, 0.5) 翻译上下文, 然后将坐标四舍五入。

    • css 缩放创建工件,只处理画布宽度和高度,除非 你想用 webGL 处理 hidpi 设备,或者以较低的分辨率渲染 同时使用 webGL 和 context2D。

    -> 在您的情况下,您的设置代码将是(没有设置 css 宽度/高度):

    (http://jsfiddle.net/gamealchemist/x9bTX/8/)

    // parameters
    var canvasHorizontalRatio = 0.9;
    var canvasHeight = 300;
    var hCenterCanvas = true;
    // setup
    var canvasWidth = Math.floor(window.innerWidth * canvasHorizontalRatio);
    var cnv = document.getElementById("myCanvas");
    cnv.width = canvasWidth;
    cnv.height = canvasHeight;
    if (hCenterCanvas)
    cnv.style['margin-left'] = Math.floor((window.innerWidth - canvasWidth) * 0.5) + 'px';
    var ctx = cnv.getContext("2d");
    ctx.translate(0.5, 0.5);
    gridContext();
         
    

    其余代码与您的原始代码相同,我只是更改了正方形的大小以获得完全相同的视觉效果。

    ctx.beginPath();
    for (var i=60; i<canvasHeight; i+=60) {
        ctx.moveTo(0,i);
        ctx.lineTo(canvasWidth,i);
    }
    for (i=60; i<canvasWidth; i+=60) {
        ctx.moveTo(i,0);
        ctx.lineTo(i,canvasHeight);
    }
    ctx.strokeStyle="#000";
    ctx.stroke();
    ctx.closePath();
    

    随着这些变化,我们开始:

    到:

    编辑:为了确保四舍五入,实际上我认为最方便的是注入上下文并更改 moveTo、lineTo :

    function gridContext() {
         var oldMoveTo = CanvasRenderingContext2D.prototype.moveTo;
         CanvasRenderingContext2D.prototype.moveTo = function (x,y) {
                   x |= 0; y |= 0; 
                   oldMoveTo.call(this, x, y); 
         }
         var oldLineTo = CanvasRenderingContext2D.prototype.lineTo;
         CanvasRenderingContext2D.prototype.lineTo = function (x,y) {
                   x |= 0; y |= 0; 
                   oldLineTo.call(this, x, y); 
         }
    } 
    

    显然,您必须为所需的所有绘图功能执行此操作。

    【讨论】:

    • 谢谢。使用 translate() 命令要优雅得多。使用myCanvas.width = myCanvas.clientWidthmyCanvas.height = myCanvas.clientHeight是不是有问题,所以画布大小可以由样式表决定?它似乎对我有用,但我还没有彻底测试过。
    • 不客气。呵呵,是的,事实上,如果您确保代码中的 css 和画布大小相同,则应该没有缩放,但最简单的确保方法是不要完全设置 css 大小。我编辑了一个更清晰的代码。
    • @GameAlchemist,请务必进行您在回答中提到的四舍五入。如果您将网格间距(使用 60)替换为非整数(例如 300/18),您的演示仍然会消除锯齿。
    • @markE :是的,您是对的,如果网格大小更改为非整数,则会失败。我更新了我的帖子。
    【解决方案2】:

    在画布上绘制线条时,线条本身正好位于像素网格上。但是因为线条只有一个像素宽,它的一半出现在网格两侧的每个像素中,导致抗锯齿效果和线条在两个像素上基本上是 50% 透明。

    相反,将您的线偏移0.5 像素。这将使它恰好出现在像素中。

    Demo

    【讨论】:

    • 一个好的开始,但是将线条偏移 0.50 像素可能/可能无法解决抗锯齿效果。例如,如果垂直网格线已经在像素边界上对齐,那么添加 0.50 实际上会导致抗锯齿。您可以扩展您的答案,包括将网格线调整为与轴对齐的像素边界。
    • 谢谢。出于好奇,关于为什么我在重新启动之前没有看到抗锯齿问题的任何想法?是否有一些全局浏览器属性可能在某些时候被无意设置?
    • 抱歉,在我的实际代码中,我有 myCanvas.width = myCanvas.clientWidthmyCanvas.height = myCanvas.clientHeight,我没有在 jsfiddle 中使用它们。我应该做些什么来适当地调整画布的大小吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    相关资源
    最近更新 更多