半径线出现在移动弧上 [英] Radius Line Appears on Moving Arc

查看:67
本文介绍了半径线出现在移动弧上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试移动这些形状,该形状由半圆和对称的上弧&下弧.它们应该只是前面的形状,但是现在它们之间有一条线,就像尾巴在移动时向后拖动.尾部未知的输出形状

I was trying to create these shapes moving, the shape is made up of a semicircle and a symmetric upper arc & lower arc. They should be just the shape in front but now there are line like a tail dragging behind when they move. The output shape with unknown tail

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

It seems like these lines are from the moveTo part of upper and lower arcs, but I can't figure out how to solve it. Where should I change to get rid of it?

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

    }

推荐答案

这是因为 arc 方法在内部从当前指针的位置一直跟踪 lineTo 弧(由cx,cy startAngle定义).

This is because the arc method internally traces a lineTo from the current pointer's position to the beginning of the arc (defined by cx, cy and startAngle).

要解决此问题,您需要 moveTo 该位置.

To workaround that, you need to moveTo that position.

这是一个使用demi圆的简单演示,其 startAngle 设置为0 rad:

Here is a simpler demonstration using a demi-circle with the startAngle set at 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 该初始点(因为还没有当前指针的位置").
因此,我们可以将所有弧初始化为仅由这些 arc 命令组成的独立Path2D对象.然后,我们只需要将这些Path2D对象合并到最后一个对象中并绘制该对象即可:

So you would have to calculate the coordinates of the point where your arc will start and moveTo that point.
This is doable, but I'm not the best with trigo and your values are quite complex, so instead, here is a workaround using Path2D objects.
If the arc command is the first of the sub-path, it will directly moveTo that initial point (since there isn't a "current pointer's position" yet).
So we can initialize all our arcs as standalone Path2D objects, made only of these arc commands. Then we just have to merge these Path2D objects into a last one and draw that:

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 ,就可以很容易地获得预期的结果.

But in your case you can achieve the expected result quite easily, by changing the order in which you draw your Path and by never calling 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();

  }
}

这篇关于半径线出现在移动弧上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆