1/** 2 * tiltfx.js 3 * http://www.codrops.com 4 * 5 * Licensed under the MIT license. 6 * http://www.opensource.org/licenses/mit-license.php 7 * 8 * Copyright 2015, Codrops 9 * http://www.codrops.com 10 */ 11(function(window) { 12 13 'use strict'; 14 15 /** 16 * ************************************************************************** 17 * utils 18 * ************************************************************************** 19 */ 20 21 // from https://gist.github.com/desandro/1866474 22 var lastTime = 0; 23 var prefixes = 'webkit moz ms o'.split(' '); 24 // get unprefixed rAF and cAF, if present 25 var requestAnimationFrame = window.requestAnimationFrame; 26 var cancelAnimationFrame = window.cancelAnimationFrame; 27 // loop through vendor prefixes and get prefixed rAF and cAF 28 var prefix; 29 for( var i = 0; i < prefixes.length; i++ ) { 30 if ( requestAnimationFrame && cancelAnimationFrame ) { 31 break; 32 } 33 prefix = prefixes[i]; 34 requestAnimationFrame = requestAnimationFrame || window[ prefix + 'RequestAnimationFrame' ]; 35 cancelAnimationFrame = cancelAnimationFrame || window[ prefix + 'CancelAnimationFrame' ] || 36 window[ prefix + 'CancelRequestAnimationFrame' ]; 37 } 38 39 // fallback to setTimeout and clearTimeout if either request/cancel is not supported 40 if ( !requestAnimationFrame || !cancelAnimationFrame ) { 41 requestAnimationFrame = function( callback, element ) { 42 var currTime = new Date().getTime(); 43 var timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) ); 44 var id = window.setTimeout( function() { 45 callback( currTime + timeToCall ); 46 }, timeToCall ); 47 lastTime = currTime + timeToCall; 48 return id; 49 }; 50 51 cancelAnimationFrame = function( id ) { 52 window.clearTimeout( id ); 53 }; 54 } 55 56 function extend( a, b ) { 57 for( var key in b ) { 58 if( b.hasOwnProperty( key ) ) { 59 a[key] = b[key]; 60 } 61 } 62 return a; 63 } 64 65 // from http://www.quirksmode.org/js/events_properties.html#position 66 function getMousePos(e) { 67 var posx = 0; 68 var posy = 0; 69 if (!e) var e = window.event; 70 if (e.pageX || e.pageY) { 71 posx = e.pageX; 72 posy = e.pageY; 73 } 74 else if (e.clientX || e.clientY) { 75 posx = e.clientX + document.body.scrollLeft 76 + document.documentElement.scrollLeft; 77 posy = e.clientY + document.body.scrollTop 78 + document.documentElement.scrollTop; 79 } 80 return { 81 x : posx, 82 y : posy 83 } 84 } 85 86 // from http://www.sberry.me/articles/javascript-event-throttling-debouncing 87 function throttle(fn, delay) { 88 var allowSample = true; 89 90 return function(e) { 91 if (allowSample) { 92 allowSample = false; 93 setTimeout(function() { allowSample = true; }, delay); 94 fn(e); 95 } 96 }; 97 } 98 99 /***************************************************************************/ 100 101 /** 102 * TiltFx fn 103 */ 104 function TiltFx(el, options) { 105 this.el = el; 106 this.options = extend( {}, this.options ); 107 extend( this.options, options ); 108 this._init(); 109 this._initEvents(); 110 } 111 112 /** 113 * TiltFx options. 114 */ 115 TiltFx.prototype.options = { 116 // number of extra image elements (div with background-image) to add to the DOM - min:1, max:5 (for a higher number, it's recommended to remove the transitions of .t
116ilt__front in the stylesheet. 117 extraImgs : 2, 118 // the opacity value for all the image elements. 119 opacity : 0.7, 120 // by default the first layer does not move. 121 bgfixed : true, 122 // image element's movement configuration 123 movement : { 124 perspective : 1000, // perspective value 125 translateX : -10, // a relative movement of -10px to 10px on the x-axis (setting a negative value reverses the direction) 126 translateY : -10, // a relative movement of -10px to 10px on the y-axis 127 translateZ : 20, // a relative movement of -20px to 20px on the z-axis (perspective value must be set). Also, this specific translation is done when the mouse moves vertically. 128 rotateX : 2, // a relative rotation of -2deg to 2deg on the x-axis (perspective value must be set) 129 rotateY : 2, // a relative rotation of -2deg to 2deg on the y-axis (perspective value must be set) 130 rotateZ : 0 // z-axis rotation; by default there's no rotation on the z-axis (perspective value must be set) 131 } 132 } 133 134 /** 135 * Initialize: build the necessary structure for the image elements and replace it with the HTML img element. 136 */ 137 TiltFx.prototype._init = function() { 138 this.tiltWrapper = document.createElement('div'); 139 this.tiltWrapper.className = 'tilt'; 140 141 // main image element. 142 this.tiltImgBack = document.createElement('div'); 143 this.tiltImgBack.className = 'tilt__back'; 144 this.tiltImgBack.style.backgroundImage = 'url(' + this.el.src + ')'; 145 this.tiltWrapper.appendChild(this.tiltImgBack); 146 147 // image elements limit. 148 if( this.options.extraImgs < 1 ) { 149 this.options.extraImgs = 1; 150 } 151 else if( this.options.extraImgs > 5 ) { 152 this.options.extraImgs = 5; 153 } 154 155 if( !this.options.movement.perspective ) { 156 this.options.movement.perspective = 0; 157 } 158 159 // add the extra image elements. 160 this.imgElems = []; 161 for(var i = 0; i < this.options.extraImgs; ++i) { 162 var el = document.createElement('div'); 163 el.className = 'tilt__front'; 164 el.style.backgroundImage = 'url(' + this.el.src + ')'; 165 el.style.opacity = this.options.opacity; 166 this.tiltWrapper.appendChild(el); 167 this.imgElems.push(el); 168 } 169 170 if( !this.options.bgfixed ) { 171 this.imgElems.push(this.tiltImgBack); 172 ++this.options.extraImgs; 173 } 174 175 // add it to the DOM and remove original img element. 176 this.el.parentNode.insertBefore(this.tiltWrapper, this.el); 177 this.el.parentNode.removeChild(this.el); 178 179 // tiltWrapper properties: width/height/left/top 180 this.view = { width : this.tiltWrapper.offsetWidth, height : this.tiltWrapper.offsetHeight }; 181 }; 182 183 /** 184 * Initialize the events on the main wrapper. 185 */ 186 TiltFx.prototype._initEvents = function() { 187 var self = this, 188 moveOpts = self.options.movement; 189 190 // mousemove event.. 191 this.tiltWrapper.parentNode.addEventListener('mousemove', function(ev) { 192 requestAnimationFrame(function() { 193 // mouse position relative to the document. 194 var mousepos = getMousePos(ev), 195 // document scrolls. 196 docScrolls = {left : document.body.scrollLeft + document.documentElement.scrollLeft, top : document.body.scrollTop + document.documentElement.scrollTop}, 197 bounds = self.tiltWrapper.getBoundingClientRect(), 198 // mouse position relative to the main element (tiltWrapper). 199 relmousepos = { 200 x : mousepos.x - bounds.left - docScrolls.left, 201 y : mousepos.y - bounds.top - docScrolls.top 202 }; 203 204 // configure the movement for each image element. 205 for(var i = 0, len = self.imgElems.length; i < len; ++i) { 206 var el = self.imgElems[i], 207 rotX = moveOpts.rotateX ? 2 * ((i+1)*moveOpts.rotateX/self.options.extraImgs) / self.view.height * relmousepos.y - ((i+1)*moveOpts.rotateX/self.options.extraImgs) : 0, 208 rotY = moveOpts.rotateY ? 2 * ((i+1)*moveOpts.rotateY/self.options.extraImgs) / self.view.width * relmousepos.x - ((i+1)*moveOpts.rotateY/self.options.extraImgs) : 0, 209 rotZ = moveOpts.rotateZ ? 2 * ((i+1)*moveOpts.rotateZ/self.options.extraImgs) / self.view.width * relmousepos.x - ((i+1)*moveOpts.rotateZ/self.options.extraImgs) : 0, 210 transX = moveOpts.translateX ? 2 * ((i+1)*moveOpts.translateX/self.options.extraImgs) / self.view.width * relmousepos.x - ((i+1)*moveOpts.translateX/self.options.extraImgs) : 0, 211 transY = moveOpts.translateY ? 2 * ((i+1)*moveOpts.translateY/self.options.extraImgs) / self.view.height * relmousepos.y - ((i+1)*moveOpts.translateY/self.options.extraImgs) : 0, 212 transZ = moveOpts.translateZ ? 2 * ((i+1)*moveOpts.translateZ/self.options.extraImgs) / self.view.height * relmousepos.y - ((i+1)*moveOpts.translateZ/self.options.extraImgs) : 0; 213 214 el.style.WebkitTransform = 'perspective(' + moveOpts.perspective + 'px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(1,0,0,' + rotX + 'deg) rotate3d(0,1,0,' + rotY + 'deg) rotate3d(0,
2140,1,' + rotZ + 'deg)'; 215 el.style.transform = 'perspective(' + moveOpts.perspective + 'px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(1,0,0,' + rotX + 'deg) rotate3d(0,1,0,' + rotY + 'deg) rotate3d(0,0,1,' + rotZ + 'deg)'; 216 } 217 }); 218 }); 219 220 // reset all when mouse leaves the main wrapper. 221 this.tiltWrapper.parentNode.addEventListener('mouseleave', function(ev) { 222 setTimeout(function() { 223 for(var i = 0, len = self.imgElems.length; i < len; ++i) { 224 var el = self.imgElems[i]; 225 el.style.WebkitTransform = 'perspective(' + moveOpts.perspective + 'px) translate3d(0,0,0) rotate3d(1,1,1,0deg)'; 226 el.style.transform = 'perspective(' + moveOpts.perspective + 'px) translate3d(0,0,0) rotate3d(1,1,1,0deg)'; 227 } 228 }, 60); 229 230 }); 231 232 // window resize 233 window.addEventListener('resize', throttle(function(ev) { 234 // recalculate tiltWrapper properties: width/height/left/top 235 self.view = { width : self.tiltWrapper.offsetWidth, height : self.tiltWrapper.offsetHeight }; 236 }, 50)); 237 }; 238 239 function init() { 240 // search for imgs with the class "utouch-tilt-effect" 241 [].slice.call(document.querySelectorAll('img.utouch-tilt-effect')).forEach(function (img) { 242 new TiltFx(img, JSON.parse(img.getAttribute('data-tilt-options'))); 243 }); 244 } 245 246jQuery(window).load(function(){ 247 init(); 248}); 249 250 window.TiltFx = TiltFx; 251 252})(window);
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.