HTML5画布|使用.moveTo()和.fillI()的细微差别

时间:2014-07-14 16:28:35

标签: javascript html5 canvas bezier

我试图用绿色填充画布(由二次曲线和贝塞尔曲线组成)。在第一条贝塞尔曲线之后,我使用moveTo并在创建下一条曲线(二次曲线)之前将其指向曲线的终点(是的,有点多余)。在我整个脸后,我用填充。脸部用绿色填充脸部,但在中间留下一个白色三角形。当我删除前面提到的冗余moveTo()时,整个形状都按照预期填充绿色。有人可以解释一下吗?

我的想法/尝试:

  • 因为三角形的点与两条交叉曲线之间的点相同,所以我首先想到的是因为曲线没有接触,然后又回过头来固定它。

  • moveTo()创建了一个新的点'在贝塞尔曲线的终点之上,所以它真的是新点和下一条曲线相交而不是贝塞尔曲线和下一条曲线?

咨询:

我查看了Mozilla开发者网络对MoveTo()的Canvas Tutorial解释,并在此处使用' moveTo()'等关键字进行了搜索。 ' .fill伪()' '相邻曲线' '相邻贝塞尔曲线。'我找到了this,但它并不是我想要的。

HTML code:

<!DOCTYPE html>
<html>
<head>
<title>FACE</title>
</head>

<body>
    <canvas id = 'canvas' height = '900' width = '900'></canvas>
    <script src = 'face.js'></script>
</body>
</html>

Javascript Code Here

var canvas = document.getElementById('canvas'); <br>
var context = canvas.getContext('2d');<br><br>
function greenHeadFront()
{
    var rightHeadx = 110.5;
    var rightHeady = 80;
    var leftHeadx = 40.5;
    var leftHeady = 80;

    context.moveTo(leftHeadx, leftHeady);
    context.bezierCurveTo(leftHeadx+6, leftHeady-40, rightHeadx-6, rightHeady-40, rightHeadx, rightHeady);        //TOP OF HEAD
    context.moveTo(rightHeadx, rightHeady);
    context.quadraticCurveTo( 115 , 100  ,  rightHeadx, rightHeady+30);//RIGHT CHEEK
    context.bezierCurveTo (100 , 114, 129, 152,   75, 131); //RIGHT CHIN
    context.moveTo(leftHeadx,leftHeady);
    context.quadraticCurveTo(35, 100, leftHeadx, leftHeady+30);//LEFT CHEEK
    context.bezierCurveTo(53, 120, 23, 148, 75, 131); //LEFT CHIN
    context.fillStyle = 'rgb(0,156,0)';
    context.fill();
    context.stroke(); 
}

greenHeadFront();


提前谢谢!!

2 个答案:

答案 0 :(得分:0)

画布路径取决于绘制路径的方向(顺时针或逆时针)。这是关于如何绘制不同方式影响填充区域的little info

也有点不相关,但我相信您缺少对context.beginPath();context.closePath();方法的调用来表示形状的开头和结尾。希望这有帮助!

答案 1 :(得分:0)

第一件事:使用硬编码常量,这可能是麻烦的来源。
另外,请不要犹豫,使用上下文转换来简化您的绘图代码 最后,如果您使用简单易懂的参数,您的代码将更容易(重新)使用:例如,您可以提供边界框的左上角&n; sx,y和图的宽度/高度画画。

所以下面我写了未经测试的代码,只是为了告诉你如何更清楚地重写你的绘图代码 这个想法是转换到图的左上角,然后缩放上下文,这样你只能使用介于0.0和1.0之间的坐标来进行绘制。
再次,不要犹豫在函数中命名常量,然后您可能会选择一些常量作为函数参数。

function greenHeadFront(x, y, width, height )
{
    context.save();
    context.translate(x,y);
    context.scale(width, height);
    // !! required !!
    context.beginPath();
    // now all coordinates are beetween (0,0) (top-left) 
    //     and (1.0,1.0) (bottom-right)
    var cheekHeight = 0.1 ; 
    context.moveTo(0.5, 1 - cheekHeight); // move to center middle point.
    context.quadraticCurveTo( ??);//RIGHT CHEEK 
    context.bezierCurveTo (??); //RIGHT CHIN
    context.bezierCurveTo(  ?? );  //TOP OF HEAD
    context.bezierCurveTo(??); //LEFT CHIN
    context.quadraticCurveTo(??);//LEFT CHEEK
    context.fillStyle = 'rgb(0,156,0)';
    context.fill();
    context.strokeStyle='#000';
    context.lineWidth=0.01;
    context.stroke();
    context.strokeRect(0,0,1,1);  // for debug
    context.restore();
}

greenHeadFront( ?? );

现在对于你的三角形问题,它是预期的行为:每次你调用moveTo时,你都在创建一个新的子路径,所以你的数字现在是由几个子路径构建的,这些路径都将被填充当你打电话给fill()时。而这些子路径并未涵盖您希望填充的所有表面。