|
1 | 1 | /** |
2 | 2 | * @license jquery.panzoom.js v3.2.2 |
3 | | - * Updated: Sat Aug 27 2016 |
| 3 | + * Updated: Wed Jun 28 2017 |
4 | 4 | * Add pan and zoom functionality to any element |
5 | 5 | * Copyright (c) timmy willison |
6 | 6 | * Released under the MIT license |
7 | 7 | * https://github.com/timmywil/jquery.panzoom/blob/master/MIT-License.txt |
8 | 8 | */ |
9 | 9 |
|
10 | | -(function(global, factory) { |
| 10 | + (function(global, factory) { |
11 | 11 | // AMD |
12 | 12 | if (typeof define === 'function' && define.amd) { |
13 | 13 | define([ 'jquery' ], function(jQuery) { |
|
297 | 297 | which: 1, |
298 | 298 |
|
299 | 299 | // The increment at which to zoom |
300 | | - // adds/subtracts to the scale each time zoomIn/Out is called |
| 300 | + // Should be a number greater than 0 |
301 | 301 | increment: 0.3, |
302 | 302 |
|
303 | | - // Turns on exponential zooming |
304 | | - // If false, zooming will be incremented linearly |
305 | | - exponential: true, |
| 303 | + // When no scale is passed, this option tells |
| 304 | + // the `zoom` method to increment |
| 305 | + // the scale *linearly* based on the increment option. |
| 306 | + // This often ends up looking like very little happened at larger zoom levels. |
| 307 | + // The default is to multiply/divide the scale based on the increment. |
| 308 | + linearZoom: false, |
306 | 309 |
|
307 | 310 | // Pan only when the scale is greater than minScale |
308 | 311 | panOnlyWhenZoomed: false, |
|
509 | 512 | return matrix || [ 1, 0, 0, 1, 0, 0 ]; |
510 | 513 | }, |
511 | 514 |
|
| 515 | + /** |
| 516 | + * Get the current scale. |
| 517 | + * @param {String} [transform] matrix-formatted transform value |
| 518 | + * @returns {Number} Current scale relative to the initial scale (height / width = 1) |
| 519 | + */ |
| 520 | + getScale: function(matrix) { |
| 521 | + return Math.sqrt(Math.pow(matrix[0], 2) + Math.pow(matrix[1], 2)); |
| 522 | + }, |
| 523 | + |
512 | 524 | /** |
513 | 525 | * Given a matrix object, quickly set the current matrix of the element |
514 | 526 | * @param {Array|String} matrix |
|
526 | 538 | if (typeof matrix === 'string') { |
527 | 539 | matrix = this.getMatrix(matrix); |
528 | 540 | } |
529 | | - var scale = +matrix[0]; |
| 541 | + var scale = this.getScale(matrix); |
530 | 542 | var contain = typeof options.contain !== 'undefined' ? options.contain : this.options.contain; |
531 | 543 |
|
532 | 544 | // Apply containment |
|
690 | 702 | if (options.disableZoom) { return; } |
691 | 703 | var animate = false; |
692 | 704 | var matrix = options.matrix || this.getMatrix(); |
693 | | - var startScale = +matrix[0]; |
| 705 | + var surfaceM = new Matrix(matrix); |
| 706 | + var startScale = this.getScale(matrix); |
694 | 707 |
|
695 | 708 | // Calculate zoom based on increment |
696 | 709 | if (typeof scale !== 'number') { |
697 | | - // Just use a number a little greater than 1 |
698 | | - // Below 1 can use normal increments |
699 | | - if (options.exponential && startScale - options.increment >= 1) { |
700 | | - scale = Math[scale ? 'sqrt' : 'pow'](startScale, 2); |
| 710 | + if (options.linearZoom) { |
| 711 | + scale = 1 + (options.increment * (scale ? -1 : 1)) / startScale; |
701 | 712 | } else { |
702 | | - scale = startScale + (options.increment * (scale ? -1 : 1)); |
| 713 | + scale = scale ? (1 / (1 + options.increment)) : (1 + options.increment); |
703 | 714 | } |
704 | 715 | animate = true; |
| 716 | + } else { |
| 717 | + scale = 1 / startScale; |
705 | 718 | } |
706 | 719 |
|
707 | 720 | // Constrain scale |
708 | | - if (scale > options.maxScale) { |
709 | | - scale = options.maxScale; |
710 | | - } else if (scale < options.minScale) { |
711 | | - scale = options.minScale; |
712 | | - } |
| 721 | + scale = Math.max(Math.min(scale, options.maxScale / startScale), options.minScale / startScale); |
| 722 | + var m = surfaceM.x(new Matrix(scale, 0, 0, 0, (typeof options.dValue === 'number' ? options.dValue / startScale : scale), 0)); |
713 | 723 |
|
714 | 724 | // Calculate focal point based on scale |
715 | 725 | var focal = options.focal; |
716 | 726 | if (focal && !options.disablePan) { |
717 | | - // Adapted from code by Florian Günther |
| 727 | + // Adapted from code by Florian Günther |
718 | 728 | // https://github.com/florianguenther/zui53 |
719 | 729 | this.resetDimensions(); |
720 | 730 | var dims = options.dims = this.dimensions; |
|
729 | 739 | } |
730 | 740 |
|
731 | 741 | var clientV = new Vector(clientX, clientY, 1); |
732 | | - var surfaceM = new Matrix(matrix); |
733 | 742 | // Supply an offset manually if necessary |
734 | 743 | var o = this.parentOffset || this.$parent.offset(); |
735 | 744 | var offsetM = new Matrix(1, 0, o.left - this.$doc.scrollLeft(), 0, 1, o.top - this.$doc.scrollTop()); |
736 | 745 | var surfaceV = surfaceM.inverse().x(offsetM.inverse().x(clientV)); |
737 | | - var scaleBy = scale / matrix[0]; |
738 | | - surfaceM = surfaceM.x(new Matrix([scaleBy, 0, 0, scaleBy, 0, 0])); |
| 746 | + surfaceM = surfaceM.x(new Matrix([scale, 0, 0, scale, 0, 0])); |
739 | 747 | clientV = offsetM.x(surfaceM.x(surfaceV)); |
740 | 748 | matrix[4] = +matrix[4] + (clientX - clientV.e(0)); |
741 | 749 | matrix[5] = +matrix[5] + (clientY - clientV.e(1)); |
742 | 750 | } |
743 | 751 |
|
744 | 752 | // Set the scale |
745 | | - matrix[0] = scale; |
746 | | - matrix[3] = typeof options.dValue === 'number' ? options.dValue : scale; |
| 753 | + matrix[0] = m.e(0); |
| 754 | + matrix[1] = m.e(3); |
| 755 | + matrix[2] = m.e(1); |
| 756 | + matrix[3] = m.e(4); |
747 | 757 |
|
748 | 758 | // Calling zoom may still pan the element |
749 | 759 | this.setMatrix(matrix, { |
|
754 | 764 |
|
755 | 765 | // Trigger zoom event |
756 | 766 | if (!options.silent) { |
757 | | - this._trigger('zoom', matrix[0], options); |
| 767 | + this._trigger('zoom', scale, options); |
758 | 768 | } |
759 | 769 | }, |
760 | 770 |
|
|
960 | 970 | if (!options.disablePan || !options.disableZoom) { |
961 | 971 | events[ str_start ] = function(e) { |
962 | 972 | var touches; |
963 | | - if (e.type === 'touchstart' ? |
| 973 | + if (/touchstart|pointerdown/.test(e.type) ? // fix double events pointer/touch on Chrome >=55 #303 |
964 | 974 | // Touch |
965 | 975 | (touches = e.touches || e.originalEvent.touches) && |
966 | 976 | ((touches.length === 1 && !options.disablePan) || touches.length === 2) : |
|
1128 | 1138 | if (this.panning) { |
1129 | 1139 | return; |
1130 | 1140 | } |
| 1141 | + |
| 1142 | + var type = event.type; |
| 1143 | + if (window.PointerEvent && (type === 'touchstart')) { // fix double events pointer/touch on Chrome >=55 #303 |
| 1144 | +// return false; |
| 1145 | + } |
| 1146 | + |
1131 | 1147 | var moveEvent, endEvent, |
1132 | 1148 | startDistance, startScale, startMiddle, |
1133 | 1149 | startPageX, startPageY, touch; |
|
1139 | 1155 | var origPageX = +original[4]; |
1140 | 1156 | var origPageY = +original[5]; |
1141 | 1157 | var panOptions = { matrix: matrix, animate: 'skip' }; |
1142 | | - var type = event.type; |
1143 | 1158 |
|
1144 | 1159 | // Use proper events |
1145 | 1160 | if (type === 'pointerdown') { |
|
1163 | 1178 | // Remove any transitions happening |
1164 | 1179 | this.transition(true); |
1165 | 1180 |
|
1166 | | - // Indicate that we are currently panning |
1167 | | - this.panning = true; |
1168 | | - |
1169 | 1181 | // Trigger start event |
1170 | 1182 | this._trigger('start', event, touches); |
1171 | 1183 |
|
|
1176 | 1188 | return; |
1177 | 1189 | } |
1178 | 1190 | startDistance = self._getDistance(touches); |
1179 | | - startScale = +matrix[0]; |
| 1191 | + startScale = self.getScale(matrix); |
1180 | 1192 | startMiddle = self._getMiddle(touches); |
1181 | 1193 | return; |
1182 | 1194 | } |
|
1199 | 1211 |
|
1200 | 1212 | var move = function(e) { |
1201 | 1213 | var coords; |
1202 | | - e.preventDefault(); |
| 1214 | + e.stopPropagation(); // chrome passive event warning https://www.chromestatus.com/features/5093566007214080 #328 |
1203 | 1215 | touches = e.touches || e.originalEvent.touches; |
1204 | 1216 | setStart(e, touches); |
1205 | 1217 |
|
|
1210 | 1222 | var middle = self._getMiddle(touches); |
1211 | 1223 | var diff = self._getDistance(touches) - startDistance; |
1212 | 1224 |
|
1213 | | - // Set zoom |
1214 | 1225 | self.zoom(diff * (options.increment / 100) + startScale, { |
1215 | 1226 | focal: middle, |
1216 | 1227 | matrix: matrix, |
|
1233 | 1244 | coords = e; |
1234 | 1245 | } |
1235 | 1246 |
|
| 1247 | + // Indicate that we are currently panning |
| 1248 | + this.panning = true; |
| 1249 | + |
1236 | 1250 | self.pan( |
1237 | 1251 | origPageX + coords.pageX - startPageX, |
1238 | 1252 | origPageY + coords.pageY - startPageY, |
|
0 commit comments