91 lines
2.7 KiB
JavaScript
91 lines
2.7 KiB
JavaScript
class SelfConnection {
|
|
|
|
constructor(state, mouse) {
|
|
this.state = state;
|
|
this.anchorAngle = 0;
|
|
this.mouseOffsetAngle = 0;
|
|
this.text = '';
|
|
|
|
if(mouse) {
|
|
this.setAnchorPoint(mouse.x, mouse.y);
|
|
}
|
|
}
|
|
|
|
setMouseStart(x, y) {
|
|
this.mouseOffsetAngle = this.anchorAngle - Math.atan2(y - this.state.y, x - this.state.x);
|
|
}
|
|
|
|
setAnchorPoint(x, y) {
|
|
this.anchorAngle = Math.atan2(y - this.state.y, x - this.state.x) + this.mouseOffsetAngle;
|
|
|
|
const snap = Math.round(this.anchorAngle / (Math.PI / 2)) * (Math.PI / 2);
|
|
|
|
if(Math.abs(this.anchorAngle - snap) < .1)
|
|
this.anchorAngle = snap;
|
|
|
|
if(this.anchorAngle < -Math.PI)
|
|
this.anchorAngle += 2 * Math.PI;
|
|
|
|
if(this.anchorAngle > Math.PI)
|
|
this.anchorAngle -= 2 * Math.PI;
|
|
}
|
|
|
|
getEndPointsAndCircle() {
|
|
const circle = {
|
|
x: this.state.x + 1.5 * radius * Math.cos(this.anchorAngle),
|
|
y: this.state.y + 1.5 * radius * Math.sin(this.anchorAngle),
|
|
radius: 0.75 * radius,
|
|
};
|
|
|
|
const startAngle = this.anchorAngle - Math.PI * .8;
|
|
const endAngle = this.anchorAngle + Math.PI * .8;
|
|
|
|
const start = {
|
|
x: circle.x + circle.radius * Math.cos(startAngle),
|
|
y: circle.y + circle.radius * Math.sin(startAngle),
|
|
};
|
|
|
|
const end = {
|
|
x: circle.x + circle.radius * Math.cos(endAngle),
|
|
y: circle.y + circle.radius * Math.sin(endAngle),
|
|
};
|
|
|
|
return {
|
|
isCircle: true,
|
|
start,
|
|
end,
|
|
startAngle,
|
|
endAngle,
|
|
circle,
|
|
};
|
|
}
|
|
|
|
draw() {
|
|
const endPoints = this.getEndPointsAndCircle();
|
|
|
|
ctx.strokeStyle = ctx.fillStyle = settings.colors.getColor(this);
|
|
|
|
ctx.beginPath();
|
|
|
|
ctx.arc(endPoints.circle.x, endPoints.circle.y, endPoints.circle.radius, endPoints.startAngle, endPoints.endAngle);
|
|
ctx.stroke();
|
|
|
|
ctx.closePath();
|
|
|
|
const textX = endPoints.circle.x + endPoints.circle.radius * Math.cos(this.anchorAngle),
|
|
textY = endPoints.circle.y + endPoints.circle.radius * Math.sin(this.anchorAngle);
|
|
ctx.drawText(this.text, textX, textY, this.anchorAngle, selectedObject === this);
|
|
|
|
ctx.drawArrow(endPoints.end.x, endPoints.end.y, endPoints.endAngle + Math.PI * .4);
|
|
}
|
|
|
|
containsPoint(x, y) {
|
|
const endPoints = this.getEndPointsAndCircle(),
|
|
dx = x - endPoints.circle.x,
|
|
dy = y - endPoints.circle.y,
|
|
distance = Math.sqrt(dx ** 2 + dy ** 2) - endPoints.circle.radius;
|
|
return Math.abs(distance) < settings.hitTargetPadding;
|
|
}
|
|
|
|
}
|