1((function () { 2 3 // Javascript has no random choice function.......... 4 function randomChoice(array) { 5 return array[Math.floor(array.length * Math.random())]; 6 } 7 8 // This function register a 'shape' node, which is not really a node, but 9 // a bezier curve attached to it (with some options to animate it) 10 function registerShapeNode() { 11 12 function drawBezierCurve(start, wide, height, middle, curve, center) { 13 14 // Move command 15 var startx = start.x; 16 var starty = start.y; 17 18 if (center) { startx = startx - wide / 2 } 19 20 M = `M ${startx} ${starty}` 21 22 // Curve command 23 var topx = startx + wide * middle; 24 var topy = starty - height; 25 26 var endx = startx + wide; 27 var endy = starty; 28 29 var ldiff = topx - startx; 30 var rdiff = startx + wide - topx; 31 32 // Left anchor point 33 var lanchorx = startx + ldiff * curve.left; 34 var lanchory = starty; 35 36 // Top left anchor point 37 var tlanchorx = topx - ldiff * curve.top; 38 var tlanchory = topy; 39 40 C = `C ${lanchorx} ${lanchory}, ${tlanchorx} ${tlanchory}, ${topx} ${topy}` 41 42 // Top right anchor point 43 var tranchorx = topx + rdiff * curve.top; 44 var tranchory = topy; 45 46 // Right anchor point 47 var ranchorx = endx - rdiff * curve.right; 48 var ranchory = endy; 49 50 S = `C ${tranchorx} ${tranchory}, ${ranchorx} ${ranchory}, ${endx} ${endy}` 51 52 // Finish the shape to the end 53 L = `L ${startx} ${starty}` 54 55 // I've spend more than 3 hours on this function 56 // https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths 57 return `${M} ${C} ${S} ${L}` 58 } 59 60 function generateRandomProperties() { 61 return { 62 base: { wide: 60, height: 40, middle: 0.5, curve: { left: 0.85, top: 0.20, right: 0.85, } }, 63 wide: Math.random() * 40, 64 height: Math.random() * 40, 65 middle: Math.random() * 0.5, 66 curve: { left: 0.3, top: 0.1, right: 0.3 }, 67 animation: randomChoice(['easeCubicInOut', 'easePolyInOut', 'easeQuadInOut']) 68 } 69 } 70 71 G6.registerNode('shape-node', { 72 drawShape: (cfg, group) => { 73 var color = cfg.color ? cfg.color : '#0aa8a7'; 74 var props = generateRandomProperties() 75 var curve = { 76 left: props.base.curve.left + props.curve.left / 2, 77 top: props.base.curve.top - props.curve.top / 2, 78 right: props.base.curve.right + props.curve.right / 2, 79 } 80 81 var path = group.addShape('path', { 82 attrs: { 83 fill: color, 84 stroke: color, 85 cursor: 'pointer', 86 opacity: 0.0, 87 path: drawBezierCurve({ x: 0, y: 0 }, props.base.wide, props.base.height + props.height, props.base.middle + props.middle * 1 / 2, curve, true), 88 }, 89 name: 'path-shape', 90 }); 91 92 var animationDelay = 1000 + Math.random() * 1000; 93 94 // In the beginning shapes are not visible 95 path.animate((ratio) => ({ opacity: 0.4 * ratio }), { repeat: false, duration: animationDelay, easing: props.animation }) 96 97 path.animate((ratio) => { 98 var bratio = Math.sin(ratio * Math.PI); 99 var wide = props.base.wide + props.wide * bratio; 100 var height = props.base.height + props.height * (1 - bratio); 101 var middle = props.base.middle + props.middle * (1 / 2 - bratio); 102 var cleft = props.base.curve.left + props.curve.left * (1 / 2 - bratio); 103 var ctop = props.base.curve.top + props.curve.top * (bratio - 1 / 2); 104 var cright = props.base.curve.right + props.curve.right * (1 / 2 - bratio); 105 var curve = { left: cleft, top: ctop, right: cright }; 106 return { 107 path: drawBezierCurve({ x: 0, y: 0 }, wide, height, middle, curve, true), 108 } 109 }, { repeat: true, duration: 4000 + Math.random() * 1000, delay: animationDelay / 2, easing: props.animation }) 110 111 return path 112 }, 113 setState(name, value, item) { 114 var shape = item.get('keyShape'); 115 if (name === 'hover') { 116 shape.animate((ratio) => ({ opacity: 0.5 + 0.3 * (value ? ratio : (1 - ratio)) }), { repeat: false, duration: 300, easing: 'easeCubic' }); 117 } 118 }, 119 }, 'rect'); 120 } 121 122 // This function register a simple fully transparent node, 123 // that can be used to put labels or add dangling edges 124 function registerInvisibleNode() { 125 var invisibleNodeDefaultSize = 25; 126 G6.registerNode('invisible-node', { 127 options: { labelCfg: { style: { fill: '#0aa8a7' } } }, 128 drawShape: (cfg, group) => { 129 var size = (cfg.size !== undefined) ? cfg.size : invisibleNodeDefaultSize; 130 return group.addShape('rect', { 131 attrs: { 132 x: -size / 2, 133 y: -size / 2, 134 width: size, 135 height: size, 136 fill: 'white', 137 stroke: 'white', 138 opacity: 0.0, 139 },
140 name: 'inode-box' 141 }); 142 }, 143 getAnchorPoints(cfg) { 144 return [[0.5, 0.5], [0.0, 0.5], [0.5, 1.0], [1.0, 0.5], [0.5, 0.0]] 145 }, 146 }, 'rect'); 147 } 148 149 // This function register a simple generic factor node 150 function registerFactorNode() { 151 var factorNodeDefaultFillColor = '#f5f7f7'; 152 var factorNodeDefaultStrokeColor = '#0aa8a7'; 153 var factorNodeDefaultSize = 50; 154 var factorNodeDefaultShadowOffset = 10; 155 var factorNodeDefaultShadowBlur = 50; 156 157 G6.registerNode('factor-node', { 158 options: { labelCfg: { style: { opacity: 0.0, }, } }, 159 drawShape: (cfg, group) => { 160 var size = (cfg.size !== undefined) ? cfg.size : factorNodeDefaultSize; 161 var shape = group.addShape('rect', { 162 attrs: { 163 x: -size / 2, 164 y: -size / 2, 165 width: size, 166 height: size, 167 fill: factorNodeDefaultFillColor, 168 stroke: factorNodeDefaultStrokeColor, 169 radius: 2, 170 lineWidth: 1.5, 171 cursor: 'pointer', 172 opacity: 1.0, 173 shadowColor: '#c2c2c2', 174 }, 175 name: 'gnode-box', 176 }); 177 178 group.addShape('text', { 179 attrs: { 180 y: 0, 181 x: 0, 182 textAlign: 'center', 183 textBaseline: 'middle', 184 lineHeight: 10, 185 text: cfg.label, 186 fill: factorNodeDefaultStrokeColor, 187 fontSize: size / 2.5, 188 fontWeight: 'bold' 189 }, 190 name: 'gnode-type-text' 191 }); 192 193 return shape 194 }, 195 setState(name, value, item) { 196 var shape = item.get('keyShape'); 197 var size = (shape.cfg.attrs.width !== undefined) ? shape.cfg.attrs.width : factorNodeDefaultSize; 198 199 if (name === 'hover') { 200 shape.animate((r) => { 201 var ratio = value ? r : (1 - r); 202 var newsize = size + (size / 10) * ratio; 203 return { 204 height: newsize, 205 width: newsize, 206 x: -newsize / 2, 207 y: -newsize / 2, 208 shadowOffsetX: factorNodeDefaultShadowOffset * ratio, 209 shadowOffsetY: factorNodeDefaultShadowOffset * ratio, 210 shadowBlur: factorNodeDefaultShadowBlur * ratio, 211 } 212 }, { repeat: false, duration: 300, easing: 'easeCubic' }); 213 } 214 }, 215 getAnchorPoints(cfg) { 216 return [[0.5, 0.5], [0.0, 0.5], [0.5, 1.0], [1.0, 0.5], [0.5, 0.0]] 217 }, 218 }, 'rect'); 219 } 220 221 // This function register a simple equality factor node 222 function registerEqualityNode() { 223 var equalityNodeDefaultFillColor = '#ffffff'; 224 var equalityNodeDefaultSize = 20; 225 var equalityNodeDefaultStrokeColor = '#0aa8a7'; 226 var equalityNodeDefaultLabelStrokeColor = '#0aa8a7'; 227 G6.registerNode('equality-node', { 228 drawShape: (cfg, group) => { 229 var shape = group.addShape('rect', { 230 attrs: { 231 x: -equalityNodeDefaultSize / 2, 232 y: -equalityNodeDefaultSize / 2, 233 width: equalityNodeDefaultSize, 234 height: equalityNodeDefaultSize, 235 fill: equalityNodeDefaultFillColor, 236 stroke: equalityNodeDefaultStrokeColor, 237 radius: 3, 238 lineWidth: 1.5, 239 cursor: 'pointer', 240 opacity: 0.7 241 }, 242 name: 'gnode-box', 243 }); 244 245 group.addShape('text', { 246 attrs: { 247 y: 0, 248 x: 0, 249 textAlign: 'center', 250 textBaseline: 'middle', 251 lineHeight: 10, 252 text: "=",
253 fill: equalityNodeDefaultLabelStrokeColor, 254 fontSize: equalityNodeDefaultSize / 2.5, 255 fontWeight: 'bold' 256 }, 257 name: 'gnode-type-text' 258 }); 259 260 return shape 261 }, 262 setState(name, value, item) { 263 var shape = item.get('keyShape'); 264 if (name === 'hover') { 265 shape.animate((r) => { 266 var ratio = value ? r : (1 - r); 267 var newsize = equalityNodeDefaultSize + (equalityNodeDefaultSize / 10) * ratio; 268 return { height: newsize, width: newsize, x: -newsize / 2, y: -newsize / 2 } 269 }, { repeat: false, duration: 300, easing: 'easeCubic' }); 270 } 271 }, 272 getAnchorPoints(cfg) { 273 return [[0.5, 0.5], [0.0, 0.5], [0.5, 1.0], [1.0, 0.5], [0.5, 0.0]] 274 }, 275 }, 'rect'); 276 } 277 278 function registerFactorEdge() { 279 var factorEdgeDefaultStrokeColor = '#0aa8a7'; 280 var animationCircleFillColor = '#edf6f5'; 281 var animationCircleStrokeColor = '#0aa8a7'; 282 var animationCircleStrokeColors = ['#17a2b8', '#fd7e14', '#dc3545', '#6f42c1', '#007bff', '#28a745'] 283 G6.registerEdge('factor-edge', { 284 options: { style: { stroke: factorEdgeDefaultStrokeColor, opacity: 0.7, lineWidth: 1.2 } }, 285 afterDraw(cfg, group) { 286 var shape = group.get('children')[0]; 287 var startPoint = shape.getPoint(0); 288 var stroke = animationCircleStrokeColor; // randomChoice(animationCircleStrokeColors); 289 var circle = group.addShape('circle', { 290 attrs: { 291 x: startPoint.x, 292 y: startPoint.y, 293 fill: animationCircleFillColor, 294 stroke: stroke, 295 lineWidth: 1.5, 296 opacity: 0.7, 297 r: 3, 298 }, 299 name: 'circle-shape', 300 }); 301 302 circle.animate((ratio) => { 303 var tmpPoint = shape.getPoint(ratio); 304 return { x: tmpPoint.x, y: tmpPoint.y, opacity: Math.sin(ratio * Math.PI), r: Math.sin(ratio * Math.PI) * 3 }; 305 }, { repeat: true, duration: (500 + 1000 * Math.random()), }); 306 }, 307 }, 'line'); 308 } 309 310 // Register custom nodes and edges 311 registerShapeNode(); 312 registerInvisibleNode(); 313 registerFactorNode(); 314 registerEqualityNode(); 315 registerFactorEdge(); 316 317 var data = { 318 nodes: [ 319 // Top shape nodes 320 { id: 'shape10', x: -110, y: 80, type: 'shape-node', color: '#17a2b8' }, 321 // { id: 'shape11', x: -100, y: 70, type: 'invisible-node', label: 'x_t' }, 322 { id: 'shape12', x: -90, y: 80, type: 'shape-node', color: '#fd7e14' }, 323 324 { id: 'shape20', x: 90, y: 80, type: 'shape-node', color: '#dc3545' }, 325 // { id: 'shape21', x: 100, y: 70, type: 'invisible-node', label: 'x_t' }, 326 { id: 'shape22', x: 110, y: 80, type: 'shape-node', color: '#17a2b8' }, 327 328 { id: 'shape30', x: 290, y: 80, type: 'shape-node', color: '#6f42c1' }, 329 // { id: 'shape31', x: 300, y: 70, type: 'invisible-node', label: 'x_t' }, 330 { id: 'shape32', x: 310, y: 80, type: 'shape-node', color: '#007bff' }, 331 332 { id: 'shape40', x: 490, y: 80, type: 'shape-node', color: '#28a745' }, 333 // { id: 'shape41', x: 500, y: 70, type: 'invisible-node', label: 'x_t' }, 334 { id: 'shape42', x: 510, y: 80, type: 'shape-node', color: '#dc3545' }, 335 336 // Bottom shape nodes 337 { id: 'shape50', x: -30, y: 270, type: 'shape-node', color: '#28a745' }, 338 { id: 'shape51', x: 170, y: 270, type: 'shape-node', color: '#6f42c1' }, 339 { id: 'shape52', x: 370, y: 270, type: 'shape-node', color: '#dc3545' }, 340 { id: 'shape53', x: 570, y: 270, type: 'shape-node', color: '#007bff' }, 341 342 // Top layer 343 { id: 'z-e00', x: -1000, y: 100, type: 'invisible-node' }, 344 { id: 'z-e01', x: 1400, y: 100, type: 'invisible-node' }, 345 346 { id: 'z-g0', x: -200, y: 100, type: 'factor-node', label: 'ð©' }, 347 { id: 'z-g0-i', x: -200, y: 0, type: 'invisible-node' }, 348 349 { id: 'z-g1', x: 0, y: 100, type: 'factor-node', label: 'ð©' }, 350 { id: 'z-g1-i', x: 0, y: 0, type: 'invisible-node' }, 351 352 { id: 'z-g2', x: 200, y: 100, type: 'factor-node', label: 'ð©' }, 353 { id: 'z-g2-i', x: 200, y: 0, type: 'invisible-node' }, 354 355 { id: 'z-g3', x: 400, y: 100, type: 'factor-node', label: 'ð©' }, 356 { id: 'z-g3-i', x: 400, y: 0, type: 'invisible-node' }, 357 358 { id: 'z-g4', x: 600, y: 100, type: 'factor-node', label: 'ð©' }, 359 { id: 'z-g4-i', x: 600, y: 0, type: 'invisible-node' }, 360 361 { id: 'z-e0', x: -100, y: 100, type: 'equality-node' }, 362 { id: 'z-e1', x: 100, y: 100, type: 'equality-node' }, 363 { id: 'z-e2', x: 300, y: 100, type: 'equality-node' }, 364 { id: 'z-e3', x: 500, y: 100, type: 'equality-node' }, 365 366 // Multiplication layer 367 { id: 'm-e00', x: -1000, y: 160, type: 'invisible-node' }, 368 { id: 'm-e01', x: 1400, y: 160, type: 'invisible-node' }, 369 370 { id: 'm-e0', x: -200, y: 160, type: 'equality-node' }, 371 { id: 'm-e1', x: 30, y: 160, type: 'equality-node' }, 372 { id: 'm-e2', x: 230, y: 160, type: 'equality-node' }, 373 { id: 'm-e3', x: 430, y: 160, type: 'equality-node' }, 374 { id: 'm-e4', x: 630, y: 160, type: 'equality-node' }, 375 376 { id: 'm-g00', x: -1000, y: 290, type: 'invisible-node' }, 377 { id: 'm-g01', x: 1400, y: 290, type: 'invisible-node' }, 378 { id: 'm-g0', x: -200, y: 290, type: 'factor-node', label: 'â', size: 30 }, 379 { id: 'm-g1', x: 30, y: 290, type: 'factor-node', label: 'â', size: 30 }, 380 { id: 'm-g2', x: 230, y: 290, type: 'factor-node', label: 'â', size: 30 }, 381 { id: 'm-g3', x: 430, y: 290, type: 'factor-node', label: 'â', size: 30 }, 382 { id: 'm-g4', x: 630, y: 290, type: 'factor-node', label: 'â', size: 30 }, 383 384 // Middle layer 385 { id: 'x-g0', x: -100, y: 225, type: 'factor-node', label: 'f', size: 30 }, 386 { id: 'x-g1', x: 100, y: 225, type: 'factor-node', label: 'f', size: 30 }, 387 { id: 'x-g2', x: 300, y: 225, type: 'factor-node', label: 'f', size: 30 }, 388 { id: 'x-g3', x: 500, y: 225, type: 'factor-node', label: 'f', size: 30 }, 389 390 { id: 's-g0', x: -100, y: 290, type: 'factor-node', label: 'ð©' }, 391 { id: 's-g1', x: 100, y: 290, type: 'factor-node', label: 'ð©' }, 392 { id: 's-g2', x: 300, y: 290, type: 'factor-node', label: 'ð©' }, 393 { id: 's-g3', x: 500, y: 290, type: 'factor-node', label: 'ð©' }, 394 395 { id: 's-e0', x: -30, y: 290, type: 'equality-node' }, 396 { id: 's-e1', x: 170, y: 290, type: 'equality-node' }, 397 { id: 's-e2', x: 370, y: 290, type: 'equality-node' }, 398 { id: 's-e3', x: 570, y: 290, type: 'equality-node' }, 399 400 // Bottom layer 401 { id: 'b-i0', x: -30, y: 390, type: 'invisible-node' }, 402 { id: 'b-i1', x: 170, y: 390, type: 'invisible-node' }, 403 { id: 'b-i2', x: 370, y: 390, type: 'invisible-node' }, 404 { id: 'b-i3', x: 570, y: 390, type: 'invisible-node' }, 405 406 407 ], 408 edges: [ 409 410 411 // Top layer 412 { source: 'z-e00', target: 'z-g0', type: 'factor-edge' }, 413 { source: 'z-g4', target: 'z-e01', type: 'factor-edge' }, 414 { source: 'z-g0-i', target: 'z-g0', type: 'factor-edge' }, 415 { source: 'z-g0', target: 'z-e0', type: 'factor-edge' }, 416 { source: 'z-e0', target: 'z-g1', type: 'factor-edge' }, 417 { source: 'z-g1-i', target: 'z-g1', type: 'factor-edge' }, 418 { source: 'z-g1', target: 'z-e1', type: 'factor-edge' }, 419 { source: 'z-e1', target: 'z-g2', type: 'factor-edge' }, 420 { source: 'z-g2-i', target: 'z-g2', type: 'factor-edge' }, 421 { source: 'z-g2', target: 'z-e2', type: 'factor-edge' }, 422 { source: 'z-e2', target: 'z-g3', type: 'factor-edge' }, 423 { source: 'z-g3-i', target: 'z-g3', type: 'factor-edge' }, 424 { source: 'z-g3', target: 'z-e3', type: 'factor-edge' }, 425 { source: 'z-e3', target: 'z-g4', type: 'factor-edge' }, 426 { source: 'z-g4-i', target: 'z-g4', type: 'factor-edge' }, 427 428 // Multiplication layer 429 { source: 'm-e00', target: 'm-e0', type: 'factor-edge' }, 430 { source: 'm-e4', target: 'm-e01', type: 'factor-edge' }, 431 { source: 'm-e0', target: 'm-e1', type: 'factor-edge' }, 432 { source: 'm-e1', target: 'm-e2', type: 'factor-edge' }, 433 { source: 'm-e2', target: 'm-e3', type: 'factor-edge' }, 434 { source: 'm-e3', target: 'm-e4', type: 'factor-edge' },
435 { source: 'm-e0', target: 'm-g0', type: 'factor-edge' }, 436 { source: 'm-e1', target: 'm-g1', type: 'factor-edge' }, 437 { source: 'm-e2', target: 'm-g2', type: 'factor-edge' }, 438 { source: 'm-e3', target: 'm-g3', type: 'factor-edge' }, 439 { source: 'm-e4', target: 'm-g4', type: 'factor-edge' }, 440 { source: 'm-g00', target: 'm-g0', type: 'factor-edge' }, 441 { source: 'm-g4', target: 'm-g01', type: 'factor-edge' }, 442 443 { source: 'm-g0', target: 's-g0', type: 'factor-edge' }, 444 { source: 's-g0', target: 's-e0', type: 'factor-edge' }, 445 { source: 's-e0', target: 'm-g1', type: 'factor-edge' }, 446 447 { source: 'm-g1', target: 's-g1', type: 'factor-edge' }, 448 { source: 's-g1', target: 's-e1', type: 'factor-edge' }, 449 { source: 's-e1', target: 'm-g2', type: 'factor-edge' }, 450 451 { source: 'm-g2', target: 's-g2', type: 'factor-edge' }, 452 { source: 's-g2', target: 's-e2', type: 'factor-edge' }, 453 { source: 's-e2', target: 'm-g3', type: 'factor-edge' }, 454 455 { source: 'm-g3', target: 's-g3', type: 'factor-edge' }, 456 { source: 's-g3', target: 's-e3', type: 'factor-edge' }, 457 { source: 's-e3', target: 'm-g4', type: 'factor-edge' }, 458 459 460 // Middle layer 461 { source: 'z-e0', target: 'x-g0', type: 'factor-edge' }, 462 { source: 'z-e1', target: 'x-g1', type: 'factor-edge' }, 463 { source: 'z-e2', target: 'x-g2', type: 'factor-edge' }, 464 { source: 'z-e3', target: 'x-g3', type: 'factor-edge' }, 465 466 { source: 'x-g0', target: 's-g0', type: 'factor-edge' }, 467 { source: 'x-g1', target: 's-g1', type: 'factor-edge' }, 468 { source: 'x-g2', target: 's-g2', type: 'factor-edge' }, 469 { source: 'x-g3', target: 's-g3', type: 'factor-edge' }, 470 471 // Bottom layer 472 { source: 's-e0', target: 'b-i0', type: 'factor-edge' }, 473 { source: 's-e1', target: 'b-i1', type: 'factor-edge' }, 474 { source: 's-e2', target: 'b-i2', type: 'factor-edge' }, 475 { source: 's-e3', target: 'b-i3', type: 'factor-edge' }, 476 ], 477 }; 478 479 var graph = new G6.Graph({ container: 'landing-graph', fitCenter: true }); 480 481 window.addEventListener('resize', () => { 482 graph.changeSize(window.innerWidth, 600) 483 graph.fitCenter(); 484 // On resize we zoom without animation, otherwise it looks weird 485 graph.zoom(1.25, { x: window.innerWidth / 2, y: 300 }); 486 }) 487 488 graph.on('node:mouseenter', (e) => graph.setItemState(e.item, 'hover', true)); 489 graph.on('node:mouseleave', (e) => graph.setItemState(e.item, 'hover', false)); 490 491 graph.data(data); 492 graph.render(); 493 494 // Fade out the placeholder after graph is rendered 495 const placeholder = document.getElementById('landing-graph-placeholder'); 496 if (placeholder) { 497 placeholder.style.transition = 'opacity 1s ease'; 498 placeholder.style.opacity = '0'; 499 } 500 501 // Fade in the graph after rendering 502 const graphElement = document.getElementById('landing-graph'); 503 if (graphElement) { 504 graphElement.style.transition = 'opacity 1s ease'; 505 graphElement.style.opacity = '1'; 506 } 507 508 window.setTimeout(() => { 509 graph.zoom(1.5, { x: window.innerWidth / 2, y: 300 }, true, { duration: 2000, easing: 'easeCubic' }); 510 }, 100) 511})())
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.