PageSourceSearch

https://nikke-jp.com/pc/js/parallax.js

js nikke-jp.com collected 2026-10-02 02:52:35 UTC 18,904 bytes, 587 lines download raw bytes

1//============================================================
2//
3// The MIT License
4//
5// Copyright (C) 2014 Matthew Wagerfield - @wagerfield
6//
7// Permission is hereby granted, free of charge, to any
8// person obtaining a copy of this software and associated
9// documentation files (the "Software"), to deal in the
10// Software without restriction, including without limitation
11// the rights to use, copy, modify, merge, publish, distribute,
12// sublicense, and/or sell copies of the Software, and to
13// permit persons to whom the Software is furnished to do
14// so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice
17// shall be included in all copies or substantial portions
18// of the Software.
19//
20// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
21// OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
23// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
24// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
25// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
28// OR OTHER DEALINGS IN THE SOFTWARE.
29//
30//============================================================
31
32/**
33 * jQuery || Zepto Parallax Plugin
34 * @author Matthew Wagerfield - @wagerfield
35 * @description Creates a parallax effect between an array of layers,
36 *              driving the motion from the gyroscope output of a smartdevice.
37 *              If no gyroscope is available, the cursor position is used.
38 */
39 ;(function($, window, document, undefined) {
40
41  // Strict Mode
42  'use strict';
43
44  // Constants
45  var NAME = 'parallax';
46  var MAGIC_NUMBER = 30;
47  var DEFAULTS = {
48    relativeInput: false,
49    clipRelativeInput: false,
50    calibrationThreshold: 100,
51    calibrationDelay: 500,
52    supportDelay: 500,
53    calibrateX: false,
54    calibrateY: true,
55    invertX: true,
56    invertY: true,
57    limitX: false,
58    limitY: false,
59    scalarX: 10.0,
60    scalarY: 10.0,
61    frictionX: 0.1,
62    frictionY: 0.1,
63    originX: 0.5,
64    originY: 0.5,
65    pointerEvents: true,
66    precision: 1
67  };
68
69  function Plugin(element, options) {
70
71    // DOM Context
72    this.element = element;
73
74    // Selections
75    this.$context = $(element).data('api', this);
76    this.$layers = this.$context.find('.layer');
77
78    // Data Extraction
79    var data = {
80      calibrateX: this.$context.data('calibrate-x') || null,
81      calibrateY: this.$context.data('calibrate-y') || null,
82      invertX: this.$context.data('invert-x') || null,
83      invertY: this.$context.data('invert-y') || null,
84      limitX: parseFloat(this.$context.data('limit-x')) || null,
85      limitY: parseFloat(this.$context.data('limit-y')) || null,
86      scalarX: parseFloat(this.$context.data('scalar-x')) || null,
87      scalarY: parseFloat(this.$context.data('scalar-y')) || null,
88      frictionX: parseFloat(this.$context.data('friction-x')) || null,
89      frictionY: parseFloat(this.$context.data('friction-y')) || null,
90      originX: parseFloat(this.$context.data('origin-x')) || null,
91      originY: parseFloat(this.$context.data('origin-y')) || null,
92      pointerEvents: this.$context.data('pointer-events') || true,
93      precision: parseFloat(this.$context.data('precision')) || 1
94    };
95
96    // Delete Null Data Values
97    for (var key in data) {
98      if (data[key] === null) delete data[key];
99    }
100
101    // Compose Settings Object
102    $.extend(this, DEFAULTS, options, data);
103
104    // States
105    this.calibrationTimer = null;
106    this.calibrationFlag = true;
107    this.enabled = false;
108    this.depthsX = [];
109    this.depthsY = [];
110    this.raf = null;
111
112    // Element Bounds
113    this.bounds = null;
114    this.ex = 0;
115    this.ey = 0;
116    this.ew = 0;
117    this.eh = 0;
118
119    // Element Center
120    this.ecx = 0;
121    this.ecy = 0;
122
123    // Element Range
124    this.erx = 0;
125    this.ery = 0;
126
127    // Calibration
128    this.cx = 0;
129    this.cy = 0;
130
131    // Input
132    this.ix = 0;
133    this.iy = 0;
134
135    // Motion
136    this.mx = 0;
137    this.my = 0;
138
139    // Velocity
140    this.vx = 0;
141    this.vy = 0;
142
143    // Callbacks
144    this.onMouseMove = this.onMouseMove.bind(this);
145    this.onDeviceOrientation = this.onDeviceOrientation.bind(this);
146    this.onOrientationTimer = this.onOrientationTimer.bind(this);
147    this.onCalibrationTimer = this.onCalibrationTimer.bind(this);
148    this.onAnimationFrame = this.onAnimationFrame.bind(this);
149    this.onWindowResize = this.onWindowResize.bind(this);
150
151    // Initialise
152    this.initialise();
153  }
154
155  Plugin.prototype.transformSupport = function(value) {
156    var element = document.createElement('div');
157    var propertySupport = false;
158    var propertyValue = null;
159    var featureSupport = false;
160    var cssProperty = null;
161    var jsProperty = null;
162    for (var i = 0, l = this.vendors.length; i < l; i++) {
163      if (this.vendors[i] !== null) {
164        cssProperty = this.vendors[i][0] + 'transform';
165        jsProperty = this.vendors[i][1] + 'Transform';
166      } else {
167        cssProperty = 'transform';
168        jsProperty = 'transform';
169      }
170      if (element.style[jsProperty] !== undefined) {
171        propertySupport = true;
172        break;
173      }
174    }
175    switch(value) {
176      case '2D':
177        featureSupport = propertySupport;
178        break;
179      case '3D':
180        if (propertySupport) {
181          var body = document.body || document.createElement('body');
182          var documentElement = document.documentElement;
183          var documentOverflow = documentElement.style.overflow;
184          var isCreatedBody = false;
185          if (!document.body) {
186            isCreatedBody = true;
187            documentElement.style.overflow = 'hidden';
188            documentElement.appendChild(body);
189            body.style.overflow = 'hidden';
190            body.style.background = '';
191          }
192          body.appendChild(element);
193          element.style[jsProperty] = 'translate3d(1px,1px,1px)';
194          propertyValue = window.getComputedStyle(element).getPropertyValue(cssProperty);
195          featureSupport = propertyValue !== undefined && propertyValue.length > 0 && propertyValue !== "none";
196          documentElement.style.overflow = documentOverflow;
197          body.removeChild(element);
198          if ( isCreatedBody ) {
199            body.removeAttribute('style');
200            body.parentNode.removeChild(body);
201          }
202        }
203        break;
204    }
205    return featureSupport;
206  };
207
208  Plugin.prototype.ww = null;
209  Plugin.prototype.wh = null;
210  Plugin.prototype.wcx = null;
211  Plugin.prototype.wcy = null;
212  Plugin.prototype.wrx = null;
213  Plugin.prototype.wry = null;
214  Plugin.prototype.portrait = null;
215  Plugin.prototype.desktop = !navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|mobi|tablet|opera mini|nexus 7)/i);
216  Plugin.prototype.vendors = [null,['-webkit-','webkit'],['-moz-','Moz'],['-o-','O'],['-ms-','ms']];
217  Plugin.prototype.motionSupport = !!window.DeviceMotionEvent;
218  Plugin.prototype.orientationSupport = !!window.DeviceOrientationEvent;
219  Plugin.prototype.orientationStatus = 0;
220  Plugin.prototype.transform2DSupport = Plugin.prototype.transformSupport('2D');
221  Plugin.prototype.transform3DSupport = Plugin.prototype.transformSupport('3D');
222  Plugin.prototype.propertyCache = {};
223
224  Plugin.prototype.initialise = function() {
225
226    // Configure Styles
227    if (this.$context.css('position') === 'static') {
228      this.$context.css({
229        position:'relative'
230      });
231    }
232
233    // Pointer events
234    if(!this.pointerEvents){
235      this.$context.css({
236        pointerEvents: 'none'
237      });
238    }
239
240    // Hardware Accelerate Context
241    this.accelerate(this.$context);
242
243    // Setup
244    this.updateLayers();
245    this.updateDimensions();
246    this.enable();
247    this.queueCalibration(this.calibrationDelay);
248  };
249
250  Plugin.prototype.updateLayers = function() {
251
252    // Cache Layer Elements
253    this.$layers = this.$context.find('.layer');
254    this.depthsX = [];
255    this.depthsY = [];
256
257    // Configure Layer Styles
258    this.$layers.css({
259      position:'absolute',
260      display:'block',
261      left: 0,
262      top: 0
263    });
264    this.$layers.first().css({
265      position:'relative'
266    });
267
268    // Hardware Accelerate Layers
269    this.accelerate(this.$layers);
270
271    // Cache Depths
272    this.$layers.each($.proxy(function(index, element) {
273      //Graceful fallback on depth if depth-x or depth-y is absent
274      var depth = $(element).data('depth') || 0;
275      this.depthsX.push($(element).data('depth-x') || depth);
276      this.depthsY.push($(element).data('depth-y') || depth);
277    }, this));
278  };
279
280  Plugin.prototype.updateDimensions = function() {
281    this.ww = window.innerWidth;
282    this.wh = window.innerHeight;
283    this.wcx = this.ww * this.originX;
284    this.wcy = this.wh * this.originY;
285    this.wrx = Math.max(this.wcx, this.ww - this.wcx);
286    this.wry = Math.max(this.wcy, this.wh - this.wcy);
287  };
288
289  Plugin.prototype.updateBounds = function() {
290    this.bounds = this.element.getBoundingClientRect();
291    this.ex = this.bounds.left;
292    this.ey = this.bounds.top;
293    this.ew = this.bounds.width;
294    this.eh = this.bounds.height;
295    this.ecx = this.ew * this.originX;
296    this.ecy = this.eh * this.originY;
297    this.erx = Math.max(this.ecx, this.ew - this.ecx);
298    this.ery = Math.max(this.ecy, this.eh - this.ecy);
299  };
300
301  Plugin.prototype.queueCalibration = function(delay) {
302    clearTimeout(this.calibrationTimer);
303    this.calibrationTimer = setTimeout(this.onCalibrationTimer, delay);
304  };
305
306  Plugin.prototype.enable = function() {
307    if (!this.enabled) {
308      this.enabled = true;
309      if (this.orientationSupport) {
310        this.portrait = null;
311        window.addEventListener('deviceorientation', this.onDeviceOrientation);
312        setTimeout(this.onOrientationTimer, this.supportDelay);
313      } else {
314        this.cx = 0;
315        this.cy = 0;
316        this.portrait = false;
317        window.addEventListener('mousemove', this.onMouseMove);
318      }
319      window.addEventListener('resize', this.onWindowResize);
320      this.raf = requestAnimationFrame(this.onAnimationFrame);
321    }
322  };
323
324  Plugin.prototype.disable = function() {
325    if (this.enabled) {
326      this.enabled = false;
327      if (this.orientationSupport) {
328        window.removeEventListener('deviceorientation', this.onDeviceOrientation);
329      } else {
330        window.removeEventListener('mousemove', this.onMouseMove);
331      }
332      window.removeEventListener('resize', this.onWindowResize);
333      cancelAnimationFrame(this.raf);
334    }
335  };
336
337  Plugin.prototype.calibrate = function(x, y) {
338    this.calibrateX = x === undefined ? this.calibrateX : x;
339    this.calibrateY = y === undefined ? this.calibrateY : y;
340  };
341
342  Plugin.prototype.invert = function(x, y) {
343    this.invertX = x === undefined ? this.invertX : x;
344    this.invertY = y === undefined ? this.invertY : y;
345  };
346
347  Plugin.prototype.friction = function(x, y) {
348    this.frictionX = x === undefined ? this.frictionX : x;
349    this.frictionY = y === undefined ? this.frictionY : y;
350  };
351
352  Plugin.prototype.scalar = function(x, y) {
353    this.scalarX = x === undefined ? this.scalarX : x;
354    this.scalarY = y === undefined ? this.scalarY : y;
355  };
356
357  Plugin.prototype.limit = function(x, y) {
358    this.limitX = x === undefined ? this.limitX : x;
359    this.limitY = y === undefined ? this.limitY : y;
360  };
361
362  Plugin.prototype.origin = function(x, y) {
363    this.originX = x === undefined ? this.originX : x;
364    this.originY = y === undefined ? this.originY : y;
365  };
366
367  Plugin.prototype.clamp = function(value, min, max) {
368    value = Math.max(value, min);
369    value = Math.min(value, max);
370    return value;
371  };
372
373  Plugin.prototype.css = function(element, property, value) {
374    var jsProperty = this.propertyCache[property];
375    if (!jsProperty) {
376      for (var i = 0, l = this.vendors.length; i < l; i++) {
377        if (this.vendors[i] !== null) {
378          jsProperty = $.camelCase(this.vendors[i][1] + '-' + property);
379        } else {
380          jsProperty = property;
381        }
382        if (element.style[jsProperty] !== undefined) {
383          this.propertyCache[property] = jsProperty;
384          break;
385        }
386      }
387    }
388    element.style[jsProperty] = value;
389  };
390
391  Plugin.prototype.accelerate = function($element) {
392    for (var i = 0, l = $element.length; i < l; i++) {
393      var element = $element[i];
394      this.css(element, 'transform', 'translate3d(0,0,0)');
395      this.css(element, 'transform-style', 'preserve-3d');
396      this.css(element, 'backface-visibility', 'hidden');
397    }
398  };
399
400  Plugin.prototype.setPosition = function(element, x, y) {
401    x += 'px';
402    y += 'px';
403    if (this.transform3DSupport) {
404      this.css(element, 'transform', 'translate3d('+x+','+y+',0)');
405    } else if (this.transform2DSupport) {
406      this.css(element, 'transform', 'translate('+x+','+y+')');
407    } else {
408      element.style.left = x;
409      element.style.top = y;
410    }
411  };
412
413  Plugin.prototype.onOrientationTimer = function(event) {
414    if (this.orientationSupport && this.orientationStatus === 0) {
415      this.disable();
416      this.orientationSupport = false;
417      this.enable();
418    }
419  };
420
421  Plugin.prototype.onCalibrationTimer = function(event) {
422    this.calibrationFlag = true;
423  };
424
425  Plugin.prototype.onWindowResize = function(event) {
426    this.updateDimensions();
427  };
428
429  Plugin.prototype.onAnimationFrame = function() {
430    this.updateBounds();
431    var dx = this.ix - this.cx;
432    var dy = this.iy - this.cy;
433    if ((Math.abs(dx) > this.calibrationThreshold) || (Math.abs(dy) > this.calibrationThreshold)) {
434      this.queueCalibration(0);
435    }
436    if (this.portrait) {
437      this.mx = this.calibrateX ? dy : this.iy;
438      this.my = this.calibrateY ? dx : this.ix;
439    } else {
440      this.mx = this.calibrateX ? dx : this.ix;
441      this.my = this.calibrateY ? dy : this.iy;
442    }
443    this.mx *= this.ew * (this.scalarX / 100);
444    this.my *= this.eh * (this.scalarY / 100);
445    if (!isNaN(parseFloat(this.limitX))) {
446      this.mx = this.clamp(this.mx, -this.limitX, this.limitX);
447    }
448    if (!isNaN(parseFloat(this.limitY))) {
449      this.my = this.clamp(this.my, -this.limitY, this.limitY);
450    }
451    this.vx += (this.mx - this.vx) * this.frictionX;
452    this.vy += (this.my - this.vy) * this.frictionY;
453    for (var i = 0, l = this.$layers.length; i < l; i++) {
454      var depthX = this.depthsX[i];
455      var depthY = this.depthsY[i];
456      var layer = this.$layers[i];
457      var xOffset = this.vx * (depthX * (this.invertX ? -1 : 1));
458      var yOffset = this.vy * (depthY * (this.invertY ? -1 : 1));
459      this.setPosition(layer, xOffset, yOffset);
460    }
461    this.raf = requestAnimationFrame(this.onAnimationFrame);
462  };
463
464  Plugin.prototype.onDeviceOrientation = function(event) {
465
466    // Validate environment and event properties.
467    if (!this.desktop && event.beta !== null && event.gamma !== null) {
468
469      // Set orientation status.
470      this.orientationStatus = 1;
471
472      // Extract Rotation
473      var x = (event.beta  || 0) / MAGIC_NUMBER; //  -90 :: 90
474      var y = (event.gamma || 0) / MAGIC_NUMBER; // -180 :: 180
475
476      // Detect Orientation Change
477      var portrait = window.innerHeight > window.innerWidth;
478      if (this.portrait !== portrait) {
479        this.portrait = portrait;
480        this.calibrationFlag = true;
481      }
482
483      // Set Calibration
484      if (this.calibrationFlag) {
485        this.calibrationFlag = false;
486        this.cx = x;
487        this.cy = y;
488      }
489
490      // Set Input
491      this.ix = x;
492      this.iy = y;
493    }
494  };
495
496  Plugin.prototype.onMouseMove = function(event) {
497
498    // Cache mouse coordinates.
499    var clientX = event.clientX;
500    var clientY = event.clientY;
501
502    // Calculate Mouse Input
503    if (!this.orientationSupport && this.relativeInput) {
504
505      // Clip mouse coordinates inside element bounds.
506      if (this.clipRelativeInput) {
507        clientX = Math.max(clientX, this.ex);
508        clientX = Math.min(clientX, this.ex + this.ew);
509        clientY = Math.max(clientY, this.ey);
510        clientY = Math.min(clientY, this.ey + this.eh);
511      }
512
513      // Calculate input relative to the element.
514      this.ix = (clientX - this.ex - this.ecx) / this.erx;
515      this.iy = (clientY - this.ey - this.ecy) / this.ery;
516
517    } else {
518
519      // Calculate input relative to the window.
520      this.ix = (clientX - this.wcx) / this.wrx;
521      this.iy = (clientY - this.wcy) / this.wry;
522    }
523  };
524
525  var API = {
526    enable: Plugin.prototype.enable,
527    disable: Plugin.prototype.disable,
528    updateLayers: Plugin.prototype.updateLayers,
529    calibrate: Plugin.prototype.calibrate,
530    friction: Plugin.prototype.friction,
531    invert: Plugin.prototype.invert,
532    scalar: Plugin.prototype.scalar,
533    limit: Plugin.prototype.limit,
534    origin: Plugin.prototype.origin
535  };
536
537  $.fn[NAME] = function (value) {
538    var args = arguments;
539    return this.each(function () {
540      var $this = $(this);
541      var plugin = $this.data(NAME);
542      if (!plugin) {
543        plugin = new Plugin(this, value);
544        $this.data(NAME, plugin);
545      }
546      if (API[value]) {
547        plugin[value].apply(plugin, Array.prototype.slice.call(args, 1));
548      }
549    });
550  };
551
552})(window.jQuery || window.Zepto, window, document);
553
554/**
555 * Request Animation Frame Polyfill.
556 * @author Tino Zijdel
557 * @author Paul Irish
558 * @see https://gist.github.com/paulirish/1579671
559 */
560;(function() {
561
562  var lastTime = 0;
563  var vendors = ['ms', 'moz', 'webkit', 'o'];
564
565  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
566    window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
567    window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
568  }
569
570  if (!window.requestAnimationFrame) {
571    window.requestAnimationFrame = function(callback, element) {
572      var currTime = new Date().getTime();
573      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
574      var id = window.setTimeout(function() { callback(currTime + timeToCall); },
575        timeToCall);
576      lastTime = currTime + timeToCall;
577      return id;
578    };
579  }
580
581  if (!window.cancelAnimationFrame) {
582    window.cancelAnimationFrame = function(id) {
583      clearTimeout(id);
584    };
585  }
586
587}());

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.