MMTTMM
这是因为该arc方法在内部跟踪 alineTo从当前指针的位置到弧的开头(由 cx、cy和startAngle 定义)。要解决这个问题,您需要处于moveTo该位置。下面是一个使用半圆且设置startAngle为 0 rad 的更简单演示:const canvas = document.createElement( "canvas" );document.body.append( canvas );const ctx = canvas.getContext( "2d" );ctx.lineWidth = 2;const cx = 50;const cy = 50;const rad = 30;ctx.beginPath();ctx.moveTo( cx, cy );ctx.arc( cx, cy, rad, 0, Math.PI );ctx.strokeStyle = "red";ctx.stroke();ctx.translate( 80, 0 );const first_point_x = cx + rad; // startAngle is 0 // so we just have to add 'rad' // to find the x coordctx.beginPath();ctx.moveTo( first_point_x, cy );ctx.arc( cx, cy, rad, 0, Math.PI );ctx.strokeStyle = "green";ctx.stroke();因此,您必须计算弧线起点和moveTo该点的坐标。这是可行的,但我对 trigo 不是最好的,并且您的值非常复杂,因此,这里有一个使用 Path2D 对象的解决方法。如果该arc命令是子路径的第一个,它将直接指向moveTo该初始点(因为还没有“当前指针的位置”)。因此,我们可以将所有弧初始化为独立的 Path2D 对象,仅由这些arc命令组成。然后我们只需将这些 Path2D 对象合并到最后一个对象中并绘制它:const canvas = document.createElement("canvas");document.body.append(canvas);const c = canvas.getContext("2d");c.lineWidth = 2;const fish = new Fish(150, 50, 50, 50, 50);fish.draw();function Fish(x, y, dx, dy, radius) { this.x = x; this.y = y; this.dx = dx; this.dy = dy; this.radius = 30; this.draw = function() { const p1 = new Path2D(); p1.arc(this.x / 0.6, this.y, this.radius, Math.PI * 1.5, Math.PI * 0.5, false) //Upper Arc const p2 = new Path2D(); p2.arc(this.x / 0.6, this.y + (3 * this.radius), this.radius * 4, Math.PI * 229 / 180, Math.PI * 1.5, false) //Lower Arc const p3 = new Path2D(); p3.arc(this.x / 0.6, this.y - (3 * this.radius), this.radius * 4, Math.PI * 131 / 180, Math.PI * 0.5, true) // merge in a single Path2D object const path = new Path2D(); path.addPath(p1); path.addPath(p2); path.addPath(p3); c.strokeStyle = "green"; c.stroke(path); }}但在您的情况下,通过更改绘制 Path 的顺序并且从不调用moveTo.const canvas = document.createElement("canvas");document.body.append(canvas);const c = canvas.getContext("2d");c.lineWidth = 2;const fish = new Fish(150, 50, 50, 50, 50);fish.draw();function Fish(x, y, dx, dy, radius) { this.x = x; this.y = y; this.dx = dx; this.dy = dy; this.radius = 30; this.draw = function() { c.beginPath(); c.arc(this.x / 0.6, this.y, this.radius, Math.PI * 1.5, Math.PI * 0.5, false) // Lower Arc c.arc(this.x / 0.6, this.y - (3 * this.radius), this.radius * 4, Math.PI * 0.5, Math.PI * 131 / 180, false) // Upper Arc // (inverse startAngle and endAngle + switch swipe to false) c.arc(this.x / 0.6, this.y + (3 * this.radius), this.radius * 4, Math.PI * 229 / 180, Math.PI * 1.5, false) c.strokeStyle = "green"; c.stroke(); }}