fsm-designer/js/components/self-connection.js

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;
}
}