首页 > 解决方案 > 移动圆弧上出现半径线

问题描述

我试图创建这些移动的形状,形状由半圆和对称的上弧和下弧组成。它们应该只是前面的形状,但现在它们移动时有一条像尾巴一样拖在后面的线。 尾部未知的输出形状

似乎这些线来自上下弧的 moveTo 部分,但我不知道如何解决它。我应该在哪里改变以摆脱它?

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)
        
        //Upper Arc
        c.moveTo(this.x, this.y);
        c.arc(this.x/0.6, this.y+(3*this.radius), this.radius*4, Math.PI * 229/180, Math.PI * 1.5, false)
        
        //Lower Arc
        c.moveTo(this.x, this.y);
        c.arc(this.x/0.6, this.y-(3*this.radius), this.radius*4, Math.PI * 131/180 , Math.PI * 0.5, true)
        c.strokeStyle = "green";
        c.stroke();

    }

标签: javascripthtmlanimationcanvas

解决方案


这是因为该arc方法在内部跟踪 alineTo从当前指针的位置到弧的起点(由 cx、cystartAngle 定义)。

要解决这个问题,您需要到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 coord
ctx.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);
    
  }
}

但是在您的情况下,您可以通过更改绘制路径的顺序并且从不调用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();

  }
}


推荐阅读