1var VanillaTilt = (function () { 2'use strict'; 3 4/** 5 * Created by Èandor Sergiu (micku7zu) on 1/27/2017. 6 * Original idea: https://github.com/gijsroge/tilt.js 7 * MIT License. 8 * Version 1.4.1 9 */ 10 11class VanillaTilt { 12 constructor(element, settings = {}) { 13 if (!(element instanceof Node)) { 14 throw ("Can't initialize VanillaTilt because " + element + " is not a Node."); 15 } 16 17 this.width = null; 18 this.height = null; 19 this.left = null; 20 this.top = null; 21 this.transitionTimeout = null; 22 this.updateCall = null; 23 24 this.updateBind = this.update.bind(this); 25 this.resetBind = this.reset.bind(this); 26 27 this.element = element; 28 this.settings = this.extendSettings(settings); 29 30 this.reverse = this.settings.reverse ? -1 : 1; 31 32 this.glare = this.isSettingTrue(this.settings.glare); 33 this.glarePrerender = this.isSettingTrue(this.settings["glare-prerender"]); 34 35 if (this.glare) { 36 this.prepareGlare(); 37 } 38 39 this.addEventListeners(); 40 } 41 42 isSettingTrue(setting) { 43 return setting === "" || setting === true || setting === 1; 44 } 45 46 addEventListeners() { 47 this.onMouseEnterBind = this.onMouseEnter.bind(this); 48 this.onMouseMoveBind = this.onMouseMove.bind(this); 49 this.onMouseLeaveBind = this.onMouseLeave.bind(this); 50 this.onWindowResizeBind = this.onWindowResizeBind.bind(this); 51 52 this.element.addEventListener("mouseenter", this.onMouseEnterBind); 53 this.element.addEventListener("mousemove", this.onMouseMoveBind); 54 this.element.addEventListener("mouseleave", this.onMouseLeaveBind); 55 if (this.glare) { 56 window.addEventListener("resize", this.onWindowResizeBind); 57 } 58 } 59 60 removeEventListeners() { 61 this.element.removeEventListener("mouseenter", this.onMouseEnterBind); 62 this.element.removeEventListener("mousemove", this.onMouseMoveBind); 63 this.element.removeEventListener("mouseleave", this.onMouseLeaveBind); 64 if (this.glare) { 65 window.removeEventListener("resize", this.onWindowResizeBind); 66 } 67 } 68 69 destroy() { 70 clearTimeout(this.transitionTimeout); 71 if (this.updateCall !== null) { 72 cancelAnimationFrame(this.updateCall); 73 } 74 75 this.reset(); 76 77 this.removeEventListeners(); 78 this.element.vanillaTilt = null; 79 delete this.element.vanillaTilt; 80 81 this.element = null; 82 } 83 84 onMouseEnter(event) { 85 this.updateElementPosition(); 86 this.element.style.willChange = "transform"; 87 this.setTransition(); 88 } 89 90 onMouseMove(event) { 91 if (this.updateCall !== null) { 92 cancelAnimationFrame(this.updateCall); 93 } 94 95 this.event = event; 96 this.updateCall = requestAnimationFrame(this.updateBind); 97 } 98 99 onMouseLeave(event) { 100 this.setTransition(); 101 102 if (this.settings.reset) { 103 requestAnimationFrame(this.resetBind); 104 } 105 } 106 107 reset() { 108 this.event = { 109 pageX: this.left + this.width / 2, 110 pageY: this.top + this.height / 2 111 }; 112 113 this.element.style.transform = "perspective(" + this.settings.perspective + "px) " + 114 "rotateX(0deg) " + 115 "rotateY(0deg) " + 116 "scale3d(1, 1, 1)"; 117 118 if (this.glare) { 119 this.glareElement.style.transform = 'rotate(180deg) translate(-50%, -50%)'; 120 this.glareElement.style.opacity = '0'; 121 } 122 } 123 124 getValues() { 125 let x = (this.event.clientX - this.left) / this.width; 126 let y = (this.event.clientY - this.top) / this.height; 127 128 x = Math.min(Math.max(x, 0), 1); 129 y = Math.min(Math.max(y, 0), 1); 130 131 let tiltX = (this.reverse * (this.settings.max / 2 - x * this.settings.max)).toFixed(2); 132 let tiltY = (this.reverse * (y * this.settings.max - this.settings.max / 2)).toFixed(2); 133 let angle = Math.atan2(this.event.clientX - (this.left + this.width / 2), -(this.event.clientY - (this.top + this.height / 2))) * (180 / Math.PI); 134 135 return { 136 tiltX: tiltX, 137 tiltY: tiltY, 138 percentageX: x * 100, 139 percentageY: y * 100, 140 angle: angle 141 }; 142 } 143 144 updateElementPosition() { 145 let rect = this.element.getBoundingClientRect(); 146 147 this.width = this.element.offsetWidth; 148 this.height = this.element.offsetHeight; 149 this.left = rect.left; 150 this.top = rect.top; 151 } 152 153 update() { 154 let values = this.getValues(); 155 156 this.element.style.transform = "perspective(" + this.settings.perspective + "px) " + 157 "rotateX(" + (this.settings.axis === "x" ? 0 : values.tiltY) + "deg) " + 158 "rotateY(" + (this.settings.axis === "y" ? 0 : values.tiltX) + "deg) " + 159 "scale3d(" + this.settings.scale + ", " + this.settings.scale + ", " + this.settings.scale + ")"; 160 161 if (this.glare) { 162 this.glareElement.style.transform = `rotate(${values.angle}deg) translate(-50%, -50%)`; 163 this.glareElement.style.opacity = `${values.percentageY * this.settings["max-glare"] / 100}`; 164 } 165 166 this.element.dispatchEvent(new CustomEvent("tiltChange", { 167 "detail": values 168 })); 169 170 this.updateCall = null; 171 } 172 173 /** 174 * Appends the glare element (if glarePrerender equals false) 175 * and sets the default style 176 */ 177 prepareGlare() { 178 // If option pre-render is enabled we assume all html/css is present for an optimal glare effect. 179 if (!this.glarePrerender) { 180 // Create glare element 181 const jsTiltGlare = document.createElement("div"); 182 jsTiltGlare.classList.add("js-tilt-glare"); 183 184 const jsTiltGlareInner = document.createElement("div"); 185 jsTiltGlareInner.classList.add("js-tilt-glare-inner"); 186 187 jsTiltGlare.appendChild(jsTiltGlareInner); 188 this.element.appendChild(jsTiltGlare); 189 } 190 191 this.glareElementWrapper = this.element.querySelector(".js-tilt-glare"); 192 this.glareElement = this.element.querySelector(".js-tilt-glare-inner"); 193 194 if (this.glarePrerender) { 195 return; 196 } 197 198 Object.assign(this.glareElementWrapper.style, { 199 "position": "absolute", 200 "top": "0", 201 "left": "0", 202 "width": "100%", 203 "height": "100%", 204 "overflow": "hidden" 205 }); 206 207 Object.assign(this.glareElement.style, { 208 'position': 'absolute', 209 'top': '50%', 210 'left': '50%', 211 'pointer-events': 'none', 212 'background-image': `linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%)`, 213 'width': `${this.element.offsetWidth * 2}px`, 214 'height': `${this.element.offsetWidth * 2}px`, 215 'transform': 'rotate(180deg) translate(-50%, -50%)', 216 'transform-origin': '0% 0%', 217 'opacity': '0', 218 }); 219 } 220 221 updateGlareSize() { 222 Object.assign(this.glareElement.style, { 223 'width': `${this.element.offsetWidth * 2}`, 224 'height': `${this.element.offsetWidth * 2}`, 225 }); 226 } 227 228 onWindowResizeBind() { 229 this.updateGlareSize(); 230 } 231 232 setTransition() { 233 clearTimeout(this.transitionTimeout); 234 this.element.style.transition = this.settings.speed + "ms " + this.settings.easing; 235 if (this.glare) this.glareElement.style.transition = `opacity ${this.settings.speed}ms ${this.settings.easing}`; 236 237 this.transitionTimeout = setTimeout(() => { 238 this.element.style.transition = ""; 239 if (this.glare) { 240 this.glareElement.style.transition = ""; 241 } 242 }, this.settings.speed); 243 244 } 245 246 extendSettings(settings) { 247 let defaultSettings = { 248 reverse: false, 249 max: 35, 250 perspective: 1000, 251 easing: "cubic-bezier(.03,.98,.52,.99)", 252 scale: "1", 253 speed: "300", 254 transition: true, 255 axis: null, 256 glare: false, 257 "max-glare": 1, 258 "glare-prerender": false, 259 reset: true 260 }; 261 262 let newSettings = {}; 263 for (var property in defaultSettings) { 264 if (property in settings) { 265 newSettings[property] = settings[property]; 266 } else if (this.element.hasAttribute("data-tilt-" + property)) { 267 let attribute = this.element.getAttribute("data-tilt-" + property); 268 try { 269 newSettings[property] = JSON.parse(attribute); 270 } catch (e) { 271 newSettings[property] = attribute; 272 } 273 274 } else { 275 newSettings[property] = defaultSettings[property]; 276 } 277 } 278 279 return newSettings; 280 } 281 282 static init(elements, settings) { 283 if (elements instanceof Node) { 284 elements = [elements]; 285 } 286 287 if (elements instanceof NodeList) { 288 elements = [].slice.call(elements); 289 } 290 291 if (!(elements instanceof Array)) { 292 return; 293 } 294
295 elements.forEach((element) => { 296 if (!("vanillaTilt" in element)) { 297 element.vanillaTilt = new VanillaTilt(element, settings); 298 } 299 }); 300 } 301} 302 303if (typeof document !== "undefined") { 304 /* expose the class to window */ 305 window.VanillaTilt = VanillaTilt; 306 307 /** 308 * Auto load 309 */ 310 VanillaTilt.init(document.querySelectorAll("[data-tilt]")); 311} 312 313return VanillaTilt; 314 315}());
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.