Skip to content

Commit 2698eac

Browse files
sim51jacomyal
authored andcommitted
[sigma] mouse event and shadowdom
Fix #1400
1 parent 7a341c3 commit 2698eac

File tree

4 files changed

+164
-1
lines changed

4 files changed

+164
-1
lines changed

packages/sigma/src/core/captors/mouse.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export default class MouseCaptor<
238238
// Only trigger the "mousemove" event when the mouse is actually hovering
239239
// the container, to avoid weirdly hovering nodes and/or edges when the
240240
// mouse is not hover the container:
241-
if (e.target === this.container) {
241+
if (e.target === this.container || e.composedPath()[0] === this.container) {
242242
this.emit("mousemove", mouseCoords);
243243
}
244244

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<style>
2+
html,
3+
body,
4+
#storybook-root,
5+
#sigma-container {
6+
width: 100%;
7+
height: 100%;
8+
margin: 0;
9+
padding: 0;
10+
overflow: hidden;
11+
font-family: sans-serif;
12+
}
13+
#sigma-container .sigma-mouse {
14+
z-index: 100;
15+
}
16+
#sigma-logs {
17+
position: absolute;
18+
top:0;
19+
max-height: 20%;
20+
overflow: hidden;
21+
}
22+
#sigma-logs > div {
23+
padding: 3px;
24+
}
25+
#sigma-logs > div > span {
26+
background: #ffffff99;
27+
}
28+
</style>
29+
<sigma-shadow></sigma-shadow>
30+
<div id="sigma-logs"></div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import Graph from "graphology";
2+
import Sigma from "sigma";
3+
import { MouseCoords } from "sigma/types";
4+
5+
import data from "../_data/data.json";
6+
7+
/**
8+
* This is a minimal example of sigma. You can use it as a base to write new
9+
* examples, or reproducible test cases for new issues, for instance.
10+
*/
11+
export default () => {
12+
const logsDOM = document.getElementById("sigma-logs") as HTMLElement;
13+
const graph = new Graph();
14+
graph.import(data);
15+
16+
function logEvent(event: string, itemType: "node" | "edge" | "positions", item: string | MouseCoords): void {
17+
const div = document.createElement("div");
18+
let message = `Event "${event}"`;
19+
if (item && itemType) {
20+
if (itemType === "positions") {
21+
item = item as MouseCoords;
22+
message += `, x ${item.x}, y ${item.y}`;
23+
} else {
24+
const label =
25+
itemType === "node" ? graph.getNodeAttribute(item, "label") : graph.getEdgeAttribute(item, "label");
26+
message += `, ${itemType} ${label || "with no label"} (id "${item}")`;
27+
28+
if (itemType === "edge") {
29+
message += `, source ${graph.getSourceAttribute(item, "label")}, target: ${graph.getTargetAttribute(
30+
item,
31+
"label",
32+
)}`;
33+
}
34+
}
35+
}
36+
div.innerHTML = `<span>${message}</span>`;
37+
logsDOM.appendChild(div);
38+
logsDOM.scrollTo({ top: logsDOM.scrollHeight });
39+
40+
if (logsDOM.children.length > 50) logsDOM.children[0].remove();
41+
}
42+
43+
window.customElements.define(
44+
"sigma-shadow",
45+
class extends HTMLElement {
46+
_container: HTMLDivElement | null = null;
47+
48+
constructor() {
49+
super();
50+
}
51+
52+
connectedCallback() {
53+
const shadowRoot = this.attachShadow({ mode: "open" });
54+
const container = document.createElement("div");
55+
container.style.cssText = `
56+
width: 100%;
57+
height: 100%;
58+
margin: 0;
59+
padding: 0;
60+
overflow: hidden;
61+
`;
62+
this._container = container;
63+
shadowRoot.appendChild(container);
64+
65+
let hoveredEdge: null | string = null;
66+
const renderer = new Sigma(graph, this._container, {
67+
enableEdgeEvents: true,
68+
edgeReducer(edge, data) {
69+
const res = { ...data };
70+
if (edge === hoveredEdge) res.color = "#cc0000";
71+
return res;
72+
},
73+
});
74+
75+
const nodeEvents = [
76+
"enterNode",
77+
"leaveNode",
78+
"downNode",
79+
"clickNode",
80+
"rightClickNode",
81+
"doubleClickNode",
82+
"wheelNode",
83+
] as const;
84+
const edgeEvents = ["downEdge", "clickEdge", "rightClickEdge", "doubleClickEdge", "wheelEdge"] as const;
85+
const stageEvents = ["downStage", "clickStage", "doubleClickStage", "wheelStage"] as const;
86+
87+
nodeEvents.forEach((eventType) => renderer.on(eventType, ({ node }) => logEvent(eventType, "node", node)));
88+
edgeEvents.forEach((eventType) => renderer.on(eventType, ({ edge }) => logEvent(eventType, "edge", edge)));
89+
90+
renderer.on("enterEdge", ({ edge }) => {
91+
logEvent("enterEdge", "edge", edge);
92+
hoveredEdge = edge;
93+
renderer.refresh();
94+
});
95+
renderer.on("leaveEdge", ({ edge }) => {
96+
logEvent("leaveEdge", "edge", edge);
97+
hoveredEdge = null;
98+
renderer.refresh();
99+
});
100+
101+
stageEvents.forEach((eventType) => {
102+
renderer.on(eventType, ({ event }) => {
103+
logEvent(eventType, "positions", event);
104+
});
105+
});
106+
}
107+
},
108+
);
109+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Meta, StoryObj } from "@storybook/html";
2+
3+
import play from ".";
4+
import template from "./index.html?raw";
5+
import source from "./index?raw";
6+
7+
const meta: Meta = {
8+
id: "events-shadowdom",
9+
title: "Examples",
10+
};
11+
export default meta;
12+
13+
type Story = StoryObj;
14+
15+
export const story: Story = {
16+
name: "Events ShadowDom",
17+
render: () => template,
18+
play: play,
19+
parameters: {
20+
storySource: {
21+
source: source,
22+
},
23+
},
24+
};

0 commit comments

Comments
 (0)