diff --git a/.gitignore b/.gitignore index 58476ba..aee5c68 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules -lib .idea .tern-port diff --git a/dist/vanilla-tilt.babel.js b/dist/vanilla-tilt.babel.js index 83275f2..4462d11 100644 --- a/dist/vanilla-tilt.babel.js +++ b/dist/vanilla-tilt.babel.js @@ -11,7 +11,7 @@ var classCallCheck = function (instance, Constructor) { * Created by Șandor Sergiu (micku7zu) on 1/27/2017. * Original idea: https://github.com/gijsroge/tilt.js * MIT License. - * Version 1.2.0 + * Version 1.2.1 */ var VanillaTilt = function () { diff --git a/dist/vanilla-tilt.js b/dist/vanilla-tilt.js index cfd939e..8a7805b 100644 --- a/dist/vanilla-tilt.js +++ b/dist/vanilla-tilt.js @@ -5,7 +5,7 @@ var VanillaTilt = (function () { * Created by Șandor Sergiu (micku7zu) on 1/27/2017. * Original idea: https://github.com/gijsroge/tilt.js * MIT License. - * Version 1.2.0 + * Version 1.2.1 */ class VanillaTilt { diff --git a/lib/README.md b/lib/README.md new file mode 100644 index 0000000..89d1762 --- /dev/null +++ b/lib/README.md @@ -0,0 +1,70 @@ +# vanilla-tilt.js +A smooth 3D tilt javascript library forked from [Tilt.js (jQuery version)](https://github.com/gijsroge/tilt.js). + +[View landing page (demos)](https://micku7zu.github.io/vanilla-tilt.js/) + +### Usage + +```html + +
+ + + + +``` + +### Options +```js +{ + reverse: false, // reverse the tilt direction + max: 35, // max tilt rotation (degrees) + perspective: 1000, // Transform perspective, the lower the more extreme the tilt gets. + scale: 1, // 2 = 200%, 1.5 = 150%, etc.. + speed: 300, // Speed of the enter/exit transition + transition: true, // Set a transition on enter/exit. + axis: null, // What axis should be disabled. Can be X or Y. + reset: true // If the tilt effect has to be reset on exit. + easing: "cubic-bezier(.03,.98,.52,.99)", // Easing on enter/exit. +} +``` + +### Events +```js +const element = document.querySelector(".js-tilt"); +VanillaTilt.init(element); +element.addEventListeners("tiltChange", callback); +``` + +### Methods +```js +const element = document.querySelector(".js-tilt"); +VanillaTilt.init(element); + +// Destroy instance +element.vanillaTilt.destroy(); + +// Get values of instance +element.vanillaTilt.getValues(); + +// Reset instance +element.vanillaTilt.reset(); +``` + +### Install +You can copy and include any of the following file: + +* [dist/vanilla-tilt.js](https://raw.githubusercontent.com/micku7zu/vanilla-tilt.js/master/dist/vanilla-tilt.js) ~ 6kb +* [dist/vanilla-tilt.min.js](https://raw.githubusercontent.com/micku7zu/vanilla-tilt.js/master/dist/vanilla-tilt.min.js) ~ 3.5kb +* [dist/vanilla-tilt.babel.js](https://raw.githubusercontent.com/micku7zu/vanilla-tilt.js/master/dist/vanilla-tilt.babel.js) ~ 8.5kb +* [dist/vanilla-tilt.babel.min.js](https://raw.githubusercontent.com/micku7zu/vanilla-tilt.js/master/dist/vanilla-tilt.babel.min.js) ~ 4.3kb + +### Credits + +Original library: [Tilt.js](http://gijsroge.github.io/tilt.js/) + +Original library author: [Gijs Rogé](https://twitter.com/GijsRoge) + +### License + +MIT License diff --git a/lib/vanilla-tilt.es2015.js b/lib/vanilla-tilt.es2015.js new file mode 100644 index 0000000..0664420 --- /dev/null +++ b/lib/vanilla-tilt.es2015.js @@ -0,0 +1,206 @@ +/** + * Created by Șandor Sergiu (micku7zu) on 1/27/2017. + * Original idea: https://github.com/gijsroge/tilt.js + * MIT License. + * Version 1.2.1 + */ + +class VanillaTilt { + constructor(element, settings = {}) { + if (!(element instanceof Node)) { + throw ("Can't initialize VanillaTilt because " + element + " is not a Node."); + } + + this.width = null; + this.height = null; + this.left = null; + this.top = null; + this.transitionTimeout = null; + this.updateCall = null; + + this.updateBind = this.update.bind(this); + + this.element = element; + this.settings = this.extendSettings(settings); + + this.reverse = this.settings.reverse ? -1 : 1; + + this.addEventListeners(); + } + + addEventListeners() { + this.onMouseEnterBind = this.onMouseEnter.bind(this); + this.onMouseMoveBind = this.onMouseMove.bind(this); + this.onMouseLeaveBind = this.onMouseLeave.bind(this); + + this.element.addEventListener("mouseenter", this.onMouseEnterBind); + this.element.addEventListener("mousemove", this.onMouseMoveBind); + this.element.addEventListener("mouseleave", this.onMouseLeaveBind); + } + + removeEventListeners() { + this.element.removeEventListener("mouseenter", this.onMouseEnterBind); + this.element.removeEventListener("mousemove", this.onMouseMoveBind); + this.element.removeEventListener("mouseleave", this.onMouseLeaveBind); + } + + destroy() { + this.removeEventListeners(); + this.element.vanillaTilt = null; + delete this.element.vanillaTilt; + + this.element = null; + } + + onMouseEnter(event) { + this.updateElementPosition(); + this.element.style.willChange = "transform"; + this.setTransition(); + } + + onMouseMove(event) { + if (this.updateCall !== null) { + cancelAnimationFrame(this.updateCall); + } + + this.event = event; + this.updateCall = requestAnimationFrame(this.updateBind); + } + + onMouseLeave(event) { + this.setTransition(); + + if (this.settings.reset) { + this.reset(); + } + } + + reset() { + requestAnimationFrame(() => { + this.event = { + pageX: this.left + this.width / 2, + pageY: this.top + this.height / 2 + }; + + this.element.style.transform = "perspective(" + this.settings.perspective + "px) " + + "rotateX(0deg) " + + "rotateY(0deg) " + + "scale3d(1, 1, 1)"; + }); + } + + getValues() { + let x = (this.event.clientX - this.left) / this.width; + let y = (this.event.clientY - this.top) / this.height; + + x = Math.min(Math.max(x, 0), 1); + y = Math.min(Math.max(y, 0), 1); + + let tiltX = (this.reverse * (this.settings.max / 2 - x * this.settings.max)).toFixed(2); + let tiltY = (this.reverse * (y * this.settings.max - this.settings.max / 2)).toFixed(2); + + return { + tiltX: tiltX, + tiltY: tiltY, + percentageX: x * 100, + percentageY: y * 100 + }; + } + + updateElementPosition() { + let rect = this.element.getBoundingClientRect(); + + this.width = this.element.offsetWidth; + this.height = this.element.offsetHeight; + this.left = rect.left; + this.top = rect.top; + } + + update() { + let values = this.getValues(); + + this.element.style.transform = "perspective(" + this.settings.perspective + "px) " + + "rotateX(" + (this.settings.axis === "x" ? 0 : values.tiltY) + "deg) " + + "rotateY(" + (this.settings.axis === "y" ? 0 : values.tiltX) + "deg) " + + "scale3d(" + this.settings.scale + ", " + this.settings.scale + ", " + this.settings.scale + ")"; + + + this.element.dispatchEvent(new CustomEvent("tiltChange", { + "detail": values + })); + + this.updateCall = null; + } + + setTransition() { + clearTimeout(this.transitionTimeout); + this.element.style.transition = this.settings.speed + "ms " + this.settings.easing; + this.transitionTimeout = setTimeout(() => this.element.style.transition = "", this.settings.speed); + } + + extendSettings(settings) { + let defaultSettings = { + reverse: false, + max: 35, + perspective: 1000, + easing: "cubic-bezier(.03,.98,.52,.99)", + scale: "1", + speed: "300", + transition: true, + axis: null, + reset: true + }; + + let newSettings = {}; + + for (var property in defaultSettings) { + if (property in settings) { + newSettings[property] = settings[property]; + } else if (this.element.hasAttribute("data-tilt-" + property)) { + let attribute = this.element.getAttribute("data-tilt-" + property); + try { + newSettings[property] = JSON.parse(attribute); + } catch (e) { + newSettings[property] = attribute; + } + + } else { + newSettings[property] = defaultSettings[property]; + } + } + + return newSettings; + } + + static init(elements, settings) { + if (elements instanceof Node) { + elements = [elements]; + } + + if (elements instanceof NodeList) { + elements = [].slice.call(elements); + } + + if (!(elements instanceof Array)) { + return; + } + + elements.forEach((element) => { + if (!("vanillaTilt" in element)) { + element.vanillaTilt = new VanillaTilt(element, settings); + } + }); + } +} + +if (typeof document !== "undefined") { + /* expose the class to window */ + window.VanillaTilt = VanillaTilt; + + /** + * Auto load + */ + VanillaTilt.init(document.querySelectorAll("[data-tilt]")); +} + +export default VanillaTilt; diff --git a/lib/vanilla-tilt.js b/lib/vanilla-tilt.js new file mode 100644 index 0000000..55829f0 --- /dev/null +++ b/lib/vanilla-tilt.js @@ -0,0 +1,217 @@ +'use strict'; + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +/** + * Created by Șandor Sergiu (micku7zu) on 1/27/2017. + * Original idea: https://github.com/gijsroge/tilt.js + * MIT License. + * Version 1.2.1 + */ + +var VanillaTilt = function () { + function VanillaTilt(element) { + var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + classCallCheck(this, VanillaTilt); + + if (!(element instanceof Node)) { + throw "Can't initialize VanillaTilt because " + element + " is not a Node."; + } + + this.width = null; + this.height = null; + this.left = null; + this.top = null; + this.transitionTimeout = null; + this.updateCall = null; + + this.updateBind = this.update.bind(this); + + this.element = element; + this.settings = this.extendSettings(settings); + + this.reverse = this.settings.reverse ? -1 : 1; + + this.addEventListeners(); + } + + VanillaTilt.prototype.addEventListeners = function addEventListeners() { + this.onMouseEnterBind = this.onMouseEnter.bind(this); + this.onMouseMoveBind = this.onMouseMove.bind(this); + this.onMouseLeaveBind = this.onMouseLeave.bind(this); + + this.element.addEventListener("mouseenter", this.onMouseEnterBind); + this.element.addEventListener("mousemove", this.onMouseMoveBind); + this.element.addEventListener("mouseleave", this.onMouseLeaveBind); + }; + + VanillaTilt.prototype.removeEventListeners = function removeEventListeners() { + this.element.removeEventListener("mouseenter", this.onMouseEnterBind); + this.element.removeEventListener("mousemove", this.onMouseMoveBind); + this.element.removeEventListener("mouseleave", this.onMouseLeaveBind); + }; + + VanillaTilt.prototype.destroy = function destroy() { + this.removeEventListeners(); + this.element.vanillaTilt = null; + delete this.element.vanillaTilt; + + this.element = null; + }; + + VanillaTilt.prototype.onMouseEnter = function onMouseEnter(event) { + this.updateElementPosition(); + this.element.style.willChange = "transform"; + this.setTransition(); + }; + + VanillaTilt.prototype.onMouseMove = function onMouseMove(event) { + if (this.updateCall !== null) { + cancelAnimationFrame(this.updateCall); + } + + this.event = event; + this.updateCall = requestAnimationFrame(this.updateBind); + }; + + VanillaTilt.prototype.onMouseLeave = function onMouseLeave(event) { + this.setTransition(); + + if (this.settings.reset) { + this.reset(); + } + }; + + VanillaTilt.prototype.reset = function reset() { + var _this = this; + + requestAnimationFrame(function () { + _this.event = { + pageX: _this.left + _this.width / 2, + pageY: _this.top + _this.height / 2 + }; + + _this.element.style.transform = "perspective(" + _this.settings.perspective + "px) " + "rotateX(0deg) " + "rotateY(0deg) " + "scale3d(1, 1, 1)"; + }); + }; + + VanillaTilt.prototype.getValues = function getValues() { + var x = (this.event.clientX - this.left) / this.width; + var y = (this.event.clientY - this.top) / this.height; + + x = Math.min(Math.max(x, 0), 1); + y = Math.min(Math.max(y, 0), 1); + + var tiltX = (this.reverse * (this.settings.max / 2 - x * this.settings.max)).toFixed(2); + var tiltY = (this.reverse * (y * this.settings.max - this.settings.max / 2)).toFixed(2); + + return { + tiltX: tiltX, + tiltY: tiltY, + percentageX: x * 100, + percentageY: y * 100 + }; + }; + + VanillaTilt.prototype.updateElementPosition = function updateElementPosition() { + var rect = this.element.getBoundingClientRect(); + + this.width = this.element.offsetWidth; + this.height = this.element.offsetHeight; + this.left = rect.left; + this.top = rect.top; + }; + + VanillaTilt.prototype.update = function update() { + var values = this.getValues(); + + this.element.style.transform = "perspective(" + this.settings.perspective + "px) " + "rotateX(" + (this.settings.axis === "x" ? 0 : values.tiltY) + "deg) " + "rotateY(" + (this.settings.axis === "y" ? 0 : values.tiltX) + "deg) " + "scale3d(" + this.settings.scale + ", " + this.settings.scale + ", " + this.settings.scale + ")"; + + this.element.dispatchEvent(new CustomEvent("tiltChange", { + "detail": values + })); + + this.updateCall = null; + }; + + VanillaTilt.prototype.setTransition = function setTransition() { + var _this2 = this; + + clearTimeout(this.transitionTimeout); + this.element.style.transition = this.settings.speed + "ms " + this.settings.easing; + this.transitionTimeout = setTimeout(function () { + return _this2.element.style.transition = ""; + }, this.settings.speed); + }; + + VanillaTilt.prototype.extendSettings = function extendSettings(settings) { + var defaultSettings = { + reverse: false, + max: 35, + perspective: 1000, + easing: "cubic-bezier(.03,.98,.52,.99)", + scale: "1", + speed: "300", + transition: true, + axis: null, + reset: true + }; + + var newSettings = {}; + + for (var property in defaultSettings) { + if (property in settings) { + newSettings[property] = settings[property]; + } else if (this.element.hasAttribute("data-tilt-" + property)) { + var attribute = this.element.getAttribute("data-tilt-" + property); + try { + newSettings[property] = JSON.parse(attribute); + } catch (e) { + newSettings[property] = attribute; + } + } else { + newSettings[property] = defaultSettings[property]; + } + } + + return newSettings; + }; + + VanillaTilt.init = function init(elements, settings) { + if (elements instanceof Node) { + elements = [elements]; + } + + if (elements instanceof NodeList) { + elements = [].slice.call(elements); + } + + if (!(elements instanceof Array)) { + return; + } + + elements.forEach(function (element) { + if (!("vanillaTilt" in element)) { + element.vanillaTilt = new VanillaTilt(element, settings); + } + }); + }; + + return VanillaTilt; +}(); + +if (typeof document !== "undefined") { + /* expose the class to window */ + window.VanillaTilt = VanillaTilt; + + /** + * Auto load + */ + VanillaTilt.init(document.querySelectorAll("[data-tilt]")); +} + +module.exports = VanillaTilt; diff --git a/package.json b/package.json index 06945c6..437cc31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vanilla-tilt", - "version": "1.2.0", + "version": "1.2.1", "description": "A smooth 3D tilt javascript library forked from Tilt.js", "main": "lib/vanilla-tilt.js", "dist": "dist/vanilla-tilt.js", @@ -8,10 +8,10 @@ "jsnext:main": "lib/vanilla-tilt.es2015.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "build": "run build:lib && cp ./README.md ./lib", + "build": "npm run build:lib && cp ./README.md ./lib", "build:lib": "cross-env NODE_ENV=production babel-node ./build.js", "build:babel": "cross-env NODE_ENV=production babel src -d lib", - "deploy": "run build && gh-pages demo", + "deploy": "npm run build && gh-pages demo", "release:patch": "release patch", "release:minor": "release minor", "release:major": "release major", @@ -54,13 +54,10 @@ "smooth", "tilt.js" ], - "author": "Sönke Kluth (http://soenkekluth.com/)", + "author": "Sergiu Șandor ", "license": "MIT", "bugs": { "url": "https://github.com/micku7zu/vanilla-tilt.js/issues" }, - "homepage": "https://github.com/micku7zu/vanilla-tilt.js#readme", - "dependencies": { - "dom-helpers": "^3.2.0" - } + "homepage": "https://github.com/micku7zu/vanilla-tilt.js#readme" } diff --git a/src/vanilla-tilt.js b/src/vanilla-tilt.js index 7130828..fadf56f 100644 --- a/src/vanilla-tilt.js +++ b/src/vanilla-tilt.js @@ -2,7 +2,7 @@ * Created by Șandor Sergiu (micku7zu) on 1/27/2017. * Original idea: https://github.com/gijsroge/tilt.js * MIT License. - * Version 1.2.0 + * Version 1.2.1 */ export default class VanillaTilt {