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