#javascript #html #animation #canvas
#javascript #HTML #Анимация #холст
Вопрос:
Я пытался создать эти движущиеся фигуры, фигура состоит из полукруга и симметричной верхней дуги и нижней дуги. Они должны быть только формой спереди, но теперь есть линия, похожая на хвост, волочащийся позади, когда они движутся. Выходная форма с неизвестным хвостом
Похоже, что эти строки взяты из 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();
}
Ответ №1:
Это потому arc
, что метод внутренне отслеживает a lineTo
от позиции текущего указателя до начала дуги (определяется cx, cy и startAngle ).
Чтобы обойти это, вам нужно moveTo
это положение.
Вот более простая демонстрация с использованием полукруга с startAngle
установленным значением 0 рад:
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();
}
}
Комментарии:
1. Наконец-то поймите, что там происходит! Большое спасибо за ваше объяснение !! > <