1/* global jQuery, TRX_ADDONS_STORAGE */ 2 3(function() { 4 5 "use strict"; 6 7 // Settings 8 var planeClassPrefix = 'trx_addons_image_effects_on_'; // class prefix of wrappers with image 9 10 var globalCanvas = false; // true - one canvas for all images is used (twitches when scrolling the page), 11 // false - separate canvas for each image is created (smooth scrolling, but WebKit limit: maximum of 16 objects per page) 12 13 var permanentDrawing = globalCanvas || false; // true - permanent redraw images on canvas, 14 // false - redraw only on ready and on hover 15 16 var curtains = null; // global curtains object (used if globalCanvas is true) 17 18 var $document = jQuery(document); 19 20 var firstLoad = false; 21 22 var sliderInited = false; 23 24 25 window.addEventListener( 'load', function() { 26 if ( typeof trx_addons_apply_filters == 'function' ) { 27 globalCanvas = trx_addons_apply_filters( 'trx_addons_filter_image_effects_use_global_canvas', globalCanvas ); 28 permanentDrawing = globalCanvas || false; 29 } 30 firstLoad = true; 31 create_planes(); 32 } ); 33 34 function create_planes() { 35 36 // not available in the edit mode of Elementor 37 if ( typeof window.elementorFrontend !== 'undefined' && elementorFrontend.isEditMode() ) { 38 return; 39 } 40 // exit if a module 'Curtains' is not available 41 if ( typeof window.Curtains == 'undefined' ) { 42 return; 43 } 44 45 // get our plane element 46 var planeElements = document.querySelectorAll( '[class*="' + planeClassPrefix + '"]:not(.trx_addons_image_effects_inited)' 47 + ( jQuery('body').hasClass( 'allow_lazy_load' ) 48 ? '.lazyload_inited' 49 : '' ) 50 ); 51 52 // exit if no image effects are present on the current page 53 if ( planeElements.length === 0 ) return; 54 55 // create global canvas and append it to the body 56 if ( globalCanvas ) { 57 curtains = create_canvas( document.body ); 58 } 59 60 // create planes and handle them 61 trx_addons_when_images_loaded( jQuery( planeElements ), function() { 62 var effect, total = 0; 63 for (var i = 0; i < planeElements.length; i++) { 64 if ( ! firstLoad && planeElements[i].closest( '.elementor-section-stretched' ) ) continue; 65 if ( ! sliderInited && planeElements[i].closest( '.slider-slide' ) ) continue; 66 total++; 67 if ( ! planeElements[i].classList.contains( 'trx_addons_image_effects_inited' ) && jQuery( planeElements[i] ).parents(':hidden').length === 0 ) { 68 effect = get_effect_name( planeElements[i] ); 69 if ( effect && typeof window['trx_addons_image_effects_callback_' + effect] == 'function' ) { 70 window['trx_addons_image_effects_callback_' + effect]( curtains, planeElements[i], i, planeElements.length ); 71 planeElements[i].classList.add("trx_addons_image_effects_inited"); 72 } 73 } 74 } 75 // mark body as all planes are loaded 76 if ( total === planeElements.length ) { 77 document.body.classList.add("trx_addons_image_effects_planes_loaded"); 78 $document.trigger('action.trx_addons_image_effects_inited', [planeElements]); 79 } 80 } ); 81 } 82 83 $document.on( 'action.got_ajax_response', function() { 84 if ( firstLoad ) { 85 create_planes(); 86 } 87 } ); 88 89 $document.on( 'action.init_hidden_elements', function() { 90 if ( firstLoad ) { 91 create_planes(); 92 } 93 } ); 94 95 $document.on( 'action.slider_inited', function() { 96 if ( ! sliderInited ) { 97 sliderInited = true; 98 create_planes(); 99 } 100 } ); 101 102 $document.on( 'action.init_lazy_load_elements', function( e, element ) { 103 var parent = element.parents('[class*="trx_addons_image_effects_on_"]:not(.trx_addons_image_effects_inited)'); 104 if ( parent.length > 0 ) { 105 parent.addClass('lazyload_inited'); 106 // Hide and load image 107 parent.css({'opacity': 0, 'transition': 'opacity 0s ease'}); 108 // Re-create canvas elements 109 create_planes(); 110 // Fade in image 111 setTimeout(function(){ 112 // Show loaded image 113 parent.css({'opacity': 1, 'transition': 'opacity 0.3s ease'}); 114 // Remove styles 115 setTimeout(function(){ 116 parent.css({'opacity': '', 'transition': ''}); 117 }, 300); 118 }, 100); 119 } 120 } ); 121 122 $document.on('action.before_remove_content action.deactivate_tab', function(e,
122cont) { 123 cont.find( '.trx_addons_image_effects_inited' ).each( function() { 124 var $self = jQuery( this ), 125 $canvas = $self.find('.trx_addons_image_effects_canvas'), 126 curtains = $self.data('curtains'); 127 if ( ! globalCanvas ) { 128 if ( curtains ) { 129 curtains.dispose(); 130 curtains = null; 131 $self.removeData( 'curtains' ); 132 } 133 } else { 134 var plane = $self.data('curtains-plane'); 135 if ( plane ) { 136 curtains.removePlane( plane ); 137 plane = null; 138 $self.removeData('curtains-plane'); 139 } 140 } 141 $canvas.remove(); 142 }); 143 }); 144 145 $document.on('action.after_add_content action.activate_tab', function(e, cont) { 146 cont.find( '.trx_addons_image_effects_inited' ).each( function() { 147 jQuery( this ) 148 .removeClass('trx_addons_image_effects_inited') 149 .find( '[id^="trx_addons_image_effects_canvas_"]' ).remove().end() 150 .find( '.trx_addons_image_effects_holder' ).removeClass('trx_addons_image_effects_holder').end(); 151 }); 152 }); 153 154 155 // Utilities 156 //------------------------------------------- 157 158 // Linear interpolation 159 function lerp(start, end, amt){ 160 return (1 - amt) * start + amt * end; 161 } 162 163 // Return name of image effect for element 164 function get_effect_name( elm ) { 165 var name = ''; 166 for ( var i=0; i < elm.classList.length; i++ ) { 167 if ( elm.classList[i].indexOf(planeClassPrefix) === 0 ) { 168 name = elm.classList[i].substring( planeClassPrefix.length ); 169 break; 170 } 171 } 172 return name; 173 } 174 175 // Change value in specified time 176 function tween_value( args ) { 177 // Defaults 178 if ( args.start == args.end ) { 179 return null; 180 } 181 if ( ! args.time ) { 182 args.time = 1; // 1s 183 } 184 185 var t = { 186 value: args.start 187 }; 188 189 // Use TweenMax (if loaded) 190 if ( typeof TweenMax != 'undefined' ) { 191 return TweenMax.to( t, args.time, { 192 value: args.end, 193 ease: args.ease ? args.ease : Power2.easeOut, 194 onUpdate: function() { 195 args.callbacks.onUpdate( t.value ); 196 }, 197 onComplete: function() { 198 if ( args.callbacks.onComplete ) { 199 args.callbacks.onComplete(); 200 } 201 } 202 } ); 203 204 // Internal tween manager 205 } else { 206 var amount = 0.1; 207 var interval = Math.min( args.time * 1000 / 20, Math.max( 1, Math.round( args.time * 1000 / ( Math.abs( args.end - args.start ) / amount ) ) ) ); 208 return setInterval( function() { 209 t.value = lerp(t.value, args.end, amount); 210 args.callbacks.onUpdate( t.value ); 211 if ( Math.abs(t.value - args.end) < 0.0001 ) { 212 t.value = args.end; 213 args.callbacks.onUpdate( t.value ); 214 if ( args.callbacks.onComplete ) { 215 args.callbacks.onComplete(); 216 } 217 } 218 }, interval ); 219 } 220 } 221 222 // Stop changing value 223 function tween_stop( handler ) { 224 // Use TweenMax (if loaded) 225 if ( typeof TweenMax != 'undefined' ) { 226 if ( handler ) handler.kill(); 227 228 // Internal tween manager 229 } else { 230 if ( handler ) clearTimeout( handler ); 231 232 } 233 } 234 235 // Return mouse coordinates relative to the current image 236 function get_mouse_position_from_event( e ) { 237 var mouse = {}; 238 // touch event 239 if (e.targetTouches) { 240 mouse.x = globalCanvas ? e.targetTouches[0].clientX : e.targetTouches[0].layerX; 241 mouse.y = globalCanvas ? e.targetTouches[0].clientY : e.targetTouches[0].layerY; 242 243 // mouse event 244 } else { 245 // In Chrome with custom scroll mouse coordinates in layerXY are incorrect 246 // but in Mozilla mouse properties offsetXY always empty (equal to 0) 247 mouse.x = globalCanvas ? e.clientX : ( e.offsetX !== 0 || e.offsetY !== 0 ? e.offsetX : e.layerX ); 248 mouse.y = globalCanvas ? e.clientY : ( e.offsetX !== 0 || e.offsetY !== 0 ? e.offsetY : e.layerY ); 249 } 250 return mouse; 251 } 252 253 // Convert our mouse/touch position to coordinates relative to the vertices of the plane 254 function mouse_to_plane_coords( plane, mpos ) { 255 var w = plane.htmlElement.clientWidth, cw = w / 2, 256 h = plane.htmlElement.clientHeight, ch = h / 2; 257 return { 258 x: ( mpos.x - cw ) / cw, 259 y: -( mpos.y - ch ) / ch 260 }; 261 } 262 263 // Add canvas holder 264 var total = 0; 265 function create_canvas( item ) { 266 267 // Append canvas holder to the item 268 var id = 'trx_addons_image_effects_canvas_'+total++, 269 div = document.createElement("div"); 270 div.setAttribute('id', id); 271 div.setAttribute('class', 'trx_addons_image_effects_canvas'); 272 item.appendChild(div); 273 274 // Set up our WebGL context and append the canvas to our wrapper 275 var webGLCurtain = new Curtains({ 276 watchScroll: globalCanvas, 277 premultipliedAlpha: true, // to avoid gray edge on images in effects 'waves', 'smudge', etc. (who changes the image border geometry) 278 container: id // if not specified - library create own canvas container 279 }); 280 281 // Handling errors 282 webGLCurtain 283 .onError(function() { 284 // we will add a class to the document body to display original images 285 document.body.classList.add("no-curtains", "trx_addons_image_effects_plane
285s_loaded"); 286 }) 287 .onContextLost(function() { 288 // on context lost, try to restore the context 289 webGLCurtain.restoreContext(); 290 }); 291 292 return webGLCurtain; 293 } 294 295 296 297 // Effect 'Waves' 298 //------------------------------------------- 299 300 // Create plane. 301 // Attention! All callbacks must be in a global scope! 302 window.trx_addons_image_effects_callback_waves = function( curtains_global, elm, index, total ) { 303 304 var curtains = curtains_global ? curtains_global : null; 305 306 var waveForceMin = 0, 307 waveForceMax = 7; 308 309 var waveFactor = elm.getAttribute('data-image-effect-waves-factor') || 4; 310 311 var mouseIn = false; 312 313 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 314 scaleFactor = 0; 315 316 var paddingOnHover = typeof trx_addons_apply_filters == 'function' 317 ? trx_addons_apply_filters( 'trx_addons_filter_image_effects_padding', 0.04, 'waves' ) 318 : 0.04; 319 320 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 321 322 var plane = null, 323 parent = null, 324 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 325 img = img_all.length > 1 326 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 327 : elm.querySelector( 'img' ); 328 329 if ( img ) { 330 if ( img_all.length > 1 ) { 331 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 332 } 333 parent = img.parentNode; 334 if ( img_all.length == 1 ) { 335 parent.classList.add('trx_addons_image_effects_holder'); 336 } 337// img.setAttribute('crossorigin', 'anonymous'); 338 img.setAttribute('data-sampler', 'wavesTexture'); 339 if ( ! globalCanvas ) { 340 curtains = create_canvas(parent); 341 if ( curtains ) jQuery(elm).data('curtains', curtains); 342 } 343 if ( curtains ) { 344 if ( ! permanentDrawing ) curtains.disableDrawing(); 345 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 346 if ( plane ) { 347 jQuery(elm).data('curtains-plane', plane); 348 handle_plane( plane ); 349 } 350 } 351 } 352 353 // Return plane params 354 function get_params() { 355 var vs = ` 356 #ifdef GL_ES 357 precision mediump float; 358 #endif 359 360 // those are the mandatory attributes that the lib sets 361 attribute vec3 aVertexPosition; 362 attribute vec2 aTextureCoord; 363 364 // those are mandatory uniforms that the lib sets and that contain our model view and projection matrix 365 uniform mat4 uMVMatrix; 366 uniform mat4 uPMatrix; 367 368 // our texture matrix uniform 369 uniform mat4 wavesTextureMatrix; 370 371 // if you want to pass your vertex and texture coords to the fragment shader 372 varying vec3 vVertexPosition; 373 varying vec2 vTextureCoord; 374 375 // effect control vars declared inside our javascript 376 uniform float uTime; 377 uniform float uMouseMoveStrength; 378 uniform float uEffectStrength; 379 uniform float uWaveFactor; 380 uniform vec2 uMousePosition; 381 uniform float hoveringWaveForce; 382 uniform float uPadding; 383 384 void main() { 385 vec3 vertexPosition = aVertexPosition; 386 float distanceFromMouse = distance(uMousePosition, vec2(vertexPosition.x, vertexPosition.y)); 387 float waveSinusoid = cos(uWaveFactor * (distanceFromMouse - (uTime / 75.0))); 388 float distanceStrength = 0.4 / (distanceFromMouse + 0.4); 389 float distortionEffect = distanceStrength * waveSinusoid * uMouseMoveStrength / uEffectStrength; 390 vertexPosition.z += distortionEffect; 391 vertexPosition.x += distortionEffect * (uMousePosition.x - vertexPosition.x) * hoveringWaveForce * 3.0; 392 vertexPosition.y += distortionEffect * (uMousePosition.y - vertexPosition.y) * hoveringWaveForce; 393 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, (1.0 + uPadding)); 394 vTextureCoord = (wavesTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 395 vVertexPosition = vertexPosition; 396 } 397 `; 398 399 var fs = ` 400 #ifdef GL_ES 401 precision mediump float; 402 #endif 403 // get our varying variables 404 varying vec3 vVertexPosition; 405 varying vec2 vTextureCoord; 406 407 // our texture sampler 408 uniform sampler2D wavesTexture; 409 410 // effect control vars 411 uniform float displacement; 412 413 void main() { 414 if ( false ) { 415 float intensity = 1.0; 416 vec2 textureCoord = vTextureCoord; 417 vec4 image1 = texture2D(wavesTexture, textureCoord); 418 vec4 image2 = texture2D(wavesTexture, textureCoord); 419 vec4 texture1 = texture2D(wavesTexture, vec2(textureCoord.x, textureCoord.y + displacement * (image2 * intensity))); 420 vec4 texture2 = texture2D(wavesTexture, vec2(textureCoord.x, textureCoord.y + (1.0 - displacement) * (image1 * intensity))); 421 vec4 result = mix(texture1, texture2, displacement); 422 gl_FragColor = result; 423 } else { 424 vec2 textureCoord = vTextureCoord; 425 gl_FragColor = texture2D(wavesTexture, textureCoord); 426 } 427 } 428 `; 429 430 return { 431 vertexShader: vs, 432 fragmentShader: fs, 433 widthSegments: 10, 434 heightSegments: 10, 435 uniforms: { 436 time: { 437 name: "uTime", 438 type: "1f", 439 value: 0 440 }, 441 mousePosition: { 442 name: "uMousePosition", 443 type: "2f", 444 value: [-.5, .5] 445 }, 446 mouseMoveStrength: { 447 name: "uMouseMoveStrength", 448 type: "1f", 449 value: .2 450 }, 451 effectStrength: { 452 name: "uEffectStrength", 453 type: "1f", 454 value: effectStrength 455 }, 456 displacement: { 457 name: "displacement", 458 type: "1f", 459 value: 0 460 }, 461 waveFactor: { 462 name: "uWaveFactor", 463 type: "1f", 464 value: waveFactor 465 }, 466 hoveringWaveForce: { 467 name: "hoveringWaveForce", 468 type: "1f", 469 value: waveForceMin 470 }, 471 padding: { 472 name: "uPadding", 473 type: "1f", 474 value: 0 475 } 476 } 477 }; 478 } 479 480 // handle plane 481 function handle_plane( plane ) { 482 plane 483 .onLoading(function() { 484// console.log('Waves onLoading'); 485 }) 486 .onReady(function() { 487// console.log('Waves onReady: Plane '+index+' of '+total+' is ready'); 488 // first render plane 489 if ( ! permanentDrawing ) curtains.needRender(); 490 // init tweens 491 plane.tweenForce = null; 492 plane.tweenScale = null; 493 plane.tweenPadding = null; 494 // now that our plane is ready we can listen to mouse move event 495 function mouse_move() { 496 if ( ! mouseIn ) { 497 mouse_enter(); 498 } 499 } 500 function mouse_enter() { 501 if ( ! mouseIn ) { 502 mouseIn = true;
503 change_wave_force( waveForceMax ); 504 change_scale( 1 ); 505 if ( paddingOnHover ) { 506 change_padding( paddingOnHover ); 507 } 508 } 509 } 510 function mouse_leave() { 511 if ( mouseIn ) { 512 mouseIn = false; 513 change_wave_force( waveForceMin ); 514 change_scale( 0 ); 515 if ( paddingOnHover ) { 516 change_padding( 0 ); 517 } 518 } 519 } 520 elm.addEventListener("mousemove", mouse_move ); 521 elm.addEventListener("touchmove", mouse_move ); 522 elm.addEventListener("mouseenter", mouse_enter ); 523 elm.addEventListener("touchstart", mouse_enter ); 524 elm.addEventListener("mouseleave", mouse_leave ); 525 elm.addEventListener("touchend", mouse_leave ); 526 }) 527 .onRender(function() { 528// if ( globalCanvas ) plane.updatePosition(); 529 plane.uniforms.time.value++; 530 531 }) 532 .onAfterResize(function() { 533// console.log('Waves afterResize: Plane '+index+' of '+total+' is resized'); 534 }); 535 536 // Change wave force value 537 function change_wave_force( to ) { 538 if ( plane.tweenForce ) { 539 tween_stop( plane.tweenForce ); 540 } 541 plane.tweenForce = tween_value( { 542 start: plane.uniforms.hoveringWaveForce.value, 543 end: to, 544 time: 1.25, 545 callbacks: { 546 onUpdate: function(value) { 547 plane.uniforms.hoveringWaveForce.value = value; 548 }, 549 onComplete: function() { 550 tween_stop( plane.tweenForce ); 551 plane.tweenForce = null; 552 } 553 } 554 } ); 555 } 556 557 // Change padding value 558 function change_padding( to ) { 559 if ( plane.tweenPadding ) { 560 tween_stop( plane.tweenPadding ); 561 } 562 plane.tweenPadding = tween_value( { 563 start: plane.uniforms.padding.value, 564 end: to, 565 time: 1.25, 566 callbacks: { 567 onUpdate: function(value) { 568 plane.uniforms.padding.value = value; 569 }, 570 onComplete: function() { 571 tween_stop( plane.tweenPadding ); 572 plane.tweenPadding = null; 573 } 574 } 575 } ); 576 } 577 578 // Change scale 579 function change_scale( to ) { 580 if ( plane.tweenScale ) { 581 tween_stop( plane.tweenScale ); 582 } 583 if ( ! permanentDrawing ) { 584 curtains.enableDrawing(); 585 } 586 plane.tweenScale = tween_value( { 587 start: scaleFactor, 588 end: to, 589 time: 1.25, 590 callbacks: { 591 onUpdate: function(value) { 592 scaleFactor = value; 593 if ( scaleOnHover ) { 594 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 595 } 596 }, 597 onComplete: function() { 598 tween_stop( plane.tweenScale ); 599 plane.tweenScale = null; 600 if ( ! permanentDrawing && to === 0 ) { 601 curtains.disableDrawing(); 602 } 603 } 604 } 605 } ); 606 } 607 } 608 }; 609 610 611 612 // Effect 'Waves2' 613 //------------------------------------------- 614 615 // Create plane. 616 // Attention! All callbacks must be in a global scope! 617 window.trx_addons_image_effects_callback_waves2 = function( curtains_global, elm, index, total ) { 618 619 var curtains = curtains_global ? curtains_global : null; 620 621 var waveForceMin = 0, 622 waveForceMax = 2; 623 624 var waveFactor = elm.getAttribute('data-image-effect-waves-factor') || 4; 625 626 var mouseIn = false; 627 628 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 629 scaleFactor = 0; 630 631 var paddingOnHover = typeof trx_addons_apply_filters == 'function' 632 ? trx_addons_apply_filters( 'trx_addons_filter_image_effects_padding', 0.04, 'waves2' ) 633 : 0.04; 634 635 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 636 637 var plane = null, 638 parent = null, 639 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 640 img = img_all.length > 1 641 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 642 : elm.querySelector( 'img' ); 643 644 if ( img ) { 645 if ( img_all.length > 1 ) { 646 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 647 } 648 parent = img.parentNode; 649 if ( img_all.length == 1 ) { 650 parent.classList.add('trx_addons_image_effects_holder'); 651 } 652// img.setAttribute('crossorigin', 'anonymous'); 653 img.setAttribute('data-sampler', 'waves2Texture'); 654 if ( ! globalCanvas ) { 655 curtains = create_canvas(parent); 656 if ( curtains ) jQuery(elm).data('curtains', curtains); 657 } 658 if ( curtains ) { 659 if ( ! permanentDrawing ) curtains.disableDrawing(); 660 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 661 if ( plane ) { 662 jQuery(elm).data('curtains-plane', plane); 663 handle_plane( plane ); 664 } 665 } 666 } 667 668 // Return plane params 669 function get_params( elm, img, parent ) { 670 var vs = ` 671 #ifdef GL_ES 672 precision mediump float; 673 #endif 674 675 // default mandatory variables 676 attribute vec3 aVertexPosition; 677 attribute vec2 aTextureCoord; 678 679 uniform mat4 uMVMatrix; 680 uniform mat4 uPMatrix; 681 682 // our texture matrix 683 uniform mat4 waves2TextureMatrix; 684 685 // custom variables 686 varying vec3 vVertexPosition; 687 varying vec2 vTextureCoord; 688 uniform float uTime; 689 uniform vec2 uResolution; 690 uniform vec2 uMousePosition; 691 uniform float uMouseMoveStrength; 692 uniform float uEffectStrength; 693 uniform float uWaveFactor; 694 uniform float uPadding; 695 696 void main() { 697 vec3 vertexPosition = aVertexPosition; 698 // get the distance between our vertex and the mouse position 699 float distanceFromMouse = distance(uMousePosition, vec2(vertexPosition.x, vertexPosition.y)); 700 // calculate our wave effect 701 float waveSinusoid = cos(uWaveFactor * (distanceFromMouse - (uTime / 75.0))); 702 // attenuate the effect based on mouse distance 703 float distanceStrength = 0.4 / (distanceFromMouse + 0.4); 704 // calculate our distortion effect 705 float distortionEffect = distanceStrength * waveSinusoid * uMouseMoveStrength / uEffectStrength; 706 // apply it to our vertex position 707 vertexPosition.z += distortionEffect; 708 vertexPosition.x += distortionEffect * (uMousePosition.x - vertexPosition.x) * (uResolution.x / uResolution.y); 709 vertexPosition.y += distortionEffect * (uMousePosition.y - vertexPosition.y); 710 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, (1.0 + uPadding)); 711 // varyings 712 vTextureCoord = (waves2TextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 713 vVertexPosition = vertexPosition; 714 } 715 `; 716 var fs = ` 717 #ifdef GL_ES 718 precision mediump float; 719 #endif 720 721 varying vec3 vVertexPosition; 722 varying vec2 vTextureCoord; 723 uniform sampler2D waves2Texture; 724 725 void main() { 726 // apply our texture 727 vec4 finalColor = texture2D(waves2Texture, vTextureCoord); 728 // fake shadows based on vertex position along Z axis 729 finalColor.rgb -= clamp(-vVertexPosition.z, 0.0, 1.0); 730 // fake lights based on vertex position along Z axis 731 finalColor.rgb += clamp(vVertexPosition.z, 0.0, 1.0); 732 // handling premultiplied alpha (useful if we were using a png with transparency) 733 finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a); 734 gl_FragColor = finalColor; 735 } 736 `; 737 738 return { 739 vertexShader: vs, 740 fragmentShader: fs, 741 widthSegments: 20, 742 heightSegments: 20, 743 uniforms: { 744 resolution: { // resolution of our plane 745 name: "uResolution", 746 type: "2f", // notice this is an length 2 array of floats 747 value: [ parent.clientWidth, parent.clientHeight ] 748 }, 749 time: { // time uniform that will be updated at each draw call 750 name: "uTime", 751 type: "1f", 752 value: 0 753 }, 754 mousePosition: { // our mouse position 755 name: "uMousePosition", 756 type: "2f", // again an array of floats 757 value: [-.5, .5] 758 }, 759 mouseMoveStrength: { // the mouse move strength 760 name: "uMouseMoveStrength", 761 type: "1f", 762 value: 0 763 }, 764 effectStrength: { // the effect strength 765 name: "uEffectStrength", 766 type: "1f", 767 value: effectStrength 768 }, 769 waveFactor: { // waves frequency 770 name: "uWaveFactor", 771 type: "1f", 772 value: waveFactor 773 }, 774 padding: { // padding around image on hover 775 name: "uPadding", 776 type: "1f", 777 value: 0 778 } 779 } 780 }; 781 } 782 783 // handle plane 784 function handle_plane( plane ) { 785 plane 786 .onLoading(function() { 787 //console.log(plane.loadingManager.sourcesLoaded); 788 }) 789 .onReady(function() { 790// console.log('Plane '+index+' of '+total+' is ready'); 791 // set a fov of 35 to reduce perspective 792 plane.setPerspective(35); 793 // first render plane 794 if ( ! permanentDrawing ) curtains.needRender(); 795 // init tweens 796 plane.tween = null; 797 plane.tweenScale = null; 798 // now that our plane is ready we can listen to mouse move event 799 function mouse_move() { 800 if ( ! mouseIn ) { 801 mouse_enter(); 802 } 803 } 804 function mouse_enter() { 805 if ( ! mouseIn ) { 806 mouseIn = true;
807 change_wave_force( waveForceMax ); 808 change_scale( 1 ); 809 if ( paddingOnHover ) { 810 change_padding( paddingOnHover ); 811 } 812 } 813 } 814 function mouse_leave() { 815 if ( mouseIn ) { 816 mouseIn = false; 817 change_wave_force( waveForceMin ); 818 change_scale( 0 ); 819 if ( paddingOnHover ) { 820 change_padding( 0 ); 821 } 822 } 823 } 824 elm.addEventListener("mousemove", mouse_move ); 825 elm.addEventListener("touchmove", mouse_move ); 826 elm.addEventListener("mouseenter", mouse_enter ); 827 elm.addEventListener("touchstart", mouse_enter ); 828 elm.addEventListener("mouseleave", mouse_leave ); 829 elm.addEventListener("touchend", mouse_leave ); 830 }) 831 .onRender(function() { 832 // increment our time uniform 833 plane.uniforms.time.value++; 834 }) 835 .onAfterResize(function() { 836// console.log('Plane '+index+' of '+total+' is resized'); 837 /* Commented, because set width and height to 0 inside slider 838 var planeBoundingRect = plane.getBoundingRect(); 839 plane.uniforms.resolution.value = [ planeBoundingRect.width, planeBoundingRect.height ]; 840 */ 841 }); 842 } 843 844 // Change wave force value 845 function change_wave_force( to ) { 846 if ( plane.tween ) { 847 tween_stop( plane.tween ); 848 } 849 plane.tween = tween_value( { 850 start: plane.uniforms.mouseMoveStrength.value, 851 end: to, 852 time: 1.25, 853 callbacks: { 854 onUpdate: function(value) { 855 plane.uniforms.mouseMoveStrength.value = value; 856 }, 857 onComplete: function() { 858 tween_stop( plane.tween ); 859 plane.tween = null 860 } 861 } 862 } ); 863 } 864 865 // Change padding value 866 function change_padding( to ) { 867 if ( plane.tweenPadding ) { 868 tween_stop( plane.tweenPadding ); 869 } 870 plane.tweenPadding = tween_value( { 871 start: plane.uniforms.padding.value, 872 end: to, 873 time: 1.25, 874 callbacks: { 875 onUpdate: function(value) { 876 plane.uniforms.padding.value = value; 877 }, 878 onComplete: function() { 879 tween_stop( plane.tweenPadding ); 880 plane.tweenPadding = null; 881 } 882 } 883 } ); 884 } 885 886 // Change scale 887 function change_scale( to ) { 888 if ( plane.tweenScale ) { 889 tween_stop( plane.tweenScale ); 890 } 891 if ( ! permanentDrawing ) { 892 curtains.enableDrawing(); 893 } 894 plane.tweenScale = tween_value( { 895 start: scaleFactor, 896 end: to, 897 time: 1.25, 898 callbacks: { 899 onUpdate: function(value) { 900 scaleFactor = value; 901 if ( scaleOnHover ) { 902 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 903 } 904 }, 905 onComplete: function() { 906 tween_stop( plane.tweenScale ); 907 plane.tweenScale = null; 908 if ( ! permanentDrawing && to === 0 ) { 909 curtains.disableDrawing(); 910 } 911 } 912 } 913 } ); 914 } 915 }; 916 917 918 919 // Effect 'Ripple' 920 //------------------------------------------- 921 922 // Create plane. 923 // Attention! All callbacks must be in a global scope! 924 window.trx_addons_image_effects_callback_ripple = function( curtains_global, elm, index, total ) { 925 926 var curtains = curtains_global ? curtains_global : null; 927 928 // Common vars 929 var mouseIn = false; 930 931 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 932 scaleFactor = 0; 933 934 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 935 936 // Effect-specific vars 937 var wavesDirection = Math.max(0.0, Math.min(1.0, elm.getAttribute('data-image-effect-waves-direction') ) ); 938 939 // Curtains init 940 var plane = null, 941 parent = null, 942 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 943 img = img_all.length > 1 944 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 945 : elm.querySelector( 'img' ); 946 947 if ( img ) { 948 if ( img_all.length > 1 ) { 949 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 950 } 951 parent = img.parentNode; 952 if ( img_all.length == 1 ) { 953 parent.classList.add('trx_addons_image_effects_holder'); 954 } 955// img.setAttribute('crossorigin', 'anonymous'); 956 img.setAttribute('data-sampler', 'rippleTexture'); 957 if ( ! globalCanvas ) { 958 curtains = create_canvas(parent); 959 if ( curtains ) jQuery(elm).data('curtains', curtains); 960 } 961 if ( curtains ) { 962 if ( ! permanentDrawing ) curtains.disableDrawing(); 963 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 964 if ( plane ) { 965 jQuery(elm).data('curtains-plane', plane); 966 handle_plane( plane ); 967 } 968 } 969 } 970 971 // Return plane params 972 function get_params() { 973 var vs = ` 974 975 #ifdef GL_ES 976 precision mediump float; 977 #endif 978 979 // those are the mandatory attributes that the lib sets 980 attribute vec3 aVertexPosition; 981 attribute vec2 aTextureCoord; 982 983 // those are mandatory uniforms that the lib sets and that contain our model view and projection matrix 984 uniform mat4 uMVMatrix; 985 uniform mat4 uPMatrix; 986 987 // our texture matrix uniform 988 uniform mat4 rippleTextureMatrix; 989 990 // if you want to pass your vertex and texture coords to the fragment shader 991 varying vec3 vVertexPosition; 992 varying vec2 vTextureCoord; 993 994 void main() { 995 // get the vertex position from its attribute 996 vec3 vertexPosition = aVertexPosition; 997 998 // set its position based on projection and model view matrix 999 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0
999); 1000 1001 // set the varying variables 1002 // thanks to the texture matrix we will be able to calculate accurate texture coords 1003 // so that our texture will always fit our plane without being distorted 1004 vTextureCoord = (rippleTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 1005 vVertexPosition = vertexPosition; 1006 } 1007 `; 1008 1009 var fs = ` 1010 #ifdef GL_ES 1011 precision mediump float; 1012 #endif 1013 1014 // get our varying variables 1015 varying vec3 vVertexPosition; 1016 varying vec2 vTextureCoord; 1017 1018 // our texture sampler 1019 uniform sampler2D rippleTexture; 1020 1021 // effect control vars declared inside our javascript 1022 uniform float uTime; // time iterator to change waves position 1023 uniform float uEffectStrength; // 5.0 - 50.0 - waves amplitude 1024 uniform float uWavesForce; // 0.0 - 1.0 - fadeIn/fadeOut on mouse hover 1025 uniform float uWavesDirection; // 0 - horizontal, 1 - vertical 1026 1027 void main() { 1028 // get our texture coords 1029 vec2 textureCoord = vTextureCoord; 1030 1031 // displace our pixels along both axis based on our time uniform and texture UVs 1032 // this will create a kind of water surface effect 1033 // try to comment a line or change the constants to see how it changes the effect 1034 // reminder : textures coords are ranging from 0.0 to 1.0 on both axis 1035 const float PI = 3.141592; 1036 1037 textureCoord.x += ( 1038 sin(textureCoord.x * 10.0 * ( 2.0 - uWavesDirection ) + ((uTime * (PI / 3.0)) * 0.031)) 1039 + sin(textureCoord.y * 10.0 * ( 2.0 - uWavesDirection ) + ((uTime * (PI / 2.489)) * 0.017)) 1040 ) / uEffectStrength / ( 2.5 + 1.5 * uWavesDirection ) * uWavesForce; // * 0.0075; 1041 1042 textureCoord.y += ( 1043 sin(textureCoord.y * 20.0 / ( 2.0 - uWavesDirection ) + ((uTime * (PI / 2.023)) * 0.023)) 1044 + sin(textureCoord.x * 20.0 / ( 2.0 - uWavesDirection ) + ((uTime * (PI / 3.1254)) * 0.037)) 1045 ) / uEffectStrength / ( 2.5 + 1.5 * ( 1.0 - uWavesDirection ) ) * uWavesForce; // * 0.0125; 1046 1047 gl_FragColor = texture2D(rippleTexture, textureCoord); 1048 } 1049 `; 1050 1051 return { 1052 vertexShader: vs, // our vertex shader ID 1053 fragmentShader: fs, // our fragment shader ID 1054// widthSegments: 10, 1055// heightSegments: 10, 1056 uniforms: { // variables passed to shaders 1057 time: { 1058 name: "uTime", 1059 type: "1f", 1060 value: 0 1061 }, 1062 effectStrength: { 1063 name: "uEffectStrength", 1064 type: "1f", 1065 value: effectStrength 1066 }, 1067 wavesForce: { 1068 name: "uWavesForce", 1069 type: "1f", 1070 value: 0 1071 }, 1072 wavesDirection: { 1073 name: "uWavesDirection", 1074 type: "1f", 1075 value: wavesDirection 1076 } 1077 } 1078 }; 1079 } 1080 1081 // handle plane 1082 function handle_plane( plane ) { 1083 plane 1084 .onLoading(function() { 1085// console.log(plane.loadingManager.sourcesLoaded); 1086 }) 1087 .onReady(function() { 1088// console.log('Plane '+index+' of '+total+' is ready'); 1089 // first render plane 1090 if ( ! permanentDrawing ) curtains.needRender(); 1091 // init tweens 1092 plane.tweenForce = null; 1093 plane.tweenScale = null; 1094 // now that our plane is ready we can listen to mouse move event 1095 function mouse_move(e) { 1096 if ( ! mouseIn ) { 1097 mouse_enter(); 1098 } 1099 } 1100 function mouse_enter() { 1101 if ( ! mouseIn ) { 1102 mouseIn = true; 1103 change_waves_force( 1 ); 1104 change_scale( 1 ); 1105 } 1106 } 1107 function mouse_leave() { 1108 if ( mouseIn ) { 1109 mouseIn = false; 1110 change_waves_force( 0 ); 1111 change_scale( 0 ); 1112 } 1113 } 1114 elm.addEventListener("mousemove", mouse_move ); 1115 elm.addEventListener("touchmove", mouse_move ); 1116 elm.addEventListener("mouseenter", mouse_enter ); 1117 elm.addEventListener("touchstart", mouse_enter ); 1118 elm.addEventListener("mouseleave", mouse_leave ); 1119 elm.addEventListener("touchend", mouse_leave ); 1120 }) 1121 .onRender(function() { 1122 plane.uniforms.time.value++; 1123 1124 }) 1125 .onAfterResize(function() { 1126// console.log('Plane '+index+' of '+total+' is resized'); 1127 }); 1128 1129 // Change wave force value 1130 function change_waves_force( to ) { 1131 if ( plane.tweenForce ) { 1132 tween_stop( plane.tweenForce ); 1133 } 1134 plane.tweenForce = tween_value( { 1135 start: plane.uniforms.wavesForce.value, 1136 end: to, 1137 time: 1.25, 1138 callbacks: { 1139 onUpdate: function(value) { 1140 plane.uniforms.wavesForce.value = value; 1141 }, 1142 onComplete: function() { 1143 tween_stop( plane.tweenForce ); 1144 plane.tweenForce = null; 1145 } 1146 } 1147 } ); 1148 } 1149 1150 // Change scale 1151 function change_scale( to ) { 1152 if ( plane.tweenScale ) { 1153 tween_stop( plane.tweenScale ); 1154 } 1155 if ( ! permanentDrawing ) { 1156 curtains.enableDrawing(); 1157 } 1158 plane.tweenScale = tween_value( { 1159 start: scaleFactor, 1160 end: to, 1161 time: 1.25, 1162 callbacks: { 1163 onUpdate: function(value) { 1164 scaleFactor = value; 1165 if ( scaleOnHover ) { 1166 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 1167 } 1168 }, 1169 onComplete: function() { 1170 tween_stop( plane.tweenScale ); 1171 plane.tweenScale = null; 1172 if ( ! permanentDrawing && to === 0 ) { 1173 curtains.disableDrawing(); 1174 } 1175 } 1176 } 1177 } ); 1178 } 1179 } 1180 }; 1181 1182 1183 1184 // Effect 'Ripple 2' 1185 //------------------------------------------- 1186 1187 // Create plane. 1188 // Attention! All callbacks must be in a global scope! 1189 window.trx_addons_image_effects_callback_ripple2 = function( curtains_global, elm, index, total ) { 1190 1191 var curtains = curtains_global ? curtains_global : null; 1192 1193 // Common vars 1194 var mouseIn = false;
1195 1196 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 1197 scaleFactor = 0; 1198 1199 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 1200 1201 // Effect-specific vars 1202 var wavesDirection = Math.max(0.0, Math.min(1.0, elm.getAttribute('data-image-effect-waves-direction') ) ); 1203 1204 // Curtains init 1205 var plane = null, 1206 parent = null, 1207 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 1208 img = img_all.length > 1 1209 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 1210 : elm.querySelector( 'img' ); 1211 1212 if ( img ) { 1213 if ( img_all.length > 1 ) { 1214 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 1215 } 1216 parent = img.parentNode; 1217 if ( img_all.length == 1 ) { 1218 parent.classList.add('trx_addons_image_effects_holder'); 1219 } 1220// img.setAttribute('crossorigin', 'anonymous'); 1221 img.setAttribute('data-sampler', 'ripple2Texture'); 1222 var displacement_url = elm.getAttribute('data-image-effect-displacement'); 1223 if ( displacement_url ) { 1224 var displacement_img = document.createElement("img"); 1225// displacement_img.setAttribute('crossorigin', 'anonymous'); 1226 displacement_img.setAttribute('src', displacement_url); 1227 displacement_img.setAttribute('data-sampler', 'ripple2Displacement'); 1228 displacement_img.classList.add('trx_addons_image_effects_ripple_displacement'); 1229 parent.appendChild(displacement_img); 1230 $document.on('action.after_add_content', function(e, cont) { 1231 cont.find( '.trx_addons_image_effects_ripple_displacement' ).remove(); 1232 }); 1233 } 1234 if ( ! globalCanvas ) { 1235 curtains = create_canvas(parent); 1236 if ( curtains ) jQuery(elm).data('curtains', curtains); 1237 } 1238 if ( curtains ) { 1239 if ( ! permanentDrawing ) curtains.disableDrawing(); 1240 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 1241 if ( plane ) { 1242 jQuery(elm).data('curtains-plane', plane); 1243 handle_plane( plane ); 1244 } 1245 } 1246 } 1247 1248 // Return plane params 1249 function get_params() { 1250 var vs = ` 1251 #ifdef GL_ES 1252 precision mediump float; 1253 #endif 1254 1255 // default mandatory variables 1256 attribute vec3 aVertexPosition; 1257 attribute vec2 aTextureCoord; 1258 1259 uniform mat4 uMVMatrix; 1260 uniform mat4 uPMatrix; 1261 1262 // our texture matrices 1263 // notice how it matches our data-sampler attributes + "Matrix" 1264 uniform mat4 ripple2TextureMatrix; 1265 1266 // varying variables 1267 varying vec3 vVertexPosition; 1268 1269 // our displacement texture will use original texture coords attributes 1270 varying vec2 vDisplacementCoord; 1271 1272 // our image will use texture coords based on their texture matrices 1273 varying vec2 vTextureCoord; 1274 1275 // custom uniforms 1276 uniform float uTime; 1277 1278 void main() { 1279 vec3 vertexPosition = aVertexPosition; 1280 1281 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0
1281); 1282 1283 // varying variables 1284 // texture coords attributes because we want our displacement texture to be contained 1285 vDisplacementCoord = aTextureCoord; 1286 // our image texture coords based on their texture matrices 1287 vTextureCoord = (ripple2TextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 1288 // vertex position as usual 1289 vVertexPosition = vertexPosition; 1290 } 1291 `; 1292 1293 var fs = ` 1294 #ifdef GL_ES 1295 precision mediump float; 1296 #endif 1297 1298 // all our varying variables 1299 varying vec3 vVertexPosition; 1300 varying vec2 vDisplacementCoord; 1301 varying vec2 vTextureCoord; 1302 1303 // our textures samplers 1304 // notice how it matches our data-sampler attributes 1305 uniform sampler2D ripple2Texture; 1306 uniform sampler2D ripple2Displacement; 1307 1308 // effect control vars declared inside our javascript 1309 uniform float uTime; // time iterator to change waves position 1310 uniform float uEffectStrength; // 5.0 - 50.0 - waves amplitude 1311 uniform float uWavesForce; // 0.0 - 1.0 - fadeIn/fadeOut on mouse hover 1312 uniform float uWavesDirection; // 0 - horizontal, 1 - vertical 1313 1314 void main( void ) { 1315 1316 // our displacement texture 1317 vec2 displacementCoords = vDisplacementCoord; 1318 1319 displacementCoords = vec2( mod(displacementCoords.x - (1.0 - uWavesDirection) * uTime / ( 400.0 + uEffectStrength * 5.0 ), 1.0), 1320 mod(displacementCoords.y - uWavesDirection * uTime / ( 600.0 + uEffectStrength * 5.0 ), 1.0) 1321 ); 1322 vec4 displacementTexture = texture2D(ripple2Displacement, displacementCoords); 1323 1324 // image texture 1325 vec2 textureCoords = vTextureCoord; 1326 1327 // displace our pixels along both axis based on our time uniform and texture UVs 1328 // this will create a kind of water surface effect 1329 // try to comment a line or change the constants to see how it changes the effect 1330 // reminder : textures coords are ranging from 0.0 to 1.0 on both axis 1331 const float PI = 3.141592; 1332 1333 textureCoords.x += 1.0 / uEffectStrength / ( 2.5 + 1.5 * uWavesDirection ) * uWavesForce * displacementTexture.r; 1334 1335 textureCoords.y -= 1.0 / uEffectStrength / ( 2.0 + 1.5 * ( 1.0 - uWavesDirection ) ) * uWavesForce * displacementTexture.r; 1336 1337 vec4 finalColor = texture2D(ripple2Texture, textureCoords); 1338 1339 // handling premultiplied alpha and apply displacement 1340 finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a); 1341 1342 // apply our shader 1343 gl_FragColor = finalColor; 1344 } 1345 `; 1346 1347 return { 1348 vertexShader: vs, // our vertex shader ID 1349 fragmentShader: fs, // our fragment shader ID 1350// widthSegments: 10, 1351// heightSegments: 10, 1352 imageCover: false, // our displacement texture has to fit the plane 1353 uniforms: { // variables passed to shaders 1354 time: { 1355 name: "uTime", 1356 type: "1f", 1357 value: 0 1358 }, 1359 effectStrength: { 1360 name: "uEffectStrength", 1361 type: "1f", 1362 value: effectStrength 1363 }, 1364 wavesForce: { 1365 name: "uWavesForce", 1366 type: "1f", 1367 value: 0 1368 }, 1369 wavesDirection: { 1370 name: "uWavesDirection", 1371 type: "1f", 1372 value: wavesDirection 1373 } 1374 } 1375 }; 1376 } 1377 1378 // handle plane 1379 function handle_plane( plane ) { 1380 plane 1381 .onLoading(function() { 1382// console.log(plane.loadingManager.sourcesLoaded); 1383 }) 1384 .onReady(function() { 1385// console.log('Plane '+index+' of '+total+' is ready'); 1386 // first render plane 1387 if ( ! permanentDrawing ) curtains.needRender(); 1388 // init tweens 1389 plane.tweenForce = null; 1390 plane.tweenScale = null; 1391 // now that our plane is ready we can listen to mouse move event 1392 function mouse_move(e) { 1393 if ( ! mouseIn ) { 1394 mouse_enter(); 1395 } 1396 } 1397 function mouse_enter() { 1398 if ( ! mouseIn ) { 1399 mouseIn = true; 1400 change_waves_force( 1 ); 1401 change_scale( 1 ); 1402 } 1403 } 1404 function mouse_leave() { 1405 if ( mouseIn ) { 1406 mouseIn = false; 1407 change_waves_force( 0 ); 1408 change_scale( 0 ); 1409 } 1410 } 1411 elm.addEventListener("mousemove", mouse_move ); 1412 elm.addEventListener("touchmove", mouse_move );
1413 elm.addEventListener("mouseenter", mouse_enter ); 1414 elm.addEventListener("touchstart", mouse_enter ); 1415 elm.addEventListener("mouseleave", mouse_leave ); 1416 elm.addEventListener("touchend", mouse_leave ); 1417 }) 1418 .onRender(function() { 1419 plane.uniforms.time.value++; 1420 1421 }) 1422 .onAfterResize(function() { 1423// console.log('Plane '+index+' of '+total+' is resized'); 1424 }); 1425 1426 // Change wave force value 1427 function change_waves_force( to ) { 1428 if ( plane.tweenForce ) { 1429 tween_stop( plane.tweenForce ); 1430 } 1431 plane.tweenForce = tween_value( { 1432 start: plane.uniforms.wavesForce.value, 1433 end: to, 1434 time: 1.25, 1435 callbacks: { 1436 onUpdate: function(value) { 1437 plane.uniforms.wavesForce.value = value; 1438 }, 1439 onComplete: function() { 1440 tween_stop( plane.tweenForce ); 1441 plane.tweenForce = null; 1442 } 1443 } 1444 } ); 1445 } 1446 1447 // Change scale 1448 function change_scale( to ) { 1449 if ( plane.tweenScale ) { 1450 tween_stop( plane.tweenScale ); 1451 } 1452 if ( ! permanentDrawing ) { 1453 curtains.enableDrawing(); 1454 } 1455 plane.tweenScale = tween_value( { 1456 start: scaleFactor, 1457 end: to, 1458 time: 1.25, 1459 callbacks: { 1460 onUpdate: function(value) { 1461 scaleFactor = value; 1462 if ( scaleOnHover ) { 1463 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 1464 } 1465 }, 1466 onComplete: function() { 1467 tween_stop( plane.tweenScale ); 1468 plane.tweenScale = null; 1469 if ( ! permanentDrawing && to === 0 ) { 1470 curtains.disableDrawing(); 1471 } 1472 } 1473 } 1474 } ); 1475 } 1476 } 1477 }; 1478 1479 1480 1481 // Effect 'Smudge' 1482 //------------------------------------------- 1483 1484 // Create plane. 1485 // Attention! All callbacks must be in a global scope! 1486 window.trx_addons_image_effects_callback_smudge = function( curtains_global, elm, index, total ) { 1487 1488 var curtains = curtains_global ? curtains_global : null; 1489 1490 var enableDrawing = false; 1491 1492 // track the mouse positions to send it to the shaders 1493 var mousePosition = { 1494 x: 0, 1495 y: 0 1496 }; 1497 1498 // we will keep track of the last position in order to calculate the movement strength/delta 1499 var mouseLastPosition = { 1500 x: 0, 1501 y: 0 1502 }; 1503 1504 var mouseStrength = false; 1505 1506 var mouseIn = false; 1507 1508 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 1509 scaleFactor = 0; 1510 1511 var paddingOnHover = typeof trx_addons_apply_filters == 'function' 1512 ? trx_addons_apply_filters( 'trx_addons_filter_image_effects_padding', 0.04, 'smudge' ) 1513 : 0.04; 1514 1515 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 1516 1517 var deltas = { 1518 max: 0, 1519 applied: 0 1520 }; 1521 1522 var plane = null, 1523 parent = null, 1524 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 1525 img = img_all.length > 1 1526 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 1527 : elm.querySelector( 'img' ); 1528 1529 if ( img ) { 1530 if ( img_all.length > 1 ) { 1531 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 1532 } 1533 parent = img.parentNode; 1534 if ( img_all.length == 1 ) { 1535 parent.classList.add('trx_addons_image_effects_holder'); 1536 } 1537// img.setAttribute('crossorigin', 'anonymous'); 1538 img.setAttribute('data-sampler', 'smudgeTexture'); 1539 if ( ! globalCanvas ) { 1540 curtains = create_canvas(parent); 1541 if ( curtains ) jQuery(elm).data('curtains', curtains); 1542 } 1543 if ( curtains ) { 1544 if ( ! permanentDrawing ) curtains.disableDrawing(); 1545 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 1546 if ( plane ) { 1547 jQuery(elm).data('curtains-plane', plane); 1548 handle_plane( plane ); 1549 } 1550 } 1551 } 1552 1553 // Return plane params 1554 function get_params( elm, img, parent ) { 1555 var vs = ` 1556 #ifdef GL_ES 1557 precision mediump float; 1558 #endif 1559 1560 // default mandatory variables 1561 attribute vec3 aVertexPosition; 1562 attribute vec2 aTextureCoord; 1563 1564 uniform mat4 uMVMatrix; 1565 uniform mat4 uPMatrix; 1566 1567 // our texture matrix 1568 uniform mat4 smudgeTextureMatrix; 1569 1570 // custom variables 1571 varying vec3 vVertexPosition; 1572 varying vec2 vTextureCoord; 1573 uniform float uTime; 1574 //uniform vec2 uResolution; 1575 uniform vec2 uMousePosition; 1576 uniform float uMouseMoveStrength; 1577 uniform float uEffectStrength; 1578 uniform float uPadding; 1579 1580 void main() { 1581 vec3 vertexPosition = aVertexPosition; 1582 // get the distance between our vertex and the mouse position 1583 float distanceFromMouse = distance(uMousePosition, vec2(vertexPosition.x, vertexPosition.y)); 1584 // attenuate the effect based on mouse distance 1585 float distanceStrength = 0.4 / (distanceFromMouse + 0.4); 1586 // calculate our distortion effect 1587 float distortionEffect = distanceStrength * uMouseMoveStrength / uEffectStrength; 1588 // apply it to our vertex position 1589 vertexPosition.z += distortionEffect; 1590 //vertexPosition.x += distortionEffect * (uMousePosition.x - vertexPosition.x) * (uResolution.x / uResolution.y); 1591 vertexPosition.x += distortionEffect * (uMousePosition.x - vertexPosition.x); 1592 vertexPosition.y += distortionEffect * (uMousePosition.y - vertexPosition.y); 1593 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, (1.0 + uPadding)); 1594 // varyings 1595 vTextureCoord = (smudgeTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 1596 vVertexPosition = vertexPosition; 1597 } 1598 `; 1599 var fs = ` 1600 #ifdef GL_ES 1601 precision mediump float; 1602 #endif 1603 1604 varying vec3 vVertexPosition; 1605 varying vec2 vTextureCoord; 1606 uniform sampler2D smudgeTexture; 1607 1608 void main() { 1609 // apply our texture 1610 vec4 finalColor = texture2D(smudgeTexture, vTextureCoord); 1611 // fake shadows based on vertex position along Z axis 1612 finalColor.rgb -= clamp(-vVertexPosition.z, 0.0, 1.0); 1613 // fake lights based on vertex position along Z axis 1614 finalColor.rgb += clamp(vVertexPosition.z, 0.0, 1.0); 1615 // handling premultiplied alpha (useful if we were using a png with transparency) 1616 finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a); 1617 gl_FragColor = finalColor; 1618 } 1619 `; 1620 1621 return { 1622 vertexShader: vs, 1623 fragmentShader: fs, 1624 widthSegments: 20, 1625 heightSegments: 20, 1626 uniforms: { 1627 /* 1628 resolution: { // resolution of our plane 1629 name: "uResolution", 1630 type: "2f", // notice this is an length 2 array of floats 1631 value: [ parent.clientWidth, parent.clientHeight ] 1632 }, 1633 */ 1634 time: { // time uniform that will be updated at each draw call 1635 name: "uTime", 1636 type: "1f", 1637 value: 0 1638 }, 1639 mousePosition: { // our mouse position 1640 name: "uMousePosition", 1641 type: "2f", // again an array of floats 1642 value: [ mousePosition.x, mousePosition.y ] 1643 }, 1644 mouseMoveStrength: { // the mouse move strength 1645 name: "uMouseMoveStrength", 1646 type: "1f", 1647 value: 0 1648 }, 1649 effectStrength: { // the smudge strength 1650 name: "uEffectStrength", 1651 type: "1f", 1652 value: effectStrength 1653 }, 1654 padding: { // paddings around image on hover 1655 name: "uPadding", 1656 type: "1f", 1657 value: 0 1658 } 1659 } 1660 }; 1661 } 1662 1663 // handle plane 1664 function handle_plane( plane ) { 1665 plane 1666 .onLoading(function() { 1667 //console.log(plane.loadingManager.sourcesLoaded); 1668 }) 1669 .onReady(function() { 1670// console.log('Plane '+index+' of '+total+' is ready'); 1671 // set a fov of 35 to reduce perspective 1672 plane.setPerspective(35); 1673 // apply a little effect once everything is ready 1674 deltas.max = 2; 1675 // first render plane 1676 if ( ! permanentDrawing ) curtains.needRender(); 1677 // init tweens 1678 plane.tweenScale = null; 1679 // now that our plane is ready we can listen to mouse move event 1680 function mouse_move(e) { 1681 if ( ! mouseIn ) { 1682 mouse_enter(); 1683 } 1684 handle_movement(e, plane); 1685 } 1686 function mouse_enter() { 1687 if ( ! mouseIn ) { 1688 mouseIn = true; 1689 change_scale( 1 ); 1690 if ( paddingOnHover ) {
1691 change_padding(paddingOnHover); 1692 } 1693 } 1694 } 1695 function mouse_leave() { 1696 if ( mouseIn ) { 1697 mouseIn = false; 1698 change_scale( 0 ); 1699 if ( paddingOnHover ) { 1700 change_padding(0); 1701 } 1702 } 1703 } 1704 elm.addEventListener("mousemove", mouse_move ); 1705 elm.addEventListener("touchmove", mouse_move ); 1706 elm.addEventListener("mouseenter", mouse_enter ); 1707 elm.addEventListener("touchstart", mouse_enter ); 1708 elm.addEventListener("mouseleave", mouse_leave ); 1709 elm.addEventListener("touchend", mouse_leave ); 1710 }) 1711 .onRender(function() { 1712 // increment our time uniform 1713 plane.uniforms.time.value++; 1714 // decrease both deltas by damping : if the user doesn't move the mouse, effect will fade away 1715 deltas.applied += (deltas.max - deltas.applied) * 0.02; 1716 deltas.max += (0 - deltas.max) * 0.01; 1717 // send the new mouse move strength value 1718 plane.uniforms.mouseMoveStrength.value = deltas.applied; 1719 if ( ! permanentDrawing && ! enableDrawing && Math.abs(deltas.applied - deltas.max) < 0.001 ) { 1720 curtains.disableDrawing(); 1721 } 1722 }) 1723 .onAfterResize(function() { 1724// console.log('Plane '+index+' of '+total+' is resized'); 1725 /* 1726 var planeBoundingRect = plane.getBoundingRect(); 1727 plane.uniforms.resolution.value = [planeBoundingRect.width, planeBoundingRect.height]; 1728 */ 1729 }); 1730 } 1731 1732 // handle the mouse move event 1733 function handle_movement(e, plane) { 1734 1735 // update mouse last pos 1736 mouseLastPosition.x = mousePosition.x; 1737 mouseLastPosition.y = mousePosition.y; 1738 1739 var mouse = {}; 1740 1741 // touch event 1742 if (e.targetTouches) { 1743 mouse.x = globalCanvas ? e.targetTouches[0].clientX : e.targetTouches[0].layerX; 1744 mouse.y = globalCanvas ? e.targetTouches[0].clientY : e.targetTouches[0].layerY; 1745 1746 // mouse event 1747 } else { 1748 // In Chrome with custom scroll mouse coordinates in layerXY are incorrect 1749 // but in Mozilla mouse properties offsetXY always empty (equal to 0) 1750 mouse.x = globalCanvas ? e.clientX : ( e.offsetX !== 0 || e.offsetY !== 0 ? e.offsetX : e.layerX ); 1751 mouse.y = globalCanvas ? e.clientY : ( e.offsetX !== 0 || e.offsetY !== 0 ? e.offsetY : e.layerY ); 1752 } 1753 1754 // lerp the mouse position a bit to smoothen the overall effect 1755 mousePosition.x = lerp(mousePosition.x, mouse.x, 0.3); 1756 mousePosition.y = lerp(mousePosition.y, mouse.y, 0.3); 1757 1758 // convert our mouse/touch position to coordinates relative to the vertices of the plane 1759 var mouseCoords = globalCanvas 1760 ? plane.mouseToPlaneCoords(mousePosition.x, mousePosition.y) 1761 : mouse_to_plane_coords( plane, mousePosition ); 1762 1763 1764 // update our mouse position uniform 1765 plane.uniforms.mousePosition.value = [mouseCoords.x, mouseCoords.y]; 1766 1767 // calculate the mouse move strength 1768 if ( mouseStrength && mouseLastPosition.x && mouseLastPosition.y ) { 1769 var delta = Math.sqrt( Math.pow( mousePosition.x - mouseLastPosition.x, 2 ) + Math.pow( mousePosition.y - mouseLastPosition.y, 2 ) ) / 20; 1770 delta = Math.min(4, delta); 1771 // update max delta only if it increased 1772 if ( delta >= deltas.max ) { 1773 deltas.max = delta; 1774 } 1775 } else { 1776 deltas.max = 2; 1777 } 1778 } 1779 1780 // Change padding value 1781 function change_padding( to ) { 1782 if ( plane.tweenPadding ) { 1783 tween_stop( plane.tweenPadding ); 1784 } 1785 plane.tweenPadding = tween_value( { 1786 start: plane.uniforms.padding.value, 1787 end: to, 1788 time: 1.25, 1789 callbacks: { 1790 onUpdate: function(value) { 1791 plane.uniforms.padding.value = value; 1792 }, 1793 onComplete: function() { 1794 tween_stop( plane.tweenPadding ); 1795 plane.tweenPadding = null; 1796 } 1797 } 1798 } ); 1799 } 1800 1801 // Change scale 1802 function change_scale( to ) { 1803 if ( plane.tweenScale ) { 1804 tween_stop( plane.tweenScale ); 1805 } 1806 if ( ! permanentDrawing ) { 1807 enableDrawing = true; 1808 curtains.enableDrawing(); 1809 } 1810 plane.tweenScale = tween_value( { 1811 start: scaleFactor, 1812 end: to, 1813 time: 1.25, 1814 callbacks: { 1815 onUpdate: function(value) { 1816 scaleFactor = value; 1817 if ( scaleOnHover ) { 1818 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 1819 } 1820 }, 1821 onComplete: function() { 1822 tween_stop( plane.tweenScale ); 1823 plane.tweenScale = null; 1824 if ( ! permanentDrawing && to === 0 ) { 1825 enableDrawing = false;
1826 //curtains.disableDrawing(); 1827 } 1828 } 1829 } 1830 } ); 1831 } 1832 1833 }; 1834 1835 1836 1837 // Effect 'Tint' 1838 //------------------------------------------- 1839 1840 // Create plane. 1841 // Attention! All callbacks must be in a global scope! 1842 window.trx_addons_image_effects_callback_tint = function( curtains_global, elm, index, total ) { 1843 1844 var curtains = curtains_global ? curtains_global : null; 1845 1846 var mouseIn = false; 1847 1848 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 1849 scaleFactor = 0, 1850 tintColor = elm.getAttribute('data-image-effect-tint-color') || TRX_ADDONS_STORAGE['theme_accent_color']; 1851 1852 var plane = null, 1853 parent = null, 1854 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 1855 img = img_all.length > 1 1856 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 1857 : elm.querySelector( 'img' ); 1858 1859 if ( img ) { 1860 if ( img_all.length > 1 ) { 1861 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 1862 } 1863 parent = img.parentNode; 1864 if ( img_all.length == 1 ) { 1865 parent.classList.add('trx_addons_image_effects_holder'); 1866 } 1867// img.setAttribute('crossorigin', 'anonymous'); 1868 img.setAttribute('data-sampler', 'tintTexture'); 1869 if ( ! globalCanvas ) { 1870 curtains = create_canvas(parent); 1871 if ( curtains ) jQuery(elm).data('curtains', curtains); 1872 } 1873 if ( curtains ) { 1874 if ( ! permanentDrawing ) curtains.disableDrawing(); 1875 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 1876 if ( plane ) { 1877 jQuery(elm).data('curtains-plane', plane); 1878 handle_plane( plane ); 1879 } 1880 } 1881 } 1882 1883 // Return plane params 1884 function get_params( elm, img, parent ) { 1885 1886 var vs = ` 1887 #ifdef GL_ES 1888 precision mediump float; 1889 #endif 1890 1891 vec3 permute(vec3 x) { 1892 return mod((x*34.0+1.0)*x, 289.0); 1893 } 1894 1895 float snoise(vec2 v) { 1896 const vec4 C = vec4(0.211325, 0.366025, -0.57735, 0.02439); 1897 vec2 i = floor(v + dot(v, C.yy)), 1898 x0 = v - i + dot(i, C.xx), 1899 i1; 1900 i1 = x0.x > x0.y ? vec2(1.0, 0.0) : vec2(0.0,1.0); 1901 vec4 x12 = x0.xyxy + C.xxzz; 1902 x12.xy -= i1, 1903 i = mod(i, 289.0); 1904 vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0,i1.x, 1.0)), 1905 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); 1906 m = m * m, m = m * m; 1907 vec3 x = 2.0 * fract(p * C.www) - 1.0, 1908 h = abs(x) - 0.5, 1909 ox = floor(x + 0.5), 1910 a0 = x - ox; 1911 m *= 1.792843 - 0.853735 * (a0 * a0 + h * h); 1912 vec3 g; 1913 g.x = a0.x * x0.x + h.x * x0.y, 1914 g.yz = a0.yz * x12.xz + h.yz * x12.yw; 1915 return 130.0 * dot(m, g); 1916 } 1917 1918 attribute vec3 aVertexPosition; 1919 attribute vec2 aTextureCoord; 1920 1921 uniform mat4 uMVMatrix, uPMatrix, tintTextureMatrix; 1922 uniform float uTime, uMouseOver; 1923 1924 varying vec2 vTintTextureCoord; 1925 varying vec3 vVertexPosition, vNoise; 1926 1927 void main(){ 1928 vec3 vP = aVertexPosition; 1929 vec2 sUV = vec2(vP.x * 0.75, vP.y * 0.75); 1930 vec3 sN = vec3(snoise(sUV * 2.0 - uTime / 360.0)); 1931 vP.z = 0.0, 1932 gl_Position = uPMatrix * uMVMatrix * vec4(vP, 1.0), 1933 vVertexPosition = vP, 1934 vTintTextureCoord = (tintTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy, 1935 vNoise = sN; 1936 } 1937 `; 1938 var fs = ` 1939 #ifdef GL_ES 1940 precision mediump float; 1941 #endif 1942 varying vec2 vTintTextureCoord; 1943 varying vec3 vVertexPosition; 1944 varying vec3 vNoise; 1945 1946 uniform sampler2D tintTexture; 1947 uniform float uMouseOver; 1948 uniform vec3 uColor; 1949 1950 void main(){ 1951 vec4 f = texture2D(tintTexture, vTintTextureCoord); 1952 f.rgb -= clamp(-vVertexPosition.z / 10.0, 0.0, 1.0); 1953 f.rgb += clamp( vVertexPosition.z / 12.5, 0.0, 1.0); 1954 vec4 lC = vec4(0.299, 0.587, 0.114, 0.0), 1955 l = vec4(1.0), 1956 tint = vec4(uColor.r / 255.0, uColor.g / 255.0, uColor.b / 255.0, 1.0); 1957 float lM = dot(f, lC), 1958 mN = clamp(uMouseOver * (1.0 - vNoise.r) - 1.0 + uMouseOver * 2.0, 0.0, 1.0); 1959 vec4 mC = (l + tint) / vec4(2.0), 1960 dT = lM >= 0.45 ? mix(mC, l, smoothstep(0.45, 0.93125, lM)) : mix(tint, mC, smoothstep(-0.03125, 0.45, lM)); 1961 f = mix(dT, f, step(0.9, mN)); 1962 f = vec4(f.rgb * f.a, f.a); 1963 gl_FragColor = f; 1964 } 1965 `; 1966 1967 return { 1968 vertexShader: vs, 1969 fragmentShader: fs, 1970 widthSegments: 5, 1971 heightSegments: 40, 1972 fov: 45, 1973 drawCheckMargins: { 1974 top: 15, 1975 right: 0, 1976 bottom: 15, 1977 left: 0 1978 }, 1979 uniforms: { 1980 time: { 1981 name: "uTime", 1982 type: "1f", 1983 value: 0 // 180 * index 1984 }, 1985 mouseOver: { 1986 name: "uMouseOver", 1987 type: "1f", 1988 value: 0 1989 }, 1990 color: { 1991 name: "uColor", 1992 type: "3f", 1993 value: trx_addons_rgb2components(tintColor) 1994 } 1995 } 1996 }; 1997 } 1998 1999 // handle plane 2000 function handle_plane( plane ) { 2001 plane 2002 .onReady(function() { 2003// console.log('Plane '+index+' of '+total+' is ready'); 2004 // first render plane 2005 if ( ! permanentDrawing ) curtains.needRender(); 2006 // init tweens 2007 plane.tween = null; 2008 plane.tweenScale = null; 2009 // now that our plane is ready we can listen to mouse move event 2010 function mouse_move(e) { 2011 if ( ! mouseIn ) { 2012 mouse_enter(); 2013 } 2014 } 2015 function mouse_enter() { 2016 if ( ! mouseIn ) { 2017 mouseIn = true; 2018 change_mouse_over( 1 ); 2019 change_scale( 1 ); 2020 } 2021 } 2022 function mouse_leave() { 2023 if ( mouseIn ) { 2024 mouseIn = false;
2025 change_mouse_over( 0 ); 2026 change_scale( 0 ); 2027 } 2028 } 2029 elm.addEventListener("mousemove", mouse_move ); 2030 elm.addEventListener("touchmove", mouse_move ); 2031 elm.addEventListener("mouseenter", mouse_enter ); 2032 elm.addEventListener("touchstart", mouse_enter ); 2033 elm.addEventListener("mouseleave", mouse_leave ); 2034 elm.addEventListener("touchend", mouse_leave ); 2035 }) 2036 .onRender(function() { 2037 plane.uniforms.time.value++; 2038 }); 2039 } 2040 2041 // Change wave force value 2042 function change_mouse_over( to ) { 2043 if ( plane.tween ) { 2044 tween_stop( plane.tween ); 2045 } 2046 plane.tween = tween_value( { 2047 start: plane.uniforms.mouseOver.value, 2048 end: to, 2049 time: 1.25, 2050 callbacks: { 2051 onUpdate: function(value) { 2052 plane.uniforms.mouseOver.value = value; 2053 }, 2054 onComplete: function() { 2055 tween_stop( plane.tween ); 2056 plane.tween = null 2057 } 2058 } 2059 } ); 2060 } 2061 2062 // Change scale 2063 function change_scale( to ) { 2064 if ( plane.tweenScale ) { 2065 tween_stop( plane.tweenScale ); 2066 } 2067 if ( ! permanentDrawing ) { 2068 curtains.enableDrawing(); 2069 } 2070 plane.tweenScale = tween_value( { 2071 start: scaleFactor, 2072 end: to, 2073 time: 1.25, 2074 callbacks: { 2075 onUpdate: function(value) { 2076 scaleFactor = value; 2077 if ( scaleOnHover ) { 2078 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 2079 } 2080 }, 2081 onComplete: function() { 2082 tween_stop( plane.tweenScale ); 2083 plane.tweenScale = null; 2084 if ( ! permanentDrawing && to === 0 ) { 2085 curtains.disableDrawing(); 2086 } 2087 } 2088 } 2089 } ); 2090 } 2091 }; 2092 2093 2094 2095 // Effect 'Swap' 2096 //------------------------------------------- 2097 2098 // Create plane. 2099 // Attention! All callbacks must be in a global scope! 2100 window.trx_addons_image_effects_callback_swap = function( curtains_global, elm, index, total ) { 2101 2102 var curtains = curtains_global ? curtains_global : null; 2103 2104 // Common vars 2105 var mouseIn = false; 2106 2107 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 2108 scaleFactor = 0; 2109 2110 var activeImage = 0; 2111 2112 // Curtains init 2113 var plane = null, 2114 parent = null, 2115 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 2116 img = img_all.length > 1 2117 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 2118 : elm.querySelector( 'img' ); 2119 2120 if ( img ) { 2121 if ( img_all.length > 1 ) { 2122 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 2123 } 2124 parent = img.parentNode; 2125 if ( img_all.length == 1 ) { 2126 parent.classList.add('trx_addons_image_effects_holder'); 2127 } 2128// img.setAttribute('crossorigin', 'anonymous'); 2129 img.setAttribute('data-sampler', 'swapTexture'); 2130 var swap_url = elm.getAttribute('data-image-effect-swap-image'); 2131 if ( swap_url ) { 2132 var swap_img = document.createElement("img"); 2133// swap_img.setAttribute('crossorigin', 'anonymous'); 2134 swap_img.setAttribute('src', swap_url); 2135 swap_img.setAttribute('data-sampler', 'swap2Texture'); 2136 swap_img.classList.add('trx_addons_image_effects_swap_image'); 2137 parent.appendChild(swap_img); 2138 $document.on('action.after_add_content', function(e, cont) { 2139 cont.find( '.trx_addons_image_effects_swap_image' ).remove(); 2140 }); 2141 } 2142 var displacement_url = elm.getAttribute('data-image-effect-displacement'); 2143 if ( displacement_url ) { 2144 var displacement_img = document.createElement("img"); 2145// displacement_img.setAttribute('crossorigin', 'anonymous'); 2146 displacement_img.setAttribute('src', displacement_url); 2147 displacement_img.setAttribute('data-sampler', 'swapDisplacement'); 2148 displacement_img.classList.add('trx_addons_image_effects_swap_displacement'); 2149 parent.appendChild(displacement_img); 2150 $document.on('action.after_add_content', function(e, cont) { 2151 cont.find( '.trx_addons_image_effects_swap_displacement' ).remove(); 2152 }); 2153 } 2154 if ( ! globalCanvas ) { 2155 curtains = create_canvas(parent); 2156 if ( curtains ) jQuery(elm).data('curtains', curtains); 2157 } 2158 if ( curtains ) { 2159 if ( ! permanentDrawing ) curtains.disableDrawing(); 2160 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 2161 if ( plane ) { 2162 jQuery(elm).data('curtains-plane', plane); 2163 handle_plane( plane ); 2164 } 2165 } 2166 } 2167 2168 // Return plane params 2169 function get_params() { 2170 var vs = ` 2171 #ifdef GL_ES 2172 precision mediump float; 2173 #endif 2174 2175 // default mandatory variables 2176 attribute vec3 aVertexPosition; 2177 attribute vec2 aTextureCoord; 2178 2179 uniform mat4 uMVMatrix; 2180 uniform mat4 uPMatrix; 2181 2182 // our texture matrices 2183 // notice how it matches our data-sampler attributes + "Matrix" 2184 uniform mat4 swapTextureMatrix; 2185 uniform mat4 swap2TextureMatrix; 2186 2187 // varying variables 2188 varying vec3 vVertexPosition; 2189 2190 // our displacement texture will use original texture coords attributes 2191 varying vec2 vTextureCoord; 2192 2193 // our image will use texture coords based on their texture matrices 2194 varying vec2 vSwapTextureCoord; 2195 varying vec2 vSwap2TextureCoord; 2196 2197 // custom uniforms 2198 uniform float uTime; 2199 2200 void main() { 2201 vec3 vertexPosition = aVertexPosition; 2202 2203 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0
2203); 2204 2205 // varying variables 2206 // texture coords attributes because we want our displacement texture to be contained 2207 vTextureCoord = aTextureCoord; 2208 // our image texture coords based on their texture matrices 2209 vSwapTextureCoord = (swapTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2210 vSwap2TextureCoord = (swap2TextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2211 // vertex position as usual 2212 vVertexPosition = vertexPosition; 2213 } 2214 `; 2215 2216 var fs = ` 2217 #ifdef GL_ES 2218 precision mediump float; 2219 #endif 2220 2221 // all our varying variables 2222 varying vec3 vVertexPosition; 2223 varying vec2 vTextureCoord; 2224 varying vec2 vSwapTextureCoord; 2225 varying vec2 vSwap2TextureCoord; 2226 2227 // custom uniforms 2228 uniform float uTime; 2229 2230 // our textures samplers 2231 // notice how it matches our data-sampler attributes 2232 uniform sampler2D swapTexture; 2233 uniform sampler2D swap2Texture; 2234 uniform sampler2D swapDisplacement; 2235 2236 void main( void ) { 2237 // our texture coords 2238 vec2 textureCoords = vTextureCoord; 2239 2240 // our displacement texture 2241 vec4 displacementTexture = texture2D(swapDisplacement, textureCoords); 2242 2243 // our displacement factor is a float varying from 1 to 0 based on the timer 2244 float displacementFactor = 1.0 - (cos(uTime / (60.0 / 3.141592)) + 1.0) / 2.0; 2245 2246 // the effect factor will tell which way we want to displace our pixels 2247 // the farther from the center of the videos, the stronger it will be 2248 vec2 effectFactor = vec2((textureCoords.x - 0.5) * 0.75, (textureCoords.y - 0.5) * 0.75
2248); 2249 2250 // calculate our displaced coordinates of the first video 2251 vec2 firstDisplacementCoords = vec2(vSwapTextureCoord.x - displacementFactor * (displacementTexture.r * effectFactor.x), vSwapTextureCoord.y- displacementFactor * (displacementTexture.r * effectFactor.y)); 2252 // opposite displacement effect on the second video 2253 vec2 secondDisplacementCoords = vec2(vSwap2TextureCoord.x - (1.0 - displacementFactor) * (displacementTexture.r * effectFactor.x), vSwap2TextureCoord.y - (1.0 - displacementFactor) * (displacementTexture.r * effectFactor.y)); 2254 2255 // apply the textures 2256 vec4 firstDistortedColor = texture2D(swapTexture, firstDisplacementCoords); 2257 vec4 secondDistortedColor = texture2D(swap2Texture, secondDisplacementCoords); 2258 2259 // blend both textures based on our displacement factor 2260 vec4 finalColor = mix(firstDistortedColor, secondDistortedColor, displacementFactor); 2261 2262 // handling premultiplied alpha 2263 finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a); 2264 2265 // apply our shader 2266 gl_FragColor = finalColor; 2267 } 2268 `; 2269 2270 return { 2271 vertexShader: vs, // our vertex shader ID 2272 fragmentShader: fs, // our fragment shader ID 2273// widthSegments: 10, 2274// heightSegments: 10, 2275 imageCover: false, // our displacement texture has to fit the plane 2276 uniforms: { // variables passed to shaders 2277 time: { 2278 name: "uTime", 2279 type: "1f", 2280 value: 0 2281 } 2282 } 2283 }; 2284 } 2285 2286 // handle plane 2287 function handle_plane( plane ) { 2288 plane 2289 .onLoading(function() { 2290// console.log(plane.loadingManager.sourcesLoaded); 2291 }) 2292 .onReady(function() { 2293// console.log('Plane '+index+' of '+total+' is ready'); 2294 // first render plane 2295 if ( ! permanentDrawing ) curtains.needRender(); 2296 // init tweens 2297 plane.tweenScale = null; 2298 // now that our plane is ready we can listen to mouse move event 2299 function mouse_move(e) { 2300 if ( ! mouseIn ) { 2301 mouse_enter(); 2302 } 2303 } 2304 function mouse_enter() { 2305 if ( ! mouseIn ) { 2306 mouseIn = true; 2307 activeImage = 1; 2308 change_scale( 1 ); 2309 } 2310 } 2311 function mouse_leave() { 2312 if ( mouseIn ) { 2313 mouseIn = false; 2314 activeImage = 0; 2315 change_scale( 0 ); 2316 } 2317 } 2318 elm.addEventListener("mousemove", mouse_move ); 2319 elm.addEventListener("touchmove", mouse_move ); 2320 elm.addEventListener("mouseenter", mouse_enter ); 2321 elm.addEventListener("touchstart", mouse_enter ); 2322 elm.addEventListener("mouseleave", mouse_leave ); 2323 elm.addEventListener("touchend", mouse_leave ); 2324 }) 2325 .onRender(function() { 2326 plane.uniforms.time.value = activeImage == 1 ? Math.min(60, plane.uniforms.time.value + 1) : Math.max(0, plane.uniforms.time.value - 1); 2327 2328 }) 2329 .onAfterResize(function() { 2330// console.log('Plane '+index+' of '+total+' is resized'); 2331 }); 2332 2333 // Change scale 2334 function change_scale( to ) { 2335 if ( plane.tweenScale ) { 2336 tween_stop( plane.tweenScale ); 2337 } 2338 if ( ! permanentDrawing ) { 2339 curtains.enableDrawing(); 2340 } 2341 plane.tweenScale = tween_value( { 2342 start: scaleFactor, 2343 end: to, 2344 time: 1.25, 2345 callbacks: { 2346 onUpdate: function(value) { 2347 scaleFactor = value; 2348 if ( scaleOnHover ) { 2349 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 2350 } 2351 }, 2352 onComplete: function() { 2353 tween_stop( plane.tweenScale ); 2354 plane.tweenScale = null; 2355 if ( ! permanentDrawing ) { 2356 curtains.disableDrawing(); 2357 } 2358 } 2359 } 2360 } ); 2361 } 2362 } 2363 }; 2364 2365 2366 2367 // Effect 'Fish' 2368 //------------------------------------------- 2369 2370 // Create plane. 2371 // Attention! All callbacks must be in a global scope! 2372 window.trx_addons_image_effects_callback_fish = function( curtains_global, elm, index, total ) { 2373 2374 var curtains = curtains_global ? curtains_global : null; 2375 2376 // Common vars 2377 var mouseIn = false; 2378 2379 // track the mouse positions to send it to the shaders 2380 var mousePosition = { 2381 x: 0, 2382 y: 0 2383 }; 2384 2385 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 2386 scaleFactor = 0; 2387 2388 var activeImage = 0; 2389 2390 // Curtains init 2391 var plane = null, 2392 parent = null, 2393 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 2394 img = img_all.length > 1 2395 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 2396 : elm.querySelector( 'img' ); 2397 2398 if ( img ) { 2399 if ( img_all.length > 1 ) { 2400 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 2401 } 2402 parent = img.parentNode; 2403 if ( img_all.length == 1 ) { 2404 parent.classList.add('trx_addons_image_effects_holder'); 2405 } 2406// img.setAttribute('crossorigin', 'anonymous'); 2407 img.setAttribute('data-sampler', 'swapTexture'); 2408 var swap_url = elm.getAttribute('data-image-effect-swap-image'); 2409 if ( swap_url ) { 2410 var swap_img = document.createElement("img"); 2411// swap_img.setAttribute('crossorigin', 'anonymous'); 2412 swap_img.setAttribute('src', swap_url); 2413 swap_img.setAttribute('data-sampler', 'swap2Texture'); 2414 swap_img.classList.add('trx_addons_image_effects_swap_image'); 2415 parent.appendChild(swap_img);
2416 $document.on('action.after_add_content', function(e, cont) { 2417 cont.find( '.trx_addons_image_effects_swap_image' ).remove(); 2418 }); 2419 } 2420 var displacement_url = elm.getAttribute('data-image-effect-displacement'); 2421 if ( displacement_url ) { 2422 var displacement_img = document.createElement("img"); 2423// displacement_img.setAttribute('crossorigin', 'anonymous'); 2424 displacement_img.setAttribute('src', displacement_url); 2425 displacement_img.setAttribute('data-sampler', 'swapDisplacement'); 2426 displacement_img.classList.add('trx_addons_image_effects_swap_displacement'); 2427 parent.appendChild(displacement_img); 2428 $document.on('action.after_add_content', function(e, cont) { 2429 cont.find( '.trx_addons_image_effects_swap_displacement' ).remove(); 2430 }); 2431 } 2432 if ( ! globalCanvas ) { 2433 curtains = create_canvas(parent); 2434 if ( curtains ) jQuery(elm).data('curtains', curtains); 2435 } 2436 if ( curtains ) { 2437 if ( ! permanentDrawing ) curtains.disableDrawing(); 2438 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 2439 if ( plane ) { 2440 jQuery(elm).data('curtains-plane', plane); 2441 handle_plane( plane ); 2442 } 2443 } 2444 } 2445 2446 // Return plane params 2447 function get_params() { 2448 var vs = ` 2449 #ifdef GL_ES 2450 precision mediump float; 2451 #endif 2452 2453 // default mandatory variables 2454 attribute vec3 aVertexPosition; 2455 attribute vec2 aTextureCoord; 2456 2457 uniform mat4 uMVMatrix; 2458 uniform mat4 uPMatrix; 2459 2460 // our texture matrices 2461 // notice how it matches our data-sampler attributes + "Matrix" 2462 uniform mat4 swapTextureMatrix; 2463 uniform mat4 swap2TextureMatrix; 2464 2465 // varying variables 2466 varying vec3 vVertexPosition; 2467 2468 // our displacement texture will use original texture coords attributes 2469 varying vec2 vTextureCoord; 2470 2471 // our image will use texture coords based on their texture matrices 2472 varying vec2 vSwapTextureCoord; 2473 varying vec2 vSwap2TextureCoord; 2474 2475 // custom uniforms 2476 uniform float uTime; 2477 2478 void main() { 2479 vec3 vertexPosition = aVertexPosition; 2480 2481 gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0
2481); 2482 2483 // varying variables 2484 // texture coords attributes because we want our displacement texture to be contained 2485 vTextureCoord = aTextureCoord; 2486 // our image texture coords based on their texture matrices 2487 vSwapTextureCoord = (swapTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2488 vSwap2TextureCoord = (swap2TextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2489 // vertex position as usual 2490 vVertexPosition = vertexPosition; 2491 } 2492 `; 2493 2494 var fs = ` 2495 #ifdef GL_ES 2496 precision mediump float; 2497 #endif 2498 2499 // all our varying variables 2500 varying vec3 vVertexPosition; 2501 varying vec2 vTextureCoord; 2502 varying vec2 vSwapTextureCoord; 2503 varying vec2 vSwap2TextureCoord; 2504 2505 // custom uniforms 2506 uniform float uPR; 2507 uniform float uScale; 2508 uniform float uEffect; 2509 uniform float uTime; 2510 2511 uniform vec2 uRes; 2512 uniform vec2 uMousePosition; 2513 2514 // our textures samplers 2515 // notice how it matches our data-sampler attributes 2516 uniform sampler2D swapTexture; 2517 uniform sampler2D swap2Texture; 2518 uniform sampler2D swapDisplacement; 2519 2520 float circle( in vec2 _st, in float _radius, in float blurriness ) { 2521 vec2 dist = _st; 2522 return 1. - smoothstep( _radius - ( _radius * blurriness ), _radius + ( _radius * blurriness ), dot( dist, dist ) * 4.0 ); 2523 } 2524 2525 void main( void ) { 2526 // our texture coords 2527 vec2 textureCoords = vTextureCoord; 2528 2529 //vec2 st = textureCoords - vec2(0.5); 2530 // Manage the device ratio 2531 vec2 res = uRes * uPR; 2532 vec2 st = gl_FragCoord.xy / res.xy - vec2(0.5); 2533 // tip: use the following formula to keep the good ratio of your coordinates 2534 st.y *= uRes.y / uRes.x; 2535 2536 vec2 mouse = uMousePosition * -0.5; 2537 // tip2: do the same for your mouse 2538 mouse.y *= uRes.y / uRes.x; 2539 //mouse *= -1.; 2540 2541 vec2 circlePos = st + mouse; 2542 float c = circle( circlePos, 0.3 * uScale, 2. ); 2543 2544 // our displacement texture 2545 vec4 displacementTexture = texture2D(swapDisplacement, textureCoords); 2546 2547 // our displacement factor is a float varying from 1 to 0 based on the timer 2548 float displacementFactor = ( 1.0 - (cos(uTime / (60.0 / 3.141592)) + 1.0) / 2.0 * uEffect ) * c; 2549 2550 // the effect factor will tell which way we want to displace our pixels 2551 // the farther from the center of the videos, the stronger it will be 2552 vec2 effectFactor = vec2( (textureCoords.x - 0.5) * 0.75 * uEffect, (textureCoords.y - 0.5) * 0.75 * uEffect ); 2553 2554 // calculate our displaced coordinates of the first video 2555 vec2 firstDisplacementCoords = vec2(vSwapTextureCoord.x - displacementFactor * (displacementTexture.r * effectFactor.x), vSwapTextureCoord.y - displacementFactor * (displacementTexture.r * effectFactor.y)); 2556 // opposite displacement effect on the second video 2557 vec2 secondDisplacementCoords = vec2(vSwap2TextureCoord.x - (1.0 - displacementFactor) * (displacementTexture.r * effectFactor.x), vSwap2TextureCoord.y - (1.0 - displacementFactor) * (displacementTexture.r * effectFactor.y)); 2558 2559 // apply the textures 2560 vec4 firstDistortedColor = texture2D(swapTexture, firstDisplacementCoords); 2561 vec4 secondDistortedColor = texture2D(swap2Texture, secondDisplacementCoords); 2562 2563 // blend both textures based on our displacement factor 2564 vec4 finalColor = mix(firstDistortedColor, secondDistortedColor, displacementFactor); 2565 2566 // handling premultiplied alpha 2567 finalColor = vec4(finalColor.rgb * finalColor.a, finalColor.a); 2568 2569 // apply our shader 2570 gl_FragColor = finalColor; 2571 } 2572 `; 2573 return { 2574 vertexShader: vs, // our vertex shader ID 2575 fragmentShader: fs, // our fragment shader ID 2576// widthSegments: 10, 2577// heightSegments: 10, 2578 imageCover: false, // our displacement texture has to fit the plane 2579 uniforms: { // variables passed to shaders 2580 mousePosition: { // our mouse position 2581 name: "uMousePosition", 2582 type: "2f", 2583 value: [ mousePosition.x, mousePosition.y ] 2584 }, 2585 imageResolution: { 2586 name: "uRes", 2587 type: "2f", 2588 value: [ img.clientWidth, img.clientHeight ] 2589 }, 2590 pixelRatio: { 2591 name: "uPR", 2592 type: "1f", 2593 value: window.devicePixelRatio.toFixed(1) 2594 }, 2595 scaleFactor: { 2596 name: "uScale", 2597 type: "1f", 2598 value: 0 2599 }, 2600 useEffect: { 2601 name: "uEffect", 2602 type: "1f", 2603 value: displacement_url != '' ? 1 : 0 2604 }, 2605 time: { 2606 name: "uTime", 2607 type: "1f", 2608 value: 0 2609 } 2610 } 2611 }; 2612 } 2613 2614 // handle plane 2615 function handle_plane( plane ) { 2616 plane 2617 .onLoading(function() { 2618// console.log(plane.loadingManager.sourcesLoaded); 2619 }) 2620 .onReady(function() { 2621// console.log('Plane '+index+' of '+total+' is ready'); 2622 // first render plane 2623 if ( ! permanentDrawing ) curtains.needRender(); 2624 // init tweens 2625 plane.tweenScale = null; 2626 // now that our plane is ready we can listen to mouse move event 2627 function mouse_move(e) { 2628 if ( ! mouseIn ) { 2629 mouse_enter(); 2630 } 2631 handle_movement(e, plane); 2632 } 2633 function mouse_enter() { 2634 if ( ! mouseIn ) { 2635 mouseIn = true; 2636 activeImage = 1; 2637 change_scale( 1 ); 2638 } 2639 } 2640 function mouse_leave() { 2641 if ( mouseIn ) { 2642 mouseIn = false;
2643 activeImage = 0; 2644 change_scale( 0 ); 2645 } 2646 } 2647 elm.addEventListener("mousemove", mouse_move ); 2648 elm.addEventListener("touchmove", mouse_move ); 2649 elm.addEventListener("mouseenter", mouse_enter ); 2650 elm.addEventListener("touchstart", mouse_enter ); 2651 elm.addEventListener("mouseleave", mouse_leave ); 2652 elm.addEventListener("touchend", mouse_leave ); 2653 }) 2654 .onRender(function() { 2655 plane.uniforms.time.value = activeImage == 1 ? Math.min(60, plane.uniforms.time.value + 1) : Math.max(0, plane.uniforms.time.value - 1); 2656 }) 2657 .onAfterResize(function() { 2658// console.log('Plane '+index+' of '+total+' is resized'); 2659 }); 2660 2661 // Change scale 2662 function change_scale( to ) { 2663 if ( plane.tweenScale ) { 2664 tween_stop( plane.tweenScale ); 2665 } 2666 if ( ! permanentDrawing && to == 1 ) { 2667 curtains.enableDrawing(); 2668 } 2669 plane.tweenScale = tween_value( { 2670 start: scaleFactor, 2671 end: to, 2672 time: 1.25, 2673 callbacks: { 2674 onUpdate: function(value) { 2675 scaleFactor = value; 2676 plane.uniforms.scaleFactor.value = value; 2677 if ( scaleOnHover ) { 2678 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 2679 } 2680 }, 2681 onComplete: function() { 2682 tween_stop( plane.tweenScale ); 2683 plane.tweenScale = null; 2684 if ( ! permanentDrawing && to == 0 ) { 2685 curtains.disableDrawing(); 2686 } 2687 } 2688 } 2689 } ); 2690 } 2691 } 2692 2693 // handle the mouse move event 2694 function handle_movement(e, plane) { 2695 2696 var mouse = get_mouse_position_from_event( e ); 2697 2698 // lerp the mouse position a bit to smoothen the overall effect 2699 mousePosition.x = lerp(mousePosition.x, mouse.x, 0.3); 2700 mousePosition.y = lerp(mousePosition.y, mouse.y, 0.3); 2701 2702 // convert our mouse/touch position to coordinates relative to the vertices of the plane 2703 var mouseCoords = globalCanvas 2704 ? plane.mouseToPlaneCoords(mousePosition.x, mousePosition.y) 2705 : mouse_to_plane_coords( plane, mousePosition ); 2706 2707 2708 // update our mouse position uniform 2709 plane.uniforms.mousePosition.value = [mouseCoords.x, mouseCoords.y]; 2710 } 2711 }; 2712 2713 2714 2715 // Effect 'Blot' 2716 //------------------------------------------- 2717 2718 // Create plane. 2719 // Attention! All callbacks must be in a global scope! 2720 window.trx_addons_image_effects_callback_blot = function( curtains_global, elm, index, total ) { 2721 2722 var curtains = curtains_global ? curtains_global : null; 2723 2724 // Common vars 2725 var mouseIn = false; 2726 2727 // track the mouse positions to send it to the shaders 2728 var mousePosition = { 2729 x: 0, 2730 y: 0 2731 }; 2732 2733 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 2734 scaleFactor = 0, 2735 tintColor = elm.getAttribute('data-image-effect-tint-color') || ''; 2736 2737 2738 var effectStrength = Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30.0 ) ); 2739 var wavesDirection = Math.max(0.0, Math.min(1.0, elm.getAttribute('data-image-effect-waves-direction') ) ); 2740 2741 var activeImage = 0; 2742 2743 // Curtains init 2744 var plane = null, 2745 parent = null, 2746 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 2747 img = img_all.length > 1 2748 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 2749 : elm.querySelector( 'img' ); 2750 2751 if ( img ) { 2752 if ( img_all.length > 1 ) { 2753 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 2754 } 2755 parent = img.parentNode; 2756 if ( img_all.length == 1 ) { 2757 parent.classList.add('trx_addons_image_effects_holder'); 2758 } 2759// img.setAttribute('crossorigin', 'anonymous'); 2760 img.setAttribute('data-sampler', 'swapTexture'); 2761 var swap_url = elm.getAttribute('data-image-effect-swap-image'); 2762 if ( swap_url ) { 2763 var swap_img = document.createElement("img"); 2764// swap_img.setAttribute('crossorigin', 'anonymous'); 2765 swap_img.setAttribute('src', swap_url); 2766 swap_img.setAttribute('data-sampler', 'swap2Texture'); 2767 swap_img.classList.add('trx_addons_image_effects_swap_image'); 2768 parent.appendChild(swap_img);
2769 $document.on('action.after_add_content', function(e, cont) { 2770 cont.find( '.trx_addons_image_effects_swap_image' ).remove(); 2771 }); 2772 } 2773 if ( ! globalCanvas ) { 2774 curtains = create_canvas(parent); 2775 if ( curtains ) jQuery(elm).data('curtains', curtains); 2776 } 2777 if ( curtains ) { 2778 if ( ! permanentDrawing ) curtains.disableDrawing(); 2779 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 2780 if ( plane ) { 2781 jQuery(elm).data('curtains-plane', plane); 2782 handle_plane( plane ); 2783 } 2784 } 2785 } 2786 2787 // Return plane params 2788 function get_params() { 2789 var vs = ` 2790 #ifdef GL_ES 2791 precision mediump float; 2792 #endif 2793 2794 // default mandatory variables 2795 attribute vec3 aVertexPosition; 2796 attribute vec2 aTextureCoord; 2797 2798 uniform mat4 uPMatrix; 2799 uniform mat4 uMVMatrix; 2800 2801 // our texture matrices 2802 // notice how it matches our data-sampler attributes + "Matrix" 2803 uniform mat4 swapTextureMatrix; 2804 uniform mat4 swap2TextureMatrix; 2805 2806 // our displacement texture will use original texture coords attributes 2807 varying vec2 vTextureCoord; 2808 2809 // our image will use texture coords based on their texture matrices 2810 varying vec2 vSwapTextureCoord; 2811 varying vec2 vSwap2TextureCoord; 2812 2813 void main() { 2814 // texture coords attributes because we want our displacement texture to be contained 2815 // our image texture coords based on their texture matrices 2816 vTextureCoord = aTextureCoord; 2817 vSwapTextureCoord = (swapTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2818 vSwap2TextureCoord = (swap2TextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy; 2819 2820 gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0
2820); 2821 } 2822 `; 2823 2824 var fs = ` 2825 #ifdef GL_ES 2826 precision mediump float; 2827 #endif 2828 2829 // all our varying variables 2830 //varying vec3 vVertexPosition; 2831 varying vec2 vTextureCoord; 2832 varying vec2 vSwapTextureCoord; 2833 varying vec2 vSwap2TextureCoord; 2834 2835 // custom uniforms 2836 uniform float uPR; 2837 uniform float uScale; 2838 uniform float uTint; 2839 uniform float uWavesTime; 2840 uniform float uTime; 2841 2842 uniform vec2 uRes; 2843 uniform vec2 uMousePosition; 2844 uniform vec3 uColor; 2845 2846 // our textures samplers 2847 // notice how it matches our data-sampler attributes 2848 uniform sampler2D swapTexture; 2849 uniform sampler2D swap2Texture; 2850 2851 uniform float uEffectStrength; // 5.0 - 50.0 - waves amplitude 2852 uniform float uWavesDirection; // 0 - horizontal, 1 - vertical 2853 2854 // noise 2d generator 2855 //--------------------------------------------------- 2856 vec3 permute3(vec3 x) { 2857 return mod((x*34.0+1.0)*x, 289.0); 2858 } 2859 float snoise2(vec2 v) { 2860 const vec4 C = vec4(0.211325, 0.366025, -0.57735, 0.02439); 2861 vec2 i = floor(v + dot(v, C.yy)), 2862 x0 = v - i + dot(i, C.xx), 2863 i1; 2864 i1 = x0.x > x0.y ? vec2(1.0, 0.0) : vec2(0.0,1.0); 2865 vec4 x12 = x0.xyxy + C.xxzz; 2866 x12.xy -= i1, 2867 i = mod(i, 289.0); 2868 vec3 p = permute3(permute3(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0,i1.x, 1.0)), 2869 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); 2870 m = m * m, m = m * m; 2871 vec3 x = 2.0 * fract(p * C.www) - 1.0, 2872 h = abs(x) - 0.5, 2873 ox = floor(x + 0.5), 2874 a0 = x - ox; 2875 m *= 1.792843 - 0.853735 * (a0 * a0 + h * h); 2876 vec3 g; 2877 g.x = a0.x * x0.x + h.x * x0.y, 2878 g.yz = a0.yz * x12.xz + h.yz * x12.yw; 2879 return 130.0 * dot(m, g); 2880 } 2881 2882 // noise 3d generator 2883 //------------------------------------------- 2884 vec3 mod289(vec3 x) { 2885 return x - floor(x * (1.0 / 289.0)) * 289.0; 2886 } 2887 vec4 mod289(vec4 x) { 2888 return x - floor(x * (1.0 / 289.0)) * 289.0; 2889 } 2890 vec4 permute4(vec4 x) { 2891 return mod289(((x*34.0)+1.0)*x); 2892 } 2893 vec4 taylorInvSqrt(vec4 r) { 2894 return 1.79284291400159 - 0.85373472095314 * r; 2895 } 2896 float snoise3(vec3 v) { 2897 const vec2 C = vec2(1.0/6.0, 1.0/3.0) ; 2898 const vec4 D = vec4(0.0, 0.5, 1.0, 2.0); 2899 // First corner 2900 vec3 i = floor(v + dot(v, C.yyy) ); 2901 vec3 x0 = v - i + dot(i, C.xxx) ; 2902 // Other corners 2903 vec3 g = step(x0.yzx, x0.xyz); 2904 vec3 l = 1.0 - g; 2905 vec3 i1 = min( g.xyz, l.zxy ); 2906 vec3 i2 = max( g.xyz, l.zxy ); 2907 2908 // x0 = x0 - 0.0 + 0.0 * C.xxx; 2909 // x1 = x0 - i1 + 1.0 * C.xxx; 2910 // x2 = x0 - i2 + 2.0 * C.xxx; 2911 // x3 = x0 - 1.0 + 3.0 * C.xxx; 2912 vec3 x1 = x0 - i1 + C.xxx; 2913 vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y 2914 vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y 2915 2916 // Permutations 2917 i = mod289(i); 2918 vec4 p = permute4( permute4( permute4( 2919 i.z + vec4(0.0, i1.z, i2.z, 1.0 )) 2920 + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 2921 + i.x + vec4(0.0, i1.x, i2.x, 1.0 )); 2922 2923 // Gradients: 7x7 points over a square, mapped onto an octahedron. 2924 // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) 2925 float n_ = 0.142857142857; // 1.0/7.0 2926 vec3 ns = n_ * D.wyz - D.xzx; 2927 2928 vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7) 2929 2930 vec4 x_ = floor(j * ns.z); 2931 vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N) 2932 2933 vec4 x = x_ *ns.x + ns.yyyy; 2934 vec4 y = y_ *ns.x + ns.yyyy; 2935 vec4 h = 1.0 - abs(x) - abs(y); 2936 2937 vec4 b0 = vec4( x.xy, y.xy ); 2938 vec4 b1 = vec4( x.zw, y.zw ); 2939 2940 //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; 2941 //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; 2942 vec4 s0 = floor(b0)*2.0 + 1.0; 2943 vec4 s1 = floor(b1)*2.0 + 1.0; 2944 vec4 sh = -step(h, vec4(0.0)); 2945 2946 vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ; 2947 vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ; 2948 2949 vec3 p0 = vec3(a0.xy,h.x); 2950 vec3 p1 = vec3(a0.zw,h.y); 2951 vec3 p2 = vec3(a1.xy,h.z); 2952 vec3 p3 = vec3(a1.zw,h.w); 2953 2954 //Normalise gradients 2955 vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3))); 2956 p0 *= norm.x; 2957 p1 *= norm.y; 2958 p2 *= norm.z; 2959 p3 *= norm.w; 2960
2961 // Mix final noise value 2962 vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0); 2963 m = m * m; 2964 return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 2965 dot(p2,x2), dot(p3,x3) ) ); 2966 } 2967 2968 // circle 2969 //------------------------------------------- 2970 float circle( in vec2 _st, in float _radius, in float blurriness ) { 2971 vec2 dist = _st; 2972 return 1. - smoothstep( _radius - ( _radius * blurriness ), _radius + ( _radius * blurriness ), dot( dist, dist ) * 4.0 ); 2973 } 2974 2975 void main( void ) { 2976 vec2 v_uv = vTextureCoord; 2977 vec2 v_sv = vSwapTextureCoord; 2978 2979 // Manage the device ratio 2980 vec2 res = uRes * uPR; 2981 vec2 st = gl_FragCoord.xy / res.xy - vec2(0.5); 2982 // tip: use the following formula to keep the good ratio of your coordinates 2983 st.y *= uRes.y / uRes.x; 2984 2985 vec2 mouse = uMousePosition * -0.5; 2986 // tip2: do the same for your mouse 2987 mouse.y *= uRes.y / uRes.x; 2988 //mouse *= -1.; 2989 2990 vec2 circlePos = st + mouse; 2991 // float c = circle( circlePos, 0.3 * uScale, 2.0 ) * 2.5; 2992 float c = circle( circlePos, 0.3 * uScale, 2.5 ) * 2.25; 2993 2994 float offx = v_uv.x + sin( v_uv.y + uTime * 0.1 ); 2995 float offy = v_uv.y - uTime * 0.1 - cos( uTime * 0.001 ) * 0.01; 2996 float n = snoise3( vec3( offx, offy, uTime * 0.1 ) * 8.0 ) - 1.0; 2997 2998 float finalMask = smoothstep( 0.4, 0.5, n + pow( c, 2.0 ) ); 2999 3000 // Add waves to the first image 3001 const float PI = 3.141592; 3002 3003 v_sv.x += ( 3004 sin(v_sv.x * 10.0 * ( 2.0 - uWavesDirection ) + ((uWavesTime * (PI / 3.0)) * 0.031)) 3005 + sin(v_sv.y * 10.0 * ( 2.0 - uWavesDirection ) + ((uWavesTime * (PI / 2.489)) * 0.017)) 3006 ) / uEffectStrength / ( 2.5 + 1.5 * uWavesDirection ) * uScale; // * 0.0075; 3007 3008 v_sv.y += ( 3009 sin(v_sv.y * 20.0 / ( 2.0 - uWavesDirection ) + ((uWavesTime * (PI / 2.023)) * 0.023)) 3010 + sin(v_sv.x * 20.0 / ( 2.0 - uWavesDirection ) + ((uWavesTime * (PI / 3.1254)) * 0.037)) 3011 ) / uEffectStrength / ( 2.5 + 1.5 * ( 1.0 - uWavesDirection ) ) * uScale; // * 0.0125; 3012 3013 vec4 imageColor = texture2D( swapTexture, v_sv ); 3014 3015 // Add tint the second image 3016 vec4 hoverColor = texture2D( swap2Texture, vSwap2TextureCoord ); 3017 vec4 tint = vec4( uColor.r / 255.0, uColor.g / 255.0, uColor.b / 255.0, 1.0 ); 3018 hoverColor = uTint > 0.0 ? mix( hoverColor, tint, 0.5) : hoverColor; 3019 3020 gl_FragColor = mix( imageColor, hoverColor, finalMask ); 3021 } 3022 `; 3023 3024 return { 3025 vertexShader: vs, // our vertex shader ID 3026 fragmentShader: fs, // our fragment shader ID 3027// widthSegments: 10, 3028// heightSegments: 10, 3029 imageCover: false, // our displacement texture has to fit the plane 3030 uniforms: { // variables passed to shaders 3031 mousePosition: { // our mouse position 3032 name: "uMousePosition", 3033 type: "2f", 3034 value: [ mousePosition.x, mousePosition.y ] 3035 }, 3036 imageResolution: { 3037 name: "uRes", 3038 type: "2f", 3039 value: [ img.clientWidth, img.clientHeight ] 3040 }, 3041 pixelRatio: { 3042 name: "uPR", 3043 type: "1f", 3044 value: window.devicePixelRatio.toFixed(1) 3045 }, 3046 scaleFactor: { 3047 name: "uScale", 3048 type: "1f", 3049 value: 0 3050 }, 3051 color: { 3052 name: "uColor", 3053 type: "3f", 3054 value: tintColor ? trx_addons_rgb2components( tintColor ) : [0, 0, 0] 3055 }, 3056 useColor: { 3057 name: "uTint", 3058 type: "1f", 3059 value: tintColor ? 1 : 0 3060 }, 3061 effectStrength: { 3062 name: "uEffectStrength", 3063 type: "1f", 3064 value: effectStrength 3065 }, 3066 wavesDirection: { 3067 name: "uWavesDirection", 3068 type: "1f", 3069 value: wavesDirection 3070 }, 3071 wavesTime: { 3072 name: "uWavesTime", 3073 type: "1f", 3074 value: 0 3075 }, 3076 time: { 3077 name: "uTime", 3078 type: "1f", 3079 value: 0 3080 } 3081 } 3082 }; 3083 } 3084 3085 // handle plane 3086 function handle_plane( plane ) { 3087 plane 3088 .onLoading(function() { 3089// console.log(plane.loadingManager.sourcesLoaded); 3090 }) 3091 .onReady(function() { 3092// console.log('Plane '+index+' of '+total+' is ready'); 3093 // first render plane 3094 if ( ! permanentDrawing ) curtains.needRender(); 3095 // init tweens 3096 plane.tweenScale = null; 3097 // now that our plane is ready we can listen to mouse move event 3098 function mouse_move(e) { 3099 if ( ! mouseIn ) { 3100 mouse_enter(); 3101 } 3102 handle_movement(e, plane); 3103 } 3104 function mouse_enter() { 3105 if ( ! mouseIn ) { 3106 mouseIn = true; 3107 activeImage = 1; 3108 change_scale( 1 ); 3109 } 3110 } 3111 function mouse_leave() { 3112 if ( mouseIn ) { 3113 mouseIn = false;
3114 activeImage = 0; 3115 change_scale( 0 ); 3116 } 3117 } 3118 elm.addEventListener("mousemove", mouse_move ); 3119 elm.addEventListener("touchmove", mouse_move ); 3120 elm.addEventListener("mouseenter", mouse_enter ); 3121 elm.addEventListener("touchstart", mouse_enter ); 3122 elm.addEventListener("mouseleave", mouse_leave ); 3123 elm.addEventListener("touchend", mouse_leave ); 3124 }) 3125 .onRender(function() { 3126 plane.uniforms.time.value += 0.01; 3127 plane.uniforms.wavesTime.value++; 3128 }) 3129 .onAfterResize(function() { 3130// console.log('Plane '+index+' of '+total+' is resized'); 3131 }); 3132 3133 // Change scale 3134 function change_scale( to ) { 3135 if ( plane.tweenScale ) { 3136 tween_stop( plane.tweenScale ); 3137 } 3138 if ( ! permanentDrawing && to == 1 ) { 3139 curtains.enableDrawing(); 3140 } 3141 plane.tweenScale = tween_value( { 3142 start: scaleFactor, 3143 end: to, 3144 time: 0.6, 3145 callbacks: { 3146 onUpdate: function(value) { 3147 scaleFactor = value; 3148 plane.uniforms.scaleFactor.value = value; 3149 if ( scaleOnHover ) { 3150 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 3151 } 3152 }, 3153 onComplete: function() { 3154 tween_stop( plane.tweenScale ); 3155 plane.tweenScale = null; 3156 if ( ! permanentDrawing && to == 0 ) { 3157 curtains.disableDrawing(); 3158 } 3159 } 3160 } 3161 } ); 3162 } 3163 } 3164 3165 // handle the mouse move event 3166 function handle_movement(e, plane) { 3167 3168 var mouse = get_mouse_position_from_event( e ); 3169 3170 // lerp the mouse position a bit to smoothen the overall effect 3171 mousePosition.x = lerp(mousePosition.x, mouse.x, 0.3); 3172 mousePosition.y = lerp(mousePosition.y, mouse.y, 0.3); 3173 3174 // convert our mouse/touch position to coordinates relative to the vertices of the plane 3175 var mouseCoords = globalCanvas 3176 ? plane.mouseToPlaneCoords(mousePosition.x, mousePosition.y) 3177 : mouse_to_plane_coords( plane, mousePosition ); 3178 3179 // update our mouse position uniform 3180 plane.uniforms.mousePosition.value = [mouseCoords.x, mouseCoords.y]; 3181 } 3182 }; 3183 3184 3185 3186 // Effect 'Scroller' 3187 //------------------------------------------- 3188 3189 // Create plane. 3190 // Attention! All callbacks must be in a global scope! 3191 window.trx_addons_image_effects_callback_scroller = function( curtains_global, elm, index, total ) { 3192 3193 var curtains = curtains_global ? curtains_global : null; 3194 3195 var mouseIn = false; 3196 3197 var scaleOnHover = elm.getAttribute('data-image-effect-scale') > 0, 3198 scaleFactor = 0; 3199 3200 var scrollDirection = 0, 3201 scrollY = -1; 3202 3203 var effectStrength = 60 - Math.max( 5.0, Math.min( 50.0, elm.getAttribute('data-image-effect-strength') || 30 ) ), 3204 effectDirection = elm.getAttribute('data-image-effect-waves-direction') || 0; 3205 3206 var plane = null, 3207 parent = null, 3208 img_all = elm.querySelectorAll( 'img:not([class*="trx_addons_image_effects_"])' ), 3209 img = img_all.length > 1 3210 ? elm.querySelector( 'img:not([class*="avatar"]):not([class*="trx_addons_extended_taxonomy_img"])' ) 3211 : elm.querySelector( 'img' ); 3212 3213 if ( img ) { 3214 if ( img_all.length > 1 ) { 3215 jQuery( img ).wrap( '<div class="trx_addons_image_effects_holder"></div>' ); 3216 } 3217 parent = img.parentNode; 3218 if ( img_all.length == 1 ) { 3219 parent.classList.add('trx_addons_image_effects_holder'); 3220 } 3221// img.setAttribute('crossorigin', 'anonymous'); 3222 img.setAttribute('data-sampler', 'scrollerTexture'); 3223 if ( ! globalCanvas ) { 3224 curtains = create_canvas(parent); 3225 if ( curtains ) jQuery(elm).data('curtains', curtains); 3226 } 3227 if ( curtains ) { 3228 plane = curtains.addPlane( parent, get_params( elm, img, parent ) ); 3229 if ( plane ) { 3230 jQuery(elm).data('curtains-plane', plane); 3231 handle_plane( plane ); 3232 } 3233 } 3234 } 3235 3236 // Return plane params 3237 function get_params( elm, img, parent ) { 3238 3239 var vs = ` 3240 #ifdef GL_ES 3241 precision mediump float; 3242 #endif 3243 3244 attribute vec3 aVertexPosition; 3245 attribute vec2 aTextureCoord; 3246 3247 uniform mat4 uMVMatrix, uPMatrix; 3248 3249 uniform float uScrollSpeed; 3250 uniform float uEffectStrength; 3251 uniform float uEffectDirection; 3252 uniform float uPadding; 3253 3254 // our texture matrices 3255 // notice how it matches our data-sampler attributes + "Matrix" 3256 uniform mat4 scrollerTextureMatrix; 3257 3258 // if you want to pass your vertex and texture coords to the fragment shader 3259 varying vec3 vVertexPosition; 3260 varying vec2 vScrollerTextureCoord; 3261 3262 void main(){ 3263 vec3 vertexPosition = aVertexPosition; 3264 if ( uEffectDirection > 0.0 ) { 3265 // Vertical wave 3266 vertexPosition.x += sin( ( vertexPosition.y + 1.0 ) * 3.141592 ) * sin( uScrollSpeed * 3.141592 ) * 0.05 * ( uEffectStrength / 30.0 ); 3267 } else { 3268 // Horizontal wave 3269 vertexPosition.y += sin( ( vertexPosition.x + 1.0 ) / 2.0 * 3.141592 ) * sin( uScrollSpeed * 3.141592 ) * 0.05 * ( uEffectStrength / 30.0 ); 3270 } 3271 vVertexPosition = vertexPosition; 3272 gl_Position = uPMatrix * uMVMatrix * vec4( vertexPosition, 1.0 + uPadding * ( uEffectStrength / 30.0 ) ); 3273 3274 vScrollerTextureCoord = ( scrollerTextureMatrix * vec4( aTextureCoord, 0.0, 1.0 ) ).xy; 3275 } 3276 `; 3277 var fs = ` 3278 #ifdef GL_ES 3279 precision mediump float; 3280 #endif 3281 3282 // all our varying variables 3283 varying vec2 vScrollerTextureCoord; 3284 3285 uniform sampler2D scrollerTexture; 3286 3287 void main(){ 3288 vec2 textureCoord = vScrollerTextureCoord; 3289 gl_FragColor = texture2D(scrollerTexture, textureCoord); 3290 } 3291 `; 3292 3293 return { 3294 vertexShader: vs, 3295 fragmentShader: fs, 3296 widthSegments: 10, 3297 heightSegments: 10, 3298 uniforms: { 3299 padding: { 3300 name: "uPadding", 3301 type: "1f", 3302 value: trx_addons_apply_filters( 'trx_addons_filter_image_effects_padding', 0.05, 'scroller' ) 3303 }, 3304 effectStrength: { 3305 name: "uEffectStrength", 3306 type: "1f", 3307 value: effectStrength 3308 }, 3309 effectDirection: { 3310 name: "uEffectDirection", 3311 type: "1f", 3312 value: effectDirection 3313 }, 3314 scrollSpeed: { 3315 name: "uScrollSpeed", 3316 type: "1f", 3317 value: 0 3318 } 3319 } 3320 }; 3321 } 3322 3323 // handle plane 3324 function handle_plane( plane ) { 3325 plane 3326 .onReady(function() { 3327// console.log('Plane '+index+' of '+total+' is ready'); 3328 // init tweens 3329 plane.tween = null; 3330 plane.tweenScale = null; 3331 var scrollBusy = false, 3332 clear_scroll_busy = trx_addons_throttle( function() { 3333 scrollBusy = false;
3334 }, 300, true ); 3335 3336 function scroll_get() { 3337 return ( typeof window.scrollY != 'undefined' ? window.scrollY : window.pageYOffset ) || 0; 3338 } 3339 // now that our plane is ready we can listen to mouse move event 3340 function scroll_start(e) { 3341 clear_scroll_busy(); 3342 if ( scrollY < 0 ) { 3343 scrollY = scroll_get(); 3344 } else if ( ! scrollDirection ) { 3345 var scrollNew = scroll_get(); 3346 scrollDirection = scrollNew > scrollY ? 1 : -1; 3347 scrollBusy = true; 3348 change_scroll( 1 ); 3349 } 3350 } 3351 window.addEventListener("scroll", scroll_start ); 3352 // now that our plane is ready we can listen to mouse move event 3353 function mouse_move(e) { 3354 if ( ! mouseIn ) { 3355 mouse_enter(); 3356 } 3357 } 3358 function mouse_enter() { 3359 if ( ! mouseIn ) { 3360 mouseIn = true; 3361 change_scale( 1 ); 3362 } 3363 } 3364 function mouse_leave() { 3365 if ( mouseIn ) { 3366 mouseIn = false; 3367 change_scale( 0 ); 3368 } 3369 } 3370 elm.addEventListener("mousemove", mouse_move ); 3371 elm.addEventListener("touchmove", mouse_move ); 3372 elm.addEventListener("mouseenter", mouse_enter ); 3373 elm.addEventListener("touchstart", mouse_enter ); 3374 elm.addEventListener("mouseleave", mouse_leave ); 3375 elm.addEventListener("touchend", mouse_leave ); 3376 }) 3377 .onRender(function() { 3378 //plane.uniforms.time.value++; 3379 }); 3380 } 3381 3382 // Change wave force value 3383 function change_scroll( to ) { 3384 if ( plane.tween ) { 3385 tween_stop( plane.tween ); 3386 } 3387 plane.tween = tween_value( { 3388 start: plane.uniforms.scrollSpeed.value, 3389 end: to, 3390 time: 1.5, 3391 callbacks: { 3392 onUpdate: function(value) { 3393 plane.uniforms.scrollSpeed.value = value * scrollDirection; 3394 }, 3395 onComplete: function() { 3396 scrollDirection = 0; 3397 scrollY = -1; 3398 plane.uniforms.scrollSpeed.value = 0; 3399 tween_stop( plane.tween ); 3400 plane.tween = null; 3401 } 3402 } 3403 } ); 3404 } 3405 3406 // Change scale 3407 function change_scale( to ) { 3408 if ( plane.tweenScale ) { 3409 tween_stop( plane.tweenScale ); 3410 } 3411 if ( ! permanentDrawing && to == 1 ) { 3412 curtains.enableDrawing(); 3413 } 3414 plane.tweenScale = tween_value( { 3415 start: scaleFactor, 3416 end: to, 3417 time: 1.0, 3418 callbacks: { 3419 onUpdate: function(value) { 3420 scaleFactor = value; 3421 if ( scaleOnHover ) { 3422 plane.textures && plane.textures[0].setScale(1 + value / 12, 1 + value / 12); 3423 } 3424 }, 3425 onComplete: function() { 3426 tween_stop( plane.tweenScale ); 3427 plane.tweenScale = null; 3428 } 3429 } 3430 } ); 3431 } 3432 }; 3433 3434})();
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.