|
1 | 1 | /*!
|
2 |
| - * Viewer v0.1.0 |
| 2 | + * Viewer v0.1.1 |
3 | 3 | * https://github.com/fengyuanchen/viewerjs
|
4 | 4 | *
|
5 | 5 | * Copyright (c) 2015 Fengyuan Chen
|
6 | 6 | * Released under the MIT license
|
7 | 7 | *
|
8 |
| - * Date: 2015-12-24T07:15:17.423Z |
| 8 | + * Date: 2015-12-28T03:06:49.640Z |
9 | 9 | */
|
10 | 10 |
|
11 | 11 | (function (global, factory) {
|
|
81 | 81 | var round = Math.round;
|
82 | 82 |
|
83 | 83 | // Utilities
|
84 |
| - var EMPTY_OBJECT = {}; |
85 |
| - var toString = EMPTY_OBJECT.toString; |
86 |
| - var hasOwnProperty = EMPTY_OBJECT.hasOwnProperty; |
| 84 | + var objectProto = Object.prototype; |
| 85 | + var toString = objectProto.toString; |
| 86 | + var hasOwnProperty = objectProto.hasOwnProperty; |
| 87 | + var slice = Array.prototype.slice; |
87 | 88 |
|
88 | 89 | function typeOf(obj) {
|
89 | 90 | return toString.call(obj).slice(8, -1).toLowerCase();
|
|
132 | 133 | }
|
133 | 134 |
|
134 | 135 | function toArray(obj, offset) {
|
135 |
| - var args = []; |
| 136 | + offset = offset >= 0 ? offset : 0; |
136 | 137 |
|
137 | 138 | if (Array.from) {
|
138 |
| - return Array.from(obj).slice(offset || 0); |
| 139 | + return Array.from(obj).slice(offset); |
139 | 140 | }
|
140 | 141 |
|
141 |
| - // This is necessary for IE8 |
142 |
| - if (isNumber(offset)) { |
143 |
| - args.push(offset); |
144 |
| - } |
145 |
| - |
146 |
| - return args.slice.apply(obj, args); |
| 142 | + return slice.call(obj, offset); |
147 | 143 | }
|
148 | 144 |
|
149 | 145 | function inArray(value, arr) {
|
|
423 | 419 | return e;
|
424 | 420 | }
|
425 | 421 |
|
| 422 | + function getOffset(element) { |
| 423 | + var doc = document.documentElement; |
| 424 | + var box = element.getBoundingClientRect(); |
| 425 | + |
| 426 | + return { |
| 427 | + left: box.left + (window.scrollX || doc && doc.scrollLeft || 0) - (doc && doc.clientLeft || 0), |
| 428 | + top: box.top + (window.scrollY || doc && doc.scrollTop || 0) - (doc && doc.clientTop || 0) |
| 429 | + }; |
| 430 | + } |
| 431 | + |
| 432 | + function getTouchesCenter(touches) { |
| 433 | + var length = touches.length; |
| 434 | + var pageX = 0; |
| 435 | + var pageY = 0; |
| 436 | + |
| 437 | + if (length) { |
| 438 | + each(touches, function (touch) { |
| 439 | + pageX += touch.pageX; |
| 440 | + pageY += touch.pageY; |
| 441 | + }); |
| 442 | + |
| 443 | + pageX /= length; |
| 444 | + pageY /= length; |
| 445 | + } |
| 446 | + |
| 447 | + return { |
| 448 | + pageX: pageX, |
| 449 | + pageY: pageY |
| 450 | + }; |
| 451 | + } |
| 452 | + |
426 | 453 | function getByTag(element, tagName, index) {
|
427 | 454 | var elements = element.getElementsByTagName(tagName);
|
428 | 455 |
|
|
1013 | 1040 | break;
|
1014 | 1041 |
|
1015 | 1042 | case 'one-to-one':
|
1016 |
| - if (imageData.ratio === 1) { |
1017 |
| - _this.zoomTo(_this.initialImageData.ratio); |
1018 |
| - } else { |
1019 |
| - _this.zoomTo(1); |
1020 |
| - } |
1021 |
| - |
| 1043 | + _this.toggle(); |
1022 | 1044 | break;
|
1023 | 1045 |
|
1024 | 1046 | case 'reset':
|
|
1179 | 1201 | delta = e.detail > 0 ? 1 : -1;
|
1180 | 1202 | }
|
1181 | 1203 |
|
1182 |
| - _this.zoom(-delta * ratio, true); |
| 1204 | + _this.zoom(-delta * ratio, true, e); |
1183 | 1205 | },
|
1184 | 1206 |
|
1185 | 1207 | keydown: function (event) {
|
|
1253 | 1275 | // Zoom in to natural size (Key: Ctrl + 1)
|
1254 | 1276 | case 49:
|
1255 | 1277 | if (e.ctrlKey || e.shiftKey) {
|
1256 |
| - e.preventDefault(); |
1257 |
| - |
1258 |
| - if (_this.imageData.ratio === 1) { |
1259 |
| - _this.zoomTo(_this.initialImageData.ratio); |
1260 |
| - } else { |
1261 |
| - _this.zoomTo(1); |
1262 |
| - } |
| 1278 | + preventDefault(e); |
| 1279 | + _this.toggle(); |
1263 | 1280 | }
|
1264 | 1281 |
|
1265 | 1282 | break;
|
|
1350 | 1367 | _this.endX = touch ? touch.pageX : e.pageX;
|
1351 | 1368 | _this.endY = touch ? touch.pageY : e.pageY;
|
1352 | 1369 |
|
1353 |
| - _this.change(); |
| 1370 | + _this.change(e); |
1354 | 1371 | }
|
1355 | 1372 | },
|
1356 | 1373 |
|
|
1399 | 1416 | removeClass(viewer, CLASS_HIDE);
|
1400 | 1417 |
|
1401 | 1418 | addListener(element, EVENT_SHOWN, function () {
|
1402 |
| - _this.view((_this.target ? inArray(_this.target, toArray(_this.images)) : 0) || _this.index); |
| 1419 | + _this.view(_this.target ? inArray(_this.target, toArray(_this.images)) : _this.index); |
1403 | 1420 | _this.target = false;
|
1404 | 1421 | }, true);
|
1405 | 1422 |
|
|
1442 | 1459 | addListener(viewer, EVENT_TRANSITIONEND, proxy(_this.hidden, _this), true);
|
1443 | 1460 | removeClass(viewer, CLASS_IN);
|
1444 | 1461 | }, true);
|
1445 |
| - _this.zoomTo(0, false, true); |
| 1462 | + _this.zoomTo(0, false, false, true); |
1446 | 1463 | } else {
|
1447 | 1464 | removeClass(viewer, CLASS_IN);
|
1448 | 1465 | _this.hidden();
|
|
1510 | 1527 | // Make the image visible if it fails to load within 1s
|
1511 | 1528 | _this.timeout = setTimeout(function () {
|
1512 | 1529 | removeClass(image, CLASS_INVISIBLE);
|
| 1530 | + _this.timeout = false; |
1513 | 1531 | }, 1000);
|
1514 | 1532 | }
|
1515 | 1533 |
|
|
1609 | 1627 | *
|
1610 | 1628 | * @param {Number} ratio
|
1611 | 1629 | * @param {Boolean} hasTooltip (optional)
|
| 1630 | + * @param {Event} _originalEvent (private) |
1612 | 1631 | */
|
1613 |
| - zoom: function (ratio, hasTooltip) { |
| 1632 | + zoom: function (ratio, hasTooltip, _originalEvent) { |
1614 | 1633 | var _this = this;
|
1615 | 1634 | var imageData = _this.imageData;
|
1616 | 1635 |
|
|
1622 | 1641 | ratio = 1 + ratio;
|
1623 | 1642 | }
|
1624 | 1643 |
|
1625 |
| - _this.zoomTo(imageData.width * ratio / imageData.naturalWidth, hasTooltip); |
| 1644 | + _this.zoomTo(imageData.width * ratio / imageData.naturalWidth, hasTooltip, _originalEvent); |
1626 | 1645 |
|
1627 | 1646 | return _this;
|
1628 | 1647 | },
|
|
1632 | 1651 | *
|
1633 | 1652 | * @param {Number} ratio
|
1634 | 1653 | * @param {Boolean} hasTooltip (optional)
|
| 1654 | + * @param {Event} _originalEvent (private) |
1635 | 1655 | * @param {Boolean} _zoomable (private)
|
1636 | 1656 | */
|
1637 |
| - zoomTo: function (ratio, hasTooltip, _zoomable) { |
| 1657 | + zoomTo: function (ratio, hasTooltip, _originalEvent, _zoomable) { |
1638 | 1658 | var _this = this;
|
1639 | 1659 | var options = _this.options;
|
1640 | 1660 | var minZoomRatio = 0.01;
|
1641 | 1661 | var maxZoomRatio = 100;
|
1642 | 1662 | var imageData = _this.imageData;
|
1643 | 1663 | var newWidth;
|
1644 | 1664 | var newHeight;
|
| 1665 | + var offset; |
| 1666 | + var center; |
1645 | 1667 |
|
1646 | 1668 | ratio = max(0, ratio);
|
1647 | 1669 |
|
|
1658 | 1680 |
|
1659 | 1681 | newWidth = imageData.naturalWidth * ratio;
|
1660 | 1682 | newHeight = imageData.naturalHeight * ratio;
|
1661 |
| - imageData.left -= (newWidth - imageData.width) / 2; |
1662 |
| - imageData.top -= (newHeight - imageData.height) / 2; |
| 1683 | + |
| 1684 | + if (_originalEvent) { |
| 1685 | + offset = getOffset(_this.viewer); |
| 1686 | + center = _originalEvent.touches ? getTouchesCenter(_originalEvent.touches) : { |
| 1687 | + pageX: _originalEvent.pageX, |
| 1688 | + pageY: _originalEvent.pageY |
| 1689 | + }; |
| 1690 | + |
| 1691 | + // Zoom from the triggering point of the event |
| 1692 | + imageData.left -= (newWidth - imageData.width) * ( |
| 1693 | + ((center.pageX - offset.left) - imageData.left) / imageData.width |
| 1694 | + ); |
| 1695 | + imageData.top -= (newHeight - imageData.height) * ( |
| 1696 | + ((center.pageY - offset.top) - imageData.top) / imageData.height |
| 1697 | + ); |
| 1698 | + } else { |
| 1699 | + |
| 1700 | + // Zoom from the center of the image |
| 1701 | + imageData.left -= (newWidth - imageData.width) / 2; |
| 1702 | + imageData.top -= (newHeight - imageData.height) / 2; |
| 1703 | + } |
| 1704 | + |
1663 | 1705 | imageData.width = newWidth;
|
1664 | 1706 | imageData.height = newHeight;
|
1665 | 1707 | imageData.ratio = ratio;
|
|
1995 | 2037 | var _this = this;
|
1996 | 2038 |
|
1997 | 2039 | if (_this.imageData.ratio === 1) {
|
1998 |
| - _this.zoomTo(_this.initialImageData.ratio); |
| 2040 | + _this.zoomTo(_this.initialImageData.ratio, true); |
1999 | 2041 | } else {
|
2000 |
| - _this.zoomTo(1); |
| 2042 | + _this.zoomTo(1, true); |
2001 | 2043 | }
|
2002 | 2044 |
|
2003 | 2045 | return _this;
|
|
2098 | 2140 | }
|
2099 | 2141 | },
|
2100 | 2142 |
|
2101 |
| - change: function () { |
| 2143 | + change: function (originalEvent) { |
2102 | 2144 | var _this = this;
|
2103 | 2145 | var offsetX = _this.endX - _this.startX;
|
2104 | 2146 | var offsetY = _this.endY - _this.startY;
|
|
2122 | 2164 | abs(_this.startY - _this.startY2),
|
2123 | 2165 | abs(_this.endX - _this.endX2),
|
2124 | 2166 | abs(_this.endY - _this.endY2)
|
2125 |
| - )); |
| 2167 | + ), false, originalEvent); |
2126 | 2168 |
|
2127 | 2169 | _this.startX2 = _this.endX2;
|
2128 | 2170 | _this.startY2 = _this.endY2;
|
|
0 commit comments