Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Touch control #24

Merged
merged 2 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
}
},
"scripts": {
"dev-vanilla": "FRAMEWORK=vanilla npx vite build --mode development --watch & FRAMEWORK=vanilla npx vite serve demo/vanilla --config demo/vanilla/vite.config.js",
"dev-react": "FRAMEWORK=react npx vite build --mode development --watch & FRAMEWORK=react npx vite serve demo/react --config demo/react/vite.config.js ",
"dev-vanilla": "FRAMEWORK=vanilla npx vite build --mode development --watch & FRAMEWORK=vanilla npx vite serve demo/vanilla --config demo/vanilla/vite.config.js --host",
"dev-react": "FRAMEWORK=react npx vite build --mode development --watch & FRAMEWORK=react npx vite serve demo/react --config demo/react/vite.config.js --host",
"format": "prettier --write src",
"lint": "eslint src --ext .ts",
"build": "vite build --mode production"
Expand Down Expand Up @@ -45,6 +45,7 @@
"vite": "^5.3.2"
},
"dependencies": {
"interactjs": "^1.10.27",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
Expand Down
15 changes: 12 additions & 3 deletions src/camera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,26 @@ class Camera {

/**
* Handle the scroll event to zoom in and out of the camera view
* @param deltaScroll Amount of scroll
* @param deltaZoom Amount of scroll
* @param mouseX Position of the mouse on the device screen
* @param mouseY
*/
handleScroll(deltaScroll: number, mouseX: number, mouseY: number) {
handleScroll(deltaZoom: number, mouseX: number, mouseY: number) {
// Mouse position should be relative to the container
mouseX -= this.containerDom.offsetLeft;
mouseY -= this.containerDom.offsetTop;

let deltaZoom = 1 * this.zoom * (-deltaScroll / 1000); // Control scroll speed
// Limit zoom
if (this.zoom + deltaZoom < 0.2) {
deltaZoom = 0.2 - this.zoom;
} else if (this.zoom + deltaZoom > 1) {
deltaZoom = 1 - this.zoom;
}

// console.debug(
// `MouseX: ${mouseX}, MouseY: ${mouseY}, cameraWidth: ${this.cameraWidth}, cameraHeight: ${this.cameraHeight}`,
// );

const zoomRatio = this.zoom / (this.zoom + deltaZoom); // Ratio of current zoom to new zoom
// Move camera to zoom in on the mouse position
this.cameraX -=
Expand All @@ -98,6 +101,12 @@ class Camera {

this.zoom += deltaZoom;

// console.log(
// (this.cameraWidth / this.zoom) *
// (zoomRatio - 1) *
// (1 - (this.cameraWidth * 1.5 - mouseX) / this.cameraWidth),
// );

this.updateCamera();
}

Expand Down
5 changes: 4 additions & 1 deletion src/components/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ export abstract class Base {
* @param dom The DOM element to bind the function to
*/
bindFunction(dom: HTMLElement) {
dom.onmousedown = this.domMouseDown.bind(this);
//dom.onmousedown = this.domMouseDown.bind(this);
dom.ontouchstart = this.domTouchStart.bind(this);
dom.onpointerdown = this.domMouseDown.bind(this);
}

domMouseDown(e: MouseEvent): void {
console.debug(`Mouse down event triggered on ${this.gid}`);
this.domCursorDown({
button: e.button,
clientX: e.clientX,
Expand All @@ -40,6 +42,7 @@ export abstract class Base {
}

domTouchStart(e: TouchEvent): void {
console.debug(`Touch start event triggered on ${this.gid}`);
this.domCursorDown({
button: 0,
clientX: e.touches[0].clientX,
Expand Down
16 changes: 11 additions & 5 deletions src/components/connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class ConnectorComponent extends ComponentBase {
config: ConnectorConfig,
parent: NodeComponent,
globals: GlobalStats,
outgoingLines: lineObject[],
incomingLines: lineObject[],
) {
super(config, parent, globals);

Expand All @@ -45,15 +47,17 @@ class ConnectorComponent extends ComponentBase {
this.dom = dom;
this.parent = parent;
this.prop = parent.prop;
this.outgoingLines = [];
this.incomingLines = [];
this.outgoingLines = outgoingLines;
this.incomingLines = incomingLines;
this.config = config;
globals.gid++;
this.name = config.name || globals.gid.toString();
this.g.globalNodeTable[this.gid] = this;
this.dom.setAttribute("sl-gid", this.gid.toString());

this.bindFunction(this.dom);

console.log(config);
}

/**
Expand All @@ -78,7 +82,7 @@ class ConnectorComponent extends ComponentBase {
requestDelete: false,
completedDelete: false,
});
this.parent.outgoingLines.push(this.outgoingLines[0]);
//this.parent.allOutgoingLines.push(this.outgoingLines[0]);

this.setAllLinePositions();
}
Expand Down Expand Up @@ -107,6 +111,7 @@ class ConnectorComponent extends ComponentBase {
const targetConnector: ConnectorComponent = this.g.globalNodeTable[
gid
] as ConnectorComponent;
console.debug("Hovering over input connector", targetConnector);
targetConnector.updateConnectorPosition();
connectorX = targetConnector.connectorX;
connectorY = targetConnector.connectorY;
Expand Down Expand Up @@ -204,7 +209,7 @@ class ConnectorComponent extends ComponentBase {

if (connector.config.maxConnectors === currentIncomingLines.length) {
console.warn(
`Connector ${connector} already has max number of connectors`,
`Connector ${connector.name} already has max number of connectors (${connector.config.maxConnectors}) connected`,
);
return false;
}
Expand All @@ -213,7 +218,6 @@ class ConnectorComponent extends ComponentBase {

this.outgoingLines[0].target = connector;
connector.incomingLines.push(this.outgoingLines[0]);
connector.parent.incomingLines.push(this.outgoingLines[0]);

return true;
}
Expand Down Expand Up @@ -311,6 +315,8 @@ class ConnectorComponent extends ComponentBase {
line.classList.add("sl-connector-line");
line.setAttribute("stroke-width", "4");

console.debug(`Created line from connector ${this.gid}`);

this.g.canvas!.appendChild(svg);

return svg;
Expand Down
49 changes: 39 additions & 10 deletions src/components/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class NodeComponent extends Base {
dom: HTMLElement | null;
connectors: { [key: string]: ConnectorComponent }; // Dictionary of all connectors in the node, using the name as the key
components: { [key: string]: ComponentBase }; // Dictionary of all components in the node except connectors
outgoingLines: lineObject[]; // Array of all lines going out of the node
incomingLines: lineObject[]; // Array of all lines coming into the node
allOutgoingLines: { [key: string]: lineObject[] }; // Dictionary of all lines going out of the node
allIncomingLines: { [key: string]: lineObject[] }; // Dictionary of all lines coming into the node

nodeWidth = 0;
nodeHeight = 0;
Expand All @@ -39,8 +39,8 @@ class NodeComponent extends Base {
this.dom = dom;
this.connectors = {};
this.components = {};
this.outgoingLines = [];
this.incomingLines = [];
this.allOutgoingLines = {};
this.allIncomingLines = {};

this.dragStartX = this.positionX;
this.dragStartY = this.positionY;
Expand Down Expand Up @@ -126,7 +126,7 @@ class NodeComponent extends Base {

filterDeletedLines(svgLines: lineObject[]) {
for (let i = 0; i < svgLines.length; i++) {
if (svgLines[i].requestDelete) {
if (svgLines[i].requestDelete && svgLines[i].completedDelete) {
svgLines.splice(i, 1);
i--;
}
Expand All @@ -139,6 +139,11 @@ class NodeComponent extends Base {
* @param outgoingLines Array of all lines outgoing from the node or connector
*/
_renderOutgoingLines(outgoingLines: lineObject[]) {
// console.debug(
// "Rendering outgoing lines",
// outgoingLines,
// outgoingLines.length,
// );
for (const line of outgoingLines) {
const connector = line.start;
if (!line.svg) {
Expand All @@ -161,6 +166,7 @@ class NodeComponent extends Base {
line.svg.style.transform = `translate3d(${connector.connectorX}px, ${connector.connectorY}px, 0)`;
connector.renderLinePosition(line);
}

this.filterDeletedLines(outgoingLines);
}

Expand All @@ -171,14 +177,31 @@ class NodeComponent extends Base {
};
}

_iterateDict(
dict: { [key: string]: any },
callback: (lines: lineObject[]) => void,
bind: any = this,
) {
for (const key in dict) {
callback.bind(bind)(dict[key]);
}
}

_renderNodeLines() {
this._renderOutgoingLines(this.outgoingLines);
// Flatten the allOutgoingLines object into an array and call the renderLines function
this._iterateDict(this.allOutgoingLines, this._renderOutgoingLines);
// For incoming lines, the renderLines function of the peer node is called.
// This is to prevent duplicate rendering of lines on some declarative frontend frameworks.
for (const line of this.incomingLines) {
const peerNode = line.start.parent;
peerNode._renderOutgoingLines(peerNode.outgoingLines);
}
this._iterateDict(this.allIncomingLines, (lines: lineObject[]) => {
for (const line of lines) {
const peerNode = line.start.parent;
this._iterateDict(
peerNode.allOutgoingLines,
peerNode._renderOutgoingLines,
peerNode,
);
}
});
}

renderNode(style: any) {
Expand Down Expand Up @@ -225,11 +248,15 @@ class NodeComponent extends Base {
maxConnectors = 1,
allowDragOut = true,
) {
this.allOutgoingLines[name] = [];
this.allIncomingLines[name] = [];
const connector = new ConnectorComponent(
dom,
{ name: name, maxConnectors: maxConnectors, allowDragOut: allowDragOut },
this,
this.g,
this.allOutgoingLines[name],
this.allIncomingLines[name],
);
this.connectors[name] = connector;
this.prop[name] = null;
Expand Down Expand Up @@ -374,11 +401,13 @@ class NodeComponent extends Base {
}

onFocus() {
console.debug("On focus");
this.setNodeStyle({ _focus: true });
this.renderNode(this.nodeStyle);
}

offFocus() {
console.debug("Off focus");
this.setNodeStyle({ _focus: false });
this.renderNode(this.nodeStyle);
}
Expand Down
Loading