fsm-designer/js/main.js
2019-02-27 21:22:38 +01:00

188 lines
4.3 KiB
JavaScript

const width = 600;
const height = 300;
const radius = 25;
const settings = {
physics: true,
speed: 2,
snapToPadding: 10
};
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
const states = [];
const connections = [];
function tick() {
states.forEach(stateA => {
states.forEach(stateB => {
if (stateA !== stateB && stateA.intersects(stateB)) {
const inter = stateA.intersection(stateB);
const angle1 = stateA.directionTo(stateB);
const angle2 = angle1 + Math.PI;
const x1 = Math.cos(angle1) * inter + stateA.x;
const y1 = Math.sin(angle1) * inter + stateA.y;
const x2 = Math.cos(angle2) * inter + stateB.x;
const y2 = Math.sin(angle2) * inter + stateB.y;
stateA.moveTo(x1, y1);
stateB.moveTo(x2, y2);
}
});
});
states.forEach(state => {
if (state.v) {
state.moveToStep();
}
});
setTimeout(tick, 1000 / 30);
}
function draw() {
ctx.clearRect(0, 0, width, height);
connections.forEach(connection => connection.draw());
states.forEach(state => state.draw());
setTimeout(draw, 1000 / 60);
}
function selectObject(x, y) {
for (let state of states) {
if ((x - state.x) * (x - state.x) + (y - state.y) * (y - state.y) < radius * radius) {
return state;
}
}
}
function getStateByPos(x, y) {
}
function checkForState(x, y) {
return !!getStateByPos(x, y);
}
function addState(x, y) {
const state = new State(x, y, '#f0f');
states.push(state);
}
function addConnection(stateA, stateB, angleA, angleB) {
const connection = new Connection(stateA, stateB, angleA, angleB);
connections.push(connection);
}
let isMouseDown = false,
isDragging = false,
lastDrag = 0,
selectedObject = null,
shiftPressed = false,
currentConnection = null,
movingObject = false;
canvas.addEventListener('mousedown', (event) => {
selectedObject = selectObject(event.x, event.y);
shiftPressed = event.shiftKey;
if (!!selectedObject) {
if (shiftPressed && selectedObject instanceof State) {
currentConnection = new SelfConnection(selectedObject, event);
} else {
movingObject = true;
}
}
});
canvas.addEventListener('mousemove', (event) => {
if (isMouseDown && !isDragging)
isDragging = true;
if (isMouseDown && isDragging) {
if (!shiftPressed) {
selectedObject.jumpTo(event.clientX, event.clientY);
}
selectedObject.setAnchorPoint(event.clientX, event.clientY);
}
if (!!currentConnection) {
let targetState = selectObject(event.x, event.y);
if (!targetState instanceof State) {
targetState = null;
}
if (!!selectedObject) {
if (targetState === selectedObject) {
currentConnection = new SelfConnection(selectedObject, event);
} else if(!!targetState) {
currentConnection = new Connection(selectedObject, targetState);
} else {
// currentConnection = new
}
} else {
}
}
});
canvas.addEventListener('mouseup', (event) => {
if (isDragging) {
lastDrag = Date.now()
}
if (shiftPressed) {
const state = getStateByPos(event.clientX, event.clientY);
addConnection(selectedObject, state, Math.PI, -Math.PI);
}
isMouseDown = false;
isDragging = false;
selectedObject = null;
});
canvas.addEventListener('click', (event) => {
const x = event.clientX,
y = event.clientY;
if (Date.now() - lastDrag < 100) {
return;
}
if (checkForState(x, y)) {
}
});
canvas.addEventListener('dblclick', (event) => {
const x = event.clientX,
y = event.clientY;
addState(x, y);
});
CanvasRenderingContext2D.prototype.drawArrow = function (x, y, angle) {
const dx = Math.cos(angle);
const dy = Math.sin(angle);
this.beginPath();
this.moveTo(x, y);
this.lineTo(x - 8 * dx + 5 * dy, y - 8 * dy - 5 * dx);
this.lineTo(x - 8 * dx - 5 * dy, y - 8 * dy + 5 * dx);
this.fill();
};
tick();
draw();