github.com/outbrain/consul@v1.4.5/website/source/assets/javascripts/animations.js (about) 1 document.addEventListener('turbolinks:load', initializeAnimations) 2 3 function initializeAnimations() { 4 var qs = document.querySelector.bind(document) 5 var qsa = document.querySelectorAll.bind(document) 6 7 // 8 // home page 9 // 10 11 var $indexDynamic = qs('#index-dynamic-animation') 12 if ($indexDynamic) { 13 var initiated = false 14 var observer = new IntersectionObserver( 15 function(entries) { 16 if (!initiated && entries[0].isIntersecting) { 17 $indexDynamic.classList.add('active') 18 var lines = qsa( 19 '#lines-origin-aws > *, #lines-origin-azure > *, #lines-origin-gcp > *' 20 ) 21 setTimeout(function() { 22 timer = setInterval(function() { 23 lines[parseInt(Math.random() * lines.length)].classList.toggle( 24 'off' 25 ) 26 }, 800) 27 }, 3000) 28 initiated = true 29 } 30 }, 31 { threshold: 0.5 } 32 ) 33 observer.observe($indexDynamic) 34 } 35 36 // 37 // configuration page 38 // 39 40 var $configChallenge = qs('#configuration-challenge-animation') 41 var $configSolution = qs('#configuration-solution-animation') 42 43 if ($configChallenge) { 44 // challenge animation 45 46 var configChallengeTimeline = new TimelineLite({ 47 onComplete: function() { 48 configChallengeTimeline.restart() 49 configSolutionTimeline.restart() 50 } 51 }) 52 53 var line1 = qs('#c-line-1') 54 var line2 = qs('#c-line-2') 55 var line3 = qs('#c-line-3') 56 var line4 = qs('#c-line-4') 57 var line5 = qs('#c-line-5') 58 var line6 = qs('#c-line-6') 59 var line7 = qs('#c-line-7') 60 var line8 = qs('#c-line-8') 61 var box1 = qs('#c-box-1') 62 var box2 = qs('#c-box-2') 63 var box3 = qs('#c-box-3') 64 var box4 = qs('#c-box-4') 65 var box5 = qs('#c-box-5') 66 var box6 = qs('#c-box-6') 67 var box7 = qs('#c-box-7') 68 var box8 = qs('#c-box-8') 69 var progressBar = qs('#c-loading-bar > rect:last-child') 70 var cog = qs('#c-configuration-server > g > path') 71 72 configChallengeTimeline 73 .to(box1, 1, {}) 74 .staggerTo( 75 [line1, line2, line3, line4, line5, line6, line7, line8], 76 1.5, 77 { css: { strokeDashoffset: 0 } }, 78 0.3, 79 'start' 80 ) 81 .staggerTo( 82 [box1, box2, box3, box4, box5, box6, box7, box8], 83 0.3, 84 { opacity: 1 }, 85 0.3, 86 '-=2.5' 87 ) 88 .fromTo( 89 progressBar, 90 3.5, 91 { attr: { width: 0 } }, 92 { attr: { width: 40 } }, 93 'start' 94 ) 95 .to( 96 cog, 97 3.5, 98 { rotation: 360, svgOrigin: '136px 127px', ease: Power1.easeOut }, 99 'start' 100 ) 101 .call(function () { 102 configSolutionTimeline.resume(configSolutionTimeline.time()) 103 }) 104 .to(line1, 2, {}) 105 .to( 106 [line1, line2, line3, line4, line5, line6, line7, line8, progressBar], 107 0.5, 108 { opacity: 0 }, 109 'reset' 110 ) 111 .to( 112 [box1, box2, box3, box4, box5, box6, box7, box8], 113 0.5, 114 { opacity: 0.5 }, 115 'reset' 116 ) 117 .pause() 118 119 // solution animation 120 121 var configSolutionTimeline = new TimelineLite() 122 123 var lines = qsa( 124 '#s-line-1, #s-line-2, #s-line-3, #s-line-4, #s-line-5, #s-line-6, #s-line-7, #s-line-8' 125 ) 126 var dots = qs('#s-dots') 127 var boxes = qsa( 128 '#s-service-box-1, #s-service-box-2, #s-service-box-3, #s-service-box-4, #s-service-box-5, #s-service-box-6, #s-service-box-7, #s-service-box-8' 129 ) 130 var progress = qs('#s-progress-indicator') 131 132 configSolutionTimeline 133 .to(boxes, 1, {}) 134 .to(lines, 1, { css: { strokeDashoffset: 0 } }, 'start') 135 .to(boxes, 0.5, { opacity: 1 }, '-=0.4') 136 .fromTo( 137 progress, 138 1, 139 { attr: { width: 0 } }, 140 { attr: { width: 40 } }, 141 'start' 142 ) 143 .to(dots, 0.25, { opacity: 1 }, '-=0.5') 144 .addPause() 145 .to(progress, 2, {}) 146 .to(lines, 0.5, { opacity: 0 }, 'reset') 147 .to(boxes, 0.5, { opacity: 0.5 }, 'reset') 148 .to(progress, 0.5, { opacity: 0 }, 'reset') 149 .to(dots, 0.5, { opacity: 0 }, 'reset') 150 .pause() 151 152 // kick off 153 $configChallenge.classList.add('active') 154 $configSolution.classList.add('active') 155 configChallengeTimeline.play() 156 configSolutionTimeline.play() 157 } 158 159 // 160 // discovery page 161 // 162 163 var $discoveryChallenge = qs('#discovery-challenge-animation') 164 var $discoverySolution = qs('#discovery-solution-animation') 165 166 if ($discoveryChallenge) { 167 // challenge animation 168 var discoveryChallengeTimeline = new TimelineLite({ 169 onComplete: function() { 170 discoveryChallengeTimeline.restart() 171 discoverySolutionTimeline.restart() 172 } 173 }) 174 175 // First, we get each of the elements we need to animate 176 var box = qs('#c-active-box') 177 var leftPlacement = qs('#c-box-left-placement') 178 var rightPlacement = qs('#c-box-right-placement') 179 var leftConnectionLines = qsa( 180 '#c-line-top-left > *, #c-line-bottom-left > *, #c-line-horizontal-left > *, #c-line-vertical-down > *' 181 ) 182 var rightConnectionLines = qsa( 183 '#c-line-top-right > *, #c-line-bottom-right > *, #c-line-horizontal-left > *, #c-line-vertical-down > *, #c-line-horizontal-right > *' 184 ) 185 var leftConnectionTop = qs('#c-line-top-left') 186 var leftConnectionBottom = qs('#c-line-bottom-left') 187 var rightHorizontalConnection = qs('#c-line-horizontal-right') 188 var rightConnectionTop = qs('#c-line-top-right') 189 var rightConnectionBottom = qs('#c-line-bottom-right') 190 var rightConnectionLinesStroke = qsa( 191 '#c-line-top-right > *, #c-line-bottom-right > *, #c-line-horizontal-right > *, #c-line-horizontal-left > *, #c-line-vertical-down > *' 192 ) 193 var leftConnectionLinesStroke = qsa( 194 '#c-line-top-left > *, #c-line-bottom-left > *, #c-line-horizontal-left > *, #c-line-vertical-down > *' 195 ) 196 var brokenLinkLeft = qs('#c-broken-link-left') 197 var brokenLinkRight = qs('#c-broken-link-right') 198 var computer = qs('#c-computer') 199 var codeLines = qs('#c-computer > g') 200 var toLoadBalancerDown = qsa( 201 '#c-computer-to-load-balancers #c-arrow-down, #c-computer-to-load-balancers #c-circle' 202 ) 203 var toLoadBalancerRight = qs('#c-computer-to-load-balancers #c-arrow-right') 204 var toLoadBalancerLeft = qs('#c-computer-to-load-balancers #c-arrow-left') 205 var toLoadBalancerRest = qs('#c-computer-to-load-balancers #c-edit-box') 206 var progressBars = qsa( 207 '#c-load-balancer-left > #c-progress-bar, #c-load-balancer-right > #c-progress-bar-2, #c-load-balancer-middle > #c-progress-bar-3' 208 ) 209 var progressBarsBars = qsa( 210 '#c-load-balancer-left > #c-progress-bar > *:last-child, #c-load-balancer-right > #c-progress-bar-2 > *:last-child, #c-load-balancer-middle > #c-progress-bar-3 > *:last-child' 211 ) 212 var farLeftBoxBorder = qs('#c-box-far-left > path') 213 214 // Then, we run each step of the animation using GSAP's TimelineLine, a 215 // fantastic way to set up a series of complex movements 216 discoveryChallengeTimeline 217 .to(box, 1, {}) 218 // box moves to new position 219 .to(box, 1, { css: { transform: 'translate(96px, 48px)' } }) 220 .to(leftPlacement, 0.5, { css: { opacity: 1 } }, '-=1') 221 .to(rightPlacement, 0.25, { css: { opacity: 0 } }, '-=0.25') 222 // connection lines turn black 223 .to(leftConnectionLines, 0.5, { css: { stroke: '#000' } }) 224 .to(farLeftBoxBorder, 0.5, { css: { fill: '#000' } }, '-=0.5') 225 // broken link appears 226 .to( 227 leftConnectionTop, 228 0.1, 229 { 230 css: { strokeDashoffset: 6 }, 231 ease: Linear.easeNone 232 }, 233 '-=0.3' 234 ) 235 .to(brokenLinkLeft, 0.2, { css: { opacity: 1 } }, '-=0.15') 236 // computer appears and code is written 237 .to(computer, 0.5, { css: { opacity: 1 } }) 238 .staggerFrom( 239 codeLines, 240 0.4, 241 { 242 css: { transform: 'translate(-64px, 0)', opacity: 0 } 243 }, 244 0.1 245 ) 246 .to(codeLines, 0.3, { 247 css: { transform: 'translate(0, 0)', opacity: 1 } 248 }) 249 // code moves to load balancers 250 .to(toLoadBalancerRest, 0.4, { css: { opacity: 1 } }) 251 .to(toLoadBalancerLeft, 0.2, { css: { opacity: 1 } }, 'loadBalancerArrows') 252 .to(toLoadBalancerRight, 0.2, { css: { opacity: 1 } }, 'loadBalancerArrows') 253 .to(toLoadBalancerDown, 0.2, { css: { opacity: 1 } }, 'loadBalancerArrows') 254 // load balancers progress bars, old broken link fades out 255 .to(progressBars, 0.2, { css: { opacity: 1 } }) 256 .staggerFromTo( 257 progressBarsBars, 258 1.5, 259 { attr: { width: 0 } }, 260 { attr: { width: 40 } }, 261 0.3 262 ) 263 .to( 264 [] 265 .concat(toLoadBalancerRest) 266 .concat([].slice.call(toLoadBalancerDown)) 267 .concat([ 268 toLoadBalancerRight, 269 toLoadBalancerLeft, 270 brokenLinkLeft, 271 leftConnectionTop, 272 leftConnectionBottom 273 ]), 274 0.5, 275 { css: { opacity: 0 } }, 276 '-=0.75' 277 ) 278 .to(computer, 0.5, { css: { opacity: .12 } }, '-=0.75') 279 .to(progressBars, 0.5, { css: { opacity: 0 } }) 280 // new connection is drawn 281 .to(rightHorizontalConnection, 0.3, { css: { strokeDashoffset: 0 } }) 282 .to(rightConnectionTop, 0.2, { 283 css: { strokeDashoffset: 0 }, 284 ease: Linear.easeNone 285 }) 286 .to(rightConnectionBottom, 0.3, { 287 css: { strokeDashoffset: 0 }, 288 ease: Linear.easeNone 289 }) 290 // connection lines turn blue 291 .to( 292 rightConnectionLinesStroke, 293 0.5, 294 { css: { stroke: '#3969ED' } }, 295 '-=0.3' 296 ) 297 .to(farLeftBoxBorder, 0.5, { css: { fill: '#3969ED' } }, '-=0.5') 298 // wait three seconds 299 .to(box, 3, {}) 300 // box moves back to original position 301 .to(box, 1, { css: { transform: 'translate(0, 0)' } }, 'loop2') 302 .to(leftPlacement, 0.25, { css: { opacity: 0 } }, '-=0.25') 303 .to(rightPlacement, 0.5, { css: { opacity: 1 } }, '-=0.5') 304 // connection lines turn black 305 .to(rightConnectionLines, 0.5, { css: { stroke: '#000' } }) 306 .to(farLeftBoxBorder, 0.5, { css: { fill: '#000' } }, '-=0.5') 307 // broken link appears 308 .to( 309 rightConnectionTop, 310 0.1, 311 { 312 css: { strokeDashoffset: 6 }, 313 ease: Linear.easeNone 314 }, 315 '-=0.3' 316 ) 317 .to(brokenLinkRight, 0.2, { css: { opacity: 1 } }, '-=0.15') 318 // computer appears and code is written 319 .from(codeLines, 0.1, { css: { opacity: 0 } }) 320 .to(computer, 0.5, { css: { opacity: 1 } }, '-=0.1') 321 .staggerFromTo( 322 codeLines, 323 0.4, 324 { css: { transform: 'translate(-64px, 0)', opacity: 0 } }, 325 { css: { transform: 'translate(0, 0)', opacity: 1 } }, 326 0.1 327 ) 328 // code moves to load balancers 329 .to(toLoadBalancerRest, 0.4, { css: { opacity: 1 } }) 330 .to(toLoadBalancerLeft, 0.2, { css: { opacity: 1 } }, 'loadBalancerArrows2') 331 .to( 332 toLoadBalancerRight, 333 0.2, 334 { css: { opacity: 1 } }, 335 'loadBalancerArrows2' 336 ) 337 .to(toLoadBalancerDown, 0.2, { css: { opacity: 1 } }, 'loadBalancerArrows2') 338 // load balancers progress bars, old broken link fades out 339 .to(progressBarsBars, 0.1, { attr: { width: 0 } }) 340 .to(progressBars, 0.2, { attr: { opacity: 1 } }) 341 .staggerFromTo( 342 progressBarsBars, 343 1.5, 344 { css: { width: 0 } }, 345 { css: { width: 40 } }, 346 0.3 347 ) 348 .to( 349 [] 350 .concat(toLoadBalancerRest) 351 .concat([].slice.call(toLoadBalancerDown)) 352 .concat([ 353 toLoadBalancerRight, 354 toLoadBalancerLeft, 355 brokenLinkRight, 356 rightConnectionTop, 357 rightConnectionBottom, 358 rightHorizontalConnection 359 ]), 360 0.5, 361 { css: { opacity: 0 } }, 362 '-=0.75' 363 ) 364 .to(computer, 0.5, { css: { opacity: .12 } }, '-=0.75') 365 .to(progressBars, 0.5, { css: { opacity: 0 } }) 366 // new connection is drawn 367 .to(leftConnectionTop, 0.01, { css: { strokeDashoffset: 17 } }) 368 .to(leftConnectionBottom, 0.01, { css: { strokeDashoffset: 56 } }) 369 .to([leftConnectionTop, leftConnectionBottom], 0.01, { 370 css: { opacity: 1 } 371 }) 372 .to(leftConnectionTop, 0.2, { 373 css: { strokeDashoffset: 0 }, 374 ease: Linear.easeNone 375 }) 376 .to(leftConnectionBottom, 0.3, { 377 css: { strokeDashoffset: 0 }, 378 ease: Linear.easeNone 379 }) 380 // connection lines turn blue 381 .to(leftConnectionLinesStroke, 0.5, { css: { stroke: '#3969ED' } }, '-=0.3') 382 .to(farLeftBoxBorder, 0.5, { css: { fill: '#3969ED' } }, '-=0.5') 383 .call(function () { 384 discoverySolutionTimeline.resume(discoverySolutionTimeline.time()) 385 }) 386 .to(box, 2, {}) 387 .pause() 388 389 // solution animation 390 var discoverySolutionTimeline = new TimelineLite() 391 392 var inactiveBox = qs('#s-active-service-1') 393 var inactiveBoxStroke = qs('#s-active-service-1 > path') 394 var activeBox = qs('#s-active-service-2') 395 var activeBoxStroke = qs('#s-active-service-2 > path') 396 var leftPlacement = qs('#s-dotted-service-box-2') 397 var rightPlacement = qs('#s-dotted-service-box-3') 398 var leftConnectionLine = qs('#s-connected-line-1') 399 var rightConnectionLine = qs('#s-connected-line-2') 400 var dottedLineLeft = qs('#s-dotted-line-left') 401 var dottedLineRight = qs('#s-dotted-lines-right') 402 var dottedLineRightPrimary = qs('#s-dotted-lines-right > path:nth-child(2)') 403 var dottedLineRightAlt = qs('#s-dotted-lines-right > path:last-child') 404 var syncLeft = qs('#s-dynamic-sync-left') 405 var syncRight = qs('#s-dynamic-sync-right') 406 var syncSpinnerLeft = qs('#s-dynamic-sync-left > path') 407 var syncSpinnerRight = qs('#s-dynamic-sync-right > path') 408 409 discoverySolutionTimeline 410 .to(activeBox, 1, {}) 411 // box moves 412 .to(activeBox, 0.5, { x: 96, y: 48 }) 413 .to(leftPlacement, 0.25, { css: { opacity: 1 } }, '-=0.5') 414 .to(rightPlacement, 0.25, { css: { opacity: 0 } }, '-=0.1') 415 // connection is broken 416 .to(leftConnectionLine, 0.75, { css: { strokeDashoffset: 222 } }, '-=0.5') 417 // box color changes to black 418 .to(activeBoxStroke, 0.25, { css: { fill: '#000' } }, '-=0.4') 419 .to(inactiveBoxStroke, 0.25, { css: { fill: '#000' } }, '-=0.4') 420 // right sync lines appear 421 .to(dottedLineRight, 0.4, { css: { opacity: 1 } }) 422 .to(syncRight, 0.2, { css: { opacity: 1 } }, '-=0.2') 423 .to(syncSpinnerRight, 1, { rotation: 360, svgOrigin: '232px 127px' }) 424 // left sync lines appear 425 .to(dottedLineLeft, 0.4, { css: { opacity: 1 } }, '-=0.6') 426 .to(syncLeft, 0.2, { css: { opacity: 1 } }, '-=0.2') 427 .to(syncSpinnerLeft, 1, { rotation: 360, svgOrigin: '88px 127px' }) 428 // connection is redrawn 429 .to(rightConnectionLine, 0.75, { css: { strokeDashoffset: 0 } }) 430 // right sync lines disappear 431 .to(dottedLineRight, 0.4, { css: { opacity: 0 } }, '-=1.2') 432 .to(syncRight, 0.2, { css: { opacity: 0 } }, '-=1.2') 433 // left sync lines disappear 434 .to(dottedLineLeft, 0.4, { css: { opacity: 0 } }, '-=0.5') 435 .to(syncLeft, 0.2, { css: { opacity: 0 } }, '-=0.5') 436 // box color changes to pink 437 .to(activeBoxStroke, 0.25, { css: { fill: '#ca2171' } }, '-=0.2') 438 .to(inactiveBoxStroke, 0.25, { css: { fill: '#ca2171' } }, '-=0.2') 439 // wait three seconds 440 .to(activeBox, 3, {}) 441 // box moves 442 .to(activeBox, 0.5, { x: 0, y: 0 }) 443 .to(leftPlacement, 0.25, { css: { opacity: 0 } }, '-=0.1') 444 .to(rightPlacement, 0.25, { css: { opacity: 1 } }, '-=0.5') 445 // connection is broken 446 .to(rightConnectionLine, 0.75, { css: { strokeDashoffset: 270 } }, '-=0.5') 447 // box color changes to black 448 .to(activeBoxStroke, 0.25, { css: { fill: '#000' } }, '-=0.4') 449 .to(inactiveBoxStroke, 0.25, { css: { fill: '#000' } }, '-=0.4') 450 // right sync lines appear 451 .to(dottedLineRightAlt, 0.01, { css: { opacity: 1 } }) 452 .to(dottedLineRightPrimary, 0.01, { css: { opacity: 0 } }) 453 .to(dottedLineRight, 0.4, { css: { opacity: 1 } }) 454 .to(syncRight, 0.2, { css: { opacity: 1 } }, '-=0.2') 455 .fromTo( 456 syncSpinnerRight, 457 1, 458 { rotation: 0 }, 459 { rotation: 360, svgOrigin: '232px 127px' } 460 ) 461 // left sync lines appear 462 .to(dottedLineLeft, 0.4, { css: { opacity: 1 } }, '-=0.6') 463 .to(syncLeft, 0.2, { css: { opacity: 1 } }, '-=0.2') 464 .fromTo( 465 syncSpinnerLeft, 466 1, 467 { rotation: 0 }, 468 { rotation: 360, svgOrigin: '88px 127px' } 469 ) 470 // connection is redrawn 471 .to(leftConnectionLine, 0.75, { css: { strokeDashoffset: 0 } }) 472 // right sync lines disappear 473 .to(dottedLineRight, 0.4, { css: { opacity: 0 } }, '-=1.2') 474 .to(syncRight, 0.2, { css: { opacity: 0 } }, '-=1.2') 475 // left sync lines disappear 476 .to(dottedLineLeft, 0.4, { css: { opacity: 0 } }, '-=0.5') 477 .to(syncLeft, 0.2, { css: { opacity: 0 } }, '-=0.5') 478 // box color changes to pink 479 .to(activeBoxStroke, 0.25, { css: { fill: '#ca2171' } }, '-=0.2') 480 .to(inactiveBoxStroke, 0.25, { css: { fill: '#ca2171' } }, '-=0.2') 481 .addPause() 482 // wait three seconds 483 .to(activeBox, 2, {}) 484 .pause() 485 486 // kick it off 487 $discoveryChallenge.classList.add('active') 488 $discoverySolution.classList.add('active') 489 discoveryChallengeTimeline.play() 490 discoverySolutionTimeline.play() 491 } 492 493 // 494 // discovery page 495 // 496 497 var $segmentationChallenge = qs('#segmentation-challenge-animation') 498 var $segmentationSolution = qs('#segmentation-solution-animation') 499 500 if ($segmentationChallenge) { 501 // challenge animation 502 var segmentationChallengeTimeline = new TimelineLite({ 503 onComplete: function() { 504 segmentationChallengeTimeline.restart() 505 segmentationSolutionTimeline.restart() 506 } 507 }) 508 509 var computerUpdatePath = qs('#c-firewall-updates #c-update_path') 510 var computerUpdateBox = qs('#c-firewall-updates #c-edit') 511 var computer = qs('#c-computer') 512 var progressBars = qsa( 513 '#c-progress-indicator, #c-progress-indicator-2, #c-progress-indicator-3' 514 ) 515 var progressBarBars = qsa( 516 '#c-progress-indicator > rect:last-child, #c-progress-indicator-2 > rect:last-child, #c-progress-indicator-3 > rect:last-child' 517 ) 518 var brokenLinks = qsa('#c-broken-link-1, #c-broken-link-2, #c-broken-link-3') 519 var box2 = qs('#c-box-2') 520 var box2Border = qs('#c-box-2 > path') 521 var box4 = qs('#c-box-4') 522 var box4Border = qs('#c-box-4 > path') 523 var box6 = qs('#c-box-6') 524 var box6Border = qs('#c-box-6 > path') 525 var box7 = qs('#c-box-7') 526 var box7Border = qs('#c-box-7 > path') 527 var path1a = qs('#c-path-1 > *:nth-child(2)') 528 var path1b = qs('#c-path-1 > *:nth-child(3)') 529 var path1c = qs('#c-path-1 > *:nth-child(1)') 530 var path2a = qs('#c-path-2 > *:nth-child(1)') 531 var path2b = qs('#c-path-2 > *:nth-child(3)') 532 var path2c = qs('#c-path-2 > *:nth-child(2)') 533 var path3a = qs('#c-path-3 > *:nth-child(2)') 534 var path3b = qs('#c-path-3 > *:nth-child(3)') 535 var path3c = qs('#c-path-3 > *:nth-child(1)') 536 537 segmentationChallengeTimeline 538 .to(box2, 1, {}) 539 // box 4 and 6 appear 540 .to(box4Border, 0.4, { css: { fill: '#000' } }, 'box4-in') 541 .fromTo( 542 box4, 543 0.3, 544 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '291px 41px' }, 545 { scale: 1, rotation: 360, opacity: 1 }, 546 'box4-in' 547 ) 548 .to(box6Border, 0.4, { css: { fill: '#000' } }, '-=0.2') 549 .fromTo( 550 box6, 551 0.3, 552 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '195px 289px' }, 553 { scale: 1, rotation: 360, opacity: 1 }, 554 '-=0.4' 555 ) 556 // wait for a moment 557 .to(box2, 1, {}) 558 // computer appears and sends updates to firewalls 559 .to(computer, 0.5, { opacity: 1 }) 560 .to(computerUpdateBox, 0.3, { opacity: 1 }, '-=0.2') 561 .to(computerUpdatePath, 0.3, { opacity: 1 }, '-=0.2') 562 // firewall progress bars 563 .to(progressBarBars, 0.01, { attr: { width: 0 } }) 564 .to(progressBars, 0.2, { opacity: 1 }) 565 .staggerTo(progressBarBars, 0.6, { attr: { width: 40 } }, 0.2) 566 // connection 1 made 567 .to(path1a, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 568 .to(path1b, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 569 .to(path1c, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 570 // progress bars and firewall update lines fade out 571 .to(progressBars, 0.7, { opacity: 0 }, 'resetComputer1') 572 .to(computerUpdateBox, 0.7, { opacity: 0 }, 'resetComputer1') 573 .to(computerUpdatePath, 0.7, { opacity: 0 }, 'resetComputer1') 574 // connection turns blue 575 .to( 576 [path1a, path1b, path1c], 577 0.5, 578 { css: { stroke: '#3969ED' } }, 579 'resetComputer1' 580 ) 581 .to( 582 [box4Border, box6Border], 583 0.5, 584 { css: { fill: '#3969ED' } }, 585 'resetComputer1' 586 ) 587 // second connection draws 588 .to( 589 path2a, 590 0.3, 591 { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }, 592 '-=0.3' 593 ) 594 .to(path2b, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 595 .to(path2c, 0.2, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 596 // second connection turns blue 597 .to([path2a, path2b, path2c], 0.5, { css: { stroke: '#3969ED' } }, '-=0.1') 598 .to(box7Border, 0.5, { css: { fill: '#3969ED' } }, '-=0.3') 599 // wait a moment 600 .to(box2, 2, {}) 601 // blue elements fade back to gray 602 .to( 603 [path1a, path1b, path1c, path2a, path2b, path2c], 604 0.5, 605 { 606 css: { stroke: '#b5b8c4' } 607 }, 608 'colorReset1' 609 ) 610 .to( 611 [box7Border, box4Border, box6Border], 612 0.5, 613 { css: { fill: '#b5b8c4' } }, 614 'colorReset1' 615 ) 616 // box 2 appears 617 .to(box2Border, 0.4, { css: { fill: '#000' } }, 'colorReset1') 618 .fromTo( 619 box2, 620 0.3, 621 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '195px 42px' }, 622 { scale: 1, rotation: 360, opacity: 1 }, 623 '-=0.4' 624 ) 625 // wait a moment 626 .to(box2, 1, {}) 627 // computer updates firewalls 628 .to(computerUpdateBox, 0.3, { opacity: 1 }, '-=0.2') 629 .to(computerUpdatePath, 0.3, { opacity: 1 }, '-=0.2') 630 // firewall progress bars 631 .to(progressBarBars, 0.01, { width: 0 }) 632 .to(progressBars, 0.2, { opacity: 1 }) 633 .staggerTo(progressBarBars, 0.6, { width: 40 }, 0.2) 634 // third connection made 635 .to(path3a, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 636 .to(path3b, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 637 .to(path3c, 0.3, { css: { strokeDashoffset: 0 }, ease: Linear.easeNone }) 638 // progress bars & computer arrows fade out 639 .to(progressBars, 0.5, { opacity: 0 }, 'computerReset2') 640 .to(computerUpdateBox, 0.5, { opacity: 0 }, 'computerReset2') 641 .to(computerUpdatePath, 0.5, { opacity: 0 }, 'computerReset2') 642 // third connection turns blue 643 .to( 644 [path3a, path3b, path3c], 645 0.5, 646 { css: { stroke: '#3969ED' } }, 647 'computerReset2' 648 ) 649 .to( 650 [box2Border, box7Border], 651 0.5, 652 { css: { fill: '#3969ED' } }, 653 'computerReset2' 654 ) 655 // wait a bit 656 .to(box2, 2, {}) 657 // third connection turns back to gray 658 .to( 659 [path3a, path3b, path3c], 660 0.5, 661 { css: { stroke: '#b5b8c4' } }, 662 'colorReset2' 663 ) 664 .to( 665 [box2Border, box7Border], 666 0.5, 667 { css: { fill: '#b5b8c4' } }, 668 'colorReset2' 669 ) 670 // boxes 2, 4, and 6 disappear 671 .to( 672 [box2, box4, box6], 673 0.6, 674 { scale: 0, rotation: 200, opacity: 0 }, 675 '-=0.4' 676 ) 677 // lines turn red and broken links appear 678 .to( 679 [path1a, path1b, path1c, path2a, path2b, path2c, path3a, path3b, path3c], 680 0.3, 681 { css: { stroke: '#ED4168' } }, 682 '-=0.2' 683 ) 684 .to(brokenLinks, 0.3, { opacity: 1 }, '-=0.3') 685 // wait a moment 686 .to(box2, 1, {}) 687 // code sent to firewalls 688 .to(computerUpdateBox, 0.3, { opacity: 1 }) 689 .to(computerUpdatePath, 0.3, { opacity: 1 }) 690 // firewall progress bars 691 .to(progressBarBars, 0.01, { width: 0 }) 692 .to(progressBars, 0.2, { opacity: 1 }) 693 .staggerTo(progressBarBars, 0.6, { width: 40 }, 0.2) 694 .to(box2, 0.5, {}) 695 // faulty connections removed 696 .to( 697 [ 698 path1a, 699 path1b, 700 path1c, 701 path2a, 702 path2b, 703 path2c, 704 path3a, 705 path3b, 706 path3c 707 ].concat(brokenLinks), 708 0.7, 709 { opacity: 0 } 710 ) 711 // progress bars and connection arrows fade out 712 .to(progressBars, 0.5, { opacity: 0 }, 'computerReset3') 713 .to(computerUpdateBox, 0.5, { opacity: 0 }, 'computerReset3') 714 .to(computerUpdatePath, 0.5, { opacity: 0 }, 'computerReset3') 715 .to(computer, 0.5, { opacity: 0 }, 'computerReset3') 716 .call(function () { 717 segmentationSolutionTimeline.resume(segmentationSolutionTimeline.time()) 718 }) 719 // wait a moment before the loop 720 .to(box2, 1, {}) 721 .pause() 722 723 // solution animation 724 var segmentationSolutionTimeline = new TimelineLite() 725 726 // service boxes 727 var box1 = qs('#s-service-2') 728 var box1Border = qs('#s-service-2 > path') 729 var box1Lock = qs('#s-service-2 #s-secure-indicator-2') 730 var box2 = qs('#s-service-4') 731 var box2Border = qs('#s-service-4 > path') 732 var box2Lock = qs('#s-service-4 #s-secure-indicator-4') 733 var box3 = qs('#s-service-6') 734 var box3Border = qs('#s-service-6 > path') 735 var box3Lock = qs('#s-service-6 #s-secure-indicator-6') 736 737 // connection paths 738 var path1a = qs('#s-connection-path-2') 739 var path1b = qs('#s-connection-path-8') 740 var path2a = qs('#s-connection-path-9') 741 var path2b = qs('#s-connection-path-10') 742 var path3a = qs('#s-connection-path-1') 743 var path3b = qs('#s-connection-path-4') 744 var path3c = qs('#s-connection-path-5') 745 var path3d = qs('#s-connection-path-6') 746 747 // inbound consul updates 748 var inboundPathLower = qs('#s-consul-inbound-paths-lower') 749 var inboundUpdateLower = qs('#s-dynamic-update-inbound-lower') 750 var inboundUpdateLowerSpinner = qs('#s-dynamic-update-inbound-lower > path') 751 var inboundPathUpper = qs('#s-consul-inbound-paths-upper') 752 var inboundUpdateUpper = qs('#s-dynamic-update-inbound-upper') 753 var inboundUpdateUpperSpinner = qs('#s-dynamic-update-inbound-upper > path') 754 755 // outbound consul updates 756 var outboundPathsLower = qsa( 757 '#s-consul-server-connection-lower, #s-consul-outbound-5, #s-consul-outbound-6, #s-consul-outbound-7' 758 ) 759 var outboundUpdateLower = qsa( 760 '#s-dynamic-update-outbound-ower, #s-tls-cert-lower' 761 ) 762 var outboundUpdateLowerSpinner = qs('#s-dynamic-update-outbound-ower > path') 763 var outboundPathsUpper1 = qsa( 764 '#s-consul-server-connection-upper, #s-consul-outbound-3, #s-consul-outbound-4' 765 ) 766 var outboundPathsUpper2 = qsa( 767 '#s-consul-server-connection-upper, #s-consul-outbound-1, #s-soncul-outbound-2' 768 ) 769 var outboundUpdateUpper = qsa( 770 '#s-tls-cert-upper, #s-dynamic-update-outbound-upper' 771 ) 772 var outboundUpdateUpperSpinner = qs('#s-dynamic-update-outbound-upper > path') 773 774 segmentationSolutionTimeline 775 .to(box2, 1, {}) 776 // boxes 2 and 3 appear 777 .fromTo( 778 box2, 779 0.3, 780 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '281px 104px' }, 781 { scale: 1, rotation: 360, opacity: 1 } 782 ) 783 .fromTo( 784 box3, 785 0.3, 786 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '185px 226px' }, 787 { scale: 1, rotation: 360, opacity: 1 }, 788 '-=0.1' 789 ) 790 // wait a moment 791 .to(box1, 0.5, {}) 792 // consul speaks to each box that needs a connection made 793 .to(outboundPathsUpper1, 0.5, { opacity: 1 }) 794 .to(outboundPathsLower, 0.5, { opacity: 1 }, '-=0.3') 795 .to(outboundUpdateUpper, 0.3, { opacity: 1 }, '-=0.3') 796 .to(outboundUpdateLower, 0.3, { opacity: 1 }, '-=0.1') 797 .to( 798 outboundUpdateUpperSpinner, 799 0.7, 800 { 801 rotation: 360, 802 svgOrigin: '44px 99px' 803 }, 804 '-=0.5' 805 ) 806 .to( 807 outboundUpdateLowerSpinner, 808 0.7, 809 { 810 rotation: 360, 811 svgOrigin: '44px 246px' 812 }, 813 '-=0.3' 814 ) 815 // pink borders, locks, connections drawn, consul talk fades 816 .to(box2Lock, 0.3, { opacity: 1 }, 'connections-1') 817 .to(box2Border, 0.3, { fill: '#CA2270' }, 'connections-1') 818 .to(box3Lock, 0.3, { opacity: 1 }, 'connections-1') 819 .to(box3Border, 0.3, { fill: '#CA2270' }, 'connections-1') 820 .to(outboundPathsUpper1, 0.7, { opacity: 0 }, 'connections-1') 821 .to(outboundPathsLower, 0.7, { opacity: 0 }, 'connections-1') 822 .to(outboundUpdateUpper, 0.7, { opacity: 0 }, 'connections-1') 823 .to(outboundUpdateLower, 0.7, { opacity: 0 }, 'connections-1') 824 .to( 825 path1a, 826 0.5, 827 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 828 'connections-1' 829 ) 830 .to( 831 path1b, 832 0.5, 833 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 834 'connections-1' 835 ) 836 .to( 837 path2a, 838 0.5, 839 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 840 'connections-1' 841 ) 842 .to( 843 path2b, 844 0.5, 845 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 846 'connections-1' 847 ) 848 // wait a moment 849 .to(box1, 0.5, {}) 850 // box 1 appears 851 .fromTo( 852 box1, 853 0.3, 854 { scale: 0, rotation: 200, opacity: 0, svgOrigin: '185px 104px' }, 855 { scale: 1, rotation: 360, opacity: 1 }, 856 '-=0.1' 857 ) 858 // wait a moment, previous paths fade ('#EEB9D1') 859 .to(box1, 0.5, {}, 'stage-1-complete') 860 .to(box2Border, 0.5, { fill: '#EEB9D1' }, 'stage-1-complete') 861 .to(box3Border, 0.5, { fill: '#EEB9D1' }, 'stage-1-complete') 862 .to(path1a, 0.5, { css: { stroke: '#EEB9D1' } }, 'stage-1-complete') 863 .to(path1b, 0.5, { css: { stroke: '#EEB9D1' } }, 'stage-1-complete') 864 .to(path2a, 0.5, { css: { stroke: '#EEB9D1' } }, 'stage-1-complete') 865 .to(path2b, 0.5, { css: { stroke: '#EEB9D1' } }, 'stage-1-complete') 866 // consul speaks to each box that needs a connection made 867 .to(outboundPathsUpper2, 0.5, { opacity: 1 }) 868 .to(outboundPathsLower, 0.5, { opacity: 1 }, '-=0.3') 869 .to(outboundUpdateUpper, 0.3, { opacity: 1 }, '-=0.3') 870 .to(outboundUpdateLower, 0.3, { opacity: 1 }, '-=0.1') 871 .to( 872 outboundUpdateUpperSpinner, 873 0.7, 874 { 875 rotation: 720, 876 svgOrigin: '44px 99px' 877 }, 878 '-=0.5' 879 ) 880 .to( 881 outboundUpdateLowerSpinner, 882 0.7, 883 { 884 rotation: 720, 885 svgOrigin: '44px 246px' 886 }, 887 '-=0.3' 888 ) 889 // connections drawn 890 .to(box1Lock, 0.3, { opacity: 1 }, 'connections-2') 891 .to(box1Border, 0.3, { fill: '#CA2270' }, 'connections-2') 892 .to( 893 path3a, 894 0.5, 895 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 896 'connections-2' 897 ) 898 .to( 899 path3b, 900 0.5, 901 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 902 'connections-2' 903 ) 904 .to( 905 path3c, 906 0.5, 907 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 908 'connections-2' 909 ) 910 .to( 911 path3d, 912 0.5, 913 { css: { strokeDashoffset: 0, stroke: '#CA2270' } }, 914 'connections-2' 915 ) 916 .to(box1, 0.7, {}, 'stage-2-complete') 917 .to(outboundPathsUpper2, 0.7, { opacity: 0 }, 'stage-2-complete') 918 .to(outboundPathsLower, 0.7, { opacity: 0 }, 'stage-2-complete') 919 .to(outboundUpdateUpper, 0.7, { opacity: 0 }, 'stage-2-complete') 920 .to(outboundUpdateLower, 0.7, { opacity: 0 }, 'stage-2-complete') 921 .to(box1Border, 0.5, { fill: '#EEB9D1' }, 'path-fade-2') 922 .to(path3a, 0.5, { css: { stroke: '#EEB9D1' } }, 'path-fade-2') 923 .to(path3b, 0.5, { css: { stroke: '#EEB9D1' } }, 'path-fade-2') 924 .to(path3c, 0.5, { css: { stroke: '#EEB9D1' } }, 'path-fade-2') 925 .to(path3d, 0.5, { css: { stroke: '#EEB9D1' } }, 'path-fade-2') 926 // wait a moment 927 .to(box1, 1, {}) 928 // all new boxes and connections fade 929 .to( 930 [ 931 box1, 932 box2, 933 box3, 934 path1a, 935 path1b, 936 path2a, 937 path2b, 938 path3a, 939 path3b, 940 path3c, 941 path3d 942 ], 943 0.5, 944 { opacity: 0.3 } 945 ) 946 // faded boxes speak to consul 947 .to(inboundPathLower, 0.5, { opacity: 1 }, 'inbound') 948 .to(inboundPathUpper, 0.5, { opacity: 1 }, 'inbound') 949 .to(inboundUpdateLower, 0.5, { opacity: 1 }, 'inbound') 950 .to(inboundUpdateUpper, 0.5, { opacity: 1 }, 'inbound') 951 .to( 952 inboundUpdateLowerSpinner, 953 0.7, 954 { 955 rotation: 360, 956 svgOrigin: '44px 237px' 957 }, 958 '-=0.3' 959 ) 960 .to( 961 inboundUpdateUpperSpinner, 962 0.7, 963 { 964 rotation: 360, 965 svgOrigin: '44px 91px' 966 }, 967 '-=0.3' 968 ) 969 // consul removes faded boxes and connections 970 .to( 971 [ 972 box1, 973 box2, 974 box3, 975 path1a, 976 path1b, 977 path2a, 978 path2b, 979 path3a, 980 path3b, 981 path3c, 982 path3d, 983 inboundPathLower, 984 inboundPathUpper, 985 inboundUpdateLower, 986 inboundUpdateUpper 987 ], 988 0.5, 989 { opacity: 0.0 } 990 ) 991 .addPause() 992 // wait a moment before the loop 993 .to(box1, 1, {}) 994 .pause() 995 996 // kick it off 997 $segmentationChallenge.classList.add('active') 998 $segmentationSolution.classList.add('active') 999 segmentationChallengeTimeline.play() 1000 segmentationSolutionTimeline.play() 1001 } 1002 }