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

我的想法/尝试:


因为三角形的点与两条相交的曲线之间的点相同,所以我首先认为是因为这些曲线没有接触,然后回过头来固定了该点。
moveTo()在贝塞尔曲线的端点上方创建一个“新点”,所以实际上是相交的新点和下一条曲线,而不是贝塞尔曲线和下一条曲线?


咨询:

我查看了Mozilla开发人员网络对moveTo()的Canvas教程的解释,并在此处使用诸如“ moveTo()”,“。fill()”,“相邻曲线”,“相邻贝塞尔曲线”之类的关键字进行搜索。我找到了this,但这并不是我想要的。

HTML代码:

<!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代码在这里

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();


 先感谢您!!

最佳答案

第一件事:不要使用硬编码的常量,这可能会引起麻烦。
另一件事,不要犹豫使用上下文转换来简化您的绘图代码。
最后,如果您使用简单易懂的参数,您的代码将更容易(重复)使用:例如,您可以提供要绘制的图形的边界框的左上角的x,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()时,这些子路径都将被填充。这些子路径并不能覆盖您要填充的所有表面。

10-02 20:33