Skip to content

Commit e17edd8

Browse files
committed
feat(init): Setup project.
1 parent fb6d372 commit e17edd8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+28495
-0
lines changed

LICENSE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,4 @@
199199
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200200
See the License for the specific language governing permissions and
201201
limitations under the License.
202+

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Invio
2+
3+
Invio 将你的 Obsidian 文档自动发布到 腾讯云对象存储COS 上,如果对你有用,请点个Star [star ![GitHub Repo stars](https://img.shields.io/github/stars/frontend-engineering/Invio)](https://github.com/frontend-engineering/Invio)

assets/assets.d.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
declare module "*.txt.js" {
2+
const value: string
3+
export default value
4+
}
5+
6+
declare module "*.txt.css" {
7+
const value: string
8+
export default value
9+
}
10+
11+
declare module "*.txt" {
12+
const value: string
13+
export default value
14+
}
15+
16+
// binary
17+
declare module "*.wasm" {
18+
const value: Uint8Array
19+
export default value
20+
}
21+

assets/graph-render-worker.txt.js

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
// Import Pixi.js library
2+
if( 'function' === typeof importScripts)
3+
{
4+
importScripts('https://d157l7jdn8e5sf.cloudfront.net/v7.2.0/webworker.js', './tinycolor.js');
5+
6+
addEventListener('message', onMessage);
7+
8+
let app;
9+
let container;
10+
let graphics;
11+
let labelText;
12+
13+
isDrawing = false;
14+
15+
let linkCount = 0;
16+
let linkSources = [];
17+
let linkTargets = [];
18+
let nodeCount = 0;
19+
let radii = [];
20+
let labels = [];
21+
let cameraOffset = {x: 0, y: 0};
22+
let positions = new Float32Array(0);
23+
let linkLength = 0;
24+
let edgePruning = 0;
25+
let colors =
26+
{
27+
background: 0x232323,
28+
link: 0xAAAAAA,
29+
node: 0xCCCCCC,
30+
outline: 0xAAAAAA,
31+
text: 0xFFFFFF,
32+
accent: 0x4023AA
33+
}
34+
35+
let hoveredNode = -1;
36+
let lastHoveredNode = -1;
37+
let grabbedNode = -1;
38+
let updateAttached = false;
39+
let attachedToGrabbed = [];
40+
let activeNode = -1;
41+
let attachedToActive = [];
42+
43+
let cameraScale = 1;
44+
let cameraScaleRoot = 1;
45+
46+
function toScreenSpace(x, y, floor = true)
47+
{
48+
if (floor)
49+
{
50+
return {x: Math.floor((x * cameraScale) + cameraOffset.x), y: Math.floor((y * cameraScale) + cameraOffset.y)};
51+
}
52+
else
53+
{
54+
return {x: (x * cameraScale) + cameraOffset.x, y: (y * cameraScale) + cameraOffset.y};
55+
}
56+
}
57+
58+
function vecToScreenSpace({x, y}, floor = true)
59+
{
60+
return toScreenSpace(x, y, floor);
61+
}
62+
63+
function toWorldspace(x, y)
64+
{
65+
return {x: (x - cameraOffset.x) / cameraScale, y: (y - cameraOffset.y) / cameraScale};
66+
}
67+
68+
function vecToWorldspace({x, y})
69+
{
70+
return toWorldspace(x, y);
71+
}
72+
73+
function setCameraCenterWorldspace({x, y})
74+
{
75+
cameraOffset.x = (canvas.width / 2) - (x * cameraScale);
76+
cameraOffset.y = (canvas.height / 2) - (y * cameraScale);
77+
}
78+
79+
function getCameraCenterWorldspace()
80+
{
81+
return toWorldspace(canvas.width / 2, canvas.height / 2);
82+
}
83+
84+
function getNodeScreenRadius(radius)
85+
{
86+
return radius * cameraScaleRoot;
87+
}
88+
89+
function getNodeWorldspaceRadius(radius)
90+
{
91+
return radius / cameraScaleRoot;
92+
}
93+
94+
function getPosition(index)
95+
{
96+
return {x: positions[index * 2], y: positions[index * 2 + 1]};
97+
}
98+
99+
function mixColors(hexStart, hexEnd, factor)
100+
{
101+
return tinycolor.mix(tinycolor(hexStart.toString(16)), tinycolor(hexEnd.toString(16)), factor).toHexNumber()
102+
}
103+
104+
function darkenColor(hexColor, factor)
105+
{
106+
return tinycolor(hexColor.toString(16)).darken(factor).toHexNumber();
107+
}
108+
109+
function lightenColor(hexColor, factor)
110+
{
111+
return tinycolor(hexColor.toString(16)).lighten(factor).toHexNumber();
112+
}
113+
114+
function invertColor(hex, bw)
115+
{
116+
hex = hex.toString(16); // force conversion
117+
118+
if (hex.indexOf('#') === 0) {
119+
hex = hex.slice(1);
120+
}
121+
// convert 3-digit hex to 6-digits.
122+
if (hex.length === 3) {
123+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
124+
}
125+
if (hex.length !== 6) {
126+
throw new Error('Invalid HEX color.');
127+
}
128+
var r = parseInt(hex.slice(0, 2), 16),
129+
g = parseInt(hex.slice(2, 4), 16),
130+
b = parseInt(hex.slice(4, 6), 16);
131+
if (bw) {
132+
// https://stackoverflow.com/a/3943023/112731
133+
return (r * 0.299 + g * 0.587 + b * 0.114) > 186
134+
? '#000000'
135+
: '#FFFFFF';
136+
}
137+
// invert color components
138+
r = (255 - r).toString(16);
139+
g = (255 - g).toString(16);
140+
b = (255 - b).toString(16);
141+
// pad each with zeros and return
142+
return "#" + padZero(r) + padZero(g) + padZero(b);
143+
}
144+
145+
let hoverFade = 0;
146+
let hoverFadeSpeed = 0.2;
147+
148+
function draw()
149+
{
150+
graphics.clear();
151+
152+
let topLines = [];
153+
if (updateAttached)
154+
{
155+
attachedToGrabbed = [];
156+
// hoverFade = 0;
157+
}
158+
159+
if (hoveredNode != -1 || grabbedNode != -1)
160+
{
161+
hoverFade = Math.min(1, hoverFade + hoverFadeSpeed);
162+
}
163+
else
164+
{
165+
hoverFade = Math.max(0, hoverFade - hoverFadeSpeed);
166+
}
167+
168+
graphics.lineStyle(1, mixColors(colors.link, colors.background, hoverFade * 50), 0.7);
169+
170+
for (let i = 0; i < linkCount; i++)
171+
{
172+
let target = linkTargets[i];
173+
let source = linkSources[i];
174+
175+
if (hoveredNode == source || hoveredNode == target || ((lastHoveredNode == source || lastHoveredNode == target) && hoverFade != 0))
176+
{
177+
if (updateAttached && hoveredNode == source)
178+
attachedToGrabbed.push(target);
179+
180+
else if (updateAttached && hoveredNode == target)
181+
attachedToGrabbed.push(source);
182+
183+
topLines.push(i);
184+
}
185+
186+
let startWorld = getPosition(source);
187+
let endWorld = getPosition(target);
188+
189+
let start = vecToScreenSpace(startWorld);
190+
let end = vecToScreenSpace(endWorld);
191+
192+
let dist = Math.sqrt(Math.pow(startWorld.x - endWorld.x, 2) + Math.pow(startWorld.y - endWorld.y, 2));
193+
194+
if (dist < (radii[source] + radii[target]) * edgePruning)
195+
{
196+
graphics.moveTo(start.x, start.y);
197+
graphics.lineTo(end.x, end.y);
198+
}
199+
}
200+
201+
let opacity = 1 - (hoverFade * 0.5);
202+
graphics.beginFill(mixColors(colors.node, colors.background, hoverFade * 50), opacity);
203+
graphics.lineStyle(0, 0xffffff);
204+
for (let i = 0; i < nodeCount; i++)
205+
{
206+
if (hoveredNode == i || (lastHoveredNode == i && hoverFade != 0) || (hoveredNode != -1 && attachedToGrabbed.includes(i))) continue;
207+
208+
let pos = vecToScreenSpace(getPosition(i));
209+
210+
graphics.drawCircle(pos.x, pos.y, getNodeScreenRadius(radii[i]));
211+
}
212+
213+
graphics.endFill();
214+
215+
216+
opacity = hoverFade * 0.7;
217+
graphics.lineStyle(1, mixColors(mixColors(colors.link, colors.accent, hoverFade * 100), colors.background, 20), opacity);
218+
219+
for (let i = 0; i < topLines.length; i++)
220+
{
221+
let target = linkTargets[topLines[i]];
222+
let source = linkSources[topLines[i]];
223+
224+
// draw lines on top when hovered
225+
let start = vecToScreenSpace(getPosition(source));
226+
let end = vecToScreenSpace(getPosition(target));
227+
228+
229+
graphics.moveTo(start.x, start.y);
230+
graphics.lineTo(end.x, end.y);
231+
}
232+
233+
if(hoveredNode != -1 || (lastHoveredNode != -1 && hoverFade != 0))
234+
{
235+
graphics.beginFill(mixColors(colors.node, colors.accent, hoverFade * 20), 0.9);
236+
graphics.lineStyle(0, 0xffffff);
237+
for (let i = 0; i < attachedToGrabbed.length; i++)
238+
{
239+
let point = attachedToGrabbed[i];
240+
241+
let pos = vecToScreenSpace(getPosition(point));
242+
243+
graphics.drawCircle(pos.x, pos.y, getNodeScreenRadius(radii[point]));
244+
}
245+
graphics.endFill();
246+
247+
let index = hoveredNode != -1 ? hoveredNode : lastHoveredNode;
248+
249+
let pos = vecToScreenSpace(getPosition(index));
250+
graphics.beginFill(mixColors(colors.node, colors.accent, hoverFade * 100), 1);
251+
graphics.lineStyle(hoverFade, mixColors(invertColor(colors.background, true), colors.accent, 50));
252+
graphics.drawCircle(pos.x, pos.y, getNodeScreenRadius(radii[index]));
253+
graphics.endFill();
254+
255+
labelText.text = labels[index];
256+
let nodePos = vecToScreenSpace(getPosition(index));
257+
labelText.x = nodePos.x - labelText.width/2;
258+
labelText.y = nodePos.y + getNodeScreenRadius(radii[index]) + hoverFade * 5 + 15;
259+
}
260+
261+
updateAttached = false;
262+
263+
if (hoveredNode == -1)
264+
{
265+
labelText.text = "";
266+
}
267+
else
268+
{
269+
270+
}
271+
272+
graphics.lineStyle(2, colors.accent);
273+
// draw the active node
274+
if (activeNode != -1)
275+
{
276+
let pos = vecToScreenSpace(getPosition(activeNode));
277+
graphics.drawCircle(pos.x, pos.y, getNodeScreenRadius(radii[activeNode]) + 4);
278+
}
279+
}
280+
281+
function onMessage(event)
282+
{
283+
if(event.data.type == "draw")
284+
{
285+
positions = new Float32Array(event.data.positions);
286+
draw();
287+
}
288+
else if(event.data.type == "update_camera")
289+
{
290+
cameraOffset = event.data.cameraOffset;
291+
cameraScale = event.data.cameraScale;
292+
cameraScaleRoot = Math.sqrt(cameraScale);
293+
}
294+
else if(event.data.type == "update_interaction")
295+
{
296+
if(hoveredNode != event.data.hoveredNode && event.data.hoveredNode != -1) updateAttached = true;
297+
if(grabbedNode != event.data.grabbedNode && event.data.hoveredNode != -1) updateAttached = true;
298+
299+
if(event.data.hoveredNode == -1) lastHoveredNode = hoveredNode;
300+
else lastHoveredNode = -1;
301+
302+
hoveredNode = event.data.hoveredNode;
303+
grabbedNode = event.data.grabbedNode;
304+
}
305+
else if(event.data.type == "resize")
306+
{
307+
app.renderer.resize(event.data.width, event.data.height);
308+
}
309+
else if(event.data.type == "set_active")
310+
{
311+
activeNode = event.data.active;
312+
}
313+
else if(event.data.type == "update_colors")
314+
{
315+
colors = event.data.colors;
316+
317+
if(labelText)
318+
{
319+
labelText.style.fill = invertColor(colors.background, true);
320+
}
321+
}
322+
else if(event.data.type == "init")
323+
{
324+
// Extract data from message
325+
linkCount = event.data.linkCount;
326+
linkSources = event.data.linkSources;
327+
linkTargets = event.data.linkTargets;
328+
nodeCount = event.data.nodeCount;
329+
radii = event.data.radii;
330+
labels = event.data.labels;
331+
linkLength = event.data.linkLength;
332+
edgePruning = event.data.edgePruning;
333+
334+
app = new PIXI.Application({... event.data.options, antialias: true, resolution: 2, backgroundAlpha: 0, transparent: true});
335+
container = new PIXI.Container();
336+
graphics = new PIXI.Graphics();
337+
app.stage.addChild(container);
338+
container.addChild(graphics);
339+
340+
labelText = new PIXI.Text("", {fontFamily : 'Arial', fontSize: 16, fontWeight: "bold", fill : invertColor(colors.background, true), align : 'center', anchor: 0.5});
341+
app.stage.addChild(labelText);
342+
343+
}
344+
else
345+
{
346+
console.log("Unknown message type sent to graph worker: " + event.data.type);
347+
}
348+
}
349+
}
350+
351+
352+
353+
354+
355+
356+

0 commit comments

Comments
 (0)