2015-09-04 49 views
3

这里是我做的小部件的照片:如何在HTML Canvas上绘制出比此图像更光滑的椭圆形?

enter image description here

这里是调用所有原始形状的主要功能:

function cylinder(ctx, w, h, fill_percent){ 
    y_origin = h; 
    x_origin = 0; 
    drawContainerBottom(ctx, x_origin, y_origin, w, h); 
    drawContentBottom(ctx, x_origin, y_origin, w, h); 
    drawContentFront(ctx, x_origin, y_origin, w, h, fill_percent); 
    drawContentTop(ctx, x_origin, y_origin, w, h, fill_percent); 
    drawContainerFront(ctx, x_origin, y_origin, w, h); 
    drawContainerTop(ctx, x_origin, y_origin, w, h); 
} 

这里是画的顶部的功能外部容器,主要看起来很糟糕:

function drawContentTop(ctx, x, y, w, h, fill_percent){ 
    Contents_offset=5; 
    w=w-2*Contents_offset; 
    x=x+Contents_offset; 
    h=h; 
    y=y-h+Contents_offset+(h-w/4-2*Contents_offset)*(1-fill_percent); 
    var i; 
    var xPos; 
    var yPos; 
    var twoPi = 2 * Math.PI; 
    ctx.beginPath(); 

    //Top 
    for (i = 0; i < twoPi; i += 0.001) { 
     xPos = (x + w/2) - (w/2 * Math.cos(i)); 
     yPos = (y + w/8) + (w/8 * Math.sin(i)); 

     if (i === 0) { 
      ctx.moveTo(xPos, yPos); 
     } else { 
      ctx.lineTo(xPos, yPos); 
     } 
    } 

    ctx.fillStyle="rgba(0, 99, 188, .5)"; 
    ctx.fill(); 
    ctx.strokeStyle="rgba(0, 99, 188, 1)"; 
    ctx.stroke(); 
}; 

以下是我如何称之为:

<canvas name='pool_graphic' class='pool_graphic' width='125' height='125' style='padding:10px'></canvas><br /> 
<canvas name='pool_graphic' class='pool_graphic' width='125' height='125' style='padding:10px'></canvas><br /> 
<script> 
    $("td canvas[name='pool_graphic']").each(function(){ 
     var ctx = this.getContext('2d'); 
     var padding = this.style.padding.replace(/[^0-9]+/, ''); 
     var w=this.width 
     var h=this.height; 
     var fill_percent=1; 
     cylinder(ctx, w, h, fill_percent); 

    }); 
</script> 

首先,当我在所有情况下使用相同的手动类型循环时,为什么它只是外部容器的顶部和底部看起来很糟糕?其次,我如何解决锯齿状问题?

编辑:只是不停地用讨论的技术tweeking,这里是我得到了什么

enter image description here

+0

当你说的顶部和底部看坏,具体是什么你指的是?当您在一边显示黑色时,您是否在谈论轮廓的外观? (即所显示图像的顶部和底部25像素)。不要忘了,抗锯齿涉及混合像素的颜色。当你有4个像素混合从黑色到白色(例如)时,与混合白色到浅灰色相比,4个像素中的每一个看起来都与它的邻居更加不同。以更高的分辨率绘图可以使这些混合区域代表图像的较小比例。 – enhzflep

+0

某种平滑或抗混叠滤波器可能会有效,但这是java脚本而不是Photoshop,所以我不知道如何。问题在于,它看起来只在最高和最低线上数字化,其他一切都很好,很流畅。这个问题最突出的地方在于椭圆形几乎看起来完全平坦的顶部和底部。 – gunslingor

+0

您可以使用画布元素使用抗锯齿(如您的图片已经这样做)。如果您希望以128x128显示图像,则可以使用256x256的画布生成图像。如果这个65536像素(256x256)的画布以128x128显示,浏览器将负责创建这些256x256像素的128x128表示。所以'

body{ background-color: ivory; } 
 
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=300 height=300></canvas>

+0

有趣的是,您使用弧函数并仍然存在问题。根据你的评论,这是一个常见的问题,可能是所有的计算机图形学,除了超级先进的软件,如Photoshop。这似乎是你真正要玩的东西,“咯咯笑”,取决于许多因素,如画布尺寸,椭圆形高度和背景颜色。我发现增加笔画宽度有助于一点点,但我敢打赌,有人有更好的解决方案。也许在光线之上画一个黑弧线,即它可能会混合到背景,而不是更好地透明。 – gunslingor

+0

假设您拥有设计自由度,增加线宽确实有所帮助。多次应用笔画也有帮助(请参阅我的答案中的代码)。 – markE

+1

是的,做多笔画有点帮助...几乎与增加线宽相同。唯一真正的问题是,它看起来像顶尖和底部是平坦的,但我可能是唯一注意到的问题。我发现Photoshops的椭圆形表现出了同样的问题,即使插图画家在某些放大镜上展示了这个问题真的很糟糕。所以这对于所有计算机图形显然是通用的。它只能根据不同的尺寸,背景颜色,分辨率等进行动态补偿和动态补偿,但这些都是不现实的......但是你们都给了我所需要的工具来减少它,我想。 – gunslingor