1(function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 3 typeof define === 'function' && define.amd ? define(['exports'], factory) : 4 (factory((global.SpriteSpin = {}))); 5}(this, (function (exports) { 'use strict'; 6 7 /** 8 * @internal 9 */ 10 var Api = /** @class */ (function () { 11 function Api(data) { 12 this.data = data; 13 } 14 return Api; 15 }()); 16 /** 17 * Adds methods to the SpriteSpin api 18 * 19 * @public 20 */ 21 function extendApi(methods) { 22 var api = Api.prototype; 23 for (var key in methods) { 24 if (methods.hasOwnProperty(key)) { 25 if (api[key]) { 26 throw new Error('API method is already defined: ' + key); 27 } 28 else { 29 api[key] = methods[key]; 30 } 31 } 32 } 33 return api; 34 } 35 36 var $$1 = window.jQuery || window.$; 37 38 function getCursorPosition(event) { 39 var touches = event.touches; 40 var source = event; 41 // jQuery Event normalization does not preserve the 'event.touches' 42 // try to grab touches from the original event 43 if (event.touches === undefined && event.originalEvent !== undefined) { 44 touches = event.originalEvent.touches; 45 } 46 // get current touch or mouse position 47 if (touches !== undefined && touches.length > 0) { 48 source = touches[0]; 49 } 50 return { 51 x: source.clientX || 0, 52 y: source.clientY || 0 53 }; 54 } 55 56 var canvas; 57 var context; 58 function detectionContext() { 59 if (context) { 60 return context; 61 } 62 if (!canvas) { 63 canvas = document.createElement('canvas'); 64 } 65 if (!canvas || !canvas.getContext) { 66 return null; 67 } 68 context = canvas.getContext('2d'); 69 return context; 70 } 71 /** 72 * Idea taken from https://github.com/stomita/ios-imagefile-megapixel 73 * Detects whether the image has been sub sampled by the browser and does not have its original dimensions. 74 * This method unfortunately does not work for images that have transparent background. 75 */ 76 function detectSubsampling(img, width, height) { 77 if (!detectionContext()) { 78 return false; 79 } 80 // sub sampling happens on images above 1 megapixel 81 if (width * height <= 1024 * 1024) { 82 return false; 83 } 84 // set canvas to 1x1 pixel size and fill it with magenta color 85 canvas.width = canvas.height = 1; 86 context.fillStyle = '#FF00FF'; 87 context.fillRect(0, 0, 1, 1); 88 // render the image with a negative offset to the left so that it would 89 // fill the canvas pixel with the top right pixel of the image. 90 context.drawImage(img, -width + 1, 0); 91 // check color value to confirm image is covering edge pixel or not. 92 // if color still magenta, the image is assumed to be sub sampled. 93 try { 94 var dat = context.getImageData(0, 0, 1, 1).data; 95 return (dat[0] === 255) && (dat[1] === 0) && (dat[2] === 255); 96 } 97 catch (err) { 98 // avoids cross origin exception for chrome when code runs without a server 99 return false; 100 } 101 } 102 103 /** 104 * 105 */ 106 function getOuterSize(data) { 107 var width = Math.floor(data.width || data.frameWidth || data.target.innerWidth()); 108 var height = Math.floor(data.height || data.frameHeight || data.target.innerHeight()); 109 return { 110 aspect: width / height, 111 height: height, 112 width: width 113 }; 114 } 115 function getComputedSize(data) { 116 var size = getOuterSize(data); 117 if (typeof window.getComputedStyle !== 'function') { 118 return size; 119 } 120 var style = window.getComputedStyle(data.target[0]); 121 if (!style.width) { 122 return size; 123 } 124 size.width = Math.floor(Number(style.width.replace('px', ''))); 125 size.height = Math.floor(size.width / size.aspect); 126 return size; 127 } 128 /** 129 * 130 */ 131 function getInnerSize(data) { 132 var width = Math.floor(data.frameWidth || data.width || data.target.innerWidth()); 133 var height = Math.floor(data.frameHeight || data.height || data.target.innerHe
133ight()); 134 return { 135 aspect: width / height, 136 height: height, 137 width: width 138 }; 139 } 140 /** 141 * 142 */ 143 function getInnerLayout(mode, inner, outer) { 144 // get mode 145 var isFit = mode === 'fit'; 146 var isFill = mode === 'fill'; 147 var isMatch = mode === 'stretch'; 148 // resulting layout 149 var layout = { 150 width: '100%', 151 height: '100%', 152 top: 0, 153 left: 0, 154 bottom: 0, 155 right: 0, 156 position: 'absolute', 157 overflow: 'hidden' 158 }; 159 // no calculation here 160 if (!mode || isMatch) { 161 return layout; 162 } 163 // get size and aspect 164 var aspectIsGreater = inner.aspect >= outer.aspect; 165 // mode == original 166 var width = inner.width; 167 var height = inner.height; 168 // keep aspect ratio but fit/fill into container 169 if (isFit && aspectIsGreater || isFill && !aspectIsGreater) { 170 width = outer.width; 171 height = outer.width / inner.aspect; 172 } 173 if (isFill && aspectIsGreater || isFit && !aspectIsGreater) { 174 height = outer.height; 175 width = outer.height * inner.aspect; 176 } 177 // floor the numbers 178 width = Math.floor(width); 179 height = Math.floor(height); 180 // position in center 181 layout.width = width; 182 layout.height = height; 183 layout.top = Math.floor((outer.height - height) / 2); 184 layout.left = Math.floor((outer.width - width) / 2); 185 layout.right = layout.left; 186 layout.bottom = layout.top; 187 return layout; 188 } 189 190 var img; 191 /** 192 * gets the original width and height of an image element 193 */ 194 function naturalSize(image) { 195 // for browsers that support naturalWidth and naturalHeight properties 196 if (image.naturalWidth) { 197 return { 198 height: image.naturalHeight, 199 width: image.naturalWidth 200 }; 201 } 202 // browsers that do not support naturalWidth and naturalHeight properties have to fall back to the width and 203 // height properties. However, the image might have a css style applied so width and height would return the 204 // css size. To avoid thet create a new Image object that is free of css rules and grab width and height 205 // properties 206 // 207 // assume that the src has already been downloaded, so no onload callback is needed. 208 img = img || new Image(); 209 img.src = image.src; 210 return { 211 height: img.height, 212 width: img.width 213 }; 214 } 215 216 /** 217 * Measures the image frames that are used in the given data object 218 */ 219 function measure(images, options) { 220 if (images.length === 1) { 221 return [measureSheet(images[0], options)]; 222 } 223 else if (options.framesX && options.framesY) { 224 return measureMutipleSheets(images, options); 225 } 226 else { 227 return measureFrames(images, options); 228 } 229 } 230 function measureSheet(image, options) { 231 var result = { id: 0, sprites: [] }; 232 measureImage(image, options, result); 233 var frames = options.frames; 234 var framesX = Number(options.framesX) || frames;
235 var framesY = Math.ceil(frames / framesX); 236 var frameWidth = Math.floor(result.width / framesX); 237 var frameHeight = Math.floor(result.height / framesY); 238 var divisor = result.isSubsampled ? 2 : 1; 239 for (var i = 0; i < frames; i++) { 240 var x = (i % framesX) * frameWidth; 241 var y = Math.floor(i / framesX) * frameHeight; 242 result.sprites.push({ 243 id: i, 244 x: x, y: y, 245 width: frameWidth, 246 height: frameHeight, 247 sampledX: x / divisor, 248 sampledY: y / divisor, 249 sampledWidth: frameWidth / divisor, 250 sampledHeight: frameHeight / divisor 251 }); 252 } 253 return result; 254 } 255 function measureFrames(images, options) { 256 var result = []; 257 for (var id = 0; id < images.length; id++) { 258 // TODO: optimize 259 // dont measure images with same size twice 260 var sheet = measureSheet(images[id], { frames: 1, framesX: 1, detectSubsampling: options.detectSubsampling }); 261 sheet.id = id; 262 result.push(sheet); 263 } 264 return result; 265 } 266 function measureMutipleSheets(images, options) { 267 var result = []; 268 for (var id = 0; id < images.length; id++) { 269 // TODO: optimize 270 // dont measure images with same size twice 271 var sheet = measureSheet(images[id], { 272 frames: undefined, 273 framesX: options.framesX, 274 framesY: options.framesY, 275 detectSubsampling: options.detectSubsampling 276 }); 277 sheet.id = id; 278 result.push(sheet); 279 } 280 return result; 281 } 282 function measureImage(image, options, result) { 283 var size = naturalSize(image); 284 result.isSubsampled = options.detectSubsampling && detectSubsampling(image, size.width, size.height); 285 result.width = size.width; 286 result.height = size.height; 287 result.sampledWidth = size.width / (result.isSubsampled ? 2 : 1); 288 result.sampledHeight = size.height / (result.isSubsampled ? 2 : 1); 289 return result; 290 } 291 function findSpecs(metrics, frames, frame, lane) { 292 var spriteId = lane * frames + frame; 293 var sheetId = 0; 294 var sprite = null; 295 var sheet = null; 296 while (true) { 297 sheet = metrics[sheetId]; 298 if (!sheet) { 299 break; 300 } 301 if (spriteId >= sheet.sprites.length) { 302 spriteId -= sheet.sprites.length; 303 sheetId++; 304 continue; 305 } 306 sprite = sheet.sprites[spriteId]; 307 break; 308 } 309 return { sprite: sprite, sheet: sheet }; 310 } 311 312 function indexOf(element, arr) { 313 for (var i = 0; i < arr.length; i++) { 314 if (arr[i] === element) { 315 return i; 316 } 317 } 318 } 319 function noop() { 320 // 321 } 322 function preload(opts) { 323 var src; 324 var input = opts.source; 325 src = typeof input === 'string' ? [input] : input; 326 // const src: string[] = ? [opts.source] : opts.source 327 var images = []; 328 var targetCount = (opts.preloadCount || src.length); 329 var onInitiated = opts.initiated || noop; 330 var onProgress = opts.progress || noop; 331 var onComplete = opts.complete || noop; 332 var count = 0; 333 var completed = false; 334 var firstLoaded = false; 335 var tick = function () { 336 count += 1; 337 onProgress({ 338 index: indexOf(this, images), 339 loaded: count, 340 total: src.length, 341 percent: Math.round((count / src.length) * 100) 342 }); 343 firstLoaded = firstLoaded || (this === images[0]); 344 if (firstLoaded && !completed && (count >= targetCount)) { 345 completed = true; 346 onComplete(images); 347 } 348 }; 349 for (var _i = 0, src_1 = src; _i < src_1.length; _i++) { 350 var url = src_1[_i]; 351 var img = new Image(); 352 // push result 353 images.push(img); 354 // bind logic, dont care about abort/errors 355 img.onload = img.onabort = img.onerror = tick; 356 // begin load 357 img.src = url; 358 } 359 onInitiated(images); 360 } 361 362 function padNumber(num, length, pad) { 363 var result = String(num); 364 while (result.length < length) { 365 result = String(pad) + result; 366 } 367 return result; 368 } 369 /** 370 * Generates an array of source strings 371 * 372 * @remarks
373 * Takes a template string and generates an array of strings by interpolating {lane} and {frame} placeholders. 374 * 375 * ``` 376 * sourceArray('http://example.com/image_{frame}.jpg, { frame: [1, 3], digits: 2 }) 377 * // gives: 378 * // [ 'http://example.com/image_01.jpg', 'http://example.com/image_02.jpg', 'http://example.com/image_03.jpg' ] 379 * 380 * sourceArray('http://example.com/image_FRAME.jpg, { frame: [1, 3], digits: 2, framePlacer: 'FRAME' }) 381 * // gives: 382 * // [ 'http://example.com/image_01.jpg', 'http://example.com/image_02.jpg', 'http://example.com/image_03.jpg' ] 383 * ``` 384 * 385 * @param template - The template string 386 * @param opts - Interpolation options 387 * 388 * @public 389 */ 390 function sourceArray(template, opts) { 391 var digits = opts.digits || 2; 392 var lPlacer = opts.lanePlacer || '{lane}'; 393 var fPlacer = opts.framePlacer || '{frame}'; 394 var fStart = 0; 395 var fEnd = 0; 396 if (opts.frame) { 397 fStart = opts.frame[0]; 398 fEnd = opts.frame[1]; 399 } 400 var lStart = 0; 401 var lEnd = 0; 402 if (opts.lane) { 403 lStart = opts.lane[0]; 404 lEnd = opts.lane[1]; 405 } 406 var result = []; 407 for (var lane = lStart; lane <= lEnd; lane += 1) { 408 for (var frame = fStart; frame <= fEnd; frame += 1) { 409 result.push(template 410 .replace(lPlacer, padNumber(lane, digits, '0')) 411 .replace(fPlacer, padNumber(frame, digits, '0'))); 412 } 413 } 414 return result; 415 } 416 417 /** 418 * The namespace that is used to bind functions to DOM events and store the data object 419 */ 420 var namespace = 'spritespin'; 421 /** 422 * Event names that are recognized by SpriteSpin. A module can implement any of these and they will be bound 423 * to the target element on which the plugin is called. 424 */ 425 var eventNames = [ 426 'mousedown', 427 'mousemove', 428 'mouseup', 429 'mouseenter', 430 'mouseover', 431 'mouseleave', 432 'mousewheel', 433 'wheel', 434 'click', 435 'dblclick', 436 'touchstart', 437 'touchmove', 438 'touchend', 439 'touchcancel', 440 'selectstart', 441 'gesturestart', 442 'gesturechange', 443 'gestureend' 444 ]; 445 /** 446 * 447 */ 448 var callbackNames = [ 449 'onInit', 450 'onProgress', 451 'onLoad', 452 'onFrameChanged', 453 'onFrame', 454 'onDraw', 455 'onComplete', 456 'onDestroy' 457 ]; 458 /** 459 * Names of events for that the default behavior should be prevented. 460 */ 461 var eventsToPrevent = [ 462 'dragstart' 463 ]; 464 /** 465 * Default set of SpriteSpin options. This also represents the majority of data attributes that are used during the 466 * lifetime of a SpriteSpin instance. The data is stored inside the target DOM element on which the plugin is called. 467 */ 468 var defaults = { 469 source: undefined, 470 width: undefined, 471 height: undefined, 472 frames: undefined, 473 framesX: undefined, 474 lanes: 1, 475 sizeMode: undefined, 476 renderer: 'canvas', 477 lane: 0, 478 frame: 0, 479 frameTime: 40, 480 animate: true, 481 retainAnimate: false, 482 reverse: false, 483 loop: true, 484 stopFrame: 0, 485 wrap: true, 486 wrapLane: false, 487 sense: 1, 488 senseLane: undefined, 489 orientation: 'horizontal', 490 detectSubsampling: true, 491 preloadCount: undefined, 492 responsive: undefined, 493 plugins: [ 494 '360', 495 'drag' 496 ] 497 }; 498 499 function noop$1() { 500 // noop 501 } 502 function wrapConsole(type) { 503 return console && console[type] ? function () { 504 var args = []; 505 for (var _i = 0; _i < arguments.length; _i++) { 506 args[_i] = arguments[_i]; 507 } 508 return console.log.apply(console, args); 509 } : noop$1; 510 } 511 var log = wrapConsole('log'); 512 var warn = wrapConsole('warn'); 513 var error = wrapConsole('error'); 514 function toArray(value) { 515 return Array.isArray(value) ? value : [value]; 516 } 517 /**
518 * clamps the given value by the given min and max values 519 */ 520 function clamp(value, min, max) { 521 return (value > max ? max : (value < min ? min : value)); 522 } 523 /** 524 * 525 */ 526 function wrap(value, min, max, size) { 527 while (value > max) { 528 value -= size; 529 } 530 while (value < min) { 531 value += size; 532 } 533 return value; 534 } 535 /** 536 * prevents default action on the given event 537 */ 538 function prevent(e) { 539 e.preventDefault(); 540 return false; 541 } 542 /** 543 * Binds on the given target and event the given function. 544 * The SpriteSpin namespace is attached to the event name 545 */ 546 function bind(target, event, func) { 547 if (func) { 548 target.bind(event + '.' + namespace, function (e) { 549 func.apply(target, [e, target.spritespin('data')]); 550 }); 551 } 552 } 553 /** 554 * Unbinds all SpriteSpin events from given target element 555 */ 556 function unbind(target) { 557 target.unbind('.' + namespace); 558 } 559 /** 560 * Checks if given object is a function 561 */ 562 function isFunction(fn) { 563 return typeof fn === 'function'; 564 } 565 function pixelRatio(context) { 566 var devicePixelRatio = window.devicePixelRatio || 1; 567 var backingStoreRatio = context.webkitBackingStorePixelRatio || 568 context.mozBackingStorePixelRatio || 569 context.msBackingStorePixelRatio || 570 context.oBackingStorePixelRatio || 571 context.backingStorePixelRatio || 1; 572 return devicePixelRatio / backingStoreRatio; 573 } 574 575 576 577 var _Utils = Object.freeze({ 578 $: $$1, 579 getCursorPosition: getCursorPosition, 580 detectSubsampling: detectSubsampling, 581 getOuterSize: getOuterSize, 582 getComputedSize: getComputedSize, 583 getInnerSize: getInnerSize, 584 getInnerLayout: getInnerLayout, 585 measure: measure, 586 findSpecs: findSpecs, 587 naturalSize: naturalSize, 588 preload: preload, 589 sourceArray: sourceArray, 590 noop: noop$1, 591 log: log, 592 warn: warn, 593 error: error, 594 toArray: toArray, 595 clamp: clamp, 596 wrap: wrap, 597 prevent: prevent, 598 bind: bind, 599 unbind: unbind, 600 isFunction: isFunction, 601 pixelRatio: pixelRatio 602 }); 603 604 /** 605 * Applies css attributes to layout the SpriteSpin containers. 606 * 607 * @internal 608 */ 609 function applyLayout(data) { 610 // disable selection 611 data.target 612 .attr('unselectable', 'on') 613 .css({ 614 width: '', 615 height: '', 616 '-ms-user-select': 'none', 617 '-moz-user-select': 'none', 618 '-khtml-user-select': 'none', 619 '-webkit-user-select': 'none', 620 'user-select': 'none' 621 }); 622 var size = data.responsive ? getComputedSize(data) : getOuterSize(data); 623 var layout = getInnerLayout(data.sizeMode, getInnerSize(data), size); 624 // apply layout on target 625 data.target.css({ 626 width: size.width, 627 height: size.height, 628 position: 'relative', 629 overflow: 'hidden' 630 }); 631 // apply layout on stage 632 data.stage 633 .css(layout) 634 .hide(); 635 if (!data.canvas) { 636 return; 637 } 638 // apply layout on canvas 639 data.canvas.css(layout).hide(); 640 // apply pixel ratio on canvas 641 data.canvasRatio = data.canvasRatio || pixelRatio(data.context); 642 if (typeof layout.width === 'number' && typeof layout.height === 'number') { 643 data.canvas[0].width = (layout.width * data.canvasRatio) || size.width; 644 data.canvas[0].height = (layout.height * data.canvasRatio) || size.height; 645 } 646 else { 647 data.canvas[0].width = (size.width * data.canvasRatio); 648 data.canvas[0].height = (size.height * data.canvasRatio); 649 } 650 // width and height must be set before calling scale 651 data.context.scale(data.canvasRatio, data.canvasRatio); 652 } 653 654 /** 655 * Gets a state object by name. 656 * @internal 657 * @param data - The SpriteSpin instance data 658 * @param name - The name of the state object 659 */ 660 function getState(data, name) { 661 data.state = data.state || {}; 662 data.state[name] = data.state[name] || {}; 663 return data.state[name]; 664 } 665 /** 666 * Gets a plugin state object by name. 667 * 668 * @remarks 669 * Plugins should use this method to get or create a state object where they can 670 * store any instance variables. 671 * 672 * @public 673 * @param data - The SpriteSpin instance data 674 * @param name - The name of the plugin 675 */ 676 function getPluginState(data, name) { 677 var state = getState(data, 'plugin');
678 state[name] = state[name] || {}; 679 return state[name]; 680 } 681 /** 682 * Checks whether a flag is set. See {@link flag}. 683 * 684 * @public 685 * @param data - The SpriteSpin instance data 686 * @param key - The name of the flag 687 */ 688 function is(data, key) { 689 return !!getState(data, 'flags')[key]; 690 } 691 /** 692 * Sets a flag value. See {@link is}. 693 * 694 * @public 695 * @param data - The SpriteSpin instance data 696 * @param key - The name of the flag 697 * @param value - The value to set 698 */ 699 function flag(data, key, value) { 700 getState(data, 'flags')[key] = !!value; 701 } 702 703 /** 704 * Gets the playback state 705 * 706 * @public 707 * @param data - The SpriteSpin instance data 708 */ 709 function getPlaybackState(data) { 710 return getState(data, 'playback'); 711 } 712 function updateLane(data, lane) { 713 data.lane = data.wrapLane 714 ? wrap(lane, 0, data.lanes - 1, data.lanes) 715 : clamp(lane, 0, data.lanes - 1); 716 } 717 function updateAnimationFrame(data) { 718 data.frame += (data.reverse ? -1 : 1); 719 // wrap the frame value to fit in range [0, data.frames) 720 data.frame = wrap(data.frame, 0, data.frames - 1, data.frames); 721 // stop animation if loop is disabled and the stopFrame is reached 722 if (!data.loop && (data.frame === data.stopFrame)) { 723 stopAnimation(data); 724 } 725 } 726 function updateInputFrame(data, frame) { 727 data.frame = Number(frame); 728 data.frame = data.wrap 729 ? wrap(data.frame, 0, data.frames - 1, data.frames) 730 : clamp(data.frame, 0, data.frames - 1); 731 } 732 function updateAnimation(data) { 733 var state = getPlaybackState(data); 734 if (state.handler) { 735 updateBefore(data); 736 updateAnimationFrame(data); 737 updateAfter(data); 738 } 739 } 740 function updateBefore(data) { 741 var state = getPlaybackState(data); 742 state.lastFrame = data.frame; 743 state.lastLane = data.lane; 744 } 745 function updateAfter(data) { 746 var state = getPlaybackState(data); 747 if (state.lastFrame !== data.frame || state.lastLane !== data.lane) { 748 data.target.trigger('onFrameChanged.' + namespace, data); 749 } 750 data.target.trigger('onFrame.' + namespace, data); 751 data.target.trigger('onDraw.' + namespace, data); 752 } 753 /** 754 * Updates the frame or lane number of the SpriteSpin data. 755 * 756 * @public 757 * @param data - The SpriteSpin instance data 758 * @param frame - The frame number to set 759 * @param lane - The lane number to set 760 */ 761 function updateFrame(data, frame, lane) { 762 updateBefore(data); 763 if (frame != null) { 764 updateInputFrame(data, frame); 765 } 766 if (lane != null) { 767 updateLane(data, lane); 768 } 769 updateAfter(data); 770 } 771 /** 772 * Stops the running animation. 773 * 774 * @public 775 * @param data - The SpriteSpin instance data 776 */ 777 function stopAnimation(data) { 778 data.animate = false; 779 var state = getPlaybackState(data); 780 if (state.handler != null) { 781 window.clearInterval(state.handler); 782 state.handler = null; 783 } 784 } 785 /** 786 * Starts animation playback if needed. 787 * 788 * @remarks 789 * Starts animation playback if `animate` property is `true` and the animation is not yet running. 790 * 791 * @public 792 * @param data - The SpriteSpin instance data 793 */ 794 function applyAnimation(data) { 795 var state = getPlaybackState(data); 796 if (state.handler && (!data.animate || state.frameTime !== data.frameTime)) { 797 stopAnimation(data); 798 } 799 if (data.animate && !state.handler) { 800 state.frameTime = data.frameTime; 801 state.handler = window.setInterval(function () { return updateAnimation(data); }, state.frameTime); 802 } 803 } 804 /** 805 * Starts the animation playback 806 * 807 * @remarks 808 * Starts the animation playback and also sets the `animate` property to `true` 809 * 810 * @public 811 * @param data - The SpriteSpin instance data 812 */ 813 function startAnimation(data) { 814 data.animate = true; 815 applyAnimation(data); 816 } 817 818 var plugins = {}; 819 /** 820 * Registers a plugin. 821 * 822 * @remarks
823 * Use this to add custom Rendering or Updating modules that can be addressed with the 'module' option. 824 * 825 * @public 826 * @param name - The name of the plugin 827 * @param plugin - The plugin implementation 828 */ 829 function registerPlugin(name, plugin) { 830 if (plugins[name]) { 831 error("Plugin name \"" + name + "\" is already taken"); 832 return; 833 } 834 plugin = plugin || {}; 835 plugins[name] = plugin; 836 return plugin; 837 } 838 /** 839 * Registers a plugin. 840 * 841 * @public 842 * @deprecated Use {@link registerPlugin} instead 843 * @param name - The name of the plugin 844 * @param plugin - The plugin implementation 845 */ 846 function registerModule(name, plugin) { 847 warn('"registerModule" is deprecated, use "registerPlugin" instead'); 848 registerPlugin(name, plugin); 849 } 850 /** 851 * Gets an active plugin by name 852 * 853 * @internal 854 * @param name - The name of the plugin 855 */ 856 function getPlugin(name) { 857 return plugins[name]; 858 } 859 /** 860 * Replaces module names on given SpriteSpin data and replaces them with actual implementations. 861 * @internal 862 */ 863 function applyPlugins(data) { 864 fixPlugins(data); 865 for (var i = 0; i < data.plugins.length; i += 1) { 866 var name_1 = data.plugins[i]; 867 if (typeof name_1 !== 'string') { 868 continue; 869 } 870 var plugin = getPlugin(name_1); 871 if (!plugin) { 872 error('No plugin found with name ' + name_1); 873 continue; 874 } 875 data.plugins[i] = plugin; 876 } 877 } 878 function fixPlugins(data) { 879 // tslint:disable no-string-literal 880 if (data['mods']) { 881 warn('"mods" option is deprecated, use "plugins" instead'); 882 data.plugins = data['mods']; 883 delete data['mods']; 884 } 885 if (data['behavior']) { 886 warn('"behavior" option is deprecated, use "plugins" instead'); 887 data.plugins.push(data['behavior']); 888 delete data['behavior']; 889 } 890 if (data['module']) { 891 warn('"module" option is deprecated, use "plugins" instead'); 892 data.plugins.push(data['module']); 893 delete data['module']; 894 } 895 } 896 897 var $$2 = $$1; 898 var counter = 0; 899 /** 900 * Collection of all SpriteSpin instances 901 */ 902 var instances = {}; 903 function pushInstance(data) { 904 counter += 1; 905 data.id = String(counter); 906 instances[data.id] = data; 907 } 908 function popInstance(data) { 909 delete instances[data.id]; 910 } 911 function eachInstance(cb) { 912 for (var id in instances) { 913 if (instances.hasOwnProperty(id)) { 914 cb(instances[id]); 915 } 916 } 917 } 918 var lazyinit = function () { 919 // replace function with a noop 920 // this logic must run only once 921 lazyinit = function () { }; 922 function onEvent(eventName, e) { 923 eachInstance(function (data) { 924 for (var _i = 0, _a = data.plugins; _i < _a.length; _i++) { 925 var module_1 = _a[_i]; 926 if (typeof module_1[eventName] === 'function') { 927 module_1[eventName].apply(data.target, [e, data]); 928 } 929 } 930 }); 931 } 932 function onResize() { 933 eachInstance(function (data) { 934 if (data.responsive) { 935 boot(data); 936 } 937 }); 938 } 939 var _loop_1 = function (eventName) { 940 $$2(window.document).bind(eventName + '.' + namespace, function (e) { 941 onEvent('document' + eventName, e); 942 }); 943 }; 944 for (var _i = 0, eventNames_1 = eventNames; _i < eventNames_1.length; _i++) { 945 var eventName = eventNames_1[_i]; 946 _loop_1(eventName); 947 } 948 var resizeTimeout = null; 949 $$2(window).on('resize', function () { 950 window.clearTimeout(resizeTimeout); 951 resizeTimeout = window.setTimeout(onResize, 100); 952 }); 953 }; 954 /** 955 * (re)binds all spritespin events on the target element 956 * 957 * @internal 958 */ 959 function applyEvents(data) { 960 var target = data.target; 961 // Clear all SpriteSpin events on the target element 962 unbind(target); 963 // disable all default browser behavior on the following events 964 // mainly prevents image drag operation 965 for (var _i = 0, eventsToPrevent_1 = eventsToPrevent; _i < eventsToPrevent_1.length; _i++) { 966 var eName = eventsToPrevent_1[_i]; 967 bind(target, eName, prevent); 968 } 969 // Bind module functions to SpriteSpin events 970 for (var _a = 0, _b = data.plugins; _a < _b.length; _a++) { 971 var plugin = _b[_a]; 972 for (var _c = 0, eventNames_2 = eventNames; _c < eventNames_2.length; _c++) { 973 var eName = eventNames_2[_c]; 974 bind(target, eName, plugin[eName]); 975 } 976 for (var _d = 0, callbackNames_1 = callbackNames; _d < callbackNames_1.length; _d++) { 977 var eName = callbackNames_1[_d]; 978 bind(target, eName, plugin[eName]); 979 } 980 } 981 // bind auto start function to load event. 982 bind(target, 'onLoad', function (e, d) { 983 applyAnimation(d); 984 }); 985 // bind all user events that have been passed on initialization 986 for (var _e = 0, callbackNames_2 = callbackNames; _e < callbackNames_2.length; _e++) { 987 var eName = callbackNames_2[_e]; 988 bind(target, eName, data[eName]); 989 } 990 } 991 function applyMetrics(data) { 992 if (!data.images) { 993 data.metrics = []; 994 } 995 data.metrics = measure(data.images, data); 996 var spec = findSpecs(data.metrics, data.frames, 0, 0); 997 if (spec.sprite) { 998 // TODO: try to remove frameWidth/frameHeight 999 data.frameWidth = spec.sprite.width; 1000 data.frameHeight = spec.sprite.height; 1001 } 1002 } 1003 /** 1004 * Runs the boot process. 1005 * 1006 * @remarks 1007 * (re)initializes plugins, (re)initializes the layout, (re)binds events and loads source images. 1008 * 1009 * @internal 1010 */ 1011 function boot(data) { 1012 applyPlugins(data); 1013 applyEvents(data); 1014 applyLayout(data); 1015 data.source = toArray(data.source); 1016 data.loading = true; 1017 data.target 1018 .addClass('loading')
1019 .trigger('onInit.' + namespace, data); 1020 preload({ 1021 source: data.source, 1022 preloadCount: data.preloadCount, 1023 progress: function (progress) { 1024 data.progress = progress; 1025 data.target.trigger('onProgress.' + namespace, data); 1026 }, 1027 complete: function (images) { 1028 data.images = images; 1029 data.loading = false; 1030 data.frames = data.frames || images.length; 1031 applyMetrics(data); 1032 applyLayout(data); 1033 data.stage.show(); 1034 data.target 1035 .removeClass('loading') 1036 .trigger('onLoad.' + namespace, data) 1037 .trigger('onFrame.' + namespace, data) 1038 .trigger('onDraw.' + namespace, data) 1039 .trigger('onComplete.' + namespace, data); 1040 } 1041 }); 1042 } 1043 /** 1044 * Creates a new SpriteSpin instance 1045 * 1046 * @public 1047 */ 1048 function create(options) { 1049 var _this = this; 1050 var target = options.target; 1051 // SpriteSpin is not initialized 1052 // Create default settings object and extend with given options 1053 var data = $$2.extend(true, {}, defaults, options); 1054 // ensure source is set 1055 data.source = data.source || []; 1056 // ensure plugins are set 1057 data.plugins = data.plugins || []; 1058 // if image tags are contained inside this DOM element 1059 // use these images as the source files 1060 target.find('img').each(function () { 1061 if (!Array.isArray(data.source)) { 1062 data.source = []; 1063 } 1064 data.source.push($$2(_this).attr('src')); 1065 }); 1066 // build inner html 1067 // <div> 1068 // <div class='spritespin-stage'></div> 1069 // <canvas class='spritespin-canvas'></canvas> 1070 // </div> 1071 target 1072 .empty() 1073 .addClass('spritespin-instance') 1074 .append("<div class='spritespin-stage'></div>"); 1075 // add the canvas element if canvas rendering is enabled and supported 1076 if (data.renderer === 'canvas') { 1077 var canvas = document.createElement('canvas'); 1078 if (!!(canvas.getContext && canvas.getContext('2d'))) { 1079 data.canvas = $$2(canvas).addClass('spritespin-canvas'); 1080 data.context = canvas.getContext('2d'); 1081 target.append(data.canvas); 1082 target.addClass('with-canvas'); 1083 } 1084 else { 1085 // fallback to image rendering mode 1086 data.renderer = 'image'; 1087 } 1088 } 1089 // setup references to DOM elements 1090 data.target = target; 1091 data.stage = target.find('.spritespin-stage'); 1092 // store the data 1093 target.data(namespace, data); 1094 pushInstance(data); 1095 return data; 1096 } 1097 /** 1098 * Creates a new SpriteSpin instance, or updates an existing one 1099 * 1100 * @public 1101 */ 1102 function createOrUpdate(options) { 1103 lazyinit(); 1104 var data = options.target.data(namespace); 1105 if (!data) { 1106 data = create(options); 1107 } 1108 else { 1109 $$2.extend(data, options); 1110 } 1111 boot(data); 1112 return data; 1113 } 1114 /** 1115 * Destroys the SpriteSpin instance 1116 * 1117 * @remarks 1118 * - stops running animation 1119 * - unbinds all events 1120 * - deletes the data on the target element 1121 * 1122 * @public 1123 */ 1124 function destroy(data) { 1125 popInstance(data); 1126 stopAnimation(data); 1127 data.target 1128 .trigger('onDestroy', data) 1129 .html(null) 1130 .attr('style', null) 1131 .attr('unselectable', null) 1132 .removeClass(['spritespin-instance', 'with-canvas']); 1133 unbind(data.target); 1134 data.target.removeData(namespace); 1135 } 1136 1137 /** 1138 * Gets the current input state 1139 * 1140 * @public 1141 * @param data - The SpriteSpin instance data 1142 */ 1143 function getInputState(data) { 1144 return getState(data, 'input'); 1145 } 1146 /** 1147 * Updates the input state using a mous or touch event. 1148 * 1149 * @public 1150 * @param e - The input event 1151 * @param data - The SpriteSpin instance data 1152 */ 1153 function updateInput(e, data) { 1154 var cursor = getCursorPosition(e); 1155 var state = getInputState(data); 1156 // cache positions from previous frame 1157 state.oldX = state.currentX; 1158 state.oldY = state.currentY; 1159 state.currentX = cursor.x;
1160 state.currentY = cursor.y; 1161 // Fix old position. 1162 if (state.oldX === undefined || state.oldY === undefined) { 1163 state.oldX = state.currentX; 1164 state.oldY = state.currentY; 1165 } 1166 // Cache the initial click/touch position and store the frame number at which the click happened. 1167 // Useful for different behavior implementations. This must be restored when the click/touch is released. 1168 if (state.startX === undefined || state.startY === undefined) { 1169 state.startX = state.currentX; 1170 state.startY = state.currentY; 1171 state.clickframe = data.frame; 1172 state.clicklane = data.lane; 1173 } 1174 // Calculate the vector from start position to current pointer position. 1175 state.dX = state.currentX - state.startX; 1176 state.dY = state.currentY - state.startY; 1177 // Calculate the vector from last frame position to current pointer position. 1178 state.ddX = state.currentX - state.oldX; 1179 state.ddY = state.currentY - state.oldY; 1180 // Normalize vectors to range [-1:+1] 1181 state.ndX = state.dX / data.target.innerWidth(); 1182 state.ndY = state.dY / data.target.innerHeight(); 1183 state.nddX = state.ddX / data.target.innerWidth(); 1184 state.nddY = state.ddY / data.target.innerHeight(); 1185 } 1186 /** 1187 * Resets the input state. 1188 * 1189 * @public 1190 */ 1191 function resetInput(data) { 1192 var input = getInputState(data); 1193 input.startX = input.startY = undefined; 1194 input.currentX = input.currentY = undefined; 1195 input.oldX = input.oldY = undefined; 1196 input.dX = input.dY = 0; 1197 input.ddX = input.ddY = 0; 1198 input.ndX = input.ndY = 0; 1199 input.nddX = input.nddY = 0; 1200 } 1201 1202 function extension(option, value) { 1203 var $target = $$1(this); 1204 if (option === 'data') { 1205 return $target.data(namespace); 1206 } 1207 if (option === 'api') { 1208 var data = $target.data(namespace); 1209 data.api = data.api || new Api(data); 1210 return data.api; 1211 } 1212 if (option === 'destroy') { 1213 return $target.each(function () { 1214 var data = $target.data(namespace); 1215 if (data) { 1216 destroy(data); 1217 } 1218 }); 1219 } 1220 if (arguments.length === 2 && typeof option === 'string') { 1221 option = (_a = {}, _a[option] = value, _a); 1222 } 1223 if (typeof option === 'object') { 1224 return createOrUpdate($$1.extend(true, { target: $target }, option)).target; 1225 } 1226 throw new Error('Invalid call to spritespin'); 1227 var _a; 1228 } 1229 $$1.fn[namespace] = extension; 1230 1231// tslint:disable:object-literal-shorthand 1232// tslint:disable:only-arrow-functions 1233 extendApi({ 1234 // Gets a value indicating whether the animation is currently running. 1235 isPlaying: function () { 1236 return getPlaybackState(this.data).handler != null; 1237 }, 1238 // Gets a value indicating whether the animation looping is enabled. 1239 isLooping: function () { 1240 return this.data.loop; 1241 }, 1242 // Starts/Stops the animation playback 1243 toggleAnimation: function () { 1244 if (this.isPlaying()) { 1245 this.stopAnimation(); 1246 } 1247 else { 1248 this.startAnimation(); 1249 } 1250 }, 1251 // Stops animation playback 1252 stopAnimation: function () { 1253 this.data.animate = false; 1254 stopAnimation(this.data); 1255 }, 1256 // Starts animation playback 1257 startAnimation: function () { 1258 this.data.animate = true; 1259 applyAnimation(this.data); 1260 }, 1261 // Sets a value indicating whether the animation should be looped or not. 1262 // This might start the animation (if the 'animate' data attribute is set to true) 1263 loop: function (value) { 1264 this.data.loop = value; 1265 applyAnimation(this.data); 1266 return this; 1267 }, 1268 // Gets the current frame number 1269 currentFrame: function () { 1270 return this.data.frame; 1271 }, 1272 // Updates SpriteSpin to the specified frame. 1273 updateFrame: function (frame) { 1274 updateFrame(this.data, frame); 1275 return this; 1276 }, 1277 // Skips the given number of frames 1278 skipFrames: function (step) { 1279 var data = this.data; 1280 updateFrame(data, data.frame + (data.reverse ? -step : +step)); 1281 return this; 1282 }, 1283 // Updates SpriteSpin so that the next frame is shown 1284 nextFrame: function () { 1285 return this.skipFrames(1); 1286 }, 1287 // Updates SpriteSpin so that the previous frame is shown 1288 prevFrame: function () { 1289 return this.skipFrames(-1); 1290 }, 1291 // Starts the animations that will play until the given frame number is reached 1292 // options: 1293 // force [boolean] starts the animation, even if current frame is the target frame 1294 // nearest [boolean] animates to the direction with minimum distance to the target frame 1295 playTo: function (frame, options) { 1296 var data = this.data; 1297 options = options || {}; 1298 if (!options.force && data.frame === frame) { 1299 return; 1300 } 1301 if (options.nearest) { 1302 // distance to the target frame 1303 var a = frame - data.frame; 1304 // distance to last frame and the to target frame 1305 var b = frame > data.frame ? a - data.frames : a + data.frames; 1306 // minimum distance 1307 var c = Math.abs(a) < Math.abs(b) ? a : b; 1308 data.reverse = c < 0; 1309 } 1310 data.animate = true; 1311 data.loop = false;
1312 data.stopFrame = frame; 1313 applyAnimation(data); 1314 return this; 1315 } 1316 }); 1317 1318 function pick(target, names) { 1319 for (var _i = 0, names_1 = names; _i < names_1.length; _i++) { 1320 var name_1 = names_1[_i]; 1321 if (target[name_1] || name_1 in target) { 1322 return name_1; 1323 } 1324 } 1325 return names[0]; 1326 } 1327 var browser = { 1328 requestFullscreen: pick(document.documentElement, [ 1329 'requestFullscreen', 1330 'webkitRequestFullScreen', 1331 'mozRequestFullScreen', 1332 'msRequestFullscreen' 1333 ]), 1334 exitFullscreen: pick(document, [ 1335 'exitFullscreen', 1336 'webkitExitFullscreen', 1337 'webkitCancelFullScreen', 1338 'mozCancelFullScreen', 1339 'msExitFullscreen' 1340 ]), 1341 fullscreenElement: pick(document, [ 1342 'fullscreenElement', 1343 'webkitFullscreenElement', 1344 'webkitCurrentFullScreenElement', 1345 'mozFullScreenElement', 1346 'msFullscreenElement' 1347 ]), 1348 fullscreenEnabled: pick(document, [ 1349 'fullscreenEnabled', 1350 'webkitFullscreenEnabled', 1351 'mozFullScreenEnabled', 1352 'msFullscreenEnabled' 1353 ]), 1354 fullscreenchange: pick(document, [ 1355 'onfullscreenchange', 1356 'onwebkitfullscreenchange', 1357 'onmozfullscreenchange', 1358 'onMSFullscreenChange' 1359 ]).replace(/^on/, ''), 1360 fullscreenerror: pick(document, [ 1361 'onfullscreenerror', 1362 'onwebkitfullscreenerror', 1363 'onmozfullscreenerror', 1364 'onMSFullscreenError' 1365 ]).replace(/^on/, '') 1366 }; 1367 var changeEvent = browser.fullscreenchange + '.' + namespace + '-fullscreen'; 1368 function unbindChangeEvent() { 1369 $$1(document).unbind(changeEvent); 1370 } 1371 function bindChangeEvent(callback) { 1372 unbindChangeEvent(); 1373 $$1(document).bind(changeEvent, callback); 1374 } 1375 var orientationEvent = 'orientationchange.' + namespace + '-fullscreen'; 1376 function unbindOrientationEvent() { 1377 $$1(window).unbind(orientationEvent); 1378 } 1379 function bindOrientationEvent(callback) { 1380 unbindOrientationEvent(); 1381 $$1(window).bind(orientationEvent, callback); 1382 } 1383 function requestFullscreenNative(e) { 1384 e = e || document.documentElement; 1385 e[browser.requestFullscreen](); 1386 } 1387 function exitFullscreen() { 1388 return document[browser.exitFullscreen](); 1389 } 1390 function fullscreenEnabled() { 1391 return document[browser.fullscreenEnabled]; 1392 } 1393 function fullscreenElement() { 1394 return document[browser.fullscreenElement]; 1395 } 1396 function isFullscreen() { 1397 return !!fullscreenElement(); 1398 } 1399 function toggleFullscreen(data, opts) { 1400 if (isFullscreen()) { 1401 this.apiRequestFullscreen(opts); 1402 } 1403 else { 1404 this.exitFullscreen(); 1405 } 1406 } 1407 function requestFullscreen(data, opts) { 1408 opts = opts || {}; 1409 var oWidth = data.width; 1410 var oHeight = data.height; 1411 var oSource = data.source; 1412 var oSize = data.sizeMode; 1413 var oResponsive = data.responsive; 1414 var enter = function () { 1415 data.width = window.screen.width; 1416 data.height = window.screen.height; 1417 data.source = (opts.source || oSource); 1418 data.sizeMode = opts.sizeMode || 'fit'; 1419 data.responsive = false; 1420 boot(data); 1421 }; 1422 var exit = function () { 1423 data.width = oWidth; 1424 data.height = oHeight; 1425 data.source = oSource; 1426 data.sizeMode = oSize; 1427 data.responsive = oResponsive; 1428 boot(data); 1429 }; 1430 bindChangeEvent(function () { 1431 if (isFullscreen()) { 1432 enter(); 1433 bindOrientationEvent(enter); 1434 } 1435 else { 1436 unbindChangeEvent(); 1437 unbindOrientationEvent();
1438 exit(); 1439 } 1440 }); 1441 requestFullscreenNative(data.target[0]); 1442 } 1443 extendApi({ 1444 fullscreenEnabled: fullscreenEnabled, 1445 fullscreenElement: fullscreenElement, 1446 exitFullscreen: exitFullscreen, 1447 toggleFullscreen: function (opts) { 1448 toggleFullscreen(this.data, opts); 1449 }, 1450 requestFullscreen: function (opts) { 1451 requestFullscreen(this.data, opts); 1452 } 1453 }); 1454 1455 (function () { 1456 var NAME = 'click'; 1457 function click(e, data) { 1458 if (data.loading || !data.stage.is(':visible')) { 1459 return; 1460 } 1461 updateInput(e, data); 1462 var input = getInputState(data); 1463 var half, pos; 1464 var target = data.target, offset = target.offset(); 1465 if (data.orientation === 'horizontal') { 1466 half = target.innerWidth() / 2; 1467 pos = input.currentX - offset.left; 1468 } 1469 else { 1470 half = target.innerHeight() / 2; 1471 pos = input.currentY - offset.top; 1472 } 1473 updateFrame(data, data.frame + (pos > half ? 1 : -1)); 1474 } 1475 registerPlugin(NAME, { 1476 name: NAME, 1477 mouseup: click, 1478 touchend: click 1479 }); 1480 })(); 1481 1482 (function () { 1483 var NAME = 'drag'; 1484 function getState$$1(data) { 1485 return getPluginState(data, NAME); 1486 } 1487 function getAxis(data) { 1488 if (typeof data.orientation === 'number') { 1489 return data.orientation * Math.PI / 180; 1490 } 1491 if (data.orientation === 'horizontal') { 1492 return 0; 1493 } 1494 return Math.PI / 2; 1495 } 1496 function dragStart(e, data) { 1497 var state = getState$$1(data); 1498 if (data.loading || is(data, 'dragging') || !data.stage.is(':visible')) { 1499 return; 1500 } 1501 // allow browser scroll only on double tap 1502 var now = new Date().getTime(); 1503 if (state.startAt && (now - state.startAt > 200)) { 1504 e.preventDefault(); 1505 } 1506 state.startAt = now; 1507 state.wasPlaying = !!getPlaybackState(data).handler; 1508 state.frame = data.frame || 0; 1509 state.lane = data.lane || 0; 1510 flag(data, 'dragging', true); 1511 updateInput(e, data); 1512 } 1513 function dragEnd(e, data) { 1514 if (is(data, 'dragging')) { 1515 flag(data, 'dragging', false); 1516 resetInput(data); 1517 if (data.retainAnimate && getState$$1(data).wasPlaying) { 1518 startAnimation(data); 1519 } 1520 } 1521 } 1522 function drag(e, data) { 1523 var state = getState$$1(data); 1524 var input = getInputState(data); 1525 if (!is(data, 'dragging')) { 1526 return; 1527 } 1528 updateInput(e, data); 1529 var rad = getAxis(data); 1530 var sn = Math.sin(rad); 1531 var cs = Math.cos(rad); 1532 var x = ((input.nddX * cs - input.nddY * sn) * data.sense) || 0; 1533 var y = ((input.nddX * sn + input.nddY * cs) * (data.senseLane || data.sense)) || 0; 1534 // accumulate 1535 state.frame += data.frames * x; 1536 state.lane += data.lanes * y; 1537 // update spritespin 1538 var oldFrame = data.frame; 1539 var oldLane = data.lane; 1540 updateFrame(data, Math.floor(state.frame), Math.floor(state.lane)); 1541 stopAnimation(data); 1542 } 1543 function mousemove(e, data) { 1544 dragStart(e, data); 1545 drag(e, data); 1546 } 1547 registerPlugin('drag', { 1548 name: 'drag', 1549 mousedown: dragStart, 1550 mousemove: drag, 1551 mouseup: dragEnd, 1552 documentmousemove: drag, 1553 documentmouseup: dragEnd, 1554 touchstart: dragStart, 1555 touchmove: drag, 1556 touchend: dragEnd, 1557 touchcancel: dragEnd 1558 }); 1559 registerPlugin('move', { 1560 name: 'move', 1561 mousemove: mousemove, 1562 mouseleave: dragEnd, 1563 touchstart: dragStart, 1564 touchmove: drag, 1565 touchend: dragEnd, 1566 touchcancel: dragEnd 1567 }); 1568 })(); 1569 1570 (function () { 1571 var NAME = 'hold'; 1572 function getState$$1(data) { 1573 return getPluginState(data, NAME); 1574 } 1575 function rememberOptions(data) { 1576 var state = getState$$1(data); 1577 state.frameTime = data.frameTime; 1578 state.animate = data.animate; 1579 state.reverse = data.reverse; 1580 } 1581 function restoreOptions(data) { 1582 var state = getState$$1(data); 1583 data.frameTime = state.frameTime; 1584 data.animate = state.animate; 1585 data.reverse = state.reverse; 1586 } 1587 function start(e, data) { 1588 if (is(data, 'loading') || is(data, 'dragging') || !data.stage.is(':visible')) { 1589 return; 1590 } 1591 rememberOptions(data); 1592 updateInput(e, data); 1593 flag(data, 'dragging', true); 1594 data.animate = true; 1595 applyAnimation(data); 1596 } 1597 function stop(e, data) { 1598 flag(data, 'dragging', false); 1599 resetInput(data); 1600 stopAnimation(data); 1601 restoreOptions(data); 1602 applyAnimation(data); 1603 } 1604 function update(e, data) { 1605 if (!is(data, 'dragging')) { 1606 return; 1607 } 1608 updateInput(e, data); 1609 var input = getInputState(data); 1610 var half, delta; 1611 var target = data.target, offset = target.offset(); 1612 if (data.orientation === 'horizontal') { 1613 half = target.innerWidth() / 2; 1614 delta = (input.currentX - offset.left - half) / half; 1615 } 1616 else { 1617 half = (data.height / 2); 1618 delta = (input.currentY - offset.top - half) / half; 1619 } 1620 data.reverse = delta < 0; 1621 delta = delta < 0 ? -delta : delta; 1622 data.frameTime = 80 * (1 - delta) + 20; 1623 if (((data.orientation === 'horizontal') && (input.dX < input.dY)) || 1624 ((data.orientation === 'vertical') && (input.dX < input.dY))) { 1625 e.preventDefault(); 1626 } 1627 } 1628 function onFrame(e, data) { 1629 data.animate = true; 1630 applyAnimation(data); 1631 } 1632 registerPlugin(NAME, { 1633 name: NAME, 1634 mousedown: start, 1635 mousemove: update, 1636 mouseup: stop, 1637 mouseleave: stop, 1638 touchstart: start, 1639 touchmove: update, 1640 touchend: stop, 1641 touchcancel: stop, 1642 onFrame: onFrame 1643 }); 1644 })(); 1645 1646 (function () { 1647 var NAME = 'swipe'; 1648 function getState$$1(data) { 1649 return getPluginState(data, NAME); 1650 } 1651 function getOption(data, name, fallback) { 1652 return data[name] || fallback; 1653 } 1654 function init(e, data) { 1655 var state = getState$$1(data); 1656 state.fling = getOption(data, 'swipeFling', 10); 1657 state.snap = getOption(data, 'swipeSnap', 0.50); 1658 } 1659 function start(e, data) { 1660 if (!data.loading && !is(data, 'dragging')) { 1661 updateInput(e, data); 1662 flag(data, 'dragging', true); 1663 } 1664 } 1665 function update(e, data) { 1666 if (!is(data, 'dragging')) { 1667 return; 1668 } 1669 updateInput(e, data); 1670 var frame = data.frame; 1671 var lane = data.lane; 1672 updateFrame(data, frame, lane); 1673 } 1674 function end(e, data) { 1675 if (!is(data, 'dragging')) { 1676 return; 1677 } 1678 flag(data, 'dragging', false); 1679 var state = getState$$1(data); 1680 var input = getInputState(data); 1681 var frame = data.frame; 1682 var lane = data.lane; 1683 var snap = state.snap; 1684 var fling = state.fling; 1685 var dS, dF; 1686 if (data.orientation === 'horizontal') { 1687 dS = input.ndX; 1688 dF = input.ddX; 1689 } 1690 else { 1691 dS = input.ndY; 1692 dF = input.ddY; 1693 } 1694 if (dS >= snap || dF >= fling) { 1695 frame = data.frame - 1; 1696 } 1697 else if (dS <= -snap || dF <= -fling) { 1698 frame = data.frame + 1; 1699 } 1700 resetInput(data); 1701 updateFrame(data, frame, lane); 1702 stopAnimation(data); 1703 } 1704 registerPlugin(NAME, { 1705 name: NAME, 1706 onLoad: init, 1707 mousedown: start, 1708 mousemove: update, 1709 mouseup: end, 1710 mouseleave: end, 1711 touchstart: start, 1712 touchmove: update, 1713 touchend: end, 1714 touchcancel: end 1715 }); 1716 })(); 1717 1718 (function () { 1719 var NAME = 'wheel'; 1720 function wheel(e, data) { 1721 if (!data.loading && data.stage.is(':visible')) { 1722 e.preventDefault(); 1723 var we = e.originalEvent; 1724 var signX = we.deltaX === 0 ? 0 : we.deltaX > 0 ? 1 : -1; 1725 var signY = we.deltaY === 0 ? 0 : we.deltaY > 0 ? 1 : -1; 1726 updateFrame(data, data.frame + signY, data.lane + signX); 1727 } 1728 } 1729 registerPlugin(NAME, { 1730 name: NAME, 1731 wheel: wheel 1732 }); 1733 })(); 1734 1735 (function () { 1736 var template = "\n<div class='spritespin-progress'>\n <div class='spritespin-progress-label'></div>\n <div class='spritespin-progress-bar'></div>\n</div>\n"; 1737 function getState$$1(data) { 1738 return getPluginState(data, NAME); 1739 } 1740 var NAME = 'progress'; 1741 function onInit(e, data) { 1742 var state = getState$$1(data); 1743 if (!state.stage) { 1744 state.stage = $$1(template); 1745 state.stage.appendTo(data.target); 1746 } 1747 state.stage.find('.spritespin-progress-label') 1748 .text("0%") 1749 .css({ 'text-align': 'center' });
1750 state.stage.find('.spritespin-progress-bar').css({ 1751 width: "0%" 1752 }); 1753 state.stage.hide().fadeIn(); 1754 } 1755 function onProgress(e, data) { 1756 var state = getState$$1(data); 1757 state.stage.find('.spritespin-progress-label') 1758 .text(data.progress.percent + "%") 1759 .css({ 'text-align': 'center' }); 1760 state.stage.find('.spritespin-progress-bar').css({ 1761 width: data.progress.percent + "%" 1762 }); 1763 } 1764 function onLoad(e, data) { 1765 $$1(getState$$1(data).stage).fadeOut(); 1766 } 1767 function onDestroy(e, data) { 1768 $$1(getState$$1(data).stage).remove(); 1769 } 1770 registerPlugin(NAME, { 1771 name: NAME, 1772 onInit: onInit, 1773 onProgress: onProgress, 1774 onLoad: onLoad, 1775 onDestroy: onDestroy 1776 }); 1777 })(); 1778 1779 (function () { 1780 var NAME = '360'; 1781 function onLoad(e, data) { 1782 data.stage.find('.spritespin-frames').detach(); 1783 if (data.renderer === 'image') { 1784 $(data.images).addClass('spritespin-frames').appendTo(data.stage); 1785 } 1786 } 1787 function onDraw(e, data) { 1788 var specs = findSpecs(data.metrics, data.frames, data.frame, data.lane); 1789 var sheet = specs.sheet; 1790 var sprite = specs.sprite; 1791 if (!sheet || !sprite) { 1792 return; 1793 } 1794 var src = data.source[sheet.id]; 1795 var image = data.images[sheet.id]; 1796 if (data.renderer === 'canvas') { 1797 data.canvas.show(); 1798 var w = data.canvas[0].width / data.canvasRatio; 1799 var h = data.canvas[0].height / data.canvasRatio; 1800 data.context.clearRect(0, 0, w, h); 1801 data.context.drawImage(image, sprite.sampledX, sprite.sampledY, sprite.sampledWidth, sprite.sampledHeight, 0, 0, w, h); 1802 return; 1803 } 1804 var scaleX = data.stage.innerWidth() / sprite.sampledWidth; 1805 var scaleY = data.stage.innerHeight() / sprite.sampledHeight; 1806 var top = Math.floor(-sprite.sampledY * scaleY); 1807 var left = Math.floor(-sprite.sampledX * scaleX); 1808 var width = Math.floor(sheet.sampledWidth * scaleX); 1809 var height = Math.floor(sheet.sampledHeight * scaleY); 1810 if (data.renderer === 'background') { 1811 data.stage.css({ 1812 'background-image': "url('" + src + "')", 1813 'background-position': left + "px " + top + "px", 1814 'background-repeat': 'no-repeat', 1815 // set custom background size to enable responsive rendering 1816 '-webkit-background-size': width + "px " + height + "px", 1817 '-moz-background-size': width + "px " + height + "px", 1818 '-o-background-size': width + "px " + height + "px", 1819 'background-size': width + "px " + height + "px" /* Chrome, Firefox 4+, IE 9+, Opera, Safari 5+ */ 1820 }); 1821 return; 1822 } 1823 $(data.images).hide(); 1824 $(image).show().css({ 1825 position: 'absolute', 1826 top: top, 1827 left: left, 1828 'max-width': 'initial', 1829 width: width, 1830 height: height 1831 }); 1832 } 1833 registerPlugin(NAME, { 1834 name: NAME, 1835 onLoad: onLoad, 1836 onDraw: onDraw 1837 }); 1838 })(); 1839 1840 (function () { 1841 var NAME = 'blur'; 1842 function getState$$1(data) { 1843 return getPluginState(data, NAME); 1844 } 1845 function getOption(data, name, fallback) { 1846 return data[name] || fallback; 1847 } 1848 function init(e, data) { 1849 var state = getState$$1(data); 1850 state.canvas = state.canvas || $$1("<canvas class='blur-layer'></canvas>"); 1851 state.context = state.context || state.canvas[0].getContext('2d'); 1852 state.steps = state.steps || []; 1853 state.fadeTime = Math.max(getOption(data, 'blurFadeTime', 200), 1); 1854 state.frameTime = Math.max(getOption(data, 'blurFrameTime', data.frameTime), 16); 1855 state.trackTime = null; 1856 state.cssBlur = !!getOption(data, 'blurCss', false); 1857 var inner = getInnerSize(data); 1858 var outer = data.responsive ? getComputedSize(data) : getOuterSize(data); 1859 var css = getInnerLayout(data.sizeMode, inner, outer); 1860 state.canvas[0].width = data.width * data.canvasRatio; 1861 state.canvas[0].height = data.height * data.canvasRatio; 1862 state.canvas.css(css).show(); 1863 state.context.scale(data.canvasRatio, data.canvasRatio); 1864 data.target.append(state.canvas); 1865 } 1866 function onFrame(e, data) { 1867 var state = getState$$1(data); 1868 trackFrame(data); 1869 if (state.timeout == null) { 1870 loop(data); 1871 } 1872 } 1873 function trackFrame(data) { 1874 var state = getState$$1(data); 1875 var ani = getPlaybackState(data); 1876 // distance between frames 1877 var d = Math.abs(data.frame - ani.lastFrame); 1878 // shortest distance 1879 d = d >= data.frames / 2 ? data.frames - d : d; 1880 state.steps.unshift({ 1881 frame: data.frame, 1882 lane: data.lane, 1883 live: 1, 1884 step: state.frameTime / state.fadeTime, 1885 d: d, 1886 alpha: 0 1887 }); 1888 } 1889 var toRemove = []; 1890 function removeOldFrames(frames) { 1891 toRemove.length = 0; 1892 for (var i = 0; i < frames.length; i += 1) { 1893 if (frames[i].alpha <= 0) { 1894 toRemove.push(i); 1895 } 1896 } 1897 for (var _i = 0, toRemove_1 = toRemove; _i < toRemove_1.length; _i++) { 1898 var item = toRemove_1[_i]; 1899 frames.splice(item, 1); 1900 } 1901 } 1902 function loop(data) { 1903 var state = getState$$1(data); 1904 state.timeout = window.setTimeout(function () { tick(data); }, state.frameTime); 1905 } 1906 function killLoop(data) { 1907 var state = getState$$1(data); 1908 window.clearTimeout(state.timeout); 1909 state.timeout = null; 1910 } 1911 function applyCssBlur(canvas, d) {
1912 var amount = Math.min(Math.max((d / 2) - 4, 0), 2.5); 1913 var blur = "blur(" + amount + "px)"; 1914 canvas.css({ 1915 '-webkit-filter': blur, 1916 filter: blur 1917 }); 1918 } 1919 function clearFrame(data, state) { 1920 state.canvas.show(); 1921 var w = state.canvas[0].width / data.canvasRatio; 1922 var h = state.canvas[0].height / data.canvasRatio; 1923 // state.context.clearRect(0, 0, w, h) 1924 } 1925 function drawFrame(data, state, step) { 1926 if (step.alpha <= 0) { 1927 return; 1928 } 1929 var specs = findSpecs(data.metrics, data.frames, step.frame, step.lane); 1930 var sheet = specs.sheet; 1931 var sprite = specs.sprite; 1932 if (!sheet || !sprite) { 1933 return; 1934 } 1935 var src = data.source[sheet.id]; 1936 var image = data.images[sheet.id]; 1937 if (image.complete === false) { 1938 return; 1939 } 1940 state.canvas.show(); 1941 var w = state.canvas[0].width / data.canvasRatio; 1942 var h = state.canvas[0].height / data.canvasRatio; 1943 state.context.globalAlpha = step.alpha; 1944 state.context.drawImage(image, sprite.sampledX, sprite.sampledY, sprite.sampledWidth, sprite.sampledHeight, 0, 0, w, h); 1945 } 1946 function tick(data) { 1947 var state = getState$$1(data); 1948 killLoop(data); 1949 if (!state.context) { 1950 return; 1951 } 1952 var d = 0; 1953 clearFrame(data, state); 1954 state.context.clearRect(0, 0, data.width, data.height); 1955 for (var _i = 0, _a = state.steps; _i < _a.length; _i++) { 1956 var step = _a[_i]; 1957 step.live = Math.max(step.live - step.step, 0); 1958 step.alpha = Math.max(step.live - 0.25, 0); 1959 drawFrame(data, state, step); 1960 d += step.alpha + step.d; 1961 } 1962 if (state.cssBlur) { 1963 applyCssBlur(state.canvas, d); 1964 } 1965 removeOldFrames(state.steps); 1966 if (state.steps.length) { 1967 loop(data); 1968 } 1969 } 1970 registerPlugin(NAME, { 1971 name: NAME, 1972 onLoad: init, 1973 onFrameChanged: onFrame 1974 }); 1975 })(); 1976 1977 (function () { 1978 var max = Math.max; 1979 var min = Math.min; 1980 var NAME = 'ease'; 1981 function getState$$1(data) { 1982 return getPluginState(data, NAME); 1983 } 1984 function getOption(data, name, fallback) { 1985 return data[name] || fallback; 1986 } 1987 function init(e, data) { 1988 var state = getState$$1(data); 1989 state.maxSamples = max(getOption(data, 'easeMaxSamples', 5), 0); 1990 state.damping = max(min(getOption(data, 'easeDamping', 0.9), 0.999), 0); 1991 state.abortTime = max(getOption(data, 'easeAbortTime', 250), 16); 1992 state.updateTime = max(getOption(data, 'easeUpdateTime', data.frameTime), 16); 1993 state.samples = []; 1994 state.steps = []; 1995 } 1996 function update(e, data) { 1997 if (is(data, 'dragging')) { 1998 killLoop(data); 1999 sampleInput(data); 2000 } 2001 } 2002 function end(e, data) { 2003 var state = getState$$1(data); 2004 var samples = state.samples; 2005 var last; 2006 var lanes = 0; 2007 var frames = 0; 2008 var time = 0; 2009 for (var _i = 0, samples_1 = samples; _i < samples_1.length; _i++) { 2010 var sample = samples_1[_i]; 2011 if (!last) { 2012 last = sample; 2013 continue; 2014 } 2015 var dt = sample.time - last.time; 2016 if (dt > state.abortTime) { 2017 lanes = frames = time = 0; 2018 return killLoop(data); 2019 } 2020 frames += sample.frame - last.frame; 2021 lanes += sample.lane - last.lane; 2022 time += dt; 2023 last = sample; 2024 } 2025 samples.length = 0; 2026 if (!time) { 2027 return; 2028 } 2029 state.lane = data.lane; 2030 state.lanes = 0; 2031 state.laneStep = lanes / time * state.updateTime; 2032 state.frame = data.frame; 2033 state.frames = 0; 2034 state.frameStep = frames / time * state.updateTime; 2035 loop(data); 2036 } 2037 function sampleInput(data) { 2038 var state = getState$$1(data); 2039 // add a new sample 2040 state.samples.push({ 2041 time: new Date().getTime(), 2042 frame: data.frame, 2043 lane: data.lane 2044 }); 2045 // drop old samples 2046 while (state.samples.length > state.maxSamples) { 2047 state.samples.shift(); 2048 } 2049 } 2050 function killLoop(data) { 2051 var state = getState$$1(data); 2052 if (state.handler != null) { 2053 window.clearTimeout(state.handler); 2054 state.handler = null; 2055 } 2056 } 2057 function loop(data) { 2058 var state = getState$$1(data); 2059 state.handler = window.setTimeout(function () { tick(data); }, state.updateTime); 2060 } 2061 function tick(data) { 2062 var state = getState$$1(data); 2063 state.lanes += state.laneStep; 2064 state.frames += state.frameStep; 2065 state.laneStep *= state.damping; 2066 state.frameStep *= state.damping; 2067 var frame = Math.floor(state.frame + state.frames); 2068 var lane = Math.floor(state.lane + state.lanes); 2069 updateFrame(data, frame, lane); 2070 if (is(data, 'dragging')) { 2071 killLoop(data); 2072 } 2073 else if (Math.abs(state.frameStep) > 0.005 || Math.abs(state.laneStep) > 0.005) { 2074 loop(data); 2075 } 2076 else { 2077 killLoop(data); 2078 } 2079 } 2080 registerPlugin(NAME, { 2081 name: NAME, 2082 onLoad: init, 2083 mousemove: update, 2084 mouseup: end, 2085 mouseleave: end, 2086 touchmove: update, 2087 touchend: end, 2088 touchcancel: end 2089 }); 2090 })(); 2091 2092 (function () { 2093 var NAME = 'gallery'; 2094 function getState$$1(data) { 2095 return getPluginState(data, NAME); 2096 } 2097 function getOption(data, name, fallback) { 2098 return data[name] || fallback; 2099 } 2100 function load(e, data) { 2101 var state = getState$$1(data); 2102 state.images = []; 2103 state.offsets = []; 2104 state.frame = data.frame; 2105 state.speed = getOption(data, 'gallerySpeed', 500); 2106 state.opacity = getOption(data, 'galleryOpacity', 0.25); 2107 state.stage = getOption(data, 'galleryStage', $$1('<div></div>')); 2108 state.stage.empty().addClass('gallery-stage').prependTo(data.stage); 2109 var size = 0; 2110 for (var _i = 0, _a = data.images; _i < _a.length; _i++) { 2111 var image = _a[_i]; 2112 var naturalSize$$1 = naturalSize(image); 2113 var scale = data.height / naturalSize$$1.height; 2114 var img = $$1(image); 2115 state.stage.append(img); 2116 state.images.push(img); 2117 state.offsets.push(-size + (data.width - image.width * scale) / 2); 2118 size += data.width; 2119 img.css({ 2120 'max-width': 'initial', 2121 opacity: state.opacity, 2122 width: data.width, 2123 height: data.height 2124 }); 2125 } 2126 var innerSize = getInnerSize(data); 2127 var outerSize = data.responsive ? getComputedSize(data) : getOuterSize(data); 2128 var layout = getInnerLayout(data.sizeMode, innerSize, outerSize); 2129 state.stage.css(layout).css({ width: size, left: state.offsets[state.frame] }); 2130 state.images[state.frame].animate({ opacity: 1 }, { duration: state.speed }); 2131 } 2132 function draw(e, data) { 2133 var state = getState$$1(data); 2134 var input = getInputState(data); 2135 var isDragging = is(data, 'dragging'); 2136 if (state.frame !== data.frame && !isDragging) { 2137 state.stage.stop(true, false).animate({ left: state.offsets[data.frame] }, { duration: state.speed }); 2138 state.images[state.frame].animate({ opacity: state.opacity }, { duration: state.speed }); 2139 state.frame = data.frame; 2140 state.images[state.frame].animate({ opacity: 1 }, { duration: state.speed }); 2141 state.stage.animate({ left: state.offsets[state.frame] }); 2142 } 2143 else if (isDragging || state.dX !== input.dX) { 2144 state.dX = input.dX; 2145 state.ddX = input.ddX; 2146 state.stage.stop(true, true).css({ left: state.offsets[state.frame] + state.dX }); 2147 } 2148 } 2149 registerPlugin(NAME, { 2150 name: NAME, 2151 onLoad: load, 2152 onDraw: draw 2153 }); 2154 })(); 2155 2156 (function () { 2157 var NAME = 'panorama'; 2158 function getState$$1(data) { 2159 return getPluginState(data, NAME); 2160 } 2161 function onLoad(e, data) { 2162 var state = getState$$1(data); 2163 var sprite = data.metrics[0]; 2164 if (!sprite) { 2165 return; 2166 } 2167 if (data.orientation === 'horizontal') {
2168 state.scale = data.target.innerHeight() / sprite.sampledHeight; 2169 data.frames = sprite.sampledWidth; 2170 } 2171 else { 2172 state.scale = data.target.innerWidth() / sprite.sampledWidth; 2173 data.frames = sprite.sampledHeight; 2174 } 2175 var width = Math.floor(sprite.sampledWidth * state.scale); 2176 var height = Math.floor(sprite.sampledHeight * state.scale); 2177 data.stage.css({ 2178 'background-image': "url(" + data.source[sprite.id] + ")", 2179 'background-repeat': 'repeat-both', 2180 // set custom background size to enable responsive rendering 2181 '-webkit-background-size': width + "px " + height + "px", 2182 '-moz-background-size': width + "px " + height + "px", 2183 '-o-background-size': width + "px " + height + "px", 2184 'background-size': width + "px " + height + "px" /* Chrome, Firefox 4+, IE 9+, Opera, Safari 5+ */ 2185 }); 2186 } 2187 function onDraw(e, data) { 2188 var state = getState$$1(data); 2189 var px = data.orientation === 'horizontal' ? 1 : 0; 2190 var py = px ? 0 : 1; 2191 var offset = data.frame % data.frames; 2192 var left = Math.round(px * offset * state.scale); 2193 var top = Math.round(py * offset * state.scale); 2194 data.stage.css({ 'background-position': left + "px " + top + "px" }); 2195 } 2196 registerPlugin(NAME, { 2197 name: NAME, 2198 onLoad: onLoad, 2199 onDraw: onDraw 2200 }); 2201 })(); 2202 2203 (function () { 2204 var NAME = 'zoom'; 2205 function getState$$1(data) { 2206 return getPluginState(data, NAME); 2207 } 2208 function getOption(data, name, fallback) { 2209 return data[name] || fallback; 2210 } 2211 function onInit(e, data) { 2212 var state = getState$$1(data); 2213 state.source = getOption(data, 'zoomSource', data.source); 2214 state.doubleClickTime = getOption(data, 'zoomDoubleClickTime', 500); 2215 state.stage = state.stage || $$1("<div class='zoom-stage'></div>"); 2216 state.stage.css({ 2217 width: '100%', 2218 height: '100%', 2219 top: 0, 2220 left: 0, 2221 bottom: 0, 2222 right: 0, 2223 position: 'absolute' 2224 }) 2225 .appendTo(data.target) 2226 .hide(); 2227 } 2228 function onDestroy(e, data) { 2229 var state = getState$$1(data); 2230 if (state.stage) { 2231 state.stage.remove(); 2232 delete state.stage; 2233 } 2234 } 2235 function updateInput$$1(e, data) { 2236 var state = getState$$1(data); 2237 if (!state.stage.is(':visible')) { 2238 return; 2239 } 2240 e.preventDefault(); 2241 // hack into drag/move module and disable dragging 2242 // prevents frame change during zoom mode 2243 flag(data, 'dragging', false); 2244 // grab touch/cursor position 2245 var cursor = getCursorPosition(e); 2246 // normalize cursor position into [0:1] range 2247 var x = cursor.x / data.width; 2248 var y = cursor.y / data.height; 2249 if (state.oldX == null) { 2250 state.oldX = x; 2251 state.oldY = y; 2252 } 2253 if (state.currentX == null) { 2254 state.currentX = x; 2255 state.currentY = y; 2256 } 2257 // calculate move delta since last frame and remember current position 2258 var dx = x - state.oldX; 2259 var dy = y - state.oldY; 2260 state.oldX = x; 2261 state.oldY = y; 2262 // invert drag direction for touch events to enable 'natural' scrolling 2263 if (e.type.match(/touch/)) { 2264 dx = -dx; 2265 dy = -dy; 2266 } 2267 // accumulate display coordinates 2268 state.currentX = clamp(state.currentX + dx, 0, 1); 2269 state.currentY = clamp(state.currentY + dy, 0, 1); 2270 updateFrame(data, data.frame, data.lane); 2271 } 2272 function onClick(e, data) { 2273 e.preventDefault(); 2274 var state = getState$$1(data); 2275 // simulate double click 2276 var clickTime = new Date().getTime(); 2277 if (!state.clickTime) { 2278 // on first click 2279 state.clickTime = clickTime; 2280 return; 2281 } 2282 // on second click 2283 var timeDelta = clickTime - state.clickTime; 2284 if (timeDelta > state.doubleClickTime) { 2285 // took too long, back to first click 2286 state.clickTime = clickTime; 2287 return; 2288 } 2289 // on valid double click 2290 state.clickTime = undefined; 2291 if (toggleZoom(data)) { 2292 updateInput$$1(e, data); 2293 } 2294 } 2295 function onMove(e, data) { 2296 var state = getState$$1(data);
2297 if (state.stage.is(':visible')) { 2298 updateInput$$1(e, data); 2299 } 2300 } 2301 function onDraw(e, data) { 2302 var state = getState$$1(data); 2303 // calculate the frame index 2304 var index = data.lane * data.frames + data.frame; 2305 // get the zoom image. Use original frames as fallback. This won't work for spritesheets 2306 var source = state.source[index]; 2307 var spec = findSpecs(data.metrics, data.frames, data.frame, data.lane); 2308 // get display position 2309 var x = state.currentX; 2310 var y = state.currentY; 2311 // fallback to centered position 2312 if (x == null) { 2313 x = state.currentX = 0.5; 2314 y = state.currentY = 0.5; 2315 } 2316 if (source) { 2317 // scale up from [0:1] to [0:100] range 2318 x = Math.floor(x * 100); 2319 y = Math.floor(y * 100); 2320 // update background image and position 2321 state.stage.css({ 2322 'background-repeat': 'no-repeat', 2323 'background-image': "url('" + source + "')", 2324 'background-position': x + "% " + y + "%" 2325 }); 2326 } 2327 else if (spec.sheet && spec.sprite) { 2328 var sprite = spec.sprite; 2329 var sheet = spec.sheet; 2330 var src = data.source[sheet.id]; 2331 var left = -Math.floor(sprite.sampledX + x * (sprite.sampledWidth - data.width)); 2332 var top_1 = -Math.floor(sprite.sampledY + y * (sprite.sampledHeight - data.height)); 2333 var width = sheet.sampledWidth; 2334 var height = sheet.sampledHeight; 2335 state.stage.css({ 2336 'background-image': "url('" + src + "')", 2337 'background-position': left + "px " + top_1 + "px", 2338 'background-repeat': 'no-repeat', 2339 // set custom background size to enable responsive rendering 2340 '-webkit-background-size': width + "px " + height + "px", 2341 '-moz-background-size': width + "px " + height + "px", 2342 '-o-background-size': width + "px " + height + "px", 2343 'background-size': width + "px " + height + "px" /* Chrome, Firefox 4+, IE 9+, Opera, Safari 5+ */ 2344 }); 2345 } 2346 } 2347 function toggleZoom(data) { 2348 var state = getState$$1(data); 2349 if (!state.stage) { 2350 throw new Error('zoom module is not initialized or is not available.'); 2351 } 2352 if (state.stage.is(':visible')) { 2353 state.stage.fadeOut(); 2354 data.stage.fadeIn(); 2355 } 2356 else { 2357 state.stage.fadeIn(); 2358 data.stage.fadeOut(); 2359 return true; 2360 } 2361 return false; 2362 } 2363 registerPlugin(NAME, { 2364 name: NAME, 2365 mousedown: onClick, 2366 touchstart: onClick, 2367 mousemove: onMove, 2368 touchmove: onMove, 2369 onInit: onInit, 2370 onDestroy: onDestroy, 2371 onDraw: onDraw 2372 }); 2373 extendApi({ 2374 toggleZoom: function () { toggleZoom(this.data); } // tslint:disable-line 2375 }); 2376 })(); 2377 2378 var Utils = _Utils; 2379 2380 exports.Utils = Utils; 2381 exports.sourceArray = sourceArray; 2382 exports.Api = Api; 2383 exports.extendApi = extendApi; 2384 exports.instances = instances; 2385 exports.applyEvents = applyEvents; 2386 exports.boot = boot; 2387 exports.create = create; 2388 exports.createOrUpdate = createOrUpdate; 2389 exports.destroy = destroy; 2390 exports.namespace = namespace; 2391 exports.eventNames = eventNames; 2392 exports.callbackNames = callbackNames; 2393 exports.eventsToPrevent = eventsToPrevent; 2394 exports.defaults = defaults; 2395 exports.getInputState = getInputState; 2396 exports.updateInput = updateInput; 2397 exports.resetInput = resetInput; 2398 exports.applyLayout = applyLayout; 2399 exports.getPlaybackState = getPlaybackState; 2400 exports.updateFrame = updateFrame; 2401 exports.stopAnimation = stopAnimation; 2402 exports.applyAnimation = applyAnimation; 2403 exports.startAnimation = startAnimation; 2404 exports.registerPlugin = registerPlugin; 2405 exports.registerModule = registerModule; 2406 exports.getPlugin = getPlugin; 2407 exports.applyPlugins = applyPlugins; 2408 exports.getState = getState; 2409 exports.getPluginState = getPluginState; 2410 exports.is = is; 2411 exports.flag = flag; 2412 2413 Object.defineProperty(exports, '__esModule', { value: true }); 2414 2415}))); 2416//# sourceMappingURL=spritespin.js.map
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.