├── .bowerrc ├── .gitignore ├── demo ├── img │ ├── autumn_season-800x450.jpg │ ├── autumn_season-1600x900.jpg │ ├── german_landscapes-1600x900.jpg │ ├── german_landscapes-800x450.jpg │ ├── japan_digital_nature-800x500.jpg │ └── japan_digital_nature-1680x1050.jpg ├── js │ └── main.js ├── amd.html ├── mobile-fallback.html ├── index.html └── container.html ├── bower.json ├── parallax-imageScroll.jquery.json ├── package.json ├── README.md ├── jquery.imageScroll.min.js └── jquery.imageScroll.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "demo/js/vendor" 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .idea/workspace.xml 3 | demo/js/vendor 4 | _test/ 5 | todo.txt -------------------------------------------------------------------------------- /demo/img/autumn_season-800x450.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/autumn_season-800x450.jpg -------------------------------------------------------------------------------- /demo/img/autumn_season-1600x900.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/autumn_season-1600x900.jpg -------------------------------------------------------------------------------- /demo/img/german_landscapes-1600x900.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/german_landscapes-1600x900.jpg -------------------------------------------------------------------------------- /demo/img/german_landscapes-800x450.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/german_landscapes-800x450.jpg -------------------------------------------------------------------------------- /demo/img/japan_digital_nature-800x500.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/japan_digital_nature-800x500.jpg -------------------------------------------------------------------------------- /demo/img/japan_digital_nature-1680x1050.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pederan/Parallax-ImageScroll/HEAD/demo/img/japan_digital_nature-1680x1050.jpg -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Parallax-ImageScroll", 3 | "version": "0.2.3", 4 | "authors": [ 5 | "Peder Andreas Nielsen " 6 | ], 7 | "main": "jquery.imageScroll.js", 8 | "license": "MIT", 9 | "ignore": [ 10 | "**/.*", 11 | "node_modules", 12 | "demo/js/vendor", 13 | "test", 14 | "tests" 15 | ], 16 | "dependencies": { 17 | "jquery": "latest" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /demo/js/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: Peder A. Nielsen 3 | * Date: 05.12.13 4 | * Company: Making Waves 5 | */ 6 | require.config({ 7 | baseUrl: '../', 8 | paths: { 9 | 'jquery': '//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min' 10 | } 11 | }); 12 | 13 | require(['jquery.imageScroll'], function (ImageScroll) { 14 | ImageScroll.defaults.speed = .2; 15 | $('.img-holder').each(function () { 16 | new ImageScroll(this, {}); 17 | }); 18 | //or 19 | //$('.img-holder').imageScroll(); 20 | }); -------------------------------------------------------------------------------- /parallax-imageScroll.jquery.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parallax-imagescroll", 3 | "version": "0.2.3", 4 | "title": "Parallax ImageScroll", 5 | "author": { 6 | "name": "Peder Andreas Nielsen", 7 | "email": "peder1976@gmail.com" 8 | }, 9 | "licenses": [ 10 | { 11 | "type": "MIT", 12 | "url": "http://opensource.org/licenses/MIT" 13 | } 14 | ], 15 | "dependencies": { 16 | "jquery": ">=1.8.0" 17 | }, 18 | "description": "Parallax ImageScroll is a simple and easy jQuery plugin for creating image parallax effects when scrolling the page, inspired by Spotify.com.", 19 | "keywords": [ 20 | "parallax", 21 | "scroll", 22 | "effect", 23 | "animation", 24 | "css3" 25 | ], 26 | "homepage": "https://github.com/pederan/Parallax-ImageScroll", 27 | "docs": "https://github.com/pederan/Parallax-ImageScroll", 28 | "demo": "http://codepen.io/pederan/full/Hheuy", 29 | "bugs": "https://github.com/pederan/Parallax-ImageScroll/issues" 30 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parallax-imagescroll", 3 | "version": "0.2.3", 4 | "title": "Parallax ImageScroll", 5 | "main": "./jquery.imageScroll.js", 6 | "author": { 7 | "name": "Peder Andreas Nielsen", 8 | "email": "peder1976@gmail.com" 9 | }, 10 | "licenses": [ 11 | { 12 | "type": "MIT", 13 | "url": "http://opensource.org/licenses/MIT" 14 | } 15 | ], 16 | "dependencies": { 17 | "jquery": ">=1.8.0" 18 | }, 19 | "description": "Parallax ImageScroll is a simple and easy jQuery plugin for creating image parallax effects when scrolling the page, inspired by Spotify.com.", 20 | "keywords": [ 21 | "jquery-plugin", 22 | "ecosystem:jquery", 23 | "parallax", 24 | "scroll", 25 | "effect", 26 | "animation", 27 | "css3" 28 | ], 29 | "homepage": "https://github.com/pederan/Parallax-ImageScroll", 30 | "repository": "https://github.com/pederan/Parallax-ImageScroll", 31 | "bugs": "https://github.com/pederan/Parallax-ImageScroll/issues" 32 | } 33 | -------------------------------------------------------------------------------- /demo/amd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Parallax-ImageScroll demo AMD 9 | 10 | 11 | 15 | 16 | 17 | 18 |
19 | 20 |
21 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

22 | 23 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

24 |
25 | 26 |
27 | 28 |
29 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

30 | 31 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

32 |
33 | 34 |
35 | 36 |
37 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

38 | 39 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

40 |
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /demo/mobile-fallback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Parallax-ImageScroll demo 9 | 10 | 11 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

23 | 24 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

25 |
26 | 27 |
28 | 29 |
30 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

31 | 32 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

33 |
34 | 35 |
36 | 37 |
38 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

39 | 40 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

41 |
42 | 43 | 44 | 45 | 52 | 53 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Parallax-ImageScroll demo 9 | 10 | 11 | 15 | 16 | 17 | 18 |
19 | 20 |
21 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

22 | 23 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

24 |
25 | 26 |
27 | 28 |
29 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

30 | 31 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

32 |
33 | 34 |
35 | 36 |
37 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

38 | 39 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

40 |
41 | 42 | 43 | 44 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /demo/container.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Parallax-ImageScroll demo 9 | 10 | 11 | 17 | 18 | 19 | 22 |
23 |
24 |
25 | 26 |
27 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

28 | 29 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

30 |
31 | 32 |
33 | 34 |
35 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

36 | 37 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

38 |
39 | 40 |
41 | 42 |
43 |

Pid ultrices mid ultrices aliquet porttitor. Tristique est turpis lacus. Nec mid, nisi eu magnis? Phasellus? Facilisis sed urna integer in. Pulvinar! Lacus enim dapibus facilisis, sociis ut turpis habitasse nunc a egestas placerat in mattis! Turpis sed? Sit pid magna sociis vel a porttitor, enim ac! Porttitor, lorem odio a tincidunt urna scelerisque, augue. Cursus, et penatibus, ridiculus tortor.

44 | 45 |

Urna sed lorem a mus duis cras mattis turpis arcu facilisis mattis tincidunt sagittis lorem, elit elit porttitor turpis? Risus purus! Mus urna tortor adipiscing dictumst, purus, sit turpis, amet mid nisi non hac in proin nunc turpis velit non mauris turpis natoque, aliquam, ac dictumst parturient lundium pulvinar est integer augue scelerisque scelerisque ultrices nascetur amet odio? Hac.

46 |
47 |
48 | 49 | 50 | 51 | 69 | 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parallax ImageScroll - jQuery plugin 2 | 3 | JQuery and amd compatible plugin to create a parallax effect with images. Heavily inspired by the [spotify.com](https://www.spotify.com) website. 4 | 5 | The plugin is really simple to use with some options to tweek. It makes use of css3 transform for animation where supported and falls back to top and left positioning for ancient browsers. 6 | 7 | [Check out the live demo](http://codepen.io/pederan/full/Hheuy). (No parallax effect and smaller image sizes for touch devices, see Touch section for details.) 8 | 9 | ### Markup 10 | 11 | Markup can consist of as many image elements as you want, but you should separate them with a content block, e.g. a section. 12 | 13 | ```html 14 |
15 |

Content that "slides" on top of the images

16 |
[optional content to be displayed on top of the images]
17 | ``` 18 | 19 | You can set parameters using html5 data attributes or with javascript, see options section for details. 20 | 21 | ### Initialization 22 | 23 | To initialize the plugin, call the imageScroll method on your image elements 24 | ```javascript 25 | $('.img-holder').imageScroll(); 26 | ``` 27 | 28 | ### AMD 29 | 30 | The plugin is AMD compatible. To use with e.g. RequireJS, you can do this. See demo files for example. 31 | ```javascript 32 | require(['jquery.imageScroll'], function (ImageScroll) { 33 | $('.img-holder').each(function () { 34 | new ImageScroll(this); 35 | }); 36 | //or 37 | //$('.img-holder').imageScroll(); 38 | }); 39 | ``` 40 | 41 | ### Options 42 | 43 | You can configure the default options, by passing an option object to the plugin 44 | ```javascript 45 | $('.img-holder').imageScroll({ 46 | coverRatio: 0.5 47 | }); 48 | ``` 49 | 50 | or set the options via data attributes, data-*optionname* (available options: image, width (mediaWidth), height (mediaHeight), cover-ratio (coverRatio), min-height (holderMinHeight), max-height (holderMaxHeight), extra-height (extraHeight) 51 | ```html 52 |
53 | ``` 54 | 55 | or set the options globally 56 | ```javascript 57 | $.fn.imageScroll.defaults.coverRatio = 0.5; 58 | //AMD 59 | ImageScroll.defaults.coverRatio = 0.5; 60 | ``` 61 | 62 | Configurable options: 63 | * ```image: null``` : The image to show (best to set this option via data attr (data-img) 64 | * ```imageAttribute: 'image'```: The data attribute name for images. Uses the value of this attribute to load the image 65 | * ```container: $('body')``` The element to which the parallax image(s) will be attached to 66 | * ```windowObject: $(window)``` The window object which listens to scroll and resize events 67 | * ```speed: 0.2``` The speed of the parallax effect. A floating number between 0 and 1, where a higher number will move the images faster upwards 68 | * ```coverRatio: 0.75 //75%``` How many percent of the screen each image should cover 69 | * ```holderClass: 'imageHolder'``` Class added to the image holder(s) 70 | * ```imgClass: 'img-holder-img'``` Class added to the image 71 | * ```holderMinHeight: 200``` The minimum height of the image in pixels 72 | * ```holderMaxHeight: null``` The maximum height of the image in pixels 73 | * ```extraHeight: 0``` Extra height added to the image. Can be useful if you want to show more of the top image 74 | * ```mediaWidth: 1600``` The original width of the image 75 | * ```mediaHeight: 900``` The original height of the image 76 | * ```parallax: true``` Whether or not you want the parallax effect, e.g. does not work very well in ancient browsers 77 | * ```touch: false``` Presents a mobile/tablet friendy version, no parallax effect and smaller images (should be used with a mobile/tablet optimized images) 78 | 79 | Public methods: 80 | * ```disable()``` 81 | * ```enable()``` 82 | * ```refresh()``` 83 | * ```destroy()``` 84 | 85 | You can call them on individual- or all the instances. 86 | ```javascript 87 | //Call method refresh on all the instances of the plugin 88 | var instances = $('.img-holder'); 89 | instances.imageScroll('refresh'); 90 | 91 | //E.g. Call method refresh on the first image 92 | //Alternative 1: 93 | var instances = $('.img-holder'); 94 | var instance = $(instances.get(0)); 95 | instance.imageScroll('refresh'); 96 | 97 | //Alternative 2: 98 | var instances = $('.img-holder'); 99 | var instance = $(instances.get(0)).data('plugin_imageScroll'); 100 | instance.refresh(); 101 | 102 | ``` 103 | 104 | ### Touch 105 | 106 | The effect is not very smooth on a touch device. You could therefore present the user with a fallback version, which displays the images with no parallax effect. You can do so by checking for touch (e.g. with Modernizr, external lib) and set dynamic options to adjust to this. 107 | ```javascript 108 | var touch = Modernizr.touch; 109 | $('.img-holder').imageScroll({ 110 | imageAttribute: (touch === true) ? 'image-mobile' : 'image', 111 | touch: touch 112 | }); 113 | ``` 114 | 115 | ### Installation 116 | 117 | Install using bower 118 | ```sh 119 | bower install Parallax-ImageScroll 120 | ``` 121 | 122 | Install using npm 123 | ```sh 124 | npm install parallax-imagescroll 125 | ``` 126 | 127 | ### Requirements 128 | 129 | jQuery version 1.8.0 or higher 130 | 131 | ### Notes 132 | 133 | If you add content on top of the parallaxed image, make sure to apply a higher z-depth for the content (applies for browsers that support 3d transforms). 134 | Example: 135 | 136 | ```html 137 |

Hello world!

138 | ``` 139 | 140 | ### Limitations 141 | 142 | Does not work very well on mobile or IE <= 9. You can then present a fallback solution by disabling parallax for ancient desktop browser (set parallax option to false) and present touch optimized images for touch devices (set touch option to true). 143 | 144 | ### MIT 145 | 146 | MIT licensed 147 | -------------------------------------------------------------------------------- /jquery.imageScroll.min.js: -------------------------------------------------------------------------------- 1 | !function(t,i){"function"==typeof define&&define.amd?define(["jquery"],i):"object"==typeof module&&"object"==typeof module.exports?module.exports=i(require("jquery")):i(t.jQuery)}(this,function(t){"use strict";function i(t,i){return typeof t===i}function e(t,i){return!!~(""+t).indexOf(i)}function s(t,i){for(var s in t){var o=t[s];if(!e(o,"-")&&void 0!==p[o])return"pfx"==i?o:!0}return!1}function o(t,e,s){for(var o in t){var n=e[t[o]];if(void 0!==n)return s===!1?t[o]:i(n,"function")?n.bind(s||e):n}return!1}function n(t,e,n){var r=t.charAt(0).toUpperCase()+t.slice(1),h=(t+" "+H.join(r+" ")+r).split(" ");return i(e,"string")||i(e,"undefined")?s(h,e):(h=(t+" "+w.join(r+" ")+r).split(" "),o(h,e,n))}var r,h,l={image:null,imageAttribute:"image",holderClass:"imageHolder",imgClass:"img-holder-img",container:t("body"),windowObject:t(window),speed:.2,coverRatio:.75,holderMinHeight:200,holderMaxHeight:null,extraHeight:0,mediaWidth:1600,mediaHeight:900,parallax:!0,touch:!1},a="imageScroll",d="plugin_"+a,c=function(t,i){return function(){return t.apply(i,arguments)}},g={},m=document.documentElement,f="imageScrollModernizr",u=document.createElement(f),p=u.style,v="Webkit Moz O ms",H=v.split(" "),w=v.toLowerCase().split(" "),b={},y=0,x="",$=function(t,i,e,s){var o,n,r,h,l=document.createElement("div"),a=document.body,d=a||document.createElement("body");if(parseInt(e,10))for(;e--;)r=document.createElement("div"),r.id=s?s[e]:f+(e+1),l.appendChild(r);return o=["­",'"].join(""),l.id=f,(a?l:d).innerHTML+=o,d.appendChild(l),a||(d.style.background="",d.style.overflow="hidden",h=m.style.overflow,m.style.overflow="hidden",m.appendChild(d)),n=i(l,t),a?l.parentNode.removeChild(l):(d.parentNode.removeChild(d),m.style.overflow=h),!!n};return b.csstransforms=function(){return!!n("transform")},b.csstransforms3d=function(){var t=!!n("perspective");return t&&"webkitPerspective"in m.style&&$("@media (transform-3d),(-webkit-transform-3d){#imageScrollModernizr{left:9px;position:absolute;height:3px;}}",function(i){t=9===i.offsetLeft&&3===i.offsetHeight}),t},g.prefixed=function(t,i,e){return i?n(t,i,e):n(t,"pfx")},window.requestAnimationFrame=g.prefixed("requestAnimationFrame",window)||function(t){var i=(new Date).getTime(),e=Math.max(0,16-(i-y)),s=window.setTimeout(function(){t(i+e)},e);return y=i+e,s},b.csstransforms3d()?x="csstransforms3d":b.csstransforms()&&(x="csstransforms"),""!==x&&(h=g.prefixed("transform")),r=function(i,e){this.$imageHolder=t(i),this.settings=t.extend({},l,e),this.image=this.$imageHolder.data(this.settings.imageAttribute)||this.settings.image,this.mediaWidth=this.$imageHolder.data("width")||this.settings.mediaWidth,this.mediaHeight=this.$imageHolder.data("height")||this.settings.mediaHeight,this.coverRatio=this.$imageHolder.data("cover-ratio")||this.settings.coverRatio,this.holderMinHeight=this.$imageHolder.data("min-height")||this.settings.holderMinHeight,this.holderMaxHeight=this.$imageHolder.data("max-height")||this.settings.holderMaxHeight,this.extraHeight=this.$imageHolder.data("extra-height")||this.settings.extraHeight,this.ticking=!1,this.refresh=c(this.refresh,this),this._onScroll=c(this._onScroll,this),this._defaults=l,this._name=a,this.init()},t.extend(r.prototype,{constructor:r,init:function(){if(!this.image)throw new Error("You need to provide either a data-img attr or an image option");this.$scrollingElement=t("",{src:this.image}).addClass(this.settings.imgClass),this.settings.touch===!0?this.$scrollingElement.css({maxWidth:"100%"}).prependTo(this.$imageHolder):this.settings.parallax===!0?(this.$scrollerHolder=t("
",{html:this.$imageHolder.html()}).css({top:0,visibility:"hidden",position:"fixed",overflow:"hidden"}).addClass(this.settings.holderClass).prependTo(this.settings.container),this.$imageHolder.css("visibility","hidden").empty(),this.$scrollingElement.css({position:"absolute",top:0,left:0,visibility:"hidden",maxWidth:"none"}).prependTo(this.$scrollerHolder)):(this.$scrollerHolder=this.$imageHolder.css({overflow:"hidden"}),this.$scrollingElement.css({position:"relative",overflow:"hidden"}).prependTo(this.$imageHolder)),this.settings.touch===!1&&(this._bindEvents(),this.refresh())},_adjustImgHolderHeights:function(){var t,i,e,s,o,n,r,h,l,a=this.settings.windowObject.height(),d=this.settings.windowObject.width()-this.settings.container.offset().left,c=this.coverRatio*a;c=null===this.holderMaxHeight||this.holderMaxHeight>c?Math.floor(c):this.holderMaxHeight,c=this.holderMinHeight=d?r=h:(n=d,r=Math.round(this.mediaHeight*(n/this.mediaWidth))),l=h-c,o=a+c,s=2*a*(1-this.settings.speed)-l,t=-(l/2+(r-h)/2),i=Math.round((n-d)*-.5),e=t-s/2,this.$scrollingElement.css({height:r,width:n}),this.$imageHolder.height(c),this.$scrollerHolder.css({height:c,width:n}),this.scrollingState={winHeight:a,fromY:e,imgTopPos:t,imgLeftPos:i,imgHolderHeight:c,imgScrollingDistance:s,travelDistance:o,holderDistanceFromTop:this.$imageHolder.offset().top-this.settings.windowObject.scrollTop()}},_bindEvents:function(){this.settings.windowObject.on("resize",this.refresh),this.settings.parallax===!0&&this.settings.windowObject.on("scroll",this._onScroll)},_unBindEvents:function(){this.settings.windowObject.off("resize",this.refresh),this.settings.parallax===!0&&this.settings.windowObject.off("scroll",this._onScroll)},_onScroll:function(){this.scrollingState.holderDistanceFromTop=this.$imageHolder.offset().top-this.settings.windowObject.scrollTop(),this._requestTick()},_requestTick:function(){var t=this;this.ticking||(this.ticking=!0,requestAnimationFrame(function(){t._updatePositions()}))},_updatePositions:function(){if(this.scrollingState.holderDistanceFromTop<=this.scrollingState.winHeight&&this.scrollingState.holderDistanceFromTop>=-this.scrollingState.imgHolderHeight){var t=this.scrollingState.holderDistanceFromTop+this.scrollingState.imgHolderHeight,i=t/this.scrollingState.travelDistance,e=Math.round(this.scrollingState.fromY+this.scrollingState.imgScrollingDistance*(1-i)),s=this.settings.container.offset().left;this.$scrollerHolder.css(this._getCSSObject({transform:h,left:s,x:Math.ceil(this.scrollingState.imgLeftPos)+(""===x&&s>0?s:0),y:Math.round(this.scrollingState.holderDistanceFromTop),visibility:"visible"})),this.$scrollingElement.css(this._getCSSObject({transform:h,x:0,y:e,visibility:"visible"}))}else this.$scrollerHolder.css({visibility:"hidden"}),this.$scrollingElement.css({visibility:"hidden"});this.ticking=!1},_updateFallbackPositions:function(){this.$scrollerHolder.css({width:"100%"}),this.$scrollingElement.css({top:this.scrollingState.imgTopPos,left:this.scrollingState.imgLeftPos})},_getCSSObject:function(t){return"csstransforms3d"===x?t.transform="translate3d("+t.x+"px, "+t.y+"px, 0)":"csstransforms"===x?t.transform="translate("+t.x+"px, "+t.y+"px)":(t.top=t.y,t.left=t.x),delete t.x,delete t.y,t},enable:function(){this.settings.touch===!1&&(this._bindEvents(),this.refresh())},disable:function(){this.settings.touch===!1&&this._unBindEvents()},refresh:function(){this.settings.touch===!1&&(this._adjustImgHolderHeights(),this.settings.parallax===!0?this._requestTick():this._updateFallbackPositions())},destroy:function(){this.settings.touch===!1&&this._unBindEvents(),this.settings.touch===!0?(this.$imageHolder.removeAttr("style"),this.$scrollingElement.remove()):this.settings.parallax===!0?(this.$scrollerHolder.find("."+this.settings.imgClass).remove(),this.$imageHolder.css({visibility:"visible",height:"auto"}).html(this.$scrollerHolder.html()),this.$scrollerHolder.remove()):(this.$imageHolder.css({overflow:"auto"}).removeAttr("style"),this.$scrollingElement.remove()),this.$imageHolder.removeData()}}),t.fn[a]=function(i){return void 0===i||"object"==typeof i?this.each(function(){t.data(this,d)||t.data(this,d,new r(this,i))}):"string"==typeof i&&"_"!==i[0]&&"init"!==i?this.each(function(){var e=t.data(this,d);e instanceof r&&"function"==typeof e[i]&&e[i].apply(e,Array.prototype.slice.call(arguments,1))}):void 0},t.fn[a].defaults=r.defaults=l,t.fn[a].Plugin=r,r}); -------------------------------------------------------------------------------- /jquery.imageScroll.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Parallax ImageScroll - jQuery plugin 3 | * Author: Peder A. Nielsen 4 | * Email: peder1976@gmail.com 5 | * Created date: 04.12.13 6 | * Updated date: 08.07.15 7 | * Version: 0.2.3 8 | * Company: Making Waves 9 | * Licensed under the MIT license 10 | */ 11 | ; 12 | (function (root, factory) { 13 | if (typeof define === 'function' && define.amd) { 14 | // AMD 15 | define(['jquery'], factory); 16 | } else if (typeof module === 'object' && typeof module.exports === 'object') { 17 | // CommonJS 18 | module.exports = factory( 19 | require('jquery') 20 | ); 21 | } else { 22 | factory(root.jQuery); 23 | } 24 | }(this, function ($) { 25 | 'use strict'; 26 | 27 | var Plugin, 28 | defaults = { 29 | image: null, 30 | imageAttribute: 'image', 31 | holderClass: 'imageHolder', 32 | imgClass: 'img-holder-img', 33 | container: $('body'), 34 | windowObject: $(window), 35 | speed: 0.2, 36 | coverRatio: 0.75, 37 | holderMinHeight: 200, 38 | holderMaxHeight: null, 39 | extraHeight: 0, 40 | mediaWidth: 1600, 41 | mediaHeight: 900, 42 | parallax: true, 43 | touch: false 44 | }, 45 | pluginName = 'imageScroll', 46 | dataKey = "plugin_" + pluginName, 47 | __bind = function (fn, me) { 48 | return function () { 49 | return fn.apply(me, arguments); 50 | }; 51 | }, 52 | ImageScrollModernizr = {}, 53 | docElement = document.documentElement, 54 | mod = 'imageScrollModernizr', 55 | modElem = document.createElement(mod), 56 | mStyle = modElem.style, 57 | omPrefixes = 'Webkit Moz O ms', 58 | cssomPrefixes = omPrefixes.split(' '), 59 | domPrefixes = omPrefixes.toLowerCase().split(' '), 60 | tests = {}, 61 | lastTickTime = 0, 62 | supportedFeature = '', 63 | transformProperty, 64 | injectElementWithStyles = function (rule, callback, nodes, testnames) { 65 | var style, ret, node, docOverflow, 66 | div = document.createElement('div'), 67 | body = document.body, 68 | fakeBody = body || document.createElement('body'); 69 | 70 | if (parseInt(nodes, 10)) { 71 | while (nodes--) { 72 | node = document.createElement('div'); 73 | node.id = testnames ? testnames[nodes] : mod + (nodes + 1); 74 | div.appendChild(node); 75 | } 76 | } 77 | 78 | style = ['­', ''].join(''); 79 | div.id = mod; 80 | (body ? div : fakeBody).innerHTML += style; 81 | fakeBody.appendChild(div); 82 | if (!body) { 83 | fakeBody.style.background = ''; 84 | fakeBody.style.overflow = 'hidden'; 85 | docOverflow = docElement.style.overflow; 86 | docElement.style.overflow = 'hidden'; 87 | docElement.appendChild(fakeBody); 88 | } 89 | 90 | ret = callback(div, rule); 91 | if (!body) { 92 | fakeBody.parentNode.removeChild(fakeBody); 93 | docElement.style.overflow = docOverflow; 94 | } else { 95 | div.parentNode.removeChild(div); 96 | } 97 | 98 | return !!ret; 99 | }; 100 | 101 | function is(obj, type) { 102 | return typeof obj === type; 103 | } 104 | 105 | function contains(str, substr) { 106 | return !!~('' + str).indexOf(substr); 107 | } 108 | 109 | function testProps(props, prefixed) { 110 | for (var i in props) { 111 | var prop = props[i]; 112 | if (!contains(prop, "-") && mStyle[prop] !== undefined) { 113 | return prefixed == 'pfx' ? prop : true; 114 | } 115 | } 116 | return false; 117 | } 118 | 119 | function testDOMProps(props, obj, elem) { 120 | for (var i in props) { 121 | var item = obj[props[i]]; 122 | if (item !== undefined) { 123 | 124 | if (elem === false) return props[i]; 125 | 126 | if (is(item, 'function')) { 127 | return item.bind(elem || obj); 128 | } 129 | 130 | return item; 131 | } 132 | } 133 | return false; 134 | } 135 | 136 | function testPropsAll(prop, prefixed, elem) { 137 | var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1), 138 | props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' '); 139 | 140 | if (is(prefixed, "string") || is(prefixed, "undefined")) { 141 | return testProps(props, prefixed); 142 | } else { 143 | props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' '); 144 | return testDOMProps(props, prefixed, elem); 145 | } 146 | } 147 | 148 | tests['csstransforms'] = function () { 149 | return !!testPropsAll('transform'); 150 | }; 151 | 152 | tests['csstransforms3d'] = function () { 153 | 154 | var ret = !!testPropsAll('perspective'); 155 | 156 | if (ret && 'webkitPerspective' in docElement.style) { 157 | 158 | injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#imageScrollModernizr{left:9px;position:absolute;height:3px;}}', function (node, rule) { 159 | ret = node.offsetLeft === 9 && node.offsetHeight === 3; 160 | }); 161 | } 162 | return ret; 163 | }; 164 | 165 | ImageScrollModernizr.prefixed = function (prop, obj, elem) { 166 | if (!obj) { 167 | return testPropsAll(prop, 'pfx'); 168 | } else { 169 | return testPropsAll(prop, obj, elem); 170 | } 171 | }; 172 | 173 | window.requestAnimationFrame = ImageScrollModernizr.prefixed('requestAnimationFrame', window) || function (callback, element) { 174 | var currTime = new Date().getTime(); 175 | var timeToCall = Math.max(0, 16 - (currTime - lastTickTime)); 176 | var id = window.setTimeout(function () { 177 | callback(currTime + timeToCall); 178 | }, 179 | timeToCall); 180 | lastTickTime = currTime + timeToCall; 181 | return id; 182 | }; 183 | 184 | if (tests['csstransforms3d']()) { 185 | supportedFeature = 'csstransforms3d'; 186 | } else if (tests['csstransforms']()) { 187 | supportedFeature = 'csstransforms'; 188 | } 189 | 190 | if (supportedFeature !== '') { 191 | transformProperty = ImageScrollModernizr.prefixed('transform'); 192 | } 193 | 194 | // The actual plugin constructor 195 | Plugin = function (imageHolder, options) { 196 | this.$imageHolder = $(imageHolder); 197 | this.settings = $.extend({}, defaults, options); 198 | this.image = this.$imageHolder.data(this.settings.imageAttribute) || this.settings.image; 199 | this.mediaWidth = this.$imageHolder.data('width') || this.settings.mediaWidth; 200 | this.mediaHeight = this.$imageHolder.data('height') || this.settings.mediaHeight; 201 | this.coverRatio = this.$imageHolder.data('cover-ratio') || this.settings.coverRatio; 202 | this.holderMinHeight = this.$imageHolder.data('min-height') || this.settings.holderMinHeight; 203 | this.holderMaxHeight = this.$imageHolder.data('max-height') || this.settings.holderMaxHeight; 204 | this.extraHeight = this.$imageHolder.data('extra-height') || this.settings.extraHeight; 205 | this.ticking = false; 206 | this.refresh = __bind(this.refresh, this); 207 | this._onScroll = __bind(this._onScroll, this); 208 | this._defaults = defaults; 209 | this._name = pluginName; 210 | this.init(); 211 | }; 212 | 213 | // Avoid Plugin.prototype conflicts 214 | $.extend(Plugin.prototype, { 215 | constructor: Plugin, 216 | init: function () { 217 | if (this.image) { 218 | this.$scrollingElement = $('', { 219 | src: this.image 220 | }).addClass(this.settings.imgClass); 221 | } else { 222 | throw new Error('You need to provide either a data-img attr or an image option'); 223 | } 224 | 225 | if (this.settings.touch === true) { 226 | this.$scrollingElement.css({maxWidth: '100%'}).prependTo(this.$imageHolder); 227 | } else if (this.settings.parallax === true) { 228 | this.$scrollerHolder = $('
', { 229 | html: this.$imageHolder.html() 230 | }).css({ 231 | top: 0, 232 | visibility: 'hidden', 233 | position: 'fixed', 234 | overflow: 'hidden' 235 | }).addClass(this.settings.holderClass).prependTo(this.settings.container); 236 | this.$imageHolder.css('visibility', 'hidden').empty(); 237 | this.$scrollingElement.css({ 238 | position: 'absolute', 239 | top: 0, 240 | left: 0, 241 | visibility: 'hidden', 242 | maxWidth: 'none' 243 | }).prependTo(this.$scrollerHolder); 244 | } else { 245 | this.$scrollerHolder = this.$imageHolder.css({overflow: 'hidden'}); 246 | this.$scrollingElement.css({position: 'relative', overflow: 'hidden'}).prependTo(this.$imageHolder); 247 | } 248 | 249 | if (this.settings.touch === false) { 250 | this._bindEvents(); 251 | this.refresh(); 252 | } 253 | }, 254 | _adjustImgHolderHeights: function () { 255 | var winHeight = this.settings.windowObject.height(), 256 | winWidth = this.settings.windowObject.width() - this.settings.container.offset().left, 257 | imgHolderHeight = this.coverRatio * winHeight, 258 | imgTopPos, 259 | imgLeftPos, 260 | fromY, 261 | imgScrollingDistance, 262 | travelDistance, 263 | imgWidth, 264 | imgHeight, 265 | fakedImgHeight, 266 | imageDiff; 267 | imgHolderHeight = this.holderMaxHeight === null || this.holderMaxHeight > imgHolderHeight ? Math.floor(imgHolderHeight) : this.holderMaxHeight; 268 | imgHolderHeight = this.holderMinHeight < imgHolderHeight ? Math.floor(imgHolderHeight) : this.holderMinHeight; 269 | imgHolderHeight += this.extraHeight; 270 | fakedImgHeight = Math.floor(winHeight - (winHeight - imgHolderHeight) * this.settings.speed); 271 | imgWidth = Math.round(this.mediaWidth * (fakedImgHeight / this.mediaHeight)); 272 | 273 | if (imgWidth >= winWidth) { 274 | imgHeight = fakedImgHeight; 275 | } else { 276 | imgWidth = winWidth; 277 | imgHeight = Math.round(this.mediaHeight * (imgWidth / this.mediaWidth)); 278 | } 279 | 280 | imageDiff = fakedImgHeight - imgHolderHeight; 281 | travelDistance = winHeight + imgHolderHeight; 282 | imgScrollingDistance = (((winHeight * 2) * (1 - this.settings.speed)) - imageDiff); 283 | imgTopPos = -((imageDiff / 2) + ((imgHeight - fakedImgHeight) / 2)); 284 | imgLeftPos = Math.round((imgWidth - winWidth) * -0.5); 285 | fromY = imgTopPos - (imgScrollingDistance / 2); 286 | 287 | this.$scrollingElement.css({ 288 | height: imgHeight, 289 | width: imgWidth 290 | }); 291 | this.$imageHolder.height(imgHolderHeight); 292 | 293 | this.$scrollerHolder.css({ 294 | height: imgHolderHeight, 295 | width: imgWidth 296 | }); 297 | 298 | this.scrollingState = { 299 | winHeight: winHeight, 300 | fromY: fromY, 301 | imgTopPos: imgTopPos, 302 | imgLeftPos: imgLeftPos, 303 | imgHolderHeight: imgHolderHeight, 304 | imgScrollingDistance: imgScrollingDistance, 305 | travelDistance: travelDistance, 306 | holderDistanceFromTop: this.$imageHolder.offset().top - this.settings.windowObject.scrollTop() 307 | }; 308 | }, 309 | _bindEvents: function () { 310 | this.settings.windowObject.on('resize', this.refresh); 311 | if (this.settings.parallax === true) { 312 | this.settings.windowObject.on('scroll', this._onScroll); 313 | } 314 | }, 315 | _unBindEvents: function () { 316 | this.settings.windowObject.off('resize', this.refresh); 317 | if (this.settings.parallax === true) { 318 | this.settings.windowObject.off('scroll', this._onScroll); 319 | } 320 | }, 321 | _onScroll: function () { 322 | this.scrollingState.holderDistanceFromTop = this.$imageHolder.offset().top - this.settings.windowObject.scrollTop(); 323 | this._requestTick(); 324 | }, 325 | _requestTick: function () { 326 | var self = this; 327 | if (!this.ticking) { 328 | this.ticking = true; 329 | requestAnimationFrame(function () { 330 | self._updatePositions(); 331 | }); 332 | } 333 | }, 334 | _updatePositions: function () { 335 | if (this.scrollingState.holderDistanceFromTop <= (this.scrollingState.winHeight) && this.scrollingState.holderDistanceFromTop >= -this.scrollingState.imgHolderHeight) { 336 | var distanceFromTopAddedWinHeight = this.scrollingState.holderDistanceFromTop + this.scrollingState.imgHolderHeight, 337 | distanceInPercent = distanceFromTopAddedWinHeight / this.scrollingState.travelDistance, 338 | currentImgYPosition = Math.round(this.scrollingState.fromY + (this.scrollingState.imgScrollingDistance * (1 - distanceInPercent))), 339 | leftOffset = this.settings.container.offset().left; 340 | 341 | this.$scrollerHolder.css(this._getCSSObject({ 342 | transform: transformProperty, 343 | left: leftOffset, 344 | x: Math.ceil(this.scrollingState.imgLeftPos) + (supportedFeature === '' && leftOffset > 0 ? leftOffset : 0), 345 | y: Math.round(this.scrollingState.holderDistanceFromTop), 346 | visibility: 'visible' 347 | })); 348 | 349 | this.$scrollingElement.css(this._getCSSObject({ 350 | transform: transformProperty, 351 | x: 0, 352 | y: currentImgYPosition, 353 | visibility: 'visible' 354 | })); 355 | } else { 356 | this.$scrollerHolder.css({visibility: 'hidden'}); 357 | this.$scrollingElement.css({visibility: 'hidden'}); 358 | } 359 | 360 | this.ticking = false; 361 | }, 362 | _updateFallbackPositions: function () { 363 | this.$scrollerHolder.css({width: '100%'}); 364 | this.$scrollingElement.css({ 365 | top: this.scrollingState.imgTopPos, 366 | left: this.scrollingState.imgLeftPos 367 | }); 368 | }, 369 | _getCSSObject: function (options) { 370 | if (supportedFeature === "csstransforms3d") { 371 | options.transform = "translate3d(" + options.x + "px, " + options.y + "px, 0)"; 372 | } else if (supportedFeature === "csstransforms") { 373 | options.transform = "translate(" + options.x + "px, " + options.y + "px)"; 374 | } else { 375 | options.top = options.y; 376 | options.left = options.x; 377 | } 378 | delete options.x; 379 | delete options.y; 380 | return options; 381 | }, 382 | enable: function () { 383 | if (this.settings.touch === false) { 384 | this._bindEvents(); 385 | this.refresh(); 386 | } 387 | }, 388 | disable: function () { 389 | if (this.settings.touch === false) { 390 | this._unBindEvents(); 391 | } 392 | }, 393 | refresh: function () { 394 | if (this.settings.touch === false) { 395 | this._adjustImgHolderHeights(); 396 | if (this.settings.parallax === true) { 397 | this._requestTick(); 398 | } else { 399 | this._updateFallbackPositions(); 400 | } 401 | } 402 | }, 403 | destroy: function () { 404 | //clean up events 405 | if (this.settings.touch === false) { 406 | this._unBindEvents(); 407 | } 408 | 409 | //restore initial html structure 410 | if (this.settings.touch === true) { 411 | this.$imageHolder.removeAttr('style'); 412 | this.$scrollingElement.remove(); 413 | } else if (this.settings.parallax === true) { 414 | this.$scrollerHolder.find('.' + this.settings.imgClass).remove(); 415 | this.$imageHolder.css({visibility: 'visible', height: 'auto'}).html(this.$scrollerHolder.html()); 416 | this.$scrollerHolder.remove(); 417 | } else { 418 | this.$imageHolder.css({overflow: 'auto'}).removeAttr('style'); 419 | this.$scrollingElement.remove(); 420 | } 421 | 422 | // Remove data 423 | this.$imageHolder.removeData(); 424 | } 425 | }); 426 | 427 | // A really lightweight plugin wrapper around the constructor, 428 | // preventing against multiple instantiations 429 | $.fn[pluginName] = function (options) { 430 | if (options === undefined || typeof options === 'object') { 431 | return this.each(function () { 432 | if (!$.data(this, dataKey)) { 433 | // Create a new instance for each element in the matched jQuery set 434 | // Also save the instance so it can be accessed later to use methods/properties etc 435 | // e.g. 436 | // var instance = $('.img-holder').data('plugin_imageScroll'); 437 | // instance.refresh(); 438 | $.data(this, dataKey, new Plugin(this, options)); 439 | } 440 | }); 441 | } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') { 442 | // Invoke the specified method on each selected element 443 | return this.each(function () { 444 | var instance = $.data(this, dataKey); 445 | // e.g. 446 | // var instance = $('.img-holder'); 447 | // instance.imageScroll('refresh'); 448 | if (instance instanceof Plugin && typeof instance[options] === 'function') { 449 | instance[options].apply(instance, Array.prototype.slice.call(arguments, 1)); 450 | } 451 | }); 452 | } 453 | }; 454 | 455 | // Expose defaults and Constructor (allowing overriding of prototype methods for example) 456 | $.fn[pluginName].defaults = Plugin.defaults = defaults; 457 | $.fn[pluginName].Plugin = Plugin; 458 | 459 | return Plugin; 460 | })); 461 | --------------------------------------------------------------------------------