openseadragon 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openseadragon/version.rb +1 -1
- data/vendor/assets/images/openseadragon/button_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/button_hover.png +0 -0
- data/vendor/assets/images/openseadragon/button_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/button_rest.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_hover.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/fullpage_rest.png +0 -0
- data/vendor/assets/images/openseadragon/home_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/home_hover.png +0 -0
- data/vendor/assets/images/openseadragon/home_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/home_rest.png +0 -0
- data/vendor/assets/images/openseadragon/next_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/next_hover.png +0 -0
- data/vendor/assets/images/openseadragon/next_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/next_rest.png +0 -0
- data/vendor/assets/images/openseadragon/previous_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/previous_hover.png +0 -0
- data/vendor/assets/images/openseadragon/previous_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/previous_rest.png +0 -0
- data/vendor/assets/images/openseadragon/rotateleft_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/rotateleft_hover.png +0 -0
- data/vendor/assets/images/openseadragon/rotateleft_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/rotateleft_rest.png +0 -0
- data/vendor/assets/images/openseadragon/rotateright_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/rotateright_hover.png +0 -0
- data/vendor/assets/images/openseadragon/rotateright_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/rotateright_rest.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_hover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/zoomin_rest.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_grouphover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_hover.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_pressed.png +0 -0
- data/vendor/assets/images/openseadragon/zoomout_rest.png +0 -0
- data/vendor/assets/javascripts/openseadragon/openseadragon.js +1807 -636
- data/vendor/assets/javascripts/openseadragon/openseadragon.js.map +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c1293c3a2424f19cf39c77892b3d3fad7447211
|
4
|
+
data.tar.gz: c3a989f62d49e246f644700e022eed592f00da41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27f131316b63cc5aeed1bd97fa24a7221303ba53ae77bcd45d408311d73448e22d267fd1f3b5575ea1c79b719478c28b8099d9220821ab9a13347f4c769e3208
|
7
|
+
data.tar.gz: 0a6bf8f4ae55f16e4fca9dce29a25443b3c0dcfbacb3cdd442bada81990bf6a8792bd5f7e221ea0fdff2551d0bfc07a4f9cc9b1560d1778580322a12bc9e0492
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -1,6 +1,6 @@
|
|
1
|
-
//! openseadragon 2.
|
2
|
-
//! Built on
|
3
|
-
//! Git commit: v2.
|
1
|
+
//! openseadragon 2.3.0
|
2
|
+
//! Built on 2017-07-14
|
3
|
+
//! Git commit: v2.3.0-2-b49fef3
|
4
4
|
//! http://openseadragon.github.io
|
5
5
|
//! License: http://openseadragon.github.io/license/
|
6
6
|
|
@@ -90,7 +90,7 @@
|
|
90
90
|
|
91
91
|
/**
|
92
92
|
* @namespace OpenSeadragon
|
93
|
-
* @version openseadragon 2.
|
93
|
+
* @version openseadragon 2.3.0
|
94
94
|
* @classdesc The root namespace for OpenSeadragon. All utility methods
|
95
95
|
* and classes are defined on or below this namespace.
|
96
96
|
*
|
@@ -191,7 +191,11 @@
|
|
191
191
|
* If 0, adjusts to fit viewer.
|
192
192
|
*
|
193
193
|
* @property {Number} [opacity=1]
|
194
|
-
* Default opacity of the tiled images (1=opaque, 0=
|
194
|
+
* Default proportional opacity of the tiled images (1=opaque, 0=hidden)
|
195
|
+
* Hidden images do not draw and only load when preloading is allowed.
|
196
|
+
*
|
197
|
+
* @property {Boolean} [preload=false]
|
198
|
+
* Default switch for loading hidden images (true loads, false blocks)
|
195
199
|
*
|
196
200
|
* @property {String} [compositeOperation=null]
|
197
201
|
* Valid values are 'source-over', 'source-atop', 'source-in', 'source-out',
|
@@ -417,6 +421,7 @@
|
|
417
421
|
* The max number of images we should keep in memory (per drawer).
|
418
422
|
*
|
419
423
|
* @property {Number} [timeout=30000]
|
424
|
+
* The max number of milliseconds that an image job may take to complete.
|
420
425
|
*
|
421
426
|
* @property {Boolean} [useCanvas=true]
|
422
427
|
* Set to false to not use an HTML canvas element for image rendering even if canvas is supported.
|
@@ -590,9 +595,16 @@
|
|
590
595
|
* not use CORS, and the canvas will be tainted.
|
591
596
|
*
|
592
597
|
* @property {Boolean} [ajaxWithCredentials=false]
|
593
|
-
* Whether to set the withCredentials XHR flag for AJAX requests
|
598
|
+
* Whether to set the withCredentials XHR flag for AJAX requests.
|
599
|
+
* Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.
|
600
|
+
*
|
601
|
+
* @property {Boolean} [loadTilesWithAjax=false]
|
602
|
+
* Whether to load tile data using AJAX requests.
|
594
603
|
* Note that this can be overridden at the {@link OpenSeadragon.TileSource} level.
|
595
604
|
*
|
605
|
+
* @property {Object} [ajaxHeaders={}]
|
606
|
+
* A set of headers to include when making AJAX requests for tile sources or tiles.
|
607
|
+
*
|
596
608
|
*/
|
597
609
|
|
598
610
|
/**
|
@@ -691,19 +703,10 @@
|
|
691
703
|
* @param {OpenSeadragon.Options} options - Viewer options.
|
692
704
|
* @returns {OpenSeadragon.Viewer}
|
693
705
|
*/
|
694
|
-
|
695
|
-
|
706
|
+
function OpenSeadragon( options ){
|
696
707
|
return new OpenSeadragon.Viewer( options );
|
697
|
-
|
698
|
-
};
|
699
|
-
|
700
|
-
if (typeof define === 'function' && define.amd) {
|
701
|
-
define(function () {
|
702
|
-
return (window.OpenSeadragon);
|
703
|
-
});
|
704
708
|
}
|
705
709
|
|
706
|
-
|
707
710
|
(function( $ ){
|
708
711
|
|
709
712
|
|
@@ -718,10 +721,10 @@ if (typeof define === 'function' && define.amd) {
|
|
718
721
|
* @since 1.0.0
|
719
722
|
*/
|
720
723
|
$.version = {
|
721
|
-
versionStr: '2.
|
724
|
+
versionStr: '2.3.0',
|
722
725
|
major: parseInt('2', 10),
|
723
|
-
minor: parseInt('
|
724
|
-
revision: parseInt('
|
726
|
+
minor: parseInt('3', 10),
|
727
|
+
revision: parseInt('0', 10)
|
725
728
|
};
|
726
729
|
|
727
730
|
|
@@ -874,7 +877,7 @@ if (typeof define === 'function' && define.amd) {
|
|
874
877
|
try {
|
875
878
|
// We test if the canvas is tainted by retrieving data from it.
|
876
879
|
// An exception will be raised if the canvas is tainted.
|
877
|
-
|
880
|
+
canvas.getContext('2d').getImageData(0, 0, 1, 1);
|
878
881
|
} catch (e) {
|
879
882
|
isTainted = true;
|
880
883
|
}
|
@@ -882,7 +885,8 @@ if (typeof define === 'function' && define.amd) {
|
|
882
885
|
};
|
883
886
|
|
884
887
|
/**
|
885
|
-
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density
|
888
|
+
* A ratio comparing the device screen's pixel density to the canvas's backing store pixel density,
|
889
|
+
* clamped to a minimum of 1. Defaults to 1 if canvas isn't supported by the browser.
|
886
890
|
* @member {Number} pixelDensityRatio
|
887
891
|
* @memberof OpenSeadragon
|
888
892
|
*/
|
@@ -895,7 +899,7 @@ if (typeof define === 'function' && define.amd) {
|
|
895
899
|
context.msBackingStorePixelRatio ||
|
896
900
|
context.oBackingStorePixelRatio ||
|
897
901
|
context.backingStorePixelRatio || 1;
|
898
|
-
return devicePixelRatio / backingStoreRatio;
|
902
|
+
return Math.max(devicePixelRatio, 1) / backingStoreRatio;
|
899
903
|
} else {
|
900
904
|
return 1;
|
901
905
|
}
|
@@ -1020,6 +1024,8 @@ if (typeof define === 'function' && define.amd) {
|
|
1020
1024
|
initialPage: 0,
|
1021
1025
|
crossOriginPolicy: false,
|
1022
1026
|
ajaxWithCredentials: false,
|
1027
|
+
loadTilesWithAjax: false,
|
1028
|
+
ajaxHeaders: {},
|
1023
1029
|
|
1024
1030
|
//PAN AND ZOOM SETTINGS AND CONSTRAINTS
|
1025
1031
|
panHorizontal: true,
|
@@ -1041,10 +1047,46 @@ if (typeof define === 'function' && define.amd) {
|
|
1041
1047
|
dblClickDistThreshold: 20,
|
1042
1048
|
springStiffness: 6.5,
|
1043
1049
|
animationTime: 1.2,
|
1044
|
-
gestureSettingsMouse: {
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1050
|
+
gestureSettingsMouse: {
|
1051
|
+
scrollToZoom: true,
|
1052
|
+
clickToZoom: true,
|
1053
|
+
dblClickToZoom: false,
|
1054
|
+
pinchToZoom: false,
|
1055
|
+
flickEnabled: false,
|
1056
|
+
flickMinSpeed: 120,
|
1057
|
+
flickMomentum: 0.25,
|
1058
|
+
pinchRotate: false
|
1059
|
+
},
|
1060
|
+
gestureSettingsTouch: {
|
1061
|
+
scrollToZoom: false,
|
1062
|
+
clickToZoom: false,
|
1063
|
+
dblClickToZoom: true,
|
1064
|
+
pinchToZoom: true,
|
1065
|
+
flickEnabled: true,
|
1066
|
+
flickMinSpeed: 120,
|
1067
|
+
flickMomentum: 0.25,
|
1068
|
+
pinchRotate: false
|
1069
|
+
},
|
1070
|
+
gestureSettingsPen: {
|
1071
|
+
scrollToZoom: false,
|
1072
|
+
clickToZoom: true,
|
1073
|
+
dblClickToZoom: false,
|
1074
|
+
pinchToZoom: false,
|
1075
|
+
flickEnabled: false,
|
1076
|
+
flickMinSpeed: 120,
|
1077
|
+
flickMomentum: 0.25,
|
1078
|
+
pinchRotate: false
|
1079
|
+
},
|
1080
|
+
gestureSettingsUnknown: {
|
1081
|
+
scrollToZoom: false,
|
1082
|
+
clickToZoom: false,
|
1083
|
+
dblClickToZoom: true,
|
1084
|
+
pinchToZoom: true,
|
1085
|
+
flickEnabled: true,
|
1086
|
+
flickMinSpeed: 120,
|
1087
|
+
flickMomentum: 0.25,
|
1088
|
+
pinchRotate: false
|
1089
|
+
},
|
1048
1090
|
zoomPerClick: 2,
|
1049
1091
|
zoomPerScroll: 1.2,
|
1050
1092
|
zoomPerSecond: 1.0,
|
@@ -1096,6 +1138,7 @@ if (typeof define === 'function' && define.amd) {
|
|
1096
1138
|
|
1097
1139
|
// APPEARANCE
|
1098
1140
|
opacity: 1,
|
1141
|
+
preload: false,
|
1099
1142
|
compositeOperation: null,
|
1100
1143
|
placeholderFillStyle: null,
|
1101
1144
|
|
@@ -1390,6 +1433,21 @@ if (typeof define === 'function' && define.amd) {
|
|
1390
1433
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
1391
1434
|
},
|
1392
1435
|
|
1436
|
+
/**
|
1437
|
+
* Compute the modulo of a number but makes sure to always return
|
1438
|
+
* a positive value.
|
1439
|
+
* @param {Number} number the number to computes the modulo of
|
1440
|
+
* @param {Number} modulo the modulo
|
1441
|
+
* @returns {Number} the result of the modulo of number
|
1442
|
+
*/
|
1443
|
+
positiveModulo: function(number, modulo) {
|
1444
|
+
var result = number % modulo;
|
1445
|
+
if (result < 0) {
|
1446
|
+
result += modulo;
|
1447
|
+
}
|
1448
|
+
return result;
|
1449
|
+
},
|
1450
|
+
|
1393
1451
|
/**
|
1394
1452
|
* Determines if a point is within the bounding rectangle of the given element (hit-test).
|
1395
1453
|
* @function
|
@@ -1504,7 +1562,7 @@ if (typeof define === 'function' && define.amd) {
|
|
1504
1562
|
};
|
1505
1563
|
} else {
|
1506
1564
|
// We can't reassign the function yet, as there was no scroll.
|
1507
|
-
return new $.Point(0,0);
|
1565
|
+
return new $.Point(0, 0);
|
1508
1566
|
}
|
1509
1567
|
|
1510
1568
|
return $.getPageScroll();
|
@@ -1672,13 +1730,15 @@ if (typeof define === 'function' && define.amd) {
|
|
1672
1730
|
* @function
|
1673
1731
|
*/
|
1674
1732
|
now: function( ) {
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1733
|
+
if (Date.now) {
|
1734
|
+
$.now = Date.now;
|
1735
|
+
} else {
|
1736
|
+
$.now = function() {
|
1737
|
+
return new Date().getTime();
|
1738
|
+
};
|
1739
|
+
}
|
1680
1740
|
|
1681
|
-
|
1741
|
+
return $.now();
|
1682
1742
|
},
|
1683
1743
|
|
1684
1744
|
|
@@ -1788,7 +1848,7 @@ if (typeof define === 'function' && define.amd) {
|
|
1788
1848
|
addClass: function( element, className ) {
|
1789
1849
|
element = $.getElement( element );
|
1790
1850
|
|
1791
|
-
if (
|
1851
|
+
if (!element.className) {
|
1792
1852
|
element.className = className;
|
1793
1853
|
} else if ( ( ' ' + element.className + ' ' ).
|
1794
1854
|
indexOf( ' ' + className + ' ' ) === -1 ) {
|
@@ -2012,6 +2072,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2012
2072
|
* @returns {String} The value of the url parameter or null if no param matches.
|
2013
2073
|
*/
|
2014
2074
|
getUrlParameter: function( key ) {
|
2075
|
+
// eslint-disable-next-line no-use-before-define
|
2015
2076
|
var value = URLPARAMS[ key ];
|
2016
2077
|
return value ? value : null;
|
2017
2078
|
},
|
@@ -2081,11 +2142,16 @@ if (typeof define === 'function' && define.amd) {
|
|
2081
2142
|
* @param {String} options.url - the url to request
|
2082
2143
|
* @param {Function} options.success - a function to call on a successful response
|
2083
2144
|
* @param {Function} options.error - a function to call on when an error occurs
|
2145
|
+
* @param {Object} options.headers - headers to add to the AJAX request
|
2146
|
+
* @param {String} options.responseType - the response type of the the AJAX request
|
2084
2147
|
* @param {Boolean} [options.withCredentials=false] - whether to set the XHR's withCredentials
|
2085
2148
|
* @throws {Error}
|
2149
|
+
* @returns {XMLHttpRequest}
|
2086
2150
|
*/
|
2087
2151
|
makeAjaxRequest: function( url, onSuccess, onError ) {
|
2088
2152
|
var withCredentials;
|
2153
|
+
var headers;
|
2154
|
+
var responseType;
|
2089
2155
|
|
2090
2156
|
// Note that our preferred API is that you pass in a single object; the named
|
2091
2157
|
// arguments are for legacy support.
|
@@ -2093,6 +2159,8 @@ if (typeof define === 'function' && define.amd) {
|
|
2093
2159
|
onSuccess = url.success;
|
2094
2160
|
onError = url.error;
|
2095
2161
|
withCredentials = url.withCredentials;
|
2162
|
+
headers = url.headers;
|
2163
|
+
responseType = url.responseType || null;
|
2096
2164
|
url = url.url;
|
2097
2165
|
}
|
2098
2166
|
|
@@ -2108,9 +2176,9 @@ if (typeof define === 'function' && define.amd) {
|
|
2108
2176
|
if ( request.readyState == 4 ) {
|
2109
2177
|
request.onreadystatechange = function(){};
|
2110
2178
|
|
2111
|
-
// With protocols other than http/https,
|
2112
|
-
// on Firefox and 0 on other browsers
|
2113
|
-
if ( request.status
|
2179
|
+
// With protocols other than http/https, a successful request status is in
|
2180
|
+
// the 200's on Firefox and 0 on other browsers
|
2181
|
+
if ( (request.status >= 200 && request.status < 300) ||
|
2114
2182
|
( request.status === 0 &&
|
2115
2183
|
protocol !== "http:" &&
|
2116
2184
|
protocol !== "https:" )) {
|
@@ -2125,13 +2193,26 @@ if (typeof define === 'function' && define.amd) {
|
|
2125
2193
|
}
|
2126
2194
|
};
|
2127
2195
|
|
2128
|
-
if (withCredentials) {
|
2129
|
-
request.withCredentials = true;
|
2130
|
-
}
|
2131
|
-
|
2132
2196
|
try {
|
2133
2197
|
request.open( "GET", url, true );
|
2134
|
-
|
2198
|
+
|
2199
|
+
if (responseType) {
|
2200
|
+
request.responseType = responseType;
|
2201
|
+
}
|
2202
|
+
|
2203
|
+
if (headers) {
|
2204
|
+
for (var headerName in headers) {
|
2205
|
+
if (headers.hasOwnProperty(headerName) && headers[headerName]) {
|
2206
|
+
request.setRequestHeader(headerName, headers[headerName]);
|
2207
|
+
}
|
2208
|
+
}
|
2209
|
+
}
|
2210
|
+
|
2211
|
+
if (withCredentials) {
|
2212
|
+
request.withCredentials = true;
|
2213
|
+
}
|
2214
|
+
|
2215
|
+
request.send(null);
|
2135
2216
|
} catch (e) {
|
2136
2217
|
var msg = e.message;
|
2137
2218
|
|
@@ -2168,7 +2249,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2168
2249
|
}
|
2169
2250
|
};
|
2170
2251
|
xdr.onerror = function (e) {
|
2171
|
-
if (
|
2252
|
+
if ($.isFunction(onError)) {
|
2172
2253
|
onError({ // Faking an xhr object
|
2173
2254
|
responseText: xdr.responseText,
|
2174
2255
|
status: 444, // 444 No Response
|
@@ -2191,6 +2272,8 @@ if (typeof define === 'function' && define.amd) {
|
|
2191
2272
|
}
|
2192
2273
|
}
|
2193
2274
|
}
|
2275
|
+
|
2276
|
+
return request;
|
2194
2277
|
},
|
2195
2278
|
|
2196
2279
|
/**
|
@@ -2331,6 +2414,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2331
2414
|
// Should only be used by IE8 in non standards mode
|
2332
2415
|
$.parseJSON = function(string) {
|
2333
2416
|
/*jshint evil:true*/
|
2417
|
+
//eslint-disable-next-line no-eval
|
2334
2418
|
return eval('(' + string + ')');
|
2335
2419
|
};
|
2336
2420
|
}
|
@@ -2346,6 +2430,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2346
2430
|
*/
|
2347
2431
|
imageFormatSupported: function( extension ) {
|
2348
2432
|
extension = extension ? extension : "";
|
2433
|
+
// eslint-disable-next-line no-use-before-define
|
2349
2434
|
return !!FILEFORMATS[ extension.toLowerCase() ];
|
2350
2435
|
}
|
2351
2436
|
|
@@ -2382,8 +2467,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2382
2467
|
(function() {
|
2383
2468
|
//A small auto-executing routine to determine the browser vendor,
|
2384
2469
|
//version and supporting feature sets.
|
2385
|
-
var
|
2386
|
-
ver = navigator.appVersion,
|
2470
|
+
var ver = navigator.appVersion,
|
2387
2471
|
ua = navigator.userAgent,
|
2388
2472
|
regex;
|
2389
2473
|
|
@@ -2405,7 +2489,7 @@ if (typeof define === 'function' && define.amd) {
|
|
2405
2489
|
}
|
2406
2490
|
break;
|
2407
2491
|
case "Netscape":
|
2408
|
-
if(
|
2492
|
+
if (window.addEventListener) {
|
2409
2493
|
if ( ua.indexOf( "Firefox" ) >= 0 ) {
|
2410
2494
|
$.Browser.vendor = $.BROWSERS.FIREFOX;
|
2411
2495
|
$.Browser.version = parseFloat(
|
@@ -2602,6 +2686,23 @@ if (typeof define === 'function' && define.amd) {
|
|
2602
2686
|
|
2603
2687
|
}(OpenSeadragon));
|
2604
2688
|
|
2689
|
+
|
2690
|
+
// Universal Module Definition, supports CommonJS, AMD and simple script tag
|
2691
|
+
(function (root, factory) {
|
2692
|
+
if (typeof define === 'function' && define.amd) {
|
2693
|
+
// expose as amd module
|
2694
|
+
define([], factory);
|
2695
|
+
} else if (typeof module === 'object' && module.exports) {
|
2696
|
+
// expose as commonjs module
|
2697
|
+
module.exports = factory();
|
2698
|
+
} else {
|
2699
|
+
// expose as window.OpenSeadragon
|
2700
|
+
root.OpenSeadragon = factory();
|
2701
|
+
}
|
2702
|
+
}(this, function () {
|
2703
|
+
return OpenSeadragon;
|
2704
|
+
}));
|
2705
|
+
|
2605
2706
|
/*
|
2606
2707
|
* OpenSeadragon - full-screen support functions
|
2607
2708
|
*
|
@@ -3100,6 +3201,7 @@ $.EventSource.prototype = {
|
|
3100
3201
|
* @memberof OpenSeadragon.MouseTracker#
|
3101
3202
|
*/
|
3102
3203
|
this.dblClickDistThreshold = options.dblClickDistThreshold || $.DEFAULT_SETTINGS.dblClickDistThreshold;
|
3204
|
+
/*eslint-disable no-multi-spaces*/
|
3103
3205
|
this.userData = options.userData || null;
|
3104
3206
|
this.stopDelay = options.stopDelay || 50;
|
3105
3207
|
|
@@ -3122,6 +3224,7 @@ $.EventSource.prototype = {
|
|
3122
3224
|
this.keyHandler = options.keyHandler || null;
|
3123
3225
|
this.focusHandler = options.focusHandler || null;
|
3124
3226
|
this.blurHandler = options.blurHandler || null;
|
3227
|
+
/*eslint-enable no-multi-spaces*/
|
3125
3228
|
|
3126
3229
|
//Store private properties in a scope sealed hash map
|
3127
3230
|
var _this = this;
|
@@ -3255,6 +3358,25 @@ $.EventSource.prototype = {
|
|
3255
3358
|
return this;
|
3256
3359
|
},
|
3257
3360
|
|
3361
|
+
/**
|
3362
|
+
* Returns the {@link OpenSeadragon.MouseTracker.GesturePointList|GesturePointList} for all but the given pointer device type.
|
3363
|
+
* @function
|
3364
|
+
* @param {String} type - The pointer device type: "mouse", "touch", "pen", etc.
|
3365
|
+
* @returns {Array.<OpenSeadragon.MouseTracker.GesturePointList>}
|
3366
|
+
*/
|
3367
|
+
getActivePointersListsExceptType: function ( type ) {
|
3368
|
+
var delegate = THIS[ this.hash ];
|
3369
|
+
var listArray = [];
|
3370
|
+
|
3371
|
+
for (var i = 0; i < delegate.activePointersLists.length; ++i) {
|
3372
|
+
if (delegate.activePointersLists[i].type !== type) {
|
3373
|
+
listArray.push(delegate.activePointersLists[i]);
|
3374
|
+
}
|
3375
|
+
}
|
3376
|
+
|
3377
|
+
return listArray;
|
3378
|
+
},
|
3379
|
+
|
3258
3380
|
/**
|
3259
3381
|
* Returns the {@link OpenSeadragon.MouseTracker.GesturePointList|GesturePointList} for the given pointer device type,
|
3260
3382
|
* creating and caching a new {@link OpenSeadragon.MouseTracker.GesturePointList|GesturePointList} if one doesn't already exist for the type.
|
@@ -3800,6 +3922,21 @@ $.EventSource.prototype = {
|
|
3800
3922
|
blurHandler: function () { }
|
3801
3923
|
};
|
3802
3924
|
|
3925
|
+
/**
|
3926
|
+
* Resets all active mousetrakers. (Added to patch issue #697 "Mouse up outside map will cause "canvas-drag" event to stick")
|
3927
|
+
*
|
3928
|
+
* @private
|
3929
|
+
* @member resetAllMouseTrackers
|
3930
|
+
* @memberof OpenSeadragon.MouseTracker
|
3931
|
+
*/
|
3932
|
+
$.MouseTracker.resetAllMouseTrackers = function(){
|
3933
|
+
for(var i = 0; i < MOUSETRACKERS.length; i++){
|
3934
|
+
if (MOUSETRACKERS[i].isTracking()){
|
3935
|
+
MOUSETRACKERS[i].setTracking(false);
|
3936
|
+
MOUSETRACKERS[i].setTracking(true);
|
3937
|
+
}
|
3938
|
+
}
|
3939
|
+
};
|
3803
3940
|
|
3804
3941
|
/**
|
3805
3942
|
* Provides continuous computation of velocity (speed and direction) of active pointers.
|
@@ -4139,6 +4276,30 @@ $.EventSource.prototype = {
|
|
4139
4276
|
}
|
4140
4277
|
}
|
4141
4278
|
return null;
|
4279
|
+
},
|
4280
|
+
|
4281
|
+
/**
|
4282
|
+
* @function Increment this pointer's contact count.
|
4283
|
+
* It will evaluate whether this pointer type is allowed to have multiple contacts.
|
4284
|
+
*/
|
4285
|
+
addContact: function() {
|
4286
|
+
++this.contacts;
|
4287
|
+
|
4288
|
+
if (this.contacts > 1 && (this.type === "mouse" || this.type === "pen")) {
|
4289
|
+
this.contacts = 1;
|
4290
|
+
}
|
4291
|
+
},
|
4292
|
+
|
4293
|
+
/**
|
4294
|
+
* @function Decrement this pointer's contact count.
|
4295
|
+
* It will make sure the count does not go below 0.
|
4296
|
+
*/
|
4297
|
+
removeContact: function() {
|
4298
|
+
--this.contacts;
|
4299
|
+
|
4300
|
+
if (this.contacts < 0) {
|
4301
|
+
this.contacts = 0;
|
4302
|
+
}
|
4142
4303
|
}
|
4143
4304
|
};
|
4144
4305
|
|
@@ -4310,6 +4471,7 @@ $.EventSource.prototype = {
|
|
4310
4471
|
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
4311
4472
|
// We emulate mouse capture by hanging listeners on the document object.
|
4312
4473
|
// (Note we listen on the capture phase so the captured handlers will get called first)
|
4474
|
+
// eslint-disable-next-line no-use-before-define
|
4313
4475
|
if (isInIframe && canAccessEvents(window.top)) {
|
4314
4476
|
$.addEvent(
|
4315
4477
|
window.top,
|
@@ -4353,6 +4515,7 @@ $.EventSource.prototype = {
|
|
4353
4515
|
eventParams = getCaptureEventParams( tracker, $.MouseTracker.havePointerEvents ? 'pointerevent' : pointerType );
|
4354
4516
|
// We emulate mouse capture by hanging listeners on the document object.
|
4355
4517
|
// (Note we listen on the capture phase so the captured handlers will get called first)
|
4518
|
+
// eslint-disable-next-line no-use-before-define
|
4356
4519
|
if (isInIframe && canAccessEvents(window.top)) {
|
4357
4520
|
$.removeEvent(
|
4358
4521
|
window.top,
|
@@ -4643,7 +4806,7 @@ $.EventSource.prototype = {
|
|
4643
4806
|
|
4644
4807
|
// Calculate deltaY
|
4645
4808
|
if ( $.MouseTracker.wheelEventName == "mousewheel" ) {
|
4646
|
-
simulatedEvent.deltaY = -
|
4809
|
+
simulatedEvent.deltaY = -event.wheelDelta / $.DEFAULT_SETTINGS.pixelsPerWheelLine;
|
4647
4810
|
} else {
|
4648
4811
|
simulatedEvent.deltaY = event.detail;
|
4649
4812
|
}
|
@@ -4941,23 +5104,26 @@ $.EventSource.prototype = {
|
|
4941
5104
|
* @private
|
4942
5105
|
* @inner
|
4943
5106
|
*/
|
4944
|
-
function
|
5107
|
+
function abortContacts( tracker, event, pointsList ) {
|
4945
5108
|
var i,
|
4946
5109
|
gPointCount = pointsList.getLength(),
|
4947
5110
|
abortGPoints = [];
|
4948
5111
|
|
4949
|
-
|
4950
|
-
|
4951
|
-
|
5112
|
+
// Check contact count for hoverable pointer types before aborting
|
5113
|
+
if (pointsList.type === 'touch' || pointsList.contacts > 0) {
|
5114
|
+
for ( i = 0; i < gPointCount; i++ ) {
|
5115
|
+
abortGPoints.push( pointsList.getByIndex( i ) );
|
5116
|
+
}
|
4952
5117
|
|
4953
|
-
|
4954
|
-
|
4955
|
-
|
4956
|
-
|
4957
|
-
|
4958
|
-
|
4959
|
-
|
4960
|
-
|
5118
|
+
if ( abortGPoints.length > 0 ) {
|
5119
|
+
// simulate touchend/mouseup
|
5120
|
+
updatePointersUp( tracker, event, abortGPoints, 0 ); // 0 means primary button press/release or touch contact
|
5121
|
+
// release pointer capture
|
5122
|
+
pointsList.captureCount = 1;
|
5123
|
+
releasePointer( tracker, pointsList.type );
|
5124
|
+
// simulate touchleave/mouseout
|
5125
|
+
updatePointersExit( tracker, event, abortGPoints );
|
5126
|
+
}
|
4961
5127
|
}
|
4962
5128
|
}
|
4963
5129
|
|
@@ -4979,7 +5145,7 @@ $.EventSource.prototype = {
|
|
4979
5145
|
|
4980
5146
|
if ( pointsList.getLength() > event.touches.length - touchCount ) {
|
4981
5147
|
$.console.warn('Tracked touch contact count doesn\'t match event.touches.length. Removing all tracked touch pointers.');
|
4982
|
-
|
5148
|
+
abortContacts( tracker, event, pointsList );
|
4983
5149
|
}
|
4984
5150
|
|
4985
5151
|
for ( i = 0; i < touchCount; i++ ) {
|
@@ -5147,12 +5313,9 @@ $.EventSource.prototype = {
|
|
5147
5313
|
* @inner
|
5148
5314
|
*/
|
5149
5315
|
function onTouchCancel( tracker, event ) {
|
5150
|
-
var
|
5151
|
-
|
5152
|
-
|
5153
|
-
pointsList = tracker.getActivePointersListByType( 'touch' );
|
5154
|
-
|
5155
|
-
abortTouchContacts( tracker, event, pointsList );
|
5316
|
+
var pointsList = tracker.getActivePointersListByType('touch');
|
5317
|
+
|
5318
|
+
abortContacts( tracker, event, pointsList );
|
5156
5319
|
}
|
5157
5320
|
|
5158
5321
|
|
@@ -5505,8 +5668,7 @@ $.EventSource.prototype = {
|
|
5505
5668
|
* Gesture points associated with the event.
|
5506
5669
|
*/
|
5507
5670
|
function updatePointersExit( tracker, event, gPoints ) {
|
5508
|
-
var
|
5509
|
-
pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type ),
|
5671
|
+
var pointsList = tracker.getActivePointersListByType(gPoints[0].type),
|
5510
5672
|
i,
|
5511
5673
|
gPointCount = gPoints.length,
|
5512
5674
|
curGPoint,
|
@@ -5630,6 +5792,14 @@ $.EventSource.prototype = {
|
|
5630
5792
|
}
|
5631
5793
|
}
|
5632
5794
|
|
5795
|
+
// Some pointers may steal control from another pointer without firing the appropriate release events
|
5796
|
+
// e.g. Touching a screen while click-dragging with certain mice.
|
5797
|
+
var otherPointsLists = tracker.getActivePointersListsExceptType(gPoints[ 0 ].type);
|
5798
|
+
for (i = 0; i < otherPointsLists.length; i++) {
|
5799
|
+
//If another pointer has contact, simulate the release
|
5800
|
+
abortContacts(tracker, event, otherPointsLists[i]); // No-op if no active pointer
|
5801
|
+
}
|
5802
|
+
|
5633
5803
|
// Only capture and track primary button, pen, and touch contacts
|
5634
5804
|
if ( buttonChanged !== 0 ) {
|
5635
5805
|
// Aux Press
|
@@ -5680,7 +5850,7 @@ $.EventSource.prototype = {
|
|
5680
5850
|
startTrackingPointer( pointsList, curGPoint );
|
5681
5851
|
}
|
5682
5852
|
|
5683
|
-
pointsList.
|
5853
|
+
pointsList.addContact();
|
5684
5854
|
//$.console.log('contacts++ ', pointsList.contacts);
|
5685
5855
|
|
5686
5856
|
if ( tracker.dragHandler || tracker.dragEndHandler || tracker.pinchHandler ) {
|
@@ -5741,7 +5911,6 @@ $.EventSource.prototype = {
|
|
5741
5911
|
var delegate = THIS[ tracker.hash ],
|
5742
5912
|
pointsList = tracker.getActivePointersListByType( gPoints[ 0 ].type ),
|
5743
5913
|
propagate,
|
5744
|
-
insideElementReleased,
|
5745
5914
|
releasePoint,
|
5746
5915
|
releaseTime,
|
5747
5916
|
i,
|
@@ -5806,7 +5975,7 @@ $.EventSource.prototype = {
|
|
5806
5975
|
{
|
5807
5976
|
eventSource: tracker,
|
5808
5977
|
pointerType: gPoints[ 0 ].type,
|
5809
|
-
position: getPointRelativeToAbsolute(
|
5978
|
+
position: getPointRelativeToAbsolute(gPoints[0].currentPos, tracker.element),
|
5810
5979
|
button: buttonChanged,
|
5811
5980
|
buttons: pointsList.buttons,
|
5812
5981
|
isTouchEvent: gPoints[ 0 ].type === 'touch',
|
@@ -5820,6 +5989,11 @@ $.EventSource.prototype = {
|
|
5820
5989
|
}
|
5821
5990
|
}
|
5822
5991
|
|
5992
|
+
// A primary mouse button may have been released while the non-primary button was down
|
5993
|
+
var otherPointsList = tracker.getActivePointersListByType("mouse");
|
5994
|
+
// Stop tracking the mouse; see https://github.com/openseadragon/openseadragon/pull/1223
|
5995
|
+
abortContacts(tracker, event, otherPointsList); // No-op if no active pointer
|
5996
|
+
|
5823
5997
|
return false;
|
5824
5998
|
}
|
5825
5999
|
|
@@ -5848,7 +6022,7 @@ $.EventSource.prototype = {
|
|
5848
6022
|
if ( wasCaptured ) {
|
5849
6023
|
// Pointer was activated in our element but could have been removed in any element since events are captured to our element
|
5850
6024
|
|
5851
|
-
pointsList.
|
6025
|
+
pointsList.removeContact();
|
5852
6026
|
//$.console.log('contacts-- ', pointsList.contacts);
|
5853
6027
|
|
5854
6028
|
if ( tracker.dragHandler || tracker.dragEndHandler || tracker.pinchHandler ) {
|
@@ -6207,7 +6381,7 @@ $.EventSource.prototype = {
|
|
6207
6381
|
} );
|
6208
6382
|
}
|
6209
6383
|
}
|
6210
|
-
|
6384
|
+
|
6211
6385
|
// True if inside an iframe, otherwise false.
|
6212
6386
|
// @member {Boolean} isInIframe
|
6213
6387
|
// @private
|
@@ -6219,7 +6393,7 @@ $.EventSource.prototype = {
|
|
6219
6393
|
return true;
|
6220
6394
|
}
|
6221
6395
|
})();
|
6222
|
-
|
6396
|
+
|
6223
6397
|
// @function
|
6224
6398
|
// @private
|
6225
6399
|
// @inner
|
@@ -6232,7 +6406,7 @@ $.EventSource.prototype = {
|
|
6232
6406
|
}
|
6233
6407
|
}
|
6234
6408
|
|
6235
|
-
}
|
6409
|
+
}(OpenSeadragon));
|
6236
6410
|
|
6237
6411
|
/*
|
6238
6412
|
* OpenSeadragon - Control
|
@@ -6351,10 +6525,10 @@ $.Control = function ( element, options, container ) {
|
|
6351
6525
|
if ( this.anchor == $.ControlAnchor.ABSOLUTE ) {
|
6352
6526
|
this.wrapper = $.makeNeutralElement( "div" );
|
6353
6527
|
this.wrapper.style.position = "absolute";
|
6354
|
-
this.wrapper.style.top = typeof (
|
6355
|
-
this.wrapper.style.left = typeof (
|
6356
|
-
this.wrapper.style.height = typeof (
|
6357
|
-
this.wrapper.style.width = typeof (
|
6528
|
+
this.wrapper.style.top = typeof (options.top) == "number" ? (options.top + 'px') : options.top;
|
6529
|
+
this.wrapper.style.left = typeof (options.left) == "number" ? (options.left + 'px') : options.left;
|
6530
|
+
this.wrapper.style.height = typeof (options.height) == "number" ? (options.height + 'px') : options.height;
|
6531
|
+
this.wrapper.style.width = typeof (options.width) == "number" ? (options.width + 'px') : options.width;
|
6358
6532
|
this.wrapper.style.margin = "0px";
|
6359
6533
|
this.wrapper.style.padding = "0px";
|
6360
6534
|
|
@@ -6483,7 +6657,7 @@ $.Control.prototype = {
|
|
6483
6657
|
i;
|
6484
6658
|
|
6485
6659
|
$.extend( true, this, {
|
6486
|
-
id: 'controldock-'
|
6660
|
+
id: 'controldock-' + $.now() + '-' + Math.floor(Math.random() * 1000000),
|
6487
6661
|
container: $.makeNeutralElement( 'div' ),
|
6488
6662
|
controls: []
|
6489
6663
|
}, options );
|
@@ -6903,6 +7077,12 @@ $.Viewer = function( options ) {
|
|
6903
7077
|
//internal state and dom identifiers
|
6904
7078
|
id: options.id,
|
6905
7079
|
hash: options.hash || nextHash++,
|
7080
|
+
/**
|
7081
|
+
* Index for page to be shown first next time open() is called (only used in sequenceMode).
|
7082
|
+
* @member {Number} initialPage
|
7083
|
+
* @memberof OpenSeadragon.Viewer#
|
7084
|
+
*/
|
7085
|
+
initialPage: 0,
|
6906
7086
|
|
6907
7087
|
//dom nodes
|
6908
7088
|
/**
|
@@ -7028,7 +7208,7 @@ $.Viewer = function( options ) {
|
|
7028
7208
|
$.ControlDock.call( this, options );
|
7029
7209
|
|
7030
7210
|
//Deal with tile sources
|
7031
|
-
if (
|
7211
|
+
if (this.xmlPath) {
|
7032
7212
|
//Deprecated option. Now it is preferred to use the tileSources option
|
7033
7213
|
this.tileSources = [ this.xmlPath ];
|
7034
7214
|
}
|
@@ -7075,7 +7255,7 @@ $.Viewer = function( options ) {
|
|
7075
7255
|
|
7076
7256
|
this.innerTracker = new $.MouseTracker({
|
7077
7257
|
element: this.canvas,
|
7078
|
-
startDisabled: this.mouseNavEnabled
|
7258
|
+
startDisabled: !this.mouseNavEnabled,
|
7079
7259
|
clickTimeThreshold: this.clickTimeThreshold,
|
7080
7260
|
clickDistThreshold: this.clickDistThreshold,
|
7081
7261
|
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
@@ -7098,7 +7278,7 @@ $.Viewer = function( options ) {
|
|
7098
7278
|
|
7099
7279
|
this.outerTracker = new $.MouseTracker({
|
7100
7280
|
element: this.container,
|
7101
|
-
startDisabled: this.mouseNavEnabled
|
7281
|
+
startDisabled: !this.mouseNavEnabled,
|
7102
7282
|
clickTimeThreshold: this.clickTimeThreshold,
|
7103
7283
|
clickDistThreshold: this.clickDistThreshold,
|
7104
7284
|
dblClickTimeThreshold: this.dblClickTimeThreshold,
|
@@ -7177,7 +7357,8 @@ $.Viewer = function( options ) {
|
|
7177
7357
|
|
7178
7358
|
// Create the image loader
|
7179
7359
|
this.imageLoader = new $.ImageLoader({
|
7180
|
-
jobLimit: this.imageLoaderLimit
|
7360
|
+
jobLimit: this.imageLoaderLimit,
|
7361
|
+
timeout: options.timeout
|
7181
7362
|
});
|
7182
7363
|
|
7183
7364
|
// Create the tile cache
|
@@ -7288,11 +7469,13 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7288
7469
|
* except for the index property; images are added in sequence.
|
7289
7470
|
* A TileSource specifier is anything you could pass as the tileSource property
|
7290
7471
|
* of the options parameter for {@link OpenSeadragon.Viewer#addTiledImage}.
|
7472
|
+
* @param {Number} initialPage - If sequenceMode is true, display this page initially
|
7473
|
+
* for the given tileSources. If specified, will overwrite the Viewer's existing initialPage property.
|
7291
7474
|
* @return {OpenSeadragon.Viewer} Chainable.
|
7292
7475
|
* @fires OpenSeadragon.Viewer.event:open
|
7293
7476
|
* @fires OpenSeadragon.Viewer.event:open-failed
|
7294
7477
|
*/
|
7295
|
-
open: function (tileSources) {
|
7478
|
+
open: function (tileSources, initialPage) {
|
7296
7479
|
var _this = this;
|
7297
7480
|
|
7298
7481
|
this.close();
|
@@ -7307,23 +7490,17 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7307
7490
|
this.referenceStrip = null;
|
7308
7491
|
}
|
7309
7492
|
|
7493
|
+
if (typeof initialPage != 'undefined' && !isNaN(initialPage)) {
|
7494
|
+
this.initialPage = initialPage;
|
7495
|
+
}
|
7496
|
+
|
7310
7497
|
this.tileSources = tileSources;
|
7311
7498
|
this._sequenceIndex = Math.max(0, Math.min(this.tileSources.length - 1, this.initialPage));
|
7312
7499
|
if (this.tileSources.length) {
|
7313
7500
|
this.open(this.tileSources[this._sequenceIndex]);
|
7314
7501
|
|
7315
7502
|
if ( this.showReferenceStrip ){
|
7316
|
-
this.
|
7317
|
-
id: this.referenceStripElement,
|
7318
|
-
position: this.referenceStripPosition,
|
7319
|
-
sizeRatio: this.referenceStripSizeRatio,
|
7320
|
-
scroll: this.referenceStripScroll,
|
7321
|
-
height: this.referenceStripHeight,
|
7322
|
-
width: this.referenceStripWidth,
|
7323
|
-
tileSources: this.tileSources,
|
7324
|
-
prefixUrl: this.prefixUrl,
|
7325
|
-
viewer: this
|
7326
|
-
});
|
7503
|
+
this.addReferenceStrip();
|
7327
7504
|
}
|
7328
7505
|
}
|
7329
7506
|
|
@@ -7481,7 +7658,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7481
7658
|
this.navigator.close();
|
7482
7659
|
}
|
7483
7660
|
|
7484
|
-
if(
|
7661
|
+
if (!this.preserveOverlays) {
|
7485
7662
|
this.clearOverlays();
|
7486
7663
|
this.overlaysContainer.innerHTML = "";
|
7487
7664
|
}
|
@@ -7652,6 +7829,22 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7652
7829
|
return this;
|
7653
7830
|
},
|
7654
7831
|
|
7832
|
+
/**
|
7833
|
+
* Turns debugging mode on or off for this viewer.
|
7834
|
+
*
|
7835
|
+
* @function
|
7836
|
+
* @param {Boolean} true to turn debug on, false to turn debug off.
|
7837
|
+
*/
|
7838
|
+
setDebugMode: function(debugMode){
|
7839
|
+
|
7840
|
+
for (var i = 0; i < this.world.getItemCount(); i++) {
|
7841
|
+
this.world.getItemAt(i).debugMode = debugMode;
|
7842
|
+
}
|
7843
|
+
|
7844
|
+
this.debugMode = debugMode;
|
7845
|
+
this.forceRedraw();
|
7846
|
+
},
|
7847
|
+
|
7655
7848
|
/**
|
7656
7849
|
* @function
|
7657
7850
|
* @return {Boolean}
|
@@ -7676,7 +7869,6 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7676
7869
|
bodyStyle = body.style,
|
7677
7870
|
docStyle = document.documentElement.style,
|
7678
7871
|
_this = this,
|
7679
|
-
hash,
|
7680
7872
|
nodes,
|
7681
7873
|
i;
|
7682
7874
|
|
@@ -7838,9 +8030,9 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
7838
8030
|
$.setPageScroll( _this.pageScroll );
|
7839
8031
|
var pageScroll = $.getPageScroll();
|
7840
8032
|
restoreScrollCounter++;
|
7841
|
-
if (
|
7842
|
-
pageScroll.x !== _this.pageScroll.x ||
|
7843
|
-
pageScroll.y !== _this.pageScroll.y
|
8033
|
+
if (restoreScrollCounter < 10 &&
|
8034
|
+
(pageScroll.x !== _this.pageScroll.x ||
|
8035
|
+
pageScroll.y !== _this.pageScroll.y)) {
|
7844
8036
|
$.requestAnimationFrame( restoreScroll );
|
7845
8037
|
}
|
7846
8038
|
};
|
@@ -8034,8 +8226,22 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8034
8226
|
* @param {OpenSeadragon.Rect} [options.clip] - An area, in image pixels, to clip to
|
8035
8227
|
* (portions of the image outside of this area will not be visible). Only works on
|
8036
8228
|
* browsers that support the HTML5 canvas.
|
8037
|
-
* @param {Number} [options.opacity]
|
8229
|
+
* @param {Number} [options.opacity=1] Proportional opacity of the tiled images (1=opaque, 0=hidden)
|
8230
|
+
* @param {Boolean} [options.preload=false] Default switch for loading hidden images (true loads, false blocks)
|
8231
|
+
* @param {Number} [options.degrees=0] Initial rotation of the tiled image around
|
8232
|
+
* its top left corner in degrees.
|
8038
8233
|
* @param {String} [options.compositeOperation] How the image is composited onto other images.
|
8234
|
+
* @param {String} [options.crossOriginPolicy] The crossOriginPolicy for this specific image,
|
8235
|
+
* overriding viewer.crossOriginPolicy.
|
8236
|
+
* @param {Boolean} [options.ajaxWithCredentials] Whether to set withCredentials on tile AJAX
|
8237
|
+
* @param {Boolean} [options.loadTilesWithAjax]
|
8238
|
+
* Whether to load tile data using AJAX requests.
|
8239
|
+
* Defaults to the setting in {@link OpenSeadragon.Options}.
|
8240
|
+
* @param {Object} [options.ajaxHeaders]
|
8241
|
+
* A set of headers to include when making tile AJAX requests.
|
8242
|
+
* Note that these headers will be merged over any headers specified in {@link OpenSeadragon.Options}.
|
8243
|
+
* Specifying a falsy value for a header will clear its existing value set at the Viewer level (if any).
|
8244
|
+
* requests.
|
8039
8245
|
* @param {Function} [options.success] A function that gets called when the image is
|
8040
8246
|
* successfully added. It's passed the event object which contains a single property:
|
8041
8247
|
* "item", the resulting TiledImage.
|
@@ -8068,9 +8274,26 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8068
8274
|
if (options.opacity === undefined) {
|
8069
8275
|
options.opacity = this.opacity;
|
8070
8276
|
}
|
8277
|
+
if (options.preload === undefined) {
|
8278
|
+
options.preload = this.preload;
|
8279
|
+
}
|
8071
8280
|
if (options.compositeOperation === undefined) {
|
8072
8281
|
options.compositeOperation = this.compositeOperation;
|
8073
8282
|
}
|
8283
|
+
if (options.crossOriginPolicy === undefined) {
|
8284
|
+
options.crossOriginPolicy = options.tileSource.crossOriginPolicy !== undefined ? options.tileSource.crossOriginPolicy : this.crossOriginPolicy;
|
8285
|
+
}
|
8286
|
+
if (options.ajaxWithCredentials === undefined) {
|
8287
|
+
options.ajaxWithCredentials = this.ajaxWithCredentials;
|
8288
|
+
}
|
8289
|
+
if (options.loadTilesWithAjax === undefined) {
|
8290
|
+
options.loadTilesWithAjax = this.loadTilesWithAjax;
|
8291
|
+
}
|
8292
|
+
if (options.ajaxHeaders === undefined || options.ajaxHeaders === null) {
|
8293
|
+
options.ajaxHeaders = this.ajaxHeaders;
|
8294
|
+
} else if ($.isPlainObject(options.ajaxHeaders) && $.isPlainObject(this.ajaxHeaders)) {
|
8295
|
+
options.ajaxHeaders = $.extend({}, this.ajaxHeaders, options.ajaxHeaders);
|
8296
|
+
}
|
8074
8297
|
|
8075
8298
|
var myQueueItem = {
|
8076
8299
|
options: options
|
@@ -8133,11 +8356,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8133
8356
|
|
8134
8357
|
this._loadQueue.push(myQueueItem);
|
8135
8358
|
|
8136
|
-
|
8137
|
-
|
8138
|
-
myQueueItem.tileSource = tileSource;
|
8139
|
-
|
8140
|
-
// add everybody at the front of the queue that's ready to go
|
8359
|
+
function processReadyItems() {
|
8141
8360
|
var queueItem, tiledImage, optionsClone;
|
8142
8361
|
while (_this._loadQueue.length) {
|
8143
8362
|
queueItem = _this._loadQueue[0];
|
@@ -8171,6 +8390,8 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8171
8390
|
clip: queueItem.options.clip,
|
8172
8391
|
placeholderFillStyle: queueItem.options.placeholderFillStyle,
|
8173
8392
|
opacity: queueItem.options.opacity,
|
8393
|
+
preload: queueItem.options.preload,
|
8394
|
+
degrees: queueItem.options.degrees,
|
8174
8395
|
compositeOperation: queueItem.options.compositeOperation,
|
8175
8396
|
springStiffness: _this.springStiffness,
|
8176
8397
|
animationTime: _this.animationTime,
|
@@ -8183,7 +8404,10 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8183
8404
|
minPixelRatio: _this.minPixelRatio,
|
8184
8405
|
smoothTileEdgesMinZoom: _this.smoothTileEdgesMinZoom,
|
8185
8406
|
iOSDevice: _this.iOSDevice,
|
8186
|
-
crossOriginPolicy:
|
8407
|
+
crossOriginPolicy: queueItem.options.crossOriginPolicy,
|
8408
|
+
ajaxWithCredentials: queueItem.options.ajaxWithCredentials,
|
8409
|
+
loadTilesWithAjax: queueItem.options.loadTilesWithAjax,
|
8410
|
+
ajaxHeaders: queueItem.options.ajaxHeaders,
|
8187
8411
|
debugMode: _this.debugMode
|
8188
8412
|
});
|
8189
8413
|
|
@@ -8219,9 +8443,20 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8219
8443
|
});
|
8220
8444
|
}
|
8221
8445
|
}
|
8446
|
+
}
|
8447
|
+
|
8448
|
+
getTileSourceImplementation( this, options.tileSource, options, function( tileSource ) {
|
8449
|
+
|
8450
|
+
myQueueItem.tileSource = tileSource;
|
8451
|
+
|
8452
|
+
// add everybody at the front of the queue that's ready to go
|
8453
|
+
processReadyItems();
|
8222
8454
|
}, function( event ) {
|
8223
8455
|
event.options = options;
|
8224
8456
|
raiseAddItemFailed(event);
|
8457
|
+
|
8458
|
+
// add everybody at the front of the queue that's ready to go
|
8459
|
+
processReadyItems();
|
8225
8460
|
} );
|
8226
8461
|
},
|
8227
8462
|
|
@@ -8325,7 +8560,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8325
8560
|
onNextHandler = $.delegate( this, onNext ),
|
8326
8561
|
onPreviousHandler = $.delegate( this, onPrevious ),
|
8327
8562
|
navImages = this.navImages,
|
8328
|
-
useGroup = true
|
8563
|
+
useGroup = true;
|
8329
8564
|
|
8330
8565
|
if( this.showSequenceControl ){
|
8331
8566
|
|
@@ -8421,7 +8656,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8421
8656
|
onBlurHandler = $.delegate( this, onBlur ),
|
8422
8657
|
navImages = this.navImages,
|
8423
8658
|
buttons = [],
|
8424
|
-
useGroup = true
|
8659
|
+
useGroup = true;
|
8425
8660
|
|
8426
8661
|
|
8427
8662
|
if ( this.showNavigationControl ) {
|
@@ -8548,7 +8783,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8548
8783
|
if( this.toolbar ){
|
8549
8784
|
this.toolbar.addControl(
|
8550
8785
|
this.navControl,
|
8551
|
-
{anchor: $.ControlAnchor.TOP_LEFT}
|
8786
|
+
{anchor: this.navigationControlAnchor || $.ControlAnchor.TOP_LEFT}
|
8552
8787
|
);
|
8553
8788
|
} else {
|
8554
8789
|
this.addControl(
|
@@ -8792,7 +9027,7 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8792
9027
|
element = $.getElement( element );
|
8793
9028
|
i = getOverlayIndex( this.currentOverlays, element );
|
8794
9029
|
|
8795
|
-
if (i>=0) {
|
9030
|
+
if (i >= 0) {
|
8796
9031
|
return this.currentOverlays[i];
|
8797
9032
|
} else {
|
8798
9033
|
return null;
|
@@ -8894,6 +9129,52 @@ $.extend( $.Viewer.prototype, $.EventSource.prototype, $.ControlDock.prototype,
|
|
8894
9129
|
*/
|
8895
9130
|
_cancelPendingImages: function() {
|
8896
9131
|
this._loadQueue = [];
|
9132
|
+
},
|
9133
|
+
|
9134
|
+
/**
|
9135
|
+
* Removes the reference strip and disables displaying it.
|
9136
|
+
* @function
|
9137
|
+
*/
|
9138
|
+
removeReferenceStrip: function() {
|
9139
|
+
this.showReferenceStrip = false;
|
9140
|
+
|
9141
|
+
if (this.referenceStrip) {
|
9142
|
+
this.referenceStrip.destroy();
|
9143
|
+
this.referenceStrip = null;
|
9144
|
+
}
|
9145
|
+
},
|
9146
|
+
|
9147
|
+
/**
|
9148
|
+
* Enables and displays the reference strip based on the currently set tileSources.
|
9149
|
+
* Works only when the Viewer has sequenceMode set to true.
|
9150
|
+
* @function
|
9151
|
+
*/
|
9152
|
+
addReferenceStrip: function() {
|
9153
|
+
this.showReferenceStrip = true;
|
9154
|
+
|
9155
|
+
if (this.sequenceMode) {
|
9156
|
+
if (this.referenceStrip) {
|
9157
|
+
return;
|
9158
|
+
}
|
9159
|
+
|
9160
|
+
if (this.tileSources.length && this.tileSources.length > 1) {
|
9161
|
+
this.referenceStrip = new $.ReferenceStrip({
|
9162
|
+
id: this.referenceStripElement,
|
9163
|
+
position: this.referenceStripPosition,
|
9164
|
+
sizeRatio: this.referenceStripSizeRatio,
|
9165
|
+
scroll: this.referenceStripScroll,
|
9166
|
+
height: this.referenceStripHeight,
|
9167
|
+
width: this.referenceStripWidth,
|
9168
|
+
tileSources: this.tileSources,
|
9169
|
+
prefixUrl: this.prefixUrl,
|
9170
|
+
viewer: this
|
9171
|
+
});
|
9172
|
+
|
9173
|
+
this.referenceStrip.setFocus( this._sequenceIndex );
|
9174
|
+
}
|
9175
|
+
} else {
|
9176
|
+
$.console.warn('Attempting to display a reference strip while "sequenceMode" is off.');
|
9177
|
+
}
|
8897
9178
|
}
|
8898
9179
|
});
|
8899
9180
|
|
@@ -8913,20 +9194,28 @@ function _getSafeElemSize (oElement) {
|
|
8913
9194
|
);
|
8914
9195
|
}
|
8915
9196
|
|
9197
|
+
|
8916
9198
|
/**
|
8917
9199
|
* @function
|
8918
9200
|
* @private
|
8919
9201
|
*/
|
8920
|
-
function getTileSourceImplementation( viewer, tileSource, successCallback,
|
9202
|
+
function getTileSourceImplementation( viewer, tileSource, imgOptions, successCallback,
|
8921
9203
|
failCallback ) {
|
8922
9204
|
var _this = viewer;
|
8923
9205
|
|
8924
9206
|
//allow plain xml strings or json strings to be parsed here
|
8925
9207
|
if ( $.type( tileSource ) == 'string' ) {
|
8926
|
-
|
9208
|
+
//xml should start with "<" and end with ">"
|
9209
|
+
if ( tileSource.match( /^\s*<.*>\s*$/ ) ) {
|
8927
9210
|
tileSource = $.parseXml( tileSource );
|
8928
|
-
|
8929
|
-
|
9211
|
+
//json should start with "{" or "[" and end with "}" or "]"
|
9212
|
+
} else if ( tileSource.match(/^\s*[\{\[].*[\}\]]\s*$/ ) ) {
|
9213
|
+
try {
|
9214
|
+
var tileSourceJ = $.parseJSON(tileSource);
|
9215
|
+
tileSource = tileSourceJ;
|
9216
|
+
} catch (e) {
|
9217
|
+
//tileSource = tileSource;
|
9218
|
+
}
|
8930
9219
|
}
|
8931
9220
|
}
|
8932
9221
|
|
@@ -8951,8 +9240,10 @@ function getTileSourceImplementation( viewer, tileSource, successCallback,
|
|
8951
9240
|
//If its still a string it means it must be a url at this point
|
8952
9241
|
tileSource = new $.TileSource({
|
8953
9242
|
url: tileSource,
|
8954
|
-
crossOriginPolicy:
|
9243
|
+
crossOriginPolicy: imgOptions.crossOriginPolicy !== undefined ?
|
9244
|
+
imgOptions.crossOriginPolicy : viewer.crossOriginPolicy,
|
8955
9245
|
ajaxWithCredentials: viewer.ajaxWithCredentials,
|
9246
|
+
ajaxHeaders: viewer.ajaxHeaders,
|
8956
9247
|
useCanvas: viewer.useCanvas,
|
8957
9248
|
success: function( event ) {
|
8958
9249
|
successCallback( event.tileSource );
|
@@ -8963,8 +9254,10 @@ function getTileSourceImplementation( viewer, tileSource, successCallback,
|
|
8963
9254
|
} );
|
8964
9255
|
|
8965
9256
|
} else if ($.isPlainObject(tileSource) || tileSource.nodeType) {
|
8966
|
-
if (
|
8967
|
-
|
9257
|
+
if (tileSource.crossOriginPolicy === undefined &&
|
9258
|
+
(imgOptions.crossOriginPolicy !== undefined || viewer.crossOriginPolicy !== undefined)) {
|
9259
|
+
tileSource.crossOriginPolicy = imgOptions.crossOriginPolicy !== undefined ?
|
9260
|
+
imgOptions.crossOriginPolicy : viewer.crossOriginPolicy;
|
8968
9261
|
}
|
8969
9262
|
if (tileSource.ajaxWithCredentials === undefined) {
|
8970
9263
|
tileSource.ajaxWithCredentials = viewer.ajaxWithCredentials;
|
@@ -9258,16 +9551,15 @@ function onCanvasClick( event ) {
|
|
9258
9551
|
this.canvas.focus();
|
9259
9552
|
}
|
9260
9553
|
|
9261
|
-
|
9262
|
-
|
9263
|
-
|
9264
|
-
|
9265
|
-
|
9266
|
-
|
9267
|
-
|
9268
|
-
|
9269
|
-
|
9270
|
-
}
|
9554
|
+
var canvasClickEventArgs = {
|
9555
|
+
tracker: event.eventSource,
|
9556
|
+
position: event.position,
|
9557
|
+
quick: event.quick,
|
9558
|
+
shift: event.shift,
|
9559
|
+
originalEvent: event.originalEvent,
|
9560
|
+
preventDefaultAction: event.preventDefaultAction
|
9561
|
+
};
|
9562
|
+
|
9271
9563
|
/**
|
9272
9564
|
* Raised when a mouse press/release or touch/remove occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
9273
9565
|
*
|
@@ -9280,15 +9572,21 @@ function onCanvasClick( event ) {
|
|
9280
9572
|
* @property {Boolean} quick - True only if the clickDistThreshold and clickTimeThreshold are both passed. Useful for differentiating between clicks and drags.
|
9281
9573
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
9282
9574
|
* @property {Object} originalEvent - The original DOM event.
|
9575
|
+
* @property {Boolean} preventDefaultAction - Set to true to prevent default click to zoom behaviour. Default: false.
|
9283
9576
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
9284
9577
|
*/
|
9285
|
-
this.raiseEvent( 'canvas-click',
|
9286
|
-
|
9287
|
-
|
9288
|
-
|
9289
|
-
|
9290
|
-
|
9291
|
-
|
9578
|
+
this.raiseEvent( 'canvas-click', canvasClickEventArgs);
|
9579
|
+
|
9580
|
+
if ( !canvasClickEventArgs.preventDefaultAction && this.viewport && event.quick ) {
|
9581
|
+
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
9582
|
+
if ( gestureSettings.clickToZoom ) {
|
9583
|
+
this.viewport.zoomBy(
|
9584
|
+
event.shift ? 1.0 / this.zoomPerClick : this.zoomPerClick,
|
9585
|
+
this.viewport.pointFromPixel( event.position, true )
|
9586
|
+
);
|
9587
|
+
this.viewport.applyConstraints();
|
9588
|
+
}
|
9589
|
+
}
|
9292
9590
|
}
|
9293
9591
|
|
9294
9592
|
function onCanvasDblClick( event ) {
|
@@ -9328,19 +9626,16 @@ function onCanvasDblClick( event ) {
|
|
9328
9626
|
function onCanvasDrag( event ) {
|
9329
9627
|
var gestureSettings;
|
9330
9628
|
|
9331
|
-
|
9332
|
-
|
9333
|
-
|
9334
|
-
|
9335
|
-
|
9336
|
-
|
9337
|
-
|
9338
|
-
|
9339
|
-
|
9340
|
-
|
9341
|
-
this.viewport.applyConstraints();
|
9342
|
-
}
|
9343
|
-
}
|
9629
|
+
var canvasDragEventArgs = {
|
9630
|
+
tracker: event.eventSource,
|
9631
|
+
position: event.position,
|
9632
|
+
delta: event.delta,
|
9633
|
+
speed: event.speed,
|
9634
|
+
direction: event.direction,
|
9635
|
+
shift: event.shift,
|
9636
|
+
originalEvent: event.originalEvent,
|
9637
|
+
preventDefaultAction: event.preventDefaultAction
|
9638
|
+
};
|
9344
9639
|
/**
|
9345
9640
|
* Raised when a mouse or touch drag operation occurs on the {@link OpenSeadragon.Viewer#canvas} element.
|
9346
9641
|
*
|
@@ -9355,17 +9650,43 @@ function onCanvasDrag( event ) {
|
|
9355
9650
|
* @property {Number} direction - Current computed direction, expressed as an angle counterclockwise relative to the positive X axis (-pi to pi, in radians). Only valid if speed > 0.
|
9356
9651
|
* @property {Boolean} shift - True if the shift key was pressed during this event.
|
9357
9652
|
* @property {Object} originalEvent - The original DOM event.
|
9653
|
+
* @property {Boolean} preventDefaultAction - Set to true to prevent default drag behaviour. Default: false.
|
9358
9654
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
9359
9655
|
*/
|
9360
|
-
this.raiseEvent( 'canvas-drag',
|
9361
|
-
|
9362
|
-
|
9363
|
-
|
9364
|
-
|
9365
|
-
|
9366
|
-
|
9367
|
-
|
9368
|
-
|
9656
|
+
this.raiseEvent( 'canvas-drag', canvasDragEventArgs);
|
9657
|
+
|
9658
|
+
if ( !event.preventDefaultAction && this.viewport ) {
|
9659
|
+
gestureSettings = this.gestureSettingsByDeviceType( event.pointerType );
|
9660
|
+
if( !this.panHorizontal ){
|
9661
|
+
event.delta.x = 0;
|
9662
|
+
}
|
9663
|
+
if( !this.panVertical ){
|
9664
|
+
event.delta.y = 0;
|
9665
|
+
}
|
9666
|
+
|
9667
|
+
if( this.constrainDuringPan ){
|
9668
|
+
var delta = this.viewport.deltaPointsFromPixels( event.delta.negate() );
|
9669
|
+
|
9670
|
+
this.viewport.centerSpringX.target.value += delta.x;
|
9671
|
+
this.viewport.centerSpringY.target.value += delta.y;
|
9672
|
+
|
9673
|
+
var bounds = this.viewport.getBounds();
|
9674
|
+
var constrainedBounds = this.viewport.getConstrainedBounds();
|
9675
|
+
|
9676
|
+
this.viewport.centerSpringX.target.value -= delta.x;
|
9677
|
+
this.viewport.centerSpringY.target.value -= delta.y;
|
9678
|
+
|
9679
|
+
if (bounds.x != constrainedBounds.x) {
|
9680
|
+
event.delta.x = 0;
|
9681
|
+
}
|
9682
|
+
|
9683
|
+
if (bounds.y != constrainedBounds.y) {
|
9684
|
+
event.delta.y = 0;
|
9685
|
+
}
|
9686
|
+
}
|
9687
|
+
|
9688
|
+
this.viewport.panBy( this.viewport.deltaPointsFromPixels( event.delta.negate() ), gestureSettings.flickEnabled && !this.constrainDuringPan);
|
9689
|
+
}
|
9369
9690
|
}
|
9370
9691
|
|
9371
9692
|
function onCanvasDragEnd( event ) {
|
@@ -9447,6 +9768,11 @@ function onCanvasEnter( event ) {
|
|
9447
9768
|
}
|
9448
9769
|
|
9449
9770
|
function onCanvasExit( event ) {
|
9771
|
+
|
9772
|
+
if (window.location != window.parent.location){
|
9773
|
+
$.MouseTracker.resetAllMouseTrackers();
|
9774
|
+
}
|
9775
|
+
|
9450
9776
|
/**
|
9451
9777
|
* Raised when a pointer leaves the {@link OpenSeadragon.Viewer#canvas} element.
|
9452
9778
|
*
|
@@ -10195,7 +10521,7 @@ $.Navigator = function( options ){
|
|
10195
10521
|
//At some browser magnification levels the display regions lines up correctly, but at some there appears to
|
10196
10522
|
//be a one pixel gap.
|
10197
10523
|
this.fudge = new $.Point(1, 1);
|
10198
|
-
this.totalBorderWidths = new $.Point(this.borderWidth*2, this.borderWidth*2).minus(this.fudge);
|
10524
|
+
this.totalBorderWidths = new $.Point(this.borderWidth * 2, this.borderWidth * 2).minus(this.fudge);
|
10199
10525
|
|
10200
10526
|
|
10201
10527
|
if ( options.controlOptions.anchor != $.ControlAnchor.NONE ) {
|
@@ -10254,8 +10580,8 @@ $.Navigator = function( options ){
|
|
10254
10580
|
|
10255
10581
|
if ( this._resizeWithViewer ) {
|
10256
10582
|
if ( options.width && options.height ) {
|
10257
|
-
this.element.style.height = typeof (
|
10258
|
-
this.element.style.width = typeof (
|
10583
|
+
this.element.style.height = typeof (options.height) == "number" ? (options.height + 'px') : options.height;
|
10584
|
+
this.element.style.width = typeof (options.width) == "number" ? (options.width + 'px') : options.width;
|
10259
10585
|
} else {
|
10260
10586
|
viewerSize = $.getElementSize( viewer.element );
|
10261
10587
|
this.element.style.height = Math.round( viewerSize.y * options.sizeRatio ) + 'px';
|
@@ -10305,8 +10631,10 @@ $.Navigator = function( options ){
|
|
10305
10631
|
});
|
10306
10632
|
|
10307
10633
|
viewer.world.addHandler("item-index-change", function(event) {
|
10308
|
-
|
10309
|
-
|
10634
|
+
window.setTimeout(function(){
|
10635
|
+
var item = _this.world.getItemAt(event.previousIndex);
|
10636
|
+
_this.world.setItemIndex(item, event.newIndex);
|
10637
|
+
}, 1);
|
10310
10638
|
});
|
10311
10639
|
|
10312
10640
|
viewer.world.addHandler("remove-item", function(event) {
|
@@ -10415,9 +10743,22 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
|
|
10415
10743
|
myItem._originalForNavigator = original;
|
10416
10744
|
_this._matchBounds(myItem, original, true);
|
10417
10745
|
|
10418
|
-
|
10746
|
+
function matchBounds() {
|
10419
10747
|
_this._matchBounds(myItem, original);
|
10420
|
-
}
|
10748
|
+
}
|
10749
|
+
|
10750
|
+
function matchOpacity() {
|
10751
|
+
_this._matchOpacity(myItem, original);
|
10752
|
+
}
|
10753
|
+
|
10754
|
+
function matchCompositeOperation() {
|
10755
|
+
_this._matchCompositeOperation(myItem, original);
|
10756
|
+
}
|
10757
|
+
|
10758
|
+
original.addHandler('bounds-change', matchBounds);
|
10759
|
+
original.addHandler('clip-change', matchBounds);
|
10760
|
+
original.addHandler('opacity-change', matchOpacity);
|
10761
|
+
original.addHandler('composite-operation-change', matchCompositeOperation);
|
10421
10762
|
}
|
10422
10763
|
});
|
10423
10764
|
|
@@ -10440,9 +10781,21 @@ $.extend( $.Navigator.prototype, $.EventSource.prototype, $.Viewer.prototype, /*
|
|
10440
10781
|
|
10441
10782
|
// private
|
10442
10783
|
_matchBounds: function(myItem, theirItem, immediately) {
|
10443
|
-
var bounds = theirItem.
|
10784
|
+
var bounds = theirItem.getBoundsNoRotate();
|
10444
10785
|
myItem.setPosition(bounds.getTopLeft(), immediately);
|
10445
10786
|
myItem.setWidth(bounds.width, immediately);
|
10787
|
+
myItem.setRotation(theirItem.getRotation(), immediately);
|
10788
|
+
myItem.setClip(theirItem.getClip());
|
10789
|
+
},
|
10790
|
+
|
10791
|
+
// private
|
10792
|
+
_matchOpacity: function(myItem, theirItem) {
|
10793
|
+
myItem.setOpacity(theirItem.opacity);
|
10794
|
+
},
|
10795
|
+
|
10796
|
+
// private
|
10797
|
+
_matchCompositeOperation: function(myItem, theirItem) {
|
10798
|
+
myItem.setCompositeOperation(theirItem.compositeOperation);
|
10446
10799
|
}
|
10447
10800
|
});
|
10448
10801
|
|
@@ -10476,6 +10829,9 @@ function onCanvasDrag( event ) {
|
|
10476
10829
|
event.delta
|
10477
10830
|
)
|
10478
10831
|
);
|
10832
|
+
if( this.viewer.constrainDuringPan ){
|
10833
|
+
this.viewer.viewport.applyConstraints();
|
10834
|
+
}
|
10479
10835
|
}
|
10480
10836
|
}
|
10481
10837
|
|
@@ -10618,14 +10974,14 @@ $.extend( $, /** @lends OpenSeadragon */{
|
|
10618
10974
|
container = I18N,
|
10619
10975
|
i;
|
10620
10976
|
|
10621
|
-
for (
|
10977
|
+
for (i = 0; i < props.length - 1; i++) {
|
10622
10978
|
// in case not a subproperty
|
10623
10979
|
container = container[ props[ i ] ] || {};
|
10624
10980
|
}
|
10625
10981
|
string = container[ props[ i ] ];
|
10626
10982
|
|
10627
10983
|
if ( typeof( string ) != "string" ) {
|
10628
|
-
$.console.
|
10984
|
+
$.console.log( "Untranslated source string:", prop );
|
10629
10985
|
string = ""; // FIXME: this breaks gettext()-style convention, which would return source
|
10630
10986
|
}
|
10631
10987
|
|
@@ -10812,6 +11168,18 @@ $.Point.prototype = {
|
|
10812
11168
|
);
|
10813
11169
|
},
|
10814
11170
|
|
11171
|
+
/**
|
11172
|
+
* Compute the squared distance between this point and another point.
|
11173
|
+
* Useful for optimizing things like comparing distances.
|
11174
|
+
* @function
|
11175
|
+
* @param {OpenSeadragon.Point} point The point to compute the squared distance with.
|
11176
|
+
* @returns {Number} The squared distance between the 2 points
|
11177
|
+
*/
|
11178
|
+
squaredDistanceTo: function( point ) {
|
11179
|
+
return Math.pow( this.x - point.x, 2 ) +
|
11180
|
+
Math.pow( this.y - point.y, 2 );
|
11181
|
+
},
|
11182
|
+
|
10815
11183
|
/**
|
10816
11184
|
* Apply a function to each coordinate of this point and return a new point.
|
10817
11185
|
* @function
|
@@ -10854,10 +11222,7 @@ $.Point.prototype = {
|
|
10854
11222
|
var sin;
|
10855
11223
|
// Avoid float computations when possible
|
10856
11224
|
if (degrees % 90 === 0) {
|
10857
|
-
var d = degrees
|
10858
|
-
if (d < 0) {
|
10859
|
-
d += 360;
|
10860
|
-
}
|
11225
|
+
var d = $.positiveModulo(degrees, 360);
|
10861
11226
|
switch (d) {
|
10862
11227
|
case 0:
|
10863
11228
|
cos = 1;
|
@@ -10961,11 +11326,15 @@ $.Point.prototype = {
|
|
10961
11326
|
* the extending classes implementation of 'configure'.
|
10962
11327
|
* @param {String} [options.url]
|
10963
11328
|
* The URL for the data necessary for this TileSource.
|
11329
|
+
* @param {String} [options.referenceStripThumbnailUrl]
|
11330
|
+
* The URL for a thumbnail image to be used by the reference strip
|
10964
11331
|
* @param {Function} [options.success]
|
10965
11332
|
* A function to be called upon successful creation.
|
10966
11333
|
* @param {Boolean} [options.ajaxWithCredentials]
|
10967
11334
|
* If this TileSource needs to make an AJAX call, this specifies whether to set
|
10968
11335
|
* the XHR's withCredentials (for accessing secure data).
|
11336
|
+
* @param {Object} [options.ajaxHeaders]
|
11337
|
+
* A set of headers to include in AJAX requests.
|
10969
11338
|
* @param {Number} [options.width]
|
10970
11339
|
* Width of the source image at max resolution in pixels.
|
10971
11340
|
* @param {Number} [options.height]
|
@@ -11088,8 +11457,8 @@ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLeve
|
|
11088
11457
|
//explicit configuration via positional args in constructor
|
11089
11458
|
//or the more idiomatic 'options' object
|
11090
11459
|
this.ready = true;
|
11091
|
-
this.aspectRatio = (
|
11092
|
-
(
|
11460
|
+
this.aspectRatio = (options.width && options.height) ?
|
11461
|
+
(options.width / options.height) : 1;
|
11093
11462
|
this.dimensions = new $.Point( options.width, options.height );
|
11094
11463
|
|
11095
11464
|
if ( this.tileSize ){
|
@@ -11219,25 +11588,20 @@ $.TileSource.prototype = {
|
|
11219
11588
|
|
11220
11589
|
/**
|
11221
11590
|
* @function
|
11222
|
-
* @
|
11591
|
+
* @returns {Number} The highest level in this tile source that can be contained in a single tile.
|
11223
11592
|
*/
|
11224
|
-
getClosestLevel: function(
|
11593
|
+
getClosestLevel: function() {
|
11225
11594
|
var i,
|
11226
|
-
tilesPerSide,
|
11227
11595
|
tiles;
|
11228
11596
|
|
11229
|
-
for(
|
11230
|
-
tiles = this.getNumTiles(
|
11231
|
-
|
11232
|
-
Math.floor( rect.x / this.getTileWidth(i) ),
|
11233
|
-
Math.floor( rect.y / this.getTileHeight(i) )
|
11234
|
-
);
|
11235
|
-
|
11236
|
-
if( tiles.x + 1 >= tilesPerSide.x && tiles.y + 1 >= tilesPerSide.y ){
|
11597
|
+
for (i = this.minLevel + 1; i <= this.maxLevel; i++){
|
11598
|
+
tiles = this.getNumTiles(i);
|
11599
|
+
if (tiles.x > 1 || tiles.y > 1) {
|
11237
11600
|
break;
|
11238
11601
|
}
|
11239
11602
|
}
|
11240
|
-
|
11603
|
+
|
11604
|
+
return i - 1;
|
11241
11605
|
},
|
11242
11606
|
|
11243
11607
|
/**
|
@@ -11245,12 +11609,28 @@ $.TileSource.prototype = {
|
|
11245
11609
|
* @param {Number} level
|
11246
11610
|
* @param {OpenSeadragon.Point} point
|
11247
11611
|
*/
|
11248
|
-
getTileAtPoint: function(
|
11249
|
-
var
|
11250
|
-
|
11251
|
-
|
11612
|
+
getTileAtPoint: function(level, point) {
|
11613
|
+
var validPoint = point.x >= 0 && point.x <= 1 &&
|
11614
|
+
point.y >= 0 && point.y <= 1 / this.aspectRatio;
|
11615
|
+
$.console.assert(validPoint, "[TileSource.getTileAtPoint] must be called with a valid point.");
|
11616
|
+
|
11617
|
+
var widthScaled = this.dimensions.x * this.getLevelScale(level);
|
11618
|
+
var pixelX = point.x * widthScaled;
|
11619
|
+
var pixelY = point.y * widthScaled;
|
11620
|
+
|
11621
|
+
var x = Math.floor(pixelX / this.getTileWidth(level));
|
11622
|
+
var y = Math.floor(pixelY / this.getTileHeight(level));
|
11623
|
+
|
11624
|
+
// When point.x == 1 or point.y == 1 / this.aspectRatio we want to
|
11625
|
+
// return the last tile of the row/column
|
11626
|
+
if (point.x >= 1) {
|
11627
|
+
x = this.getNumTiles(level).x - 1;
|
11628
|
+
}
|
11629
|
+
if (point.y >= 1 / this.aspectRatio) {
|
11630
|
+
y = this.getNumTiles(level).y - 1;
|
11631
|
+
}
|
11252
11632
|
|
11253
|
-
return new $.Point(
|
11633
|
+
return new $.Point(x, y);
|
11254
11634
|
},
|
11255
11635
|
|
11256
11636
|
/**
|
@@ -11348,7 +11728,7 @@ $.TileSource.prototype = {
|
|
11348
11728
|
//TODO: Its not very flexible to require tile sources to end jsonp
|
11349
11729
|
// request for info with a url that ends with '.js' but for
|
11350
11730
|
// now it's the only way I see to distinguish uniformly.
|
11351
|
-
callbackName = url.split(
|
11731
|
+
callbackName = url.split('/').pop().replace('.js', '');
|
11352
11732
|
$.jsonp({
|
11353
11733
|
url: url,
|
11354
11734
|
async: false,
|
@@ -11360,6 +11740,7 @@ $.TileSource.prototype = {
|
|
11360
11740
|
$.makeAjaxRequest( {
|
11361
11741
|
url: url,
|
11362
11742
|
withCredentials: this.ajaxWithCredentials,
|
11743
|
+
headers: this.ajaxHeaders,
|
11363
11744
|
success: function( xhr ) {
|
11364
11745
|
var data = processResponse( xhr );
|
11365
11746
|
callback( data );
|
@@ -11444,7 +11825,7 @@ $.TileSource.prototype = {
|
|
11444
11825
|
},
|
11445
11826
|
|
11446
11827
|
/**
|
11447
|
-
* Responsible for
|
11828
|
+
* Responsible for retrieving the url which will return an image for the
|
11448
11829
|
* region specified by the given x, y, and level components.
|
11449
11830
|
* This method is not implemented by this class other than to throw an Error
|
11450
11831
|
* announcing you have to implement it. Because of the variety of tile
|
@@ -11460,6 +11841,23 @@ $.TileSource.prototype = {
|
|
11460
11841
|
throw new Error( "Method not implemented." );
|
11461
11842
|
},
|
11462
11843
|
|
11844
|
+
/**
|
11845
|
+
* Responsible for retrieving the headers which will be attached to the image request for the
|
11846
|
+
* region specified by the given x, y, and level components.
|
11847
|
+
* This option is only relevant if {@link OpenSeadragon.Options}.loadTilesWithAjax is set to true.
|
11848
|
+
* The headers returned here will override headers specified at the Viewer or TiledImage level.
|
11849
|
+
* Specifying a falsy value for a header will clear its existing value set at the Viewer or
|
11850
|
+
* TiledImage level (if any).
|
11851
|
+
* @function
|
11852
|
+
* @param {Number} level
|
11853
|
+
* @param {Number} x
|
11854
|
+
* @param {Number} y
|
11855
|
+
* @returns {Object}
|
11856
|
+
*/
|
11857
|
+
getTileAjaxHeaders: function( level, x, y ) {
|
11858
|
+
return {};
|
11859
|
+
},
|
11860
|
+
|
11463
11861
|
/**
|
11464
11862
|
* @function
|
11465
11863
|
* @param {Number} level
|
@@ -11468,12 +11866,12 @@ $.TileSource.prototype = {
|
|
11468
11866
|
*/
|
11469
11867
|
tileExists: function( level, x, y ) {
|
11470
11868
|
var numTiles = this.getNumTiles( level );
|
11471
|
-
return
|
11472
|
-
|
11473
|
-
|
11474
|
-
|
11475
|
-
|
11476
|
-
|
11869
|
+
return level >= this.minLevel &&
|
11870
|
+
level <= this.maxLevel &&
|
11871
|
+
x >= 0 &&
|
11872
|
+
y >= 0 &&
|
11873
|
+
x < numTiles.x &&
|
11874
|
+
y < numTiles.y;
|
11477
11875
|
}
|
11478
11876
|
};
|
11479
11877
|
|
@@ -11514,7 +11912,11 @@ function processResponse( xhr ){
|
|
11514
11912
|
data = xhr.responseText;
|
11515
11913
|
}
|
11516
11914
|
}else if( responseText.match(/\s*[\{\[].*/) ){
|
11517
|
-
|
11915
|
+
try{
|
11916
|
+
data = $.parseJSON(responseText);
|
11917
|
+
} catch(e){
|
11918
|
+
data = responseText;
|
11919
|
+
}
|
11518
11920
|
}else{
|
11519
11921
|
data = responseText;
|
11520
11922
|
}
|
@@ -11665,8 +12067,10 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|
11665
12067
|
}
|
11666
12068
|
}
|
11667
12069
|
|
11668
|
-
|
11669
|
-
|
12070
|
+
ns = (ns || '').toLowerCase();
|
12071
|
+
|
12072
|
+
return (ns.indexOf('schemas.microsoft.com/deepzoom/2008') !== -1 ||
|
12073
|
+
ns.indexOf('schemas.microsoft.com/deepzoom/2009') !== -1);
|
11670
12074
|
},
|
11671
12075
|
|
11672
12076
|
/**
|
@@ -11692,7 +12096,7 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|
11692
12096
|
|
11693
12097
|
if (url && !options.tilesUrl) {
|
11694
12098
|
options.tilesUrl = url.replace(
|
11695
|
-
/([^\/]+?)(\.(dzi|xml|js)
|
12099
|
+
/([^\/]+?)(\.(dzi|xml|js)?(\?[^\/]*)?)?\/?$/, '$1_files/');
|
11696
12100
|
|
11697
12101
|
if (url.search(/\.(dzi|xml|js)\?/) != -1) {
|
11698
12102
|
options.queryParams = url.match(/\?.*/);
|
@@ -11749,10 +12153,10 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|
11749
12153
|
xMax = xMin + rect.width * scale;
|
11750
12154
|
yMax = yMin + rect.height * scale;
|
11751
12155
|
|
11752
|
-
xMin = Math.floor( xMin / this.
|
11753
|
-
yMin = Math.floor( yMin / this.
|
11754
|
-
xMax = Math.ceil( xMax / this.
|
11755
|
-
yMax = Math.ceil( yMax / this.
|
12156
|
+
xMin = Math.floor( xMin / this._tileWidth );
|
12157
|
+
yMin = Math.floor( yMin / this._tileWidth ); // DZI tiles are square, so we just use _tileWidth
|
12158
|
+
xMax = Math.ceil( xMax / this._tileWidth );
|
12159
|
+
yMax = Math.ceil( yMax / this._tileWidth );
|
11756
12160
|
|
11757
12161
|
if ( xMin <= x && x < xMax && yMin <= y && y < yMax ) {
|
11758
12162
|
return true;
|
@@ -11969,6 +12373,7 @@ function configureFromObject( tileSource, configuration ){
|
|
11969
12373
|
*/
|
11970
12374
|
$.IIIFTileSource = function( options ){
|
11971
12375
|
|
12376
|
+
/* eslint-disable camelcase */
|
11972
12377
|
|
11973
12378
|
$.extend( true, this, options );
|
11974
12379
|
|
@@ -12010,7 +12415,7 @@ $.IIIFTileSource = function( options ){
|
|
12010
12415
|
} else if ( canBeTiled(options.profile) ) {
|
12011
12416
|
// use the largest of tileOptions that is smaller than the short dimension
|
12012
12417
|
var shortDim = Math.min( this.height, this.width ),
|
12013
|
-
tileOptions = [256,512,1024],
|
12418
|
+
tileOptions = [256, 512, 1024],
|
12014
12419
|
smallerTiles = [];
|
12015
12420
|
|
12016
12421
|
for ( var c = 0; c < tileOptions.length; c++ ) {
|
@@ -12026,11 +12431,11 @@ $.IIIFTileSource = function( options ){
|
|
12026
12431
|
options.tileSize = shortDim;
|
12027
12432
|
}
|
12028
12433
|
} else if (this.sizes && this.sizes.length > 0) {
|
12029
|
-
// This info.json can't be tiled, but we can still construct a legacy pyramid from the sizes array.
|
12030
|
-
// In this mode, IIIFTileSource will call functions from the abstract baseTileSource or the
|
12031
|
-
// LegacyTileSource instead of performing IIIF tiling.
|
12434
|
+
// This info.json can't be tiled, but we can still construct a legacy pyramid from the sizes array.
|
12435
|
+
// In this mode, IIIFTileSource will call functions from the abstract baseTileSource or the
|
12436
|
+
// LegacyTileSource instead of performing IIIF tiling.
|
12032
12437
|
this.emulateLegacyImagePyramid = true;
|
12033
|
-
|
12438
|
+
|
12034
12439
|
options.levels = constructLevels( this );
|
12035
12440
|
// use the largest available size to define tiles
|
12036
12441
|
$.extend( true, options, {
|
@@ -12065,7 +12470,7 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|
12065
12470
|
* @param {Object|Array} data
|
12066
12471
|
* @param {String} optional - url
|
12067
12472
|
*/
|
12068
|
-
|
12473
|
+
|
12069
12474
|
supports: function( data, url ) {
|
12070
12475
|
// Version 2.0 and forwards
|
12071
12476
|
if (data.protocol && data.protocol == 'http://iiif.io/api/image') {
|
@@ -12317,14 +12722,16 @@ $.extend( $.IIIFTileSource.prototype, $.TileSource.prototype, /** @lends OpenSea
|
|
12317
12722
|
*/
|
12318
12723
|
function constructLevels(options) {
|
12319
12724
|
var levels = [];
|
12320
|
-
for(var i=0; i<options.sizes.length; i++) {
|
12725
|
+
for(var i = 0; i < options.sizes.length; i++) {
|
12321
12726
|
levels.push({
|
12322
12727
|
url: options['@id'] + '/full/' + options.sizes[i].width + ',/0/default.jpg',
|
12323
12728
|
width: options.sizes[i].width,
|
12324
12729
|
height: options.sizes[i].height
|
12325
12730
|
});
|
12326
12731
|
}
|
12327
|
-
return levels.sort(function(a,b){
|
12732
|
+
return levels.sort(function(a, b) {
|
12733
|
+
return a.width - b.width;
|
12734
|
+
});
|
12328
12735
|
}
|
12329
12736
|
|
12330
12737
|
|
@@ -12611,7 +13018,7 @@ $.TmsTileSource = function( width, height, tileSize, tileOverlap, tilesUrl ) {
|
|
12611
13018
|
} else {
|
12612
13019
|
max = bufferedHeight / 256;
|
12613
13020
|
}
|
12614
|
-
options.maxLevel = Math.ceil(Math.log(max)/Math.log(2)) - 1;
|
13021
|
+
options.maxLevel = Math.ceil(Math.log(max) / Math.log(2)) - 1;
|
12615
13022
|
options.tileSize = 256;
|
12616
13023
|
options.width = bufferedWidth;
|
12617
13024
|
options.height = bufferedHeight;
|
@@ -12657,13 +13064,156 @@ $.extend( $.TmsTileSource.prototype, $.TileSource.prototype, /** @lends OpenSead
|
|
12657
13064
|
// Convert from Deep Zoom definition to TMS zoom definition
|
12658
13065
|
var yTiles = this.getNumTiles( level ).y - 1;
|
12659
13066
|
|
12660
|
-
return this.tilesUrl + level + "/" + x + "/" +
|
13067
|
+
return this.tilesUrl + level + "/" + x + "/" + (yTiles - y) + ".png";
|
12661
13068
|
}
|
12662
13069
|
});
|
12663
13070
|
|
12664
13071
|
|
12665
13072
|
}( OpenSeadragon ));
|
12666
13073
|
|
13074
|
+
(function($) {
|
13075
|
+
|
13076
|
+
/**
|
13077
|
+
* @class ZoomifyTileSource
|
13078
|
+
* @classdesc A tilesource implementation for the zoomify format.
|
13079
|
+
*
|
13080
|
+
* A description of the format can be found here:
|
13081
|
+
* https://ecommons.cornell.edu/bitstream/handle/1813/5410/Introducing_Zoomify_Image.pdf
|
13082
|
+
*
|
13083
|
+
* There are two ways of creating a zoomify tilesource for openseadragon
|
13084
|
+
*
|
13085
|
+
* 1) Supplying all necessary information in the tilesource object. A minimal example object for this method looks like this:
|
13086
|
+
*
|
13087
|
+
* {
|
13088
|
+
* type: "zoomifytileservice",
|
13089
|
+
* width: 1000,
|
13090
|
+
* height: 1000,
|
13091
|
+
* tilesUrl: "/test/data/zoomify/"
|
13092
|
+
* }
|
13093
|
+
*
|
13094
|
+
* The tileSize is currently hardcoded to 256 (the usual Zoomify default). The tileUrl must the path to the image _directory_.
|
13095
|
+
*
|
13096
|
+
* 2) Loading image metadata from xml file: (CURRENTLY NOT SUPPORTED)
|
13097
|
+
*
|
13098
|
+
* When creating zoomify formatted images one "xml" like file with name ImageProperties.xml
|
13099
|
+
* will be created as well. Here is an example of such a file:
|
13100
|
+
*
|
13101
|
+
* <IMAGE_PROPERTIES WIDTH="1000" HEIGHT="1000" NUMTILES="21" NUMIMAGES="1" VERSION="1.8" TILESIZE="256" />
|
13102
|
+
*
|
13103
|
+
* To use this xml file as metadata source you must supply the path to the ImageProperties.xml file and leave out all other parameters:
|
13104
|
+
* As stated above, this method of loading a zoomify tilesource is currently not supported
|
13105
|
+
*
|
13106
|
+
* {
|
13107
|
+
* type: "zoomifytileservice",
|
13108
|
+
* tilesUrl: "/test/data/zoomify/ImageProperties.xml"
|
13109
|
+
* }
|
13110
|
+
|
13111
|
+
*
|
13112
|
+
* @memberof OpenSeadragon
|
13113
|
+
* @extends OpenSeadragon.TileSource
|
13114
|
+
* @param {Number} width - the pixel width of the image.
|
13115
|
+
* @param {Number} height
|
13116
|
+
* @param {Number} tileSize
|
13117
|
+
* @param {String} tilesUrl
|
13118
|
+
*/
|
13119
|
+
$.ZoomifyTileSource = function(options) {
|
13120
|
+
options.tileSize = 256;
|
13121
|
+
|
13122
|
+
var currentImageSize = {
|
13123
|
+
x: options.width,
|
13124
|
+
y: options.height
|
13125
|
+
};
|
13126
|
+
options.imageSizes = [{
|
13127
|
+
x: options.width,
|
13128
|
+
y: options.height
|
13129
|
+
}];
|
13130
|
+
options.gridSize = [this._getGridSize(options.width, options.height, options.tileSize)];
|
13131
|
+
|
13132
|
+
while (parseInt(currentImageSize.x, 10) > options.tileSize || parseInt(currentImageSize.y, 10) > options.tileSize) {
|
13133
|
+
currentImageSize.x = Math.floor(currentImageSize.x / 2);
|
13134
|
+
currentImageSize.y = Math.floor(currentImageSize.y / 2);
|
13135
|
+
options.imageSizes.push({
|
13136
|
+
x: currentImageSize.x,
|
13137
|
+
y: currentImageSize.y
|
13138
|
+
});
|
13139
|
+
options.gridSize.push(this._getGridSize(currentImageSize.x, currentImageSize.y, options.tileSize));
|
13140
|
+
}
|
13141
|
+
options.imageSizes.reverse();
|
13142
|
+
options.gridSize.reverse();
|
13143
|
+
options.minLevel = 0;
|
13144
|
+
options.maxLevel = options.gridSize.length - 1;
|
13145
|
+
|
13146
|
+
OpenSeadragon.TileSource.apply(this, [options]);
|
13147
|
+
};
|
13148
|
+
|
13149
|
+
$.extend($.ZoomifyTileSource.prototype, $.TileSource.prototype, /** @lends OpenSeadragon.ZoomifyTileSource.prototype */ {
|
13150
|
+
|
13151
|
+
//private
|
13152
|
+
_getGridSize: function(width, height, tileSize) {
|
13153
|
+
return {
|
13154
|
+
x: Math.ceil(width / tileSize),
|
13155
|
+
y: Math.ceil(height / tileSize)
|
13156
|
+
};
|
13157
|
+
},
|
13158
|
+
|
13159
|
+
//private
|
13160
|
+
_calculateAbsoluteTileNumber: function(level, x, y) {
|
13161
|
+
var num = 0;
|
13162
|
+
var size = {};
|
13163
|
+
|
13164
|
+
//Sum up all tiles below the level we want the number of tiles
|
13165
|
+
for (var z = 0; z < level; z++) {
|
13166
|
+
size = this.gridSize[z];
|
13167
|
+
num += size.x * size.y;
|
13168
|
+
}
|
13169
|
+
//Add the tiles of the level
|
13170
|
+
size = this.gridSize[level];
|
13171
|
+
num += size.x * y + x;
|
13172
|
+
return num;
|
13173
|
+
},
|
13174
|
+
|
13175
|
+
/**
|
13176
|
+
* Determine if the data and/or url imply the image service is supported by
|
13177
|
+
* this tile source.
|
13178
|
+
* @function
|
13179
|
+
* @param {Object|Array} data
|
13180
|
+
* @param {String} optional - url
|
13181
|
+
*/
|
13182
|
+
supports: function(data, url) {
|
13183
|
+
return (data.type && "zoomifytileservice" == data.type);
|
13184
|
+
},
|
13185
|
+
|
13186
|
+
/**
|
13187
|
+
*
|
13188
|
+
* @function
|
13189
|
+
* @param {Object} data - the raw configuration
|
13190
|
+
* @param {String} url - the url the data was retreived from if any.
|
13191
|
+
* @return {Object} options - A dictionary of keyword arguments sufficient
|
13192
|
+
* to configure this tile sources constructor.
|
13193
|
+
*/
|
13194
|
+
configure: function(data, url) {
|
13195
|
+
return data;
|
13196
|
+
},
|
13197
|
+
|
13198
|
+
/**
|
13199
|
+
* @function
|
13200
|
+
* @param {Number} level
|
13201
|
+
* @param {Number} x
|
13202
|
+
* @param {Number} y
|
13203
|
+
*/
|
13204
|
+
getTileUrl: function(level, x, y) {
|
13205
|
+
//console.log(level);
|
13206
|
+
var result = 0;
|
13207
|
+
var num = this._calculateAbsoluteTileNumber(level, x, y);
|
13208
|
+
result = Math.floor(num / 256);
|
13209
|
+
return this.tilesUrl + 'TileGroup' + result + '/' + level + '-' + x + '-' + y + '.jpg';
|
13210
|
+
|
13211
|
+
}
|
13212
|
+
});
|
13213
|
+
|
13214
|
+
}(OpenSeadragon));
|
13215
|
+
|
13216
|
+
|
12667
13217
|
/*
|
12668
13218
|
* OpenSeadragon - LegacyTileSource
|
12669
13219
|
*
|
@@ -12835,16 +13385,6 @@ $.extend( $.LegacyTileSource.prototype, $.TileSource.prototype, /** @lends OpenS
|
|
12835
13385
|
}
|
12836
13386
|
},
|
12837
13387
|
|
12838
|
-
/**
|
12839
|
-
* @function
|
12840
|
-
* @param {Number} level
|
12841
|
-
* @param {OpenSeadragon.Point} point
|
12842
|
-
*/
|
12843
|
-
getTileAtPoint: function( level, point ) {
|
12844
|
-
return new $.Point( 0, 0 );
|
12845
|
-
},
|
12846
|
-
|
12847
|
-
|
12848
13388
|
/**
|
12849
13389
|
* This method is not implemented by this class other than to throw an Error
|
12850
13390
|
* announcing you have to implement it. Because of the variety of tile
|
@@ -12880,12 +13420,7 @@ function filterFiles( files ){
|
|
12880
13420
|
file = files[ i ];
|
12881
13421
|
if( file.height &&
|
12882
13422
|
file.width &&
|
12883
|
-
file.url
|
12884
|
-
file.url.toLowerCase().match(/^.*\.(png|jpg|jpeg|gif)(?:\?.*)?$/) || (
|
12885
|
-
file.mimetype &&
|
12886
|
-
file.mimetype.toLowerCase().match(/^.*\/(png|jpg|jpeg|gif)$/)
|
12887
|
-
)
|
12888
|
-
) ){
|
13423
|
+
file.url ){
|
12889
13424
|
//This is sufficient to serve as a level
|
12890
13425
|
filtered.push({
|
12891
13426
|
url: file.url,
|
@@ -12898,7 +13433,7 @@ function filterFiles( files ){
|
|
12898
13433
|
}
|
12899
13434
|
}
|
12900
13435
|
|
12901
|
-
return filtered.sort(function(a,b){
|
13436
|
+
return filtered.sort(function(a, b) {
|
12902
13437
|
return a.height - b.height;
|
12903
13438
|
});
|
12904
13439
|
|
@@ -12934,7 +13469,7 @@ function configureFromXML( tileSource, xmlDoc ){
|
|
12934
13469
|
for ( i = 0; i < levels.length; i++ ) {
|
12935
13470
|
level = levels[ i ];
|
12936
13471
|
|
12937
|
-
conf.levels
|
13472
|
+
conf.levels.push({
|
12938
13473
|
url: level.getAttribute( "url" ),
|
12939
13474
|
width: parseInt( level.getAttribute( "width" ), 10 ),
|
12940
13475
|
height: parseInt( level.getAttribute( "height" ), 10 )
|
@@ -13086,8 +13621,9 @@ function configureFromObject( tileSource, configuration ){
|
|
13086
13621
|
}
|
13087
13622
|
|
13088
13623
|
$.addEvent(image, 'load', function () {
|
13089
|
-
|
13090
|
-
_this.
|
13624
|
+
/* IE8 fix since it has no naturalWidth and naturalHeight */
|
13625
|
+
_this.width = Object.prototype.hasOwnProperty.call(image, 'naturalWidth') ? image.naturalWidth : image.width;
|
13626
|
+
_this.height = Object.prototype.hasOwnProperty.call(image, 'naturalHeight') ? image.naturalHeight : image.height;
|
13091
13627
|
_this.aspectRatio = _this.width / _this.height;
|
13092
13628
|
_this.dimensions = new $.Point(_this.width, _this.height);
|
13093
13629
|
_this._tileWidth = _this.width;
|
@@ -13138,14 +13674,6 @@ function configureFromObject( tileSource, configuration ){
|
|
13138
13674
|
return new $.Point(0, 0);
|
13139
13675
|
}
|
13140
13676
|
},
|
13141
|
-
/**
|
13142
|
-
* @function
|
13143
|
-
* @param {Number} level
|
13144
|
-
* @param {OpenSeadragon.Point} point
|
13145
|
-
*/
|
13146
|
-
getTileAtPoint: function (level, point) {
|
13147
|
-
return new $.Point(0, 0);
|
13148
|
-
},
|
13149
13677
|
/**
|
13150
13678
|
* Retrieves a tile url
|
13151
13679
|
* @function
|
@@ -13182,8 +13710,9 @@ function configureFromObject( tileSource, configuration ){
|
|
13182
13710
|
_buildLevels: function () {
|
13183
13711
|
var levels = [{
|
13184
13712
|
url: this._image.src,
|
13185
|
-
|
13186
|
-
|
13713
|
+
/* IE8 fix since it has no naturalWidth and naturalHeight */
|
13714
|
+
width: Object.prototype.hasOwnProperty.call(this._image, 'naturalWidth') ? this._image.naturalWidth : this._image.width,
|
13715
|
+
height: Object.prototype.hasOwnProperty.call(this._image, 'naturalHeight') ? this._image.naturalHeight : this._image.height
|
13187
13716
|
}];
|
13188
13717
|
|
13189
13718
|
if (!this.buildPyramid || !$.supportsCanvas || !this.useCanvas) {
|
@@ -13192,8 +13721,10 @@ function configureFromObject( tileSource, configuration ){
|
|
13192
13721
|
return levels;
|
13193
13722
|
}
|
13194
13723
|
|
13195
|
-
|
13196
|
-
var
|
13724
|
+
/* IE8 fix since it has no naturalWidth and naturalHeight */
|
13725
|
+
var currentWidth = Object.prototype.hasOwnProperty.call(this._image, 'naturalWidth') ? this._image.naturalWidth : this._image.width;
|
13726
|
+
var currentHeight = Object.prototype.hasOwnProperty.call(this._image, 'naturalHeight') ? this._image.naturalHeight : this._image.height;
|
13727
|
+
|
13197
13728
|
|
13198
13729
|
var bigCanvas = document.createElement("canvas");
|
13199
13730
|
var bigContext = bigCanvas.getContext("2d");
|
@@ -13273,14 +13804,14 @@ function configureFromObject( tileSource, configuration ){
|
|
13273
13804
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
13274
13805
|
*/
|
13275
13806
|
|
13276
|
-
(function(
|
13807
|
+
(function($) {
|
13277
13808
|
|
13278
13809
|
// deprecated
|
13279
|
-
$.TileSourceCollection = function(
|
13810
|
+
$.TileSourceCollection = function(tileSize, tileSources, rows, layout) {
|
13280
13811
|
$.console.error('TileSourceCollection is deprecated; use World instead');
|
13281
13812
|
};
|
13282
13813
|
|
13283
|
-
}(
|
13814
|
+
}(OpenSeadragon));
|
13284
13815
|
|
13285
13816
|
/*
|
13286
13817
|
* OpenSeadragon - Button
|
@@ -13345,7 +13876,7 @@ $.ButtonState = {
|
|
13345
13876
|
* @memberof OpenSeadragon
|
13346
13877
|
* @extends OpenSeadragon.EventSource
|
13347
13878
|
* @param {Object} options
|
13348
|
-
* @param {Element} [options.element=null] Element to use as the button. If not specified, an HTML <
|
13879
|
+
* @param {Element} [options.element=null] Element to use as the button. If not specified, an HTML <div> element is created.
|
13349
13880
|
* @param {String} [options.tooltip=null] Provides context help for the button when the
|
13350
13881
|
* user hovers over it.
|
13351
13882
|
* @param {String} [options.srcRest=null] URL of image to use in 'rest' state.
|
@@ -13404,7 +13935,7 @@ $.Button = function( options ) {
|
|
13404
13935
|
* @member {Element} element
|
13405
13936
|
* @memberof OpenSeadragon.Button#
|
13406
13937
|
*/
|
13407
|
-
this.element
|
13938
|
+
this.element = options.element || $.makeNeutralElement("div");
|
13408
13939
|
|
13409
13940
|
//if the user has specified the element to bind the control to explicitly
|
13410
13941
|
//then do not add the default control images
|
@@ -13442,7 +13973,7 @@ $.Button = function( options ) {
|
|
13442
13973
|
this.imgDown.style.visibility =
|
13443
13974
|
"hidden";
|
13444
13975
|
|
13445
|
-
if (
|
13976
|
+
if ($.Browser.vendor == $.BROWSERS.FIREFOX && $.Browser.version < 3) {
|
13446
13977
|
this.imgGroup.style.top =
|
13447
13978
|
this.imgHover.style.top =
|
13448
13979
|
this.imgDown.style.top =
|
@@ -13456,13 +13987,13 @@ $.Button = function( options ) {
|
|
13456
13987
|
}
|
13457
13988
|
|
13458
13989
|
|
13459
|
-
this.addHandler(
|
13460
|
-
this.addHandler(
|
13461
|
-
this.addHandler(
|
13462
|
-
this.addHandler(
|
13463
|
-
this.addHandler(
|
13464
|
-
this.addHandler(
|
13465
|
-
this.addHandler(
|
13990
|
+
this.addHandler("press", this.onPress);
|
13991
|
+
this.addHandler("release", this.onRelease);
|
13992
|
+
this.addHandler("click", this.onClick);
|
13993
|
+
this.addHandler("enter", this.onEnter);
|
13994
|
+
this.addHandler("exit", this.onExit);
|
13995
|
+
this.addHandler("focus", this.onFocus);
|
13996
|
+
this.addHandler("blur", this.onBlur);
|
13466
13997
|
|
13467
13998
|
/**
|
13468
13999
|
* The button's current state.
|
@@ -14011,10 +14542,7 @@ $.Rect = function(x, y, width, height, degrees) {
|
|
14011
14542
|
this.degrees = typeof(degrees) === "number" ? degrees : 0;
|
14012
14543
|
|
14013
14544
|
// Normalizes the rectangle.
|
14014
|
-
this.degrees = this.degrees
|
14015
|
-
if (this.degrees < 0) {
|
14016
|
-
this.degrees += 360;
|
14017
|
-
}
|
14545
|
+
this.degrees = $.positiveModulo(this.degrees, 360);
|
14018
14546
|
var newTopLeft, newWidth;
|
14019
14547
|
if (this.degrees >= 270) {
|
14020
14548
|
newTopLeft = this.getTopRight();
|
@@ -14372,19 +14900,21 @@ $.Rect.prototype = {
|
|
14372
14900
|
* @return {OpenSeadragon.Rect}
|
14373
14901
|
*/
|
14374
14902
|
rotate: function(degrees, pivot) {
|
14375
|
-
degrees = degrees
|
14903
|
+
degrees = $.positiveModulo(degrees, 360);
|
14376
14904
|
if (degrees === 0) {
|
14377
14905
|
return this.clone();
|
14378
14906
|
}
|
14379
|
-
if (degrees < 0) {
|
14380
|
-
degrees += 360;
|
14381
|
-
}
|
14382
14907
|
|
14383
14908
|
pivot = pivot || this.getCenter();
|
14384
14909
|
var newTopLeft = this.getTopLeft().rotate(degrees, pivot);
|
14385
14910
|
var newTopRight = this.getTopRight().rotate(degrees, pivot);
|
14386
14911
|
|
14387
14912
|
var diff = newTopRight.minus(newTopLeft);
|
14913
|
+
// Handle floating point error
|
14914
|
+
diff = diff.apply(function(x) {
|
14915
|
+
var EPSILON = 1e-15;
|
14916
|
+
return Math.abs(x) < EPSILON ? 0 : x;
|
14917
|
+
});
|
14388
14918
|
var radians = Math.atan(diff.y / diff.x);
|
14389
14919
|
if (diff.x < 0) {
|
14390
14920
|
radians += Math.PI;
|
@@ -14668,6 +15198,7 @@ $.ReferenceStrip = function ( options ) {
|
|
14668
15198
|
this.panelWidth = ( viewerSize.x * this.sizeRatio ) + 8;
|
14669
15199
|
this.panelHeight = ( viewerSize.y * this.sizeRatio ) + 8;
|
14670
15200
|
this.panels = [];
|
15201
|
+
this.miniViewers = {};
|
14671
15202
|
|
14672
15203
|
/*jshint loopfunc:true*/
|
14673
15204
|
for ( i = 0; i < viewer.tileSources.length; i++ ) {
|
@@ -14783,6 +15314,12 @@ $.extend( $.ReferenceStrip.prototype, $.EventSource.prototype, $.Viewer.prototyp
|
|
14783
15314
|
|
14784
15315
|
// Overrides Viewer.destroy
|
14785
15316
|
destroy: function() {
|
15317
|
+
if (this.miniViewers) {
|
15318
|
+
for (var key in this.miniViewers) {
|
15319
|
+
this.miniViewers[key].destroy();
|
15320
|
+
}
|
15321
|
+
}
|
15322
|
+
|
14786
15323
|
if (this.element) {
|
14787
15324
|
this.element.parentNode.removeChild(this.element);
|
14788
15325
|
}
|
@@ -14911,9 +15448,19 @@ function loadPanels( strip, viewerSize, scroll ) {
|
|
14911
15448
|
for ( i = activePanelsStart; i < activePanelsEnd && i < strip.panels.length; i++ ) {
|
14912
15449
|
element = strip.panels[i];
|
14913
15450
|
if ( !element.activePanel ) {
|
15451
|
+
var miniTileSource;
|
15452
|
+
var originalTileSource = strip.viewer.tileSources[i];
|
15453
|
+
if (originalTileSource.referenceStripThumbnailUrl) {
|
15454
|
+
miniTileSource = {
|
15455
|
+
type: 'image',
|
15456
|
+
url: originalTileSource.referenceStripThumbnailUrl
|
15457
|
+
};
|
15458
|
+
} else {
|
15459
|
+
miniTileSource = originalTileSource;
|
15460
|
+
}
|
14914
15461
|
miniViewer = new $.Viewer( {
|
14915
15462
|
id: element.id,
|
14916
|
-
tileSources: [
|
15463
|
+
tileSources: [miniTileSource],
|
14917
15464
|
element: element,
|
14918
15465
|
navigatorSizeRatio: strip.sizeRatio,
|
14919
15466
|
showNavigator: false,
|
@@ -14953,6 +15500,8 @@ function loadPanels( strip, viewerSize, scroll ) {
|
|
14953
15500
|
miniViewer.displayRegion
|
14954
15501
|
);
|
14955
15502
|
|
15503
|
+
strip.miniViewers[element.id] = miniViewer;
|
15504
|
+
|
14956
15505
|
element.activePanel = true;
|
14957
15506
|
}
|
14958
15507
|
}
|
@@ -15082,9 +15631,7 @@ function onKeyPress( event ) {
|
|
15082
15631
|
}
|
15083
15632
|
}
|
15084
15633
|
|
15085
|
-
|
15086
|
-
|
15087
|
-
} ( OpenSeadragon ) );
|
15634
|
+
}(OpenSeadragon));
|
15088
15635
|
|
15089
15636
|
/*
|
15090
15637
|
* OpenSeadragon - DisplayRect
|
@@ -15366,6 +15913,7 @@ $.Spring.prototype = {
|
|
15366
15913
|
|
15367
15914
|
/**
|
15368
15915
|
* @function
|
15916
|
+
* @returns true if the value got updated, false otherwise
|
15369
15917
|
*/
|
15370
15918
|
update: function() {
|
15371
15919
|
this.current.time = $.now();
|
@@ -15386,14 +15934,17 @@ $.Spring.prototype = {
|
|
15386
15934
|
transform(
|
15387
15935
|
this.springStiffness,
|
15388
15936
|
( this.current.time - this.start.time ) /
|
15389
|
-
( this.target.time
|
15937
|
+
( this.target.time - this.start.time )
|
15390
15938
|
);
|
15391
15939
|
|
15940
|
+
var oldValue = this.current.value;
|
15392
15941
|
if (this._exponential) {
|
15393
15942
|
this.current.value = Math.exp(currentValue);
|
15394
15943
|
} else {
|
15395
15944
|
this.current.value = currentValue;
|
15396
15945
|
}
|
15946
|
+
|
15947
|
+
return oldValue != this.current.value;
|
15397
15948
|
},
|
15398
15949
|
|
15399
15950
|
/**
|
@@ -15450,15 +16001,27 @@ function transform( stiffness, x ) {
|
|
15450
16001
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
15451
16002
|
*/
|
15452
16003
|
|
15453
|
-
(function(
|
16004
|
+
(function($){
|
15454
16005
|
|
15455
|
-
|
15456
|
-
|
16006
|
+
/**
|
16007
|
+
* @private
|
16008
|
+
* @class ImageJob
|
16009
|
+
* @classdesc Handles downloading of a single image.
|
16010
|
+
* @param {Object} options - Options for this ImageJob.
|
16011
|
+
* @param {String} [options.src] - URL of image to download.
|
16012
|
+
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
16013
|
+
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
16014
|
+
* @param {String} [options.crossOriginPolicy] - CORS policy to use for downloads
|
16015
|
+
* @param {Function} [options.callback] - Called once image has been downloaded.
|
16016
|
+
* @param {Function} [options.abort] - Called when this image job is aborted.
|
16017
|
+
* @param {Number} [options.timeout] - The max number of milliseconds that this image job may take to complete.
|
16018
|
+
*/
|
16019
|
+
function ImageJob (options) {
|
15457
16020
|
|
15458
|
-
$.extend(
|
15459
|
-
timeout:
|
15460
|
-
jobId:
|
15461
|
-
}, options
|
16021
|
+
$.extend(true, this, {
|
16022
|
+
timeout: $.DEFAULT_SETTINGS.timeout,
|
16023
|
+
jobId: null
|
16024
|
+
}, options);
|
15462
16025
|
|
15463
16026
|
/**
|
15464
16027
|
* Image object which will contain downloaded image.
|
@@ -15470,42 +16033,103 @@ function ImageJob ( options ) {
|
|
15470
16033
|
|
15471
16034
|
ImageJob.prototype = {
|
15472
16035
|
errorMsg: null,
|
16036
|
+
|
16037
|
+
/**
|
16038
|
+
* Starts the image job.
|
16039
|
+
* @method
|
16040
|
+
*/
|
15473
16041
|
start: function(){
|
15474
|
-
var
|
16042
|
+
var self = this;
|
16043
|
+
var selfAbort = this.abort;
|
15475
16044
|
|
15476
16045
|
this.image = new Image();
|
15477
16046
|
|
15478
|
-
if ( this.crossOriginPolicy !== false ) {
|
15479
|
-
this.image.crossOrigin = this.crossOriginPolicy;
|
15480
|
-
}
|
15481
|
-
|
15482
16047
|
this.image.onload = function(){
|
15483
|
-
|
16048
|
+
self.finish(true);
|
15484
16049
|
};
|
15485
|
-
this.image.onabort = this.image.onerror = function(){
|
15486
|
-
|
15487
|
-
|
16050
|
+
this.image.onabort = this.image.onerror = function() {
|
16051
|
+
self.errorMsg = "Image load aborted";
|
16052
|
+
self.finish(false);
|
15488
16053
|
};
|
15489
16054
|
|
15490
|
-
this.jobId = window.setTimeout(
|
15491
|
-
|
15492
|
-
|
16055
|
+
this.jobId = window.setTimeout(function(){
|
16056
|
+
self.errorMsg = "Image load exceeded timeout";
|
16057
|
+
self.finish(false);
|
15493
16058
|
}, this.timeout);
|
15494
16059
|
|
15495
|
-
|
16060
|
+
// Load the tile with an AJAX request if the loadWithAjax option is
|
16061
|
+
// set. Otherwise load the image by setting the source proprety of the image object.
|
16062
|
+
if (this.loadWithAjax) {
|
16063
|
+
this.request = $.makeAjaxRequest({
|
16064
|
+
url: this.src,
|
16065
|
+
withCredentials: this.ajaxWithCredentials,
|
16066
|
+
headers: this.ajaxHeaders,
|
16067
|
+
responseType: "arraybuffer",
|
16068
|
+
success: function(request) {
|
16069
|
+
var blb;
|
16070
|
+
// Make the raw data into a blob.
|
16071
|
+
// BlobBuilder fallback adapted from
|
16072
|
+
// http://stackoverflow.com/questions/15293694/blob-constructor-browser-compatibility
|
16073
|
+
try {
|
16074
|
+
blb = new window.Blob([request.response]);
|
16075
|
+
} catch (e) {
|
16076
|
+
var BlobBuilder = (
|
16077
|
+
window.BlobBuilder ||
|
16078
|
+
window.WebKitBlobBuilder ||
|
16079
|
+
window.MozBlobBuilder ||
|
16080
|
+
window.MSBlobBuilder
|
16081
|
+
);
|
16082
|
+
if (e.name === 'TypeError' && BlobBuilder) {
|
16083
|
+
var bb = new BlobBuilder();
|
16084
|
+
bb.append(request.response);
|
16085
|
+
blb = bb.getBlob();
|
16086
|
+
}
|
16087
|
+
}
|
16088
|
+
// If the blob is empty for some reason consider the image load a failure.
|
16089
|
+
if (blb.size === 0) {
|
16090
|
+
self.errorMsg = "Empty image response.";
|
16091
|
+
self.finish(false);
|
16092
|
+
}
|
16093
|
+
// Create a URL for the blob data and make it the source of the image object.
|
16094
|
+
// This will still trigger Image.onload to indicate a successful tile load.
|
16095
|
+
var url = (window.URL || window.webkitURL).createObjectURL(blb);
|
16096
|
+
self.image.src = url;
|
16097
|
+
},
|
16098
|
+
error: function(request) {
|
16099
|
+
self.errorMsg = "Image load aborted - XHR error";
|
16100
|
+
self.finish(false);
|
16101
|
+
}
|
16102
|
+
});
|
16103
|
+
|
16104
|
+
// Provide a function to properly abort the request.
|
16105
|
+
this.abort = function() {
|
16106
|
+
self.request.abort();
|
16107
|
+
|
16108
|
+
// Call the existing abort function if available
|
16109
|
+
if (typeof selfAbort === "function") {
|
16110
|
+
selfAbort();
|
16111
|
+
}
|
16112
|
+
};
|
16113
|
+
} else {
|
16114
|
+
if (this.crossOriginPolicy !== false) {
|
16115
|
+
this.image.crossOrigin = this.crossOriginPolicy;
|
16116
|
+
}
|
16117
|
+
|
16118
|
+
this.image.src = this.src;
|
16119
|
+
}
|
15496
16120
|
},
|
15497
16121
|
|
15498
|
-
finish: function(
|
16122
|
+
finish: function(successful) {
|
15499
16123
|
this.image.onload = this.image.onerror = this.image.onabort = null;
|
15500
16124
|
if (!successful) {
|
15501
16125
|
this.image = null;
|
15502
16126
|
}
|
15503
16127
|
|
15504
|
-
if (
|
15505
|
-
window.clearTimeout(
|
16128
|
+
if (this.jobId) {
|
16129
|
+
window.clearTimeout(this.jobId);
|
15506
16130
|
}
|
15507
16131
|
|
15508
|
-
this.callback(
|
16132
|
+
this.callback(this);
|
15509
16133
|
}
|
15510
16134
|
|
15511
16135
|
};
|
@@ -15517,14 +16141,16 @@ ImageJob.prototype = {
|
|
15517
16141
|
* You generally won't have to interact with the ImageLoader directly.
|
15518
16142
|
* @param {Object} options - Options for this ImageLoader.
|
15519
16143
|
* @param {Number} [options.jobLimit] - The number of concurrent image requests. See imageLoaderLimit in {@link OpenSeadragon.Options} for details.
|
16144
|
+
* @param {Number} [options.timeout] - The max number of milliseconds that an image job may take to complete.
|
15520
16145
|
*/
|
15521
|
-
$.ImageLoader = function(
|
16146
|
+
$.ImageLoader = function(options) {
|
15522
16147
|
|
15523
|
-
$.extend(
|
16148
|
+
$.extend(true, this, {
|
15524
16149
|
jobLimit: $.DEFAULT_SETTINGS.imageLoaderLimit,
|
16150
|
+
timeout: $.DEFAULT_SETTINGS.timeout,
|
15525
16151
|
jobQueue: [],
|
15526
16152
|
jobsInProgress: 0
|
15527
|
-
}, options
|
16153
|
+
}, options);
|
15528
16154
|
|
15529
16155
|
};
|
15530
16156
|
|
@@ -15534,22 +16160,32 @@ $.ImageLoader.prototype = {
|
|
15534
16160
|
/**
|
15535
16161
|
* Add an unloaded image to the loader queue.
|
15536
16162
|
* @method
|
15537
|
-
* @param {
|
15538
|
-
* @param {String}
|
15539
|
-
* @param {
|
15540
|
-
|
15541
|
-
|
16163
|
+
* @param {Object} options - Options for this job.
|
16164
|
+
* @param {String} [options.src] - URL of image to download.
|
16165
|
+
* @param {String} [options.loadWithAjax] - Whether to load this image with AJAX.
|
16166
|
+
* @param {String} [options.ajaxHeaders] - Headers to add to the image request if using AJAX.
|
16167
|
+
* @param {String|Boolean} [options.crossOriginPolicy] - CORS policy to use for downloads
|
16168
|
+
* @param {Boolean} [options.ajaxWithCredentials] - Whether to set withCredentials on AJAX
|
16169
|
+
* requests.
|
16170
|
+
* @param {Function} [options.callback] - Called once image has been downloaded.
|
16171
|
+
* @param {Function} [options.abort] - Called when this image job is aborted.
|
16172
|
+
*/
|
16173
|
+
addJob: function(options) {
|
15542
16174
|
var _this = this,
|
15543
|
-
complete = function(
|
15544
|
-
completeJob(
|
16175
|
+
complete = function(job) {
|
16176
|
+
completeJob(_this, job, options.callback);
|
15545
16177
|
},
|
15546
16178
|
jobOptions = {
|
15547
16179
|
src: options.src,
|
16180
|
+
loadWithAjax: options.loadWithAjax,
|
16181
|
+
ajaxHeaders: options.loadWithAjax ? options.ajaxHeaders : null,
|
15548
16182
|
crossOriginPolicy: options.crossOriginPolicy,
|
16183
|
+
ajaxWithCredentials: options.ajaxWithCredentials,
|
15549
16184
|
callback: complete,
|
15550
|
-
abort: options.abort
|
16185
|
+
abort: options.abort,
|
16186
|
+
timeout: this.timeout
|
15551
16187
|
},
|
15552
|
-
newJob = new ImageJob(
|
16188
|
+
newJob = new ImageJob(jobOptions);
|
15553
16189
|
|
15554
16190
|
if ( !this.jobLimit || this.jobsInProgress < this.jobLimit ) {
|
15555
16191
|
newJob.start();
|
@@ -15584,21 +16220,21 @@ $.ImageLoader.prototype = {
|
|
15584
16220
|
* @param job - The ImageJob that has completed.
|
15585
16221
|
* @param callback - Called once cleanup is finished.
|
15586
16222
|
*/
|
15587
|
-
function completeJob(
|
16223
|
+
function completeJob(loader, job, callback) {
|
15588
16224
|
var nextJob;
|
15589
16225
|
|
15590
16226
|
loader.jobsInProgress--;
|
15591
16227
|
|
15592
|
-
if (
|
16228
|
+
if ((!loader.jobLimit || loader.jobsInProgress < loader.jobLimit) && loader.jobQueue.length > 0) {
|
15593
16229
|
nextJob = loader.jobQueue.shift();
|
15594
16230
|
nextJob.start();
|
15595
16231
|
loader.jobsInProgress++;
|
15596
16232
|
}
|
15597
16233
|
|
15598
|
-
callback(
|
16234
|
+
callback(job.image, job.errorMsg, job.request);
|
15599
16235
|
}
|
15600
16236
|
|
15601
|
-
}(
|
16237
|
+
}(OpenSeadragon));
|
15602
16238
|
|
15603
16239
|
/*
|
15604
16240
|
* OpenSeadragon - Tile
|
@@ -15649,8 +16285,10 @@ function completeJob( loader, job, callback ) {
|
|
15649
16285
|
* @param {String} url The URL of this tile's image.
|
15650
16286
|
* @param {CanvasRenderingContext2D} context2D The context2D of this tile if it
|
15651
16287
|
* is provided directly by the tile source.
|
16288
|
+
* @param {Boolean} loadWithAjax Whether this tile image should be loaded with an AJAX request .
|
16289
|
+
* @param {Object} ajaxHeaders The headers to send with this tile's AJAX request (if applicable).
|
15652
16290
|
*/
|
15653
|
-
$.Tile = function(level, x, y, bounds, exists, url, context2D) {
|
16291
|
+
$.Tile = function(level, x, y, bounds, exists, url, context2D, loadWithAjax, ajaxHeaders) {
|
15654
16292
|
/**
|
15655
16293
|
* The zoom level this tile belongs to.
|
15656
16294
|
* @member {Number} level
|
@@ -15693,6 +16331,29 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D) {
|
|
15693
16331
|
* @memberOf OpenSeadragon.Tile#
|
15694
16332
|
*/
|
15695
16333
|
this.context2D = context2D;
|
16334
|
+
/**
|
16335
|
+
* Whether to load this tile's image with an AJAX request.
|
16336
|
+
* @member {Boolean} loadWithAjax
|
16337
|
+
* @memberof OpenSeadragon.Tile#
|
16338
|
+
*/
|
16339
|
+
this.loadWithAjax = loadWithAjax;
|
16340
|
+
/**
|
16341
|
+
* The headers to be used in requesting this tile's image.
|
16342
|
+
* Only used if loadWithAjax is set to true.
|
16343
|
+
* @member {Object} ajaxHeaders
|
16344
|
+
* @memberof OpenSeadragon.Tile#
|
16345
|
+
*/
|
16346
|
+
this.ajaxHeaders = ajaxHeaders;
|
16347
|
+
/**
|
16348
|
+
* The unique cache key for this tile.
|
16349
|
+
* @member {String} cacheKey
|
16350
|
+
* @memberof OpenSeadragon.Tile#
|
16351
|
+
*/
|
16352
|
+
if (this.ajaxHeaders) {
|
16353
|
+
this.cacheKey = this.url + "+" + JSON.stringify(this.ajaxHeaders);
|
16354
|
+
} else {
|
16355
|
+
this.cacheKey = this.url;
|
16356
|
+
}
|
15696
16357
|
/**
|
15697
16358
|
* Is this tile loaded?
|
15698
16359
|
* @member {Boolean} loaded
|
@@ -15756,11 +16417,13 @@ $.Tile = function(level, x, y, bounds, exists, url, context2D) {
|
|
15756
16417
|
*/
|
15757
16418
|
this.opacity = null;
|
15758
16419
|
/**
|
15759
|
-
* The distance of this tile to the viewport center.
|
15760
|
-
*
|
16420
|
+
* The squared distance of this tile to the viewport center.
|
16421
|
+
* Use for comparing tiles.
|
16422
|
+
* @private
|
16423
|
+
* @member {Number} squaredDistance
|
15761
16424
|
* @memberof OpenSeadragon.Tile#
|
15762
16425
|
*/
|
15763
|
-
this.
|
16426
|
+
this.squaredDistance = null;
|
15764
16427
|
/**
|
15765
16428
|
* The visibility score of this tile.
|
15766
16429
|
* @member {Number} visibility
|
@@ -16040,6 +16703,7 @@ $.Tile.prototype = {
|
|
16040
16703
|
* compatibility.
|
16041
16704
|
* @member OverlayPlacement
|
16042
16705
|
* @memberof OpenSeadragon
|
16706
|
+
* @see OpenSeadragon.Placement
|
16043
16707
|
* @static
|
16044
16708
|
* @readonly
|
16045
16709
|
* @type {Object}
|
@@ -16246,6 +16910,8 @@ $.Tile.prototype = {
|
|
16246
16910
|
element.prevNextSibling = element.nextSibling;
|
16247
16911
|
container.appendChild(element);
|
16248
16912
|
|
16913
|
+
// have to set position before calculating size, fix #1116
|
16914
|
+
this.style.position = "absolute";
|
16249
16915
|
// this.size is used by overlays which don't get scaled in at
|
16250
16916
|
// least one direction when this.checkResize is set to false.
|
16251
16917
|
this.size = $.getElementSize(element);
|
@@ -16284,7 +16950,6 @@ $.Tile.prototype = {
|
|
16284
16950
|
style[transformProp] = "";
|
16285
16951
|
}
|
16286
16952
|
}
|
16287
|
-
style.position = "absolute";
|
16288
16953
|
|
16289
16954
|
if (style.display !== 'none') {
|
16290
16955
|
style.display = 'block';
|
@@ -16399,7 +17064,7 @@ $.Tile.prototype = {
|
|
16399
17064
|
* @param {OpenSeadragon.Point|OpenSeadragon.Rect|Object} location
|
16400
17065
|
* If an object is specified, the options are the same than the constructor
|
16401
17066
|
* except for the element which can not be changed.
|
16402
|
-
* @param {OpenSeadragon.Placement}
|
17067
|
+
* @param {OpenSeadragon.Placement} placement
|
16403
17068
|
*/
|
16404
17069
|
update: function(location, placement) {
|
16405
17070
|
var options = $.isPlainObject(location) ? location : {
|
@@ -16761,8 +17426,8 @@ $.Drawer.prototype = {
|
|
16761
17426
|
return new $.Rect(
|
16762
17427
|
topLeft.x * $.pixelDensityRatio,
|
16763
17428
|
topLeft.y * $.pixelDensityRatio,
|
16764
|
-
size.x
|
16765
|
-
size.y
|
17429
|
+
size.x * $.pixelDensityRatio,
|
17430
|
+
size.y * $.pixelDensityRatio
|
16766
17431
|
);
|
16767
17432
|
},
|
16768
17433
|
|
@@ -16805,6 +17470,9 @@ $.Drawer.prototype = {
|
|
16805
17470
|
if (this.viewport.getRotation() === 0) {
|
16806
17471
|
var self = this;
|
16807
17472
|
this.viewer.addHandler('rotate', function resizeSketchCanvas() {
|
17473
|
+
if (self.viewport.getRotation() === 0) {
|
17474
|
+
return;
|
17475
|
+
}
|
16808
17476
|
self.viewer.removeHandler('rotate', resizeSketchCanvas);
|
16809
17477
|
var sketchCanvasSize = self._calculateSketchCanvasSize();
|
16810
17478
|
self.sketchCanvas.width = sketchCanvasSize.x;
|
@@ -16899,6 +17567,24 @@ $.Drawer.prototype = {
|
|
16899
17567
|
this.context.globalCompositeOperation = compositeOperation;
|
16900
17568
|
}
|
16901
17569
|
if (bounds) {
|
17570
|
+
// Internet Explorer, Microsoft Edge, and Safari have problems
|
17571
|
+
// when you call context.drawImage with negative x or y
|
17572
|
+
// or x + width or y + height greater than the canvas width or height respectively.
|
17573
|
+
if (bounds.x < 0) {
|
17574
|
+
bounds.width += bounds.x;
|
17575
|
+
bounds.x = 0;
|
17576
|
+
}
|
17577
|
+
if (bounds.x + bounds.width > this.canvas.width) {
|
17578
|
+
bounds.width = this.canvas.width - bounds.x;
|
17579
|
+
}
|
17580
|
+
if (bounds.y < 0) {
|
17581
|
+
bounds.height += bounds.y;
|
17582
|
+
bounds.y = 0;
|
17583
|
+
}
|
17584
|
+
if (bounds.y + bounds.height > this.canvas.height) {
|
17585
|
+
bounds.height = this.canvas.height - bounds.y;
|
17586
|
+
}
|
17587
|
+
|
16902
17588
|
this.context.drawImage(
|
16903
17589
|
this.sketchCanvas,
|
16904
17590
|
bounds.x,
|
@@ -16929,7 +17615,7 @@ $.Drawer.prototype = {
|
|
16929
17615
|
position.x - widthExt * scale,
|
16930
17616
|
position.y - heightExt * scale,
|
16931
17617
|
(this.canvas.width + 2 * widthExt) * scale,
|
16932
|
-
(this.canvas.height
|
17618
|
+
(this.canvas.height + 2 * heightExt) * scale,
|
16933
17619
|
-widthExt,
|
16934
17620
|
-heightExt,
|
16935
17621
|
this.canvas.width + 2 * widthExt,
|
@@ -16940,7 +17626,7 @@ $.Drawer.prototype = {
|
|
16940
17626
|
},
|
16941
17627
|
|
16942
17628
|
// private
|
16943
|
-
drawDebugInfo: function(
|
17629
|
+
drawDebugInfo: function(tile, count, i, tiledImage) {
|
16944
17630
|
if ( !this.useCanvas ) {
|
16945
17631
|
return;
|
16946
17632
|
}
|
@@ -16953,7 +17639,14 @@ $.Drawer.prototype = {
|
|
16953
17639
|
context.fillStyle = this.debugGridColor;
|
16954
17640
|
|
16955
17641
|
if ( this.viewport.degrees !== 0 ) {
|
16956
|
-
this._offsetForRotation(this.viewport.degrees);
|
17642
|
+
this._offsetForRotation({degrees: this.viewport.degrees});
|
17643
|
+
}
|
17644
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
17645
|
+
this._offsetForRotation({
|
17646
|
+
degrees: tiledImage.getRotation(true),
|
17647
|
+
point: tiledImage.viewport.pixelFromPointNoRotate(
|
17648
|
+
tiledImage._getRotationPoint(true), true)
|
17649
|
+
});
|
16957
17650
|
}
|
16958
17651
|
|
16959
17652
|
context.strokeRect(
|
@@ -17017,6 +17710,9 @@ $.Drawer.prototype = {
|
|
17017
17710
|
if ( this.viewport.degrees !== 0 ) {
|
17018
17711
|
this._restoreRotationChanges();
|
17019
17712
|
}
|
17713
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
17714
|
+
this._restoreRotationChanges();
|
17715
|
+
}
|
17020
17716
|
context.restore();
|
17021
17717
|
},
|
17022
17718
|
|
@@ -17050,17 +17746,22 @@ $.Drawer.prototype = {
|
|
17050
17746
|
return new $.Point(canvas.width, canvas.height);
|
17051
17747
|
},
|
17052
17748
|
|
17749
|
+
getCanvasCenter: function() {
|
17750
|
+
return new $.Point(this.canvas.width / 2, this.canvas.height / 2);
|
17751
|
+
},
|
17752
|
+
|
17053
17753
|
// private
|
17054
|
-
_offsetForRotation: function(
|
17055
|
-
var
|
17056
|
-
|
17754
|
+
_offsetForRotation: function(options) {
|
17755
|
+
var point = options.point ?
|
17756
|
+
options.point.times($.pixelDensityRatio) :
|
17757
|
+
this.getCanvasCenter();
|
17057
17758
|
|
17058
|
-
var context = this._getContext(useSketch);
|
17759
|
+
var context = this._getContext(options.useSketch);
|
17059
17760
|
context.save();
|
17060
17761
|
|
17061
|
-
context.translate(
|
17062
|
-
context.rotate(Math.PI / 180 * degrees);
|
17063
|
-
context.translate(-
|
17762
|
+
context.translate(point.x, point.y);
|
17763
|
+
context.rotate(Math.PI / 180 * options.degrees);
|
17764
|
+
context.translate(-point.x, -point.y);
|
17064
17765
|
},
|
17065
17766
|
|
17066
17767
|
// private
|
@@ -17161,11 +17862,11 @@ $.Viewport = function( options ) {
|
|
17161
17862
|
//backward compatibility for positional args while prefering more
|
17162
17863
|
//idiomatic javascript options object as the only argument
|
17163
17864
|
var args = arguments;
|
17164
|
-
if(
|
17865
|
+
if (args.length && args[0] instanceof $.Point) {
|
17165
17866
|
options = {
|
17166
|
-
containerSize: args[
|
17167
|
-
contentSize: args[
|
17168
|
-
config: args[
|
17867
|
+
containerSize: args[0],
|
17868
|
+
contentSize: args[1],
|
17869
|
+
config: args[2]
|
17169
17870
|
};
|
17170
17871
|
}
|
17171
17872
|
|
@@ -17586,10 +18287,9 @@ $.Viewport.prototype = {
|
|
17586
18287
|
* @function
|
17587
18288
|
* @private
|
17588
18289
|
* @param {OpenSeadragon.Rect} bounds
|
17589
|
-
* @param {Boolean} immediately
|
17590
18290
|
* @return {OpenSeadragon.Rect} constrained bounds.
|
17591
18291
|
*/
|
17592
|
-
_applyBoundaryConstraints: function(bounds
|
18292
|
+
_applyBoundaryConstraints: function(bounds) {
|
17593
18293
|
var newBounds = new $.Rect(
|
17594
18294
|
bounds.x,
|
17595
18295
|
bounds.y,
|
@@ -17632,6 +18332,16 @@ $.Viewport.prototype = {
|
|
17632
18332
|
}
|
17633
18333
|
}
|
17634
18334
|
|
18335
|
+
return newBounds;
|
18336
|
+
},
|
18337
|
+
|
18338
|
+
/**
|
18339
|
+
* @function
|
18340
|
+
* @private
|
18341
|
+
* @param {Boolean} [immediately=false] - whether the function that triggered this event was
|
18342
|
+
* called with the "immediately" flag
|
18343
|
+
*/
|
18344
|
+
_raiseConstraintsEvent: function(immediately) {
|
17635
18345
|
if (this.viewer) {
|
17636
18346
|
/**
|
17637
18347
|
* Raised when the viewport constraints are applied (see {@link OpenSeadragon.Viewport#applyConstraints}).
|
@@ -17640,15 +18350,14 @@ $.Viewport.prototype = {
|
|
17640
18350
|
* @memberof OpenSeadragon.Viewer
|
17641
18351
|
* @type {object}
|
17642
18352
|
* @property {OpenSeadragon.Viewer} eventSource - A reference to the Viewer which raised this event.
|
17643
|
-
* @property {Boolean} immediately
|
18353
|
+
* @property {Boolean} immediately - whether the function that triggered this event was
|
18354
|
+
* called with the "immediately" flag
|
17644
18355
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
17645
18356
|
*/
|
17646
18357
|
this.viewer.raiseEvent( 'constrain', {
|
17647
18358
|
immediately: immediately
|
17648
18359
|
});
|
17649
18360
|
}
|
17650
|
-
|
17651
|
-
return newBounds;
|
17652
18361
|
},
|
17653
18362
|
|
17654
18363
|
/**
|
@@ -17668,8 +18377,8 @@ $.Viewport.prototype = {
|
|
17668
18377
|
}
|
17669
18378
|
|
17670
18379
|
var bounds = this.getBoundsNoRotate();
|
17671
|
-
var constrainedBounds = this._applyBoundaryConstraints(
|
17672
|
-
|
18380
|
+
var constrainedBounds = this._applyBoundaryConstraints(bounds);
|
18381
|
+
this._raiseConstraintsEvent(immediately);
|
17673
18382
|
|
17674
18383
|
if (bounds.x !== constrainedBounds.x ||
|
17675
18384
|
bounds.y !== constrainedBounds.y ||
|
@@ -17739,8 +18448,9 @@ $.Viewport.prototype = {
|
|
17739
18448
|
newBounds.y = center.y - newBounds.height / 2;
|
17740
18449
|
}
|
17741
18450
|
|
17742
|
-
newBounds = this._applyBoundaryConstraints(newBounds
|
18451
|
+
newBounds = this._applyBoundaryConstraints(newBounds);
|
17743
18452
|
center = newBounds.getCenter();
|
18453
|
+
this._raiseConstraintsEvent(immediately);
|
17744
18454
|
}
|
17745
18455
|
|
17746
18456
|
if (immediately) {
|
@@ -17834,6 +18544,23 @@ $.Viewport.prototype = {
|
|
17834
18544
|
},
|
17835
18545
|
|
17836
18546
|
|
18547
|
+
/**
|
18548
|
+
* Returns bounds taking constraints into account
|
18549
|
+
* Added to improve constrained panning
|
18550
|
+
* @param {Boolean} current - Pass true for the current location; defaults to false (target location).
|
18551
|
+
* @return {OpenSeadragon.Viewport} Chainable.
|
18552
|
+
*/
|
18553
|
+
getConstrainedBounds: function(current) {
|
18554
|
+
var bounds,
|
18555
|
+
constrainedBounds;
|
18556
|
+
|
18557
|
+
bounds = this.getBounds(current);
|
18558
|
+
|
18559
|
+
constrainedBounds = this._applyBoundaryConstraints(bounds);
|
18560
|
+
|
18561
|
+
return constrainedBounds;
|
18562
|
+
},
|
18563
|
+
|
17837
18564
|
/**
|
17838
18565
|
* @function
|
17839
18566
|
* @param {OpenSeadragon.Point} delta
|
@@ -17906,7 +18633,8 @@ $.Viewport.prototype = {
|
|
17906
18633
|
* @return {OpenSeadragon.Viewport} Chainable.
|
17907
18634
|
* @fires OpenSeadragon.Viewer.event:zoom
|
17908
18635
|
*/
|
17909
|
-
zoomTo: function(
|
18636
|
+
zoomTo: function(zoom, refPoint, immediately) {
|
18637
|
+
var _this = this;
|
17910
18638
|
|
17911
18639
|
this.zoomPoint = refPoint instanceof $.Point &&
|
17912
18640
|
!isNaN(refPoint.x) &&
|
@@ -17914,13 +18642,15 @@ $.Viewport.prototype = {
|
|
17914
18642
|
refPoint :
|
17915
18643
|
null;
|
17916
18644
|
|
17917
|
-
if (
|
17918
|
-
this.
|
18645
|
+
if (immediately) {
|
18646
|
+
this._adjustCenterSpringsForZoomPoint(function() {
|
18647
|
+
_this.zoomSpring.resetTo(zoom);
|
18648
|
+
});
|
17919
18649
|
} else {
|
17920
|
-
this.zoomSpring.springTo(
|
18650
|
+
this.zoomSpring.springTo(zoom);
|
17921
18651
|
}
|
17922
18652
|
|
17923
|
-
if(
|
18653
|
+
if (this.viewer) {
|
17924
18654
|
/**
|
17925
18655
|
* Raised when the viewport zoom level changes (see {@link OpenSeadragon.Viewport#zoomBy} and {@link OpenSeadragon.Viewport#zoomTo}).
|
17926
18656
|
*
|
@@ -17933,7 +18663,7 @@ $.Viewport.prototype = {
|
|
17933
18663
|
* @property {Boolean} immediately
|
17934
18664
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
17935
18665
|
*/
|
17936
|
-
this.viewer.raiseEvent(
|
18666
|
+
this.viewer.raiseEvent('zoom', {
|
17937
18667
|
zoom: zoom,
|
17938
18668
|
refPoint: refPoint,
|
17939
18669
|
immediately: immediately
|
@@ -17953,11 +18683,7 @@ $.Viewport.prototype = {
|
|
17953
18683
|
return this;
|
17954
18684
|
}
|
17955
18685
|
|
17956
|
-
degrees = degrees
|
17957
|
-
if (degrees < 0) {
|
17958
|
-
degrees += 360;
|
17959
|
-
}
|
17960
|
-
this.degrees = degrees;
|
18686
|
+
this.degrees = $.positiveModulo(degrees, 360);
|
17961
18687
|
this._setContentBounds(
|
17962
18688
|
this.viewer.world.getHomeBounds(),
|
17963
18689
|
this.viewer.world.getContentFactor());
|
@@ -18043,10 +18769,29 @@ $.Viewport.prototype = {
|
|
18043
18769
|
* @returns {Boolean} True if any change has been made, false otherwise.
|
18044
18770
|
*/
|
18045
18771
|
update: function() {
|
18772
|
+
var _this = this;
|
18773
|
+
this._adjustCenterSpringsForZoomPoint(function() {
|
18774
|
+
_this.zoomSpring.update();
|
18775
|
+
});
|
18776
|
+
|
18777
|
+
this.centerSpringX.update();
|
18778
|
+
this.centerSpringY.update();
|
18779
|
+
|
18780
|
+
var changed = this.centerSpringX.current.value !== this._oldCenterX ||
|
18781
|
+
this.centerSpringY.current.value !== this._oldCenterY ||
|
18782
|
+
this.zoomSpring.current.value !== this._oldZoom;
|
18783
|
+
|
18784
|
+
this._oldCenterX = this.centerSpringX.current.value;
|
18785
|
+
this._oldCenterY = this.centerSpringY.current.value;
|
18786
|
+
this._oldZoom = this.zoomSpring.current.value;
|
18787
|
+
|
18788
|
+
return changed;
|
18789
|
+
},
|
18046
18790
|
|
18791
|
+
_adjustCenterSpringsForZoomPoint: function(zoomSpringHandler) {
|
18047
18792
|
if (this.zoomPoint) {
|
18048
18793
|
var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
18049
|
-
|
18794
|
+
zoomSpringHandler();
|
18050
18795
|
var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true);
|
18051
18796
|
|
18052
18797
|
var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel);
|
@@ -18060,21 +18805,8 @@ $.Viewport.prototype = {
|
|
18060
18805
|
this.zoomPoint = null;
|
18061
18806
|
}
|
18062
18807
|
} else {
|
18063
|
-
|
18808
|
+
zoomSpringHandler();
|
18064
18809
|
}
|
18065
|
-
|
18066
|
-
this.centerSpringX.update();
|
18067
|
-
this.centerSpringY.update();
|
18068
|
-
|
18069
|
-
var changed = this.centerSpringX.current.value !== this._oldCenterX ||
|
18070
|
-
this.centerSpringY.current.value !== this._oldCenterY ||
|
18071
|
-
this.zoomSpring.current.value !== this._oldZoom;
|
18072
|
-
|
18073
|
-
this._oldCenterX = this.centerSpringX.current.value;
|
18074
|
-
this._oldCenterY = this.centerSpringY.current.value;
|
18075
|
-
this._oldZoom = this.zoomSpring.current.value;
|
18076
|
-
|
18077
|
-
return changed;
|
18078
18810
|
},
|
18079
18811
|
|
18080
18812
|
/**
|
@@ -18313,6 +19045,7 @@ $.Viewport.prototype = {
|
|
18313
19045
|
* in image coordinate system.
|
18314
19046
|
* @param {Number} [pixelWidth] the width in pixel of the rectangle.
|
18315
19047
|
* @param {Number} [pixelHeight] the height in pixel of the rectangle.
|
19048
|
+
* @returns {OpenSeadragon.Rect} This image's bounds in viewport coordinates
|
18316
19049
|
*/
|
18317
19050
|
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight) {
|
18318
19051
|
var rect = imageX;
|
@@ -18664,11 +19397,18 @@ $.Viewport.prototype = {
|
|
18664
19397
|
* @param {Number} [options.minPixelRatio] - See {@link OpenSeadragon.Options}.
|
18665
19398
|
* @param {Number} [options.smoothTileEdgesMinZoom] - See {@link OpenSeadragon.Options}.
|
18666
19399
|
* @param {Boolean} [options.iOSDevice] - See {@link OpenSeadragon.Options}.
|
18667
|
-
* @param {Number} [options.opacity=1] -
|
19400
|
+
* @param {Number} [options.opacity=1] - Set to draw at proportional opacity. If zero, images will not draw.
|
19401
|
+
* @param {Boolean} [options.preload=false] - Set true to load even when the image is hidden by zero opacity.
|
18668
19402
|
* @param {String} [options.compositeOperation] - How the image is composited onto other images; see compositeOperation in {@link OpenSeadragon.Options} for possible values.
|
18669
19403
|
* @param {Boolean} [options.debugMode] - See {@link OpenSeadragon.Options}.
|
18670
19404
|
* @param {String|CanvasGradient|CanvasPattern|Function} [options.placeholderFillStyle] - See {@link OpenSeadragon.Options}.
|
18671
19405
|
* @param {String|Boolean} [options.crossOriginPolicy] - See {@link OpenSeadragon.Options}.
|
19406
|
+
* @param {Boolean} [options.ajaxWithCredentials] - See {@link OpenSeadragon.Options}.
|
19407
|
+
* @param {Boolean} [options.loadTilesWithAjax]
|
19408
|
+
* Whether to load tile data using AJAX requests.
|
19409
|
+
* Defaults to the setting in {@link OpenSeadragon.Options}.
|
19410
|
+
* @param {Object} [options.ajaxHeaders={}]
|
19411
|
+
* A set of headers to include when making tile AJAX requests.
|
18672
19412
|
*/
|
18673
19413
|
$.TiledImage = function( options ) {
|
18674
19414
|
var _this = this;
|
@@ -18726,17 +19466,22 @@ $.TiledImage = function( options ) {
|
|
18726
19466
|
var fitBoundsPlacement = options.fitBoundsPlacement || OpenSeadragon.Placement.CENTER;
|
18727
19467
|
delete options.fitBoundsPlacement;
|
18728
19468
|
|
19469
|
+
var degrees = options.degrees || 0;
|
19470
|
+
delete options.degrees;
|
19471
|
+
|
18729
19472
|
$.extend( true, this, {
|
18730
19473
|
|
18731
19474
|
//internal state properties
|
18732
19475
|
viewer: null,
|
18733
19476
|
tilesMatrix: {}, // A '3d' dictionary [level][x][y] --> Tile.
|
18734
|
-
coverage: {}, // A '3d' dictionary [level][x][y] --> Boolean.
|
19477
|
+
coverage: {}, // A '3d' dictionary [level][x][y] --> Boolean; shows what areas have been drawn.
|
19478
|
+
loadingCoverage: {}, // A '3d' dictionary [level][x][y] --> Boolean; shows what areas are loaded or are being loaded/blended.
|
18735
19479
|
lastDrawn: [], // An unordered list of Tiles drawn last frame.
|
18736
19480
|
lastResetTime: 0, // Last time for which the tiledImage was reset.
|
18737
19481
|
_midDraw: false, // Is the tiledImage currently updating the viewport?
|
18738
19482
|
_needsDraw: true, // Does the tiledImage need to update the viewport again?
|
18739
19483
|
_hasOpaqueTile: false, // Do we have even one fully opaque tile?
|
19484
|
+
_tilesLoading: 0, // The number of pending tile requests.
|
18740
19485
|
//configurable settings
|
18741
19486
|
springStiffness: $.DEFAULT_SETTINGS.springStiffness,
|
18742
19487
|
animationTime: $.DEFAULT_SETTINGS.animationTime,
|
@@ -18751,12 +19496,18 @@ $.TiledImage = function( options ) {
|
|
18751
19496
|
iOSDevice: $.DEFAULT_SETTINGS.iOSDevice,
|
18752
19497
|
debugMode: $.DEFAULT_SETTINGS.debugMode,
|
18753
19498
|
crossOriginPolicy: $.DEFAULT_SETTINGS.crossOriginPolicy,
|
19499
|
+
ajaxWithCredentials: $.DEFAULT_SETTINGS.ajaxWithCredentials,
|
18754
19500
|
placeholderFillStyle: $.DEFAULT_SETTINGS.placeholderFillStyle,
|
18755
19501
|
opacity: $.DEFAULT_SETTINGS.opacity,
|
19502
|
+
preload: $.DEFAULT_SETTINGS.preload,
|
18756
19503
|
compositeOperation: $.DEFAULT_SETTINGS.compositeOperation
|
18757
|
-
|
18758
19504
|
}, options );
|
18759
19505
|
|
19506
|
+
this._preload = this.preload;
|
19507
|
+
delete this.preload;
|
19508
|
+
|
19509
|
+
this._fullyLoaded = false;
|
19510
|
+
|
18760
19511
|
this._xSpring = new $.Spring({
|
18761
19512
|
initial: x,
|
18762
19513
|
springStiffness: this.springStiffness,
|
@@ -18775,6 +19526,12 @@ $.TiledImage = function( options ) {
|
|
18775
19526
|
animationTime: this.animationTime
|
18776
19527
|
});
|
18777
19528
|
|
19529
|
+
this._degreesSpring = new $.Spring({
|
19530
|
+
initial: degrees,
|
19531
|
+
springStiffness: this.springStiffness,
|
19532
|
+
animationTime: this.animationTime
|
19533
|
+
});
|
19534
|
+
|
18778
19535
|
this._updateForScale();
|
18779
19536
|
|
18780
19537
|
if (fitBounds) {
|
@@ -18813,10 +19570,41 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18813
19570
|
},
|
18814
19571
|
|
18815
19572
|
/**
|
18816
|
-
*
|
18817
|
-
* {@link OpenSeadragon.TiledImage#update}.
|
19573
|
+
* @returns {Boolean} Whether all tiles necessary for this TiledImage to draw at the current view have been loaded.
|
18818
19574
|
*/
|
18819
|
-
|
19575
|
+
getFullyLoaded: function() {
|
19576
|
+
return this._fullyLoaded;
|
19577
|
+
},
|
19578
|
+
|
19579
|
+
// private
|
19580
|
+
_setFullyLoaded: function(flag) {
|
19581
|
+
if (flag === this._fullyLoaded) {
|
19582
|
+
return;
|
19583
|
+
}
|
19584
|
+
|
19585
|
+
this._fullyLoaded = flag;
|
19586
|
+
|
19587
|
+
/**
|
19588
|
+
* Fired when the TiledImage's "fully loaded" flag (whether all tiles necessary for this TiledImage
|
19589
|
+
* to draw at the current view have been loaded) changes.
|
19590
|
+
*
|
19591
|
+
* @event fully-loaded-change
|
19592
|
+
* @memberof OpenSeadragon.TiledImage
|
19593
|
+
* @type {object}
|
19594
|
+
* @property {Boolean} fullyLoaded - The new "fully loaded" value.
|
19595
|
+
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the TiledImage which raised the event.
|
19596
|
+
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
19597
|
+
*/
|
19598
|
+
this.raiseEvent('fully-loaded-change', {
|
19599
|
+
fullyLoaded: this._fullyLoaded
|
19600
|
+
});
|
19601
|
+
},
|
19602
|
+
|
19603
|
+
/**
|
19604
|
+
* Clears all tiles and triggers an update on the next call to
|
19605
|
+
* {@link OpenSeadragon.TiledImage#update}.
|
19606
|
+
*/
|
19607
|
+
reset: function() {
|
18820
19608
|
this._tileCache.clearTilesFor(this);
|
18821
19609
|
this.lastResetTime = $.now();
|
18822
19610
|
this._needsDraw = true;
|
@@ -18827,16 +19615,12 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18827
19615
|
* @returns {Boolean} Whether the TiledImage animated.
|
18828
19616
|
*/
|
18829
19617
|
update: function() {
|
18830
|
-
var
|
18831
|
-
var
|
18832
|
-
var
|
18833
|
-
|
18834
|
-
this._xSpring.update();
|
18835
|
-
this._ySpring.update();
|
18836
|
-
this._scaleSpring.update();
|
19618
|
+
var xUpdated = this._xSpring.update();
|
19619
|
+
var yUpdated = this._ySpring.update();
|
19620
|
+
var scaleUpdated = this._scaleSpring.update();
|
19621
|
+
var degreesUpdated = this._degreesSpring.update();
|
18837
19622
|
|
18838
|
-
if (
|
18839
|
-
this._scaleSpring.current.value !== oldScale) {
|
19623
|
+
if (xUpdated || yUpdated || scaleUpdated || degreesUpdated) {
|
18840
19624
|
this._updateForScale();
|
18841
19625
|
this._needsDraw = true;
|
18842
19626
|
return true;
|
@@ -18849,9 +19633,9 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18849
19633
|
* Draws the TiledImage to its Drawer.
|
18850
19634
|
*/
|
18851
19635
|
draw: function() {
|
18852
|
-
if (this.opacity !== 0) {
|
19636
|
+
if (this.opacity !== 0 || this._preload) {
|
18853
19637
|
this._midDraw = true;
|
18854
|
-
|
19638
|
+
this._updateViewport();
|
18855
19639
|
this._midDraw = false;
|
18856
19640
|
}
|
18857
19641
|
},
|
@@ -18864,17 +19648,35 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18864
19648
|
},
|
18865
19649
|
|
18866
19650
|
/**
|
19651
|
+
* Get this TiledImage's bounds in viewport coordinates.
|
19652
|
+
* @param {Boolean} [current=false] - Pass true for the current location;
|
19653
|
+
* false for target location.
|
18867
19654
|
* @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates.
|
18868
|
-
* @param {Boolean} [current=false] - Pass true for the current location; false for target location.
|
18869
19655
|
*/
|
18870
19656
|
getBounds: function(current) {
|
18871
|
-
|
18872
|
-
|
18873
|
-
|
18874
|
-
}
|
19657
|
+
return this.getBoundsNoRotate(current)
|
19658
|
+
.rotate(this.getRotation(current), this._getRotationPoint(current));
|
19659
|
+
},
|
18875
19660
|
|
18876
|
-
|
18877
|
-
|
19661
|
+
/**
|
19662
|
+
* Get this TiledImage's bounds in viewport coordinates without taking
|
19663
|
+
* rotation into account.
|
19664
|
+
* @param {Boolean} [current=false] - Pass true for the current location;
|
19665
|
+
* false for target location.
|
19666
|
+
* @returns {OpenSeadragon.Rect} This TiledImage's bounds in viewport coordinates.
|
19667
|
+
*/
|
19668
|
+
getBoundsNoRotate: function(current) {
|
19669
|
+
return current ?
|
19670
|
+
new $.Rect(
|
19671
|
+
this._xSpring.current.value,
|
19672
|
+
this._ySpring.current.value,
|
19673
|
+
this._worldWidthCurrent,
|
19674
|
+
this._worldHeightCurrent) :
|
19675
|
+
new $.Rect(
|
19676
|
+
this._xSpring.target.value,
|
19677
|
+
this._ySpring.target.value,
|
19678
|
+
this._worldWidthTarget,
|
19679
|
+
this._worldHeightTarget);
|
18878
19680
|
},
|
18879
19681
|
|
18880
19682
|
// deprecated
|
@@ -18890,9 +19692,11 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18890
19692
|
* @returns {$.Rect} The clipped bounds in viewport coordinates.
|
18891
19693
|
*/
|
18892
19694
|
getClippedBounds: function(current) {
|
18893
|
-
var bounds = this.
|
19695
|
+
var bounds = this.getBoundsNoRotate(current);
|
18894
19696
|
if (this._clip) {
|
18895
|
-
var
|
19697
|
+
var worldWidth = current ?
|
19698
|
+
this._worldWidthCurrent : this._worldWidthTarget;
|
19699
|
+
var ratio = worldWidth / this.source.dimensions.x;
|
18896
19700
|
var clip = this._clip.times(ratio);
|
18897
19701
|
bounds = new $.Rect(
|
18898
19702
|
bounds.x + clip.x,
|
@@ -18900,7 +19704,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18900
19704
|
clip.width,
|
18901
19705
|
clip.height);
|
18902
19706
|
}
|
18903
|
-
return bounds;
|
19707
|
+
return bounds.rotate(this.getRotation(current), this._getRotationPoint(current));
|
18904
19708
|
},
|
18905
19709
|
|
18906
19710
|
/**
|
@@ -18925,21 +19729,24 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18925
19729
|
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
18926
19730
|
* @return {OpenSeadragon.Point} A point representing the coordinates in the image.
|
18927
19731
|
*/
|
18928
|
-
viewportToImageCoordinates: function(
|
19732
|
+
viewportToImageCoordinates: function(viewerX, viewerY, current) {
|
19733
|
+
var point;
|
18929
19734
|
if (viewerX instanceof $.Point) {
|
18930
19735
|
//they passed a point instead of individual components
|
18931
19736
|
current = viewerY;
|
18932
|
-
|
18933
|
-
|
18934
|
-
|
18935
|
-
|
18936
|
-
if (current) {
|
18937
|
-
return this._viewportToImageDelta(viewerX - this._xSpring.current.value,
|
18938
|
-
viewerY - this._ySpring.current.value);
|
19737
|
+
point = viewerX;
|
19738
|
+
} else {
|
19739
|
+
point = new $.Point(viewerX, viewerY);
|
18939
19740
|
}
|
18940
19741
|
|
18941
|
-
|
18942
|
-
|
19742
|
+
point = point.rotate(-this.getRotation(current), this._getRotationPoint(current));
|
19743
|
+
return current ?
|
19744
|
+
this._viewportToImageDelta(
|
19745
|
+
point.x - this._xSpring.current.value,
|
19746
|
+
point.y - this._ySpring.current.value) :
|
19747
|
+
this._viewportToImageDelta(
|
19748
|
+
point.x - this._xSpring.target.value,
|
19749
|
+
point.y - this._ySpring.target.value);
|
18943
19750
|
},
|
18944
19751
|
|
18945
19752
|
// private
|
@@ -18957,7 +19764,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18957
19764
|
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
18958
19765
|
* @return {OpenSeadragon.Point} A point representing the coordinates in the viewport.
|
18959
19766
|
*/
|
18960
|
-
imageToViewportCoordinates: function(
|
19767
|
+
imageToViewportCoordinates: function(imageX, imageY, current) {
|
18961
19768
|
if (imageX instanceof $.Point) {
|
18962
19769
|
//they passed a point instead of individual components
|
18963
19770
|
current = imageY;
|
@@ -18974,7 +19781,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18974
19781
|
point.y += this._ySpring.target.value;
|
18975
19782
|
}
|
18976
19783
|
|
18977
|
-
return point;
|
19784
|
+
return point.rotate(this.getRotation(current), this._getRotationPoint(current));
|
18978
19785
|
},
|
18979
19786
|
|
18980
19787
|
/**
|
@@ -18988,7 +19795,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
18988
19795
|
* @param {Boolean} [current=false] - Pass true to use the current location; false for target location.
|
18989
19796
|
* @return {OpenSeadragon.Rect} A rect representing the coordinates in the viewport.
|
18990
19797
|
*/
|
18991
|
-
imageToViewportRectangle: function(
|
19798
|
+
imageToViewportRectangle: function(imageX, imageY, pixelWidth, pixelHeight, current) {
|
18992
19799
|
var rect = imageX;
|
18993
19800
|
if (rect instanceof $.Rect) {
|
18994
19801
|
//they passed a rect instead of individual components
|
@@ -19005,7 +19812,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19005
19812
|
coordA.y,
|
19006
19813
|
coordB.x,
|
19007
19814
|
coordB.y,
|
19008
|
-
rect.degrees
|
19815
|
+
rect.degrees + this.getRotation(current)
|
19009
19816
|
);
|
19010
19817
|
},
|
19011
19818
|
|
@@ -19037,7 +19844,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19037
19844
|
coordA.y,
|
19038
19845
|
coordB.x,
|
19039
19846
|
coordB.y,
|
19040
|
-
rect.degrees
|
19847
|
+
rect.degrees - this.getRotation(current)
|
19041
19848
|
);
|
19042
19849
|
},
|
19043
19850
|
|
@@ -19085,6 +19892,20 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19085
19892
|
OpenSeadragon.getElementPosition( this.viewer.element ));
|
19086
19893
|
},
|
19087
19894
|
|
19895
|
+
// private
|
19896
|
+
// Convert rectangle in viewport coordinates to this tiled image point
|
19897
|
+
// coordinates (x in [0, 1] and y in [0, aspectRatio])
|
19898
|
+
_viewportToTiledImageRectangle: function(rect) {
|
19899
|
+
var scale = this._scaleSpring.current.value;
|
19900
|
+
rect = rect.rotate(-this.getRotation(true), this._getRotationPoint(true));
|
19901
|
+
return new $.Rect(
|
19902
|
+
(rect.x - this._xSpring.current.value) / scale,
|
19903
|
+
(rect.y - this._ySpring.current.value) / scale,
|
19904
|
+
rect.width / scale,
|
19905
|
+
rect.height / scale,
|
19906
|
+
rect.degrees);
|
19907
|
+
},
|
19908
|
+
|
19088
19909
|
/**
|
19089
19910
|
* Convert a viewport zoom to an image zoom.
|
19090
19911
|
* Image zoom: ratio of the original image size to displayed image size.
|
@@ -19098,7 +19919,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19098
19919
|
viewportToImageZoom: function( viewportZoom ) {
|
19099
19920
|
var ratio = this._scaleSpring.current.value *
|
19100
19921
|
this.viewport._containerInnerSize.x / this.source.dimensions.x;
|
19101
|
-
return ratio * viewportZoom
|
19922
|
+
return ratio * viewportZoom;
|
19102
19923
|
},
|
19103
19924
|
|
19104
19925
|
/**
|
@@ -19249,6 +20070,7 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19249
20070
|
* @param {OpenSeadragon.Rect|null} newClip - An area, in image pixels, to clip to
|
19250
20071
|
* (portions of the image outside of this area will not be visible). Only works on
|
19251
20072
|
* browsers that support the HTML5 canvas.
|
20073
|
+
* @fires OpenSeadragon.TiledImage.event:clip-change
|
19252
20074
|
*/
|
19253
20075
|
setClip: function(newClip) {
|
19254
20076
|
$.console.assert(!newClip || newClip instanceof $.Rect,
|
@@ -19261,6 +20083,16 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19261
20083
|
}
|
19262
20084
|
|
19263
20085
|
this._needsDraw = true;
|
20086
|
+
/**
|
20087
|
+
* Raised when the TiledImage's clip is changed.
|
20088
|
+
* @event clip-change
|
20089
|
+
* @memberOf OpenSeadragon.TiledImage
|
20090
|
+
* @type {object}
|
20091
|
+
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
20092
|
+
* TiledImage which raised the event.
|
20093
|
+
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
20094
|
+
*/
|
20095
|
+
this.raiseEvent('clip-change');
|
19264
20096
|
},
|
19265
20097
|
|
19266
20098
|
/**
|
@@ -19272,10 +20104,85 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19272
20104
|
|
19273
20105
|
/**
|
19274
20106
|
* @param {Number} opacity Opacity the tiled image should be drawn at.
|
20107
|
+
* @fires OpenSeadragon.TiledImage.event:opacity-change
|
19275
20108
|
*/
|
19276
20109
|
setOpacity: function(opacity) {
|
20110
|
+
if (opacity === this.opacity) {
|
20111
|
+
return;
|
20112
|
+
}
|
20113
|
+
|
19277
20114
|
this.opacity = opacity;
|
19278
20115
|
this._needsDraw = true;
|
20116
|
+
/**
|
20117
|
+
* Raised when the TiledImage's opacity is changed.
|
20118
|
+
* @event opacity-change
|
20119
|
+
* @memberOf OpenSeadragon.TiledImage
|
20120
|
+
* @type {object}
|
20121
|
+
* @property {Number} opacity - The new opacity value.
|
20122
|
+
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
20123
|
+
* TiledImage which raised the event.
|
20124
|
+
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
20125
|
+
*/
|
20126
|
+
this.raiseEvent('opacity-change', {
|
20127
|
+
opacity: this.opacity
|
20128
|
+
});
|
20129
|
+
},
|
20130
|
+
|
20131
|
+
/**
|
20132
|
+
* @returns {Boolean} whether the tiledImage can load its tiles even when it has zero opacity.
|
20133
|
+
*/
|
20134
|
+
getPreload: function() {
|
20135
|
+
return this._preload;
|
20136
|
+
},
|
20137
|
+
|
20138
|
+
/**
|
20139
|
+
* Set true to load even when hidden. Set false to block loading when hidden.
|
20140
|
+
*/
|
20141
|
+
setPreload: function(preload) {
|
20142
|
+
this._preload = !!preload;
|
20143
|
+
this._needsDraw = true;
|
20144
|
+
},
|
20145
|
+
|
20146
|
+
/**
|
20147
|
+
* Get the rotation of this tiled image in degrees.
|
20148
|
+
* @param {Boolean} [current=false] True for current rotation, false for target.
|
20149
|
+
* @returns {Number} the rotation of this tiled image in degrees.
|
20150
|
+
*/
|
20151
|
+
getRotation: function(current) {
|
20152
|
+
return current ?
|
20153
|
+
this._degreesSpring.current.value :
|
20154
|
+
this._degreesSpring.target.value;
|
20155
|
+
},
|
20156
|
+
|
20157
|
+
/**
|
20158
|
+
* Set the current rotation of this tiled image in degrees.
|
20159
|
+
* @param {Number} degrees the rotation in degrees.
|
20160
|
+
* @param {Boolean} [immediately=false] Whether to animate to the new angle
|
20161
|
+
* or rotate immediately.
|
20162
|
+
* @fires OpenSeadragon.TiledImage.event:bounds-change
|
20163
|
+
*/
|
20164
|
+
setRotation: function(degrees, immediately) {
|
20165
|
+
if (this._degreesSpring.target.value === degrees &&
|
20166
|
+
this._degreesSpring.isAtTargetValue()) {
|
20167
|
+
return;
|
20168
|
+
}
|
20169
|
+
if (immediately) {
|
20170
|
+
this._degreesSpring.resetTo(degrees);
|
20171
|
+
} else {
|
20172
|
+
this._degreesSpring.springTo(degrees);
|
20173
|
+
}
|
20174
|
+
this._needsDraw = true;
|
20175
|
+
this._raiseBoundsChange();
|
20176
|
+
},
|
20177
|
+
|
20178
|
+
/**
|
20179
|
+
* @private
|
20180
|
+
* Get the point around which this tiled image is rotated
|
20181
|
+
* @param {Boolean} current True for current rotation point, false for target.
|
20182
|
+
* @returns {OpenSeadragon.Point}
|
20183
|
+
*/
|
20184
|
+
_getRotationPoint: function(current) {
|
20185
|
+
return this.getBoundsNoRotate(current).getCenter();
|
19279
20186
|
},
|
19280
20187
|
|
19281
20188
|
/**
|
@@ -19287,10 +20194,28 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19287
20194
|
|
19288
20195
|
/**
|
19289
20196
|
* @param {String} compositeOperation the tiled image should be drawn with this globalCompositeOperation.
|
20197
|
+
* @fires OpenSeadragon.TiledImage.event:composite-operation-change
|
19290
20198
|
*/
|
19291
20199
|
setCompositeOperation: function(compositeOperation) {
|
20200
|
+
if (compositeOperation === this.compositeOperation) {
|
20201
|
+
return;
|
20202
|
+
}
|
20203
|
+
|
19292
20204
|
this.compositeOperation = compositeOperation;
|
19293
20205
|
this._needsDraw = true;
|
20206
|
+
/**
|
20207
|
+
* Raised when the TiledImage's opacity is changed.
|
20208
|
+
* @event composite-operation-change
|
20209
|
+
* @memberOf OpenSeadragon.TiledImage
|
20210
|
+
* @type {object}
|
20211
|
+
* @property {String} compositeOperation - The new compositeOperation value.
|
20212
|
+
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
20213
|
+
* TiledImage which raised the event.
|
20214
|
+
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
20215
|
+
*/
|
20216
|
+
this.raiseEvent('composite-operation-change', {
|
20217
|
+
compositeOperation: this.compositeOperation
|
20218
|
+
});
|
19294
20219
|
},
|
19295
20220
|
|
19296
20221
|
// private
|
@@ -19336,7 +20261,8 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19336
20261
|
* @event bounds-change
|
19337
20262
|
* @memberOf OpenSeadragon.TiledImage
|
19338
20263
|
* @type {object}
|
19339
|
-
* @property {OpenSeadragon.
|
20264
|
+
* @property {OpenSeadragon.TiledImage} eventSource - A reference to the
|
20265
|
+
* TiledImage which raised the event.
|
19340
20266
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
19341
20267
|
*/
|
19342
20268
|
this.raiseEvent('bounds-change');
|
@@ -19345,184 +20271,208 @@ $.extend($.TiledImage.prototype, $.EventSource.prototype, /** @lends OpenSeadrag
|
|
19345
20271
|
// private
|
19346
20272
|
_isBottomItem: function() {
|
19347
20273
|
return this.viewer.world.getItemAt(0) === this;
|
19348
|
-
}
|
19349
|
-
});
|
19350
|
-
|
19351
|
-
/**
|
19352
|
-
* @private
|
19353
|
-
* @inner
|
19354
|
-
* Pretty much every other line in this needs to be documented so it's clear
|
19355
|
-
* how each piece of this routine contributes to the drawing process. That's
|
19356
|
-
* why there are so many TODO's inside this function.
|
19357
|
-
*/
|
19358
|
-
function updateViewport( tiledImage ) {
|
19359
|
-
|
19360
|
-
tiledImage._needsDraw = false;
|
20274
|
+
},
|
19361
20275
|
|
19362
|
-
|
19363
|
-
|
19364
|
-
|
19365
|
-
|
19366
|
-
|
19367
|
-
|
19368
|
-
|
19369
|
-
|
19370
|
-
|
19371
|
-
|
19372
|
-
|
19373
|
-
tiledImage.source.minLevel,
|
19374
|
-
Math.floor(
|
19375
|
-
Math.log( tiledImage.minZoomImageRatio ) /
|
19376
|
-
Math.log( 2 )
|
19377
|
-
)
|
19378
|
-
),
|
19379
|
-
highestLevel = Math.min(
|
19380
|
-
Math.abs(tiledImage.source.maxLevel),
|
20276
|
+
// private
|
20277
|
+
_getLevelsInterval: function() {
|
20278
|
+
var lowestLevel = Math.max(
|
20279
|
+
this.source.minLevel,
|
20280
|
+
Math.floor(Math.log(this.minZoomImageRatio) / Math.log(2))
|
20281
|
+
);
|
20282
|
+
var currentZeroRatio = this.viewport.deltaPixelsFromPointsNoRotate(
|
20283
|
+
this.source.getPixelRatio(0), true).x *
|
20284
|
+
this._scaleSpring.current.value;
|
20285
|
+
var highestLevel = Math.min(
|
20286
|
+
Math.abs(this.source.maxLevel),
|
19381
20287
|
Math.abs(Math.floor(
|
19382
|
-
Math.log(
|
19383
|
-
Math.log( 2 )
|
20288
|
+
Math.log(currentZeroRatio / this.minPixelRatio) / Math.log(2)
|
19384
20289
|
))
|
19385
|
-
)
|
19386
|
-
renderPixelRatioC,
|
19387
|
-
renderPixelRatioT,
|
19388
|
-
zeroRatioT,
|
19389
|
-
optimalRatio,
|
19390
|
-
levelOpacity,
|
19391
|
-
levelVisibility;
|
19392
|
-
|
19393
|
-
// Reset tile's internal drawn state
|
19394
|
-
while (tiledImage.lastDrawn.length > 0) {
|
19395
|
-
tile = tiledImage.lastDrawn.pop();
|
19396
|
-
tile.beingDrawn = false;
|
19397
|
-
}
|
19398
|
-
|
19399
|
-
if (!tiledImage.wrapHorizontal && !tiledImage.wrapVertical) {
|
19400
|
-
var tiledImageBounds = tiledImage.getClippedBounds(true);
|
19401
|
-
var intersection = viewportBounds.intersection(tiledImageBounds);
|
19402
|
-
if (intersection === null) {
|
19403
|
-
return;
|
19404
|
-
}
|
19405
|
-
viewportBounds = intersection;
|
19406
|
-
}
|
19407
|
-
viewportBounds = viewportBounds.getBoundingBox();
|
19408
|
-
viewportBounds.x -= tiledImage._xSpring.current.value;
|
19409
|
-
viewportBounds.y -= tiledImage._ySpring.current.value;
|
19410
|
-
|
19411
|
-
var viewportTL = viewportBounds.getTopLeft();
|
19412
|
-
var viewportBR = viewportBounds.getBottomRight();
|
19413
|
-
|
19414
|
-
//Don't draw if completely outside of the viewport
|
19415
|
-
if ( !tiledImage.wrapHorizontal && (viewportBR.x < 0 || viewportTL.x > tiledImage._worldWidthCurrent ) ) {
|
19416
|
-
return;
|
19417
|
-
}
|
19418
|
-
|
19419
|
-
if ( !tiledImage.wrapVertical && ( viewportBR.y < 0 || viewportTL.y > tiledImage._worldHeightCurrent ) ) {
|
19420
|
-
return;
|
19421
|
-
}
|
19422
|
-
|
19423
|
-
// Calculate viewport rect / bounds
|
19424
|
-
if ( !tiledImage.wrapHorizontal ) {
|
19425
|
-
viewportTL.x = Math.max( viewportTL.x, 0 );
|
19426
|
-
viewportBR.x = Math.min( viewportBR.x, tiledImage._worldWidthCurrent );
|
19427
|
-
}
|
20290
|
+
);
|
19428
20291
|
|
19429
|
-
|
19430
|
-
|
19431
|
-
|
19432
|
-
|
20292
|
+
// Calculations for the interval of levels to draw
|
20293
|
+
// can return invalid intervals; fix that here if necessary
|
20294
|
+
lowestLevel = Math.min(lowestLevel, highestLevel);
|
20295
|
+
return {
|
20296
|
+
lowestLevel: lowestLevel,
|
20297
|
+
highestLevel: highestLevel
|
20298
|
+
};
|
20299
|
+
},
|
19433
20300
|
|
19434
|
-
|
19435
|
-
|
19436
|
-
|
19437
|
-
|
20301
|
+
/**
|
20302
|
+
* @private
|
20303
|
+
* @inner
|
20304
|
+
* Pretty much every other line in this needs to be documented so it's clear
|
20305
|
+
* how each piece of this routine contributes to the drawing process. That's
|
20306
|
+
* why there are so many TODO's inside this function.
|
20307
|
+
*/
|
20308
|
+
_updateViewport: function() {
|
20309
|
+
this._needsDraw = false;
|
20310
|
+
this._tilesLoading = 0;
|
20311
|
+
this.loadingCoverage = {};
|
19438
20312
|
|
19439
|
-
|
19440
|
-
|
19441
|
-
|
19442
|
-
|
20313
|
+
// Reset tile's internal drawn state
|
20314
|
+
while (this.lastDrawn.length > 0) {
|
20315
|
+
var tile = this.lastDrawn.pop();
|
20316
|
+
tile.beingDrawn = false;
|
20317
|
+
}
|
19443
20318
|
|
19444
|
-
|
19445
|
-
|
19446
|
-
|
19447
|
-
true
|
19448
|
-
).x * tiledImage._scaleSpring.current.value;
|
20319
|
+
var viewport = this.viewport;
|
20320
|
+
var drawArea = this._viewportToTiledImageRectangle(
|
20321
|
+
viewport.getBoundsWithMargins(true));
|
19449
20322
|
|
19450
|
-
if (
|
19451
|
-
|
19452
|
-
|
19453
|
-
|
19454
|
-
|
19455
|
-
|
20323
|
+
if (!this.wrapHorizontal && !this.wrapVertical) {
|
20324
|
+
var tiledImageBounds = this._viewportToTiledImageRectangle(
|
20325
|
+
this.getClippedBounds(true));
|
20326
|
+
drawArea = drawArea.intersection(tiledImageBounds);
|
20327
|
+
if (drawArea === null) {
|
20328
|
+
return;
|
20329
|
+
}
|
19456
20330
|
}
|
19457
20331
|
|
19458
|
-
|
19459
|
-
|
19460
|
-
|
19461
|
-
|
19462
|
-
|
20332
|
+
var levelsInterval = this._getLevelsInterval();
|
20333
|
+
var lowestLevel = levelsInterval.lowestLevel;
|
20334
|
+
var highestLevel = levelsInterval.highestLevel;
|
20335
|
+
var bestTile = null;
|
20336
|
+
var haveDrawn = false;
|
20337
|
+
var currentTime = $.now();
|
19463
20338
|
|
19464
|
-
|
19465
|
-
|
19466
|
-
|
19467
|
-
tiledImage.source.getClosestLevel( tiledImage.viewport.containerSize ) - 1,
|
19468
|
-
0
|
19469
|
-
)
|
19470
|
-
),
|
19471
|
-
false
|
19472
|
-
).x * tiledImage._scaleSpring.current.value;
|
20339
|
+
// Update any level that will be drawn
|
20340
|
+
for (var level = highestLevel; level >= lowestLevel; level--) {
|
20341
|
+
var drawLevel = false;
|
19473
20342
|
|
19474
|
-
|
19475
|
-
|
19476
|
-
|
20343
|
+
//Avoid calculations for draw if we have already drawn this
|
20344
|
+
var currentRenderPixelRatio = viewport.deltaPixelsFromPointsNoRotate(
|
20345
|
+
this.source.getPixelRatio(level),
|
20346
|
+
true
|
20347
|
+
).x * this._scaleSpring.current.value;
|
19477
20348
|
|
19478
|
-
|
20349
|
+
if (level === lowestLevel ||
|
20350
|
+
(!haveDrawn && currentRenderPixelRatio >= this.minPixelRatio)) {
|
20351
|
+
drawLevel = true;
|
20352
|
+
haveDrawn = true;
|
20353
|
+
} else if (!haveDrawn) {
|
20354
|
+
continue;
|
20355
|
+
}
|
19479
20356
|
|
19480
|
-
|
19481
|
-
|
19482
|
-
|
20357
|
+
//Perform calculations for draw if we haven't drawn this
|
20358
|
+
var targetRenderPixelRatio = viewport.deltaPixelsFromPointsNoRotate(
|
20359
|
+
this.source.getPixelRatio(level),
|
20360
|
+
false
|
20361
|
+
).x * this._scaleSpring.current.value;
|
20362
|
+
|
20363
|
+
var targetZeroRatio = viewport.deltaPixelsFromPointsNoRotate(
|
20364
|
+
this.source.getPixelRatio(
|
20365
|
+
Math.max(
|
20366
|
+
this.source.getClosestLevel(),
|
20367
|
+
0
|
20368
|
+
)
|
20369
|
+
),
|
20370
|
+
false
|
20371
|
+
).x * this._scaleSpring.current.value;
|
20372
|
+
|
20373
|
+
var optimalRatio = this.immediateRender ? 1 : targetZeroRatio;
|
20374
|
+
var levelOpacity = Math.min(1, (currentRenderPixelRatio - 0.5) / 0.5);
|
20375
|
+
var levelVisibility = optimalRatio / Math.abs(
|
20376
|
+
optimalRatio - targetRenderPixelRatio
|
20377
|
+
);
|
19483
20378
|
|
19484
|
-
|
19485
|
-
|
19486
|
-
|
19487
|
-
|
19488
|
-
|
19489
|
-
|
19490
|
-
|
19491
|
-
|
19492
|
-
|
19493
|
-
|
19494
|
-
|
19495
|
-
|
19496
|
-
);
|
20379
|
+
// Update the level and keep track of 'best' tile to load
|
20380
|
+
bestTile = updateLevel(
|
20381
|
+
this,
|
20382
|
+
haveDrawn,
|
20383
|
+
drawLevel,
|
20384
|
+
level,
|
20385
|
+
levelOpacity,
|
20386
|
+
levelVisibility,
|
20387
|
+
drawArea,
|
20388
|
+
currentTime,
|
20389
|
+
bestTile
|
20390
|
+
);
|
19497
20391
|
|
19498
|
-
|
19499
|
-
|
19500
|
-
|
19501
|
-
|
20392
|
+
// Stop the loop if lower-res tiles would all be covered by
|
20393
|
+
// already drawn tiles
|
20394
|
+
if (providesCoverage(this.coverage, level)) {
|
20395
|
+
break;
|
20396
|
+
}
|
19502
20397
|
}
|
19503
|
-
}
|
19504
20398
|
|
19505
|
-
|
19506
|
-
|
20399
|
+
// Perform the actual drawing
|
20400
|
+
drawTiles(this, this.lastDrawn);
|
19507
20401
|
|
19508
|
-
|
19509
|
-
|
19510
|
-
|
19511
|
-
|
20402
|
+
// Load the new 'best' tile
|
20403
|
+
if (bestTile && !bestTile.context2D) {
|
20404
|
+
loadTile(this, bestTile, currentTime);
|
20405
|
+
this._needsDraw = true;
|
20406
|
+
this._setFullyLoaded(false);
|
20407
|
+
} else {
|
20408
|
+
this._setFullyLoaded(this._tilesLoading === 0);
|
20409
|
+
}
|
20410
|
+
},
|
19512
20411
|
|
19513
|
-
|
20412
|
+
// private
|
20413
|
+
_getCornerTiles: function(level, topLeftBound, bottomRightBound) {
|
20414
|
+
var leftX;
|
20415
|
+
var rightX;
|
20416
|
+
if (this.wrapHorizontal) {
|
20417
|
+
leftX = $.positiveModulo(topLeftBound.x, 1);
|
20418
|
+
rightX = $.positiveModulo(bottomRightBound.x, 1);
|
20419
|
+
} else {
|
20420
|
+
leftX = Math.max(0, topLeftBound.x);
|
20421
|
+
rightX = Math.min(1, bottomRightBound.x);
|
20422
|
+
}
|
20423
|
+
var topY;
|
20424
|
+
var bottomY;
|
20425
|
+
var aspectRatio = 1 / this.source.aspectRatio;
|
20426
|
+
if (this.wrapVertical) {
|
20427
|
+
topY = $.positiveModulo(topLeftBound.y, aspectRatio);
|
20428
|
+
bottomY = $.positiveModulo(bottomRightBound.y, aspectRatio);
|
20429
|
+
} else {
|
20430
|
+
topY = Math.max(0, topLeftBound.y);
|
20431
|
+
bottomY = Math.min(aspectRatio, bottomRightBound.y);
|
20432
|
+
}
|
19514
20433
|
|
20434
|
+
var topLeftTile = this.source.getTileAtPoint(level, new $.Point(leftX, topY));
|
20435
|
+
var bottomRightTile = this.source.getTileAtPoint(level, new $.Point(rightX, bottomY));
|
20436
|
+
var numTiles = this.source.getNumTiles(level);
|
19515
20437
|
|
19516
|
-
|
20438
|
+
if (this.wrapHorizontal) {
|
20439
|
+
topLeftTile.x += numTiles.x * Math.floor(topLeftBound.x);
|
20440
|
+
bottomRightTile.x += numTiles.x * Math.floor(bottomRightBound.x);
|
20441
|
+
}
|
20442
|
+
if (this.wrapVertical) {
|
20443
|
+
topLeftTile.y += numTiles.y * Math.floor(topLeftBound.y / aspectRatio);
|
20444
|
+
bottomRightTile.y += numTiles.y * Math.floor(bottomRightBound.y / aspectRatio);
|
20445
|
+
}
|
19517
20446
|
|
19518
|
-
|
19519
|
-
|
19520
|
-
|
19521
|
-
|
19522
|
-
|
20447
|
+
return {
|
20448
|
+
topLeft: topLeftTile,
|
20449
|
+
bottomRight: bottomRightTile,
|
20450
|
+
};
|
20451
|
+
}
|
20452
|
+
});
|
19523
20453
|
|
20454
|
+
/**
|
20455
|
+
* @private
|
20456
|
+
* @inner
|
20457
|
+
* Updates all tiles at a given resolution level.
|
20458
|
+
* @param {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn.
|
20459
|
+
* @param {Boolean} haveDrawn
|
20460
|
+
* @param {Boolean} drawLevel
|
20461
|
+
* @param {Number} level
|
20462
|
+
* @param {Number} levelOpacity
|
20463
|
+
* @param {Number} levelVisibility
|
20464
|
+
* @param {OpenSeadragon.Point} viewportTL - The index of the most top-left visible tile.
|
20465
|
+
* @param {OpenSeadragon.Point} viewportBR - The index of the most bottom-right visible tile.
|
20466
|
+
* @param {Number} currentTime
|
20467
|
+
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw.
|
20468
|
+
*/
|
20469
|
+
function updateLevel(tiledImage, haveDrawn, drawLevel, level, levelOpacity,
|
20470
|
+
levelVisibility, drawArea, currentTime, best) {
|
19524
20471
|
|
19525
|
-
|
20472
|
+
var topLeftBound = drawArea.getBoundingBox().getTopLeft();
|
20473
|
+
var bottomRightBound = drawArea.getBoundingBox().getBottomRight();
|
20474
|
+
|
20475
|
+
if (tiledImage.viewer) {
|
19526
20476
|
/**
|
19527
20477
|
* <em>- Needs documentation -</em>
|
19528
20478
|
*
|
@@ -19535,41 +20485,50 @@ function updateLevel( tiledImage, haveDrawn, drawLevel, level, levelOpacity, lev
|
|
19535
20485
|
* @property {Object} level
|
19536
20486
|
* @property {Object} opacity
|
19537
20487
|
* @property {Object} visibility
|
19538
|
-
* @property {
|
19539
|
-
* @property {Object}
|
20488
|
+
* @property {OpenSeadragon.Rect} drawArea
|
20489
|
+
* @property {Object} topleft deprecated, use drawArea instead
|
20490
|
+
* @property {Object} bottomright deprecated, use drawArea instead
|
19540
20491
|
* @property {Object} currenttime
|
19541
20492
|
* @property {Object} best
|
19542
20493
|
* @property {?Object} userData - Arbitrary subscriber-defined object.
|
19543
20494
|
*/
|
19544
|
-
tiledImage.viewer.raiseEvent(
|
20495
|
+
tiledImage.viewer.raiseEvent('update-level', {
|
19545
20496
|
tiledImage: tiledImage,
|
19546
20497
|
havedrawn: haveDrawn,
|
19547
20498
|
level: level,
|
19548
20499
|
opacity: levelOpacity,
|
19549
20500
|
visibility: levelVisibility,
|
19550
|
-
|
19551
|
-
|
20501
|
+
drawArea: drawArea,
|
20502
|
+
topleft: topLeftBound,
|
20503
|
+
bottomright: bottomRightBound,
|
19552
20504
|
currenttime: currentTime,
|
19553
20505
|
best: best
|
19554
20506
|
});
|
19555
20507
|
}
|
19556
20508
|
|
19557
|
-
|
19558
|
-
|
19559
|
-
tileBR = tiledImage.source.getTileAtPoint( level, viewportBR.divide( tiledImage._scaleSpring.current.value ));
|
19560
|
-
numberOfTiles = tiledImage.source.getNumTiles( level );
|
19561
|
-
|
19562
|
-
resetCoverage( tiledImage.coverage, level );
|
19563
|
-
|
19564
|
-
if ( !tiledImage.wrapHorizontal ) {
|
19565
|
-
tileBR.x = Math.min( tileBR.x, numberOfTiles.x - 1 );
|
19566
|
-
}
|
19567
|
-
if ( !tiledImage.wrapVertical ) {
|
19568
|
-
tileBR.y = Math.min( tileBR.y, numberOfTiles.y - 1 );
|
19569
|
-
}
|
20509
|
+
resetCoverage(tiledImage.coverage, level);
|
20510
|
+
resetCoverage(tiledImage.loadingCoverage, level);
|
19570
20511
|
|
19571
|
-
|
19572
|
-
|
20512
|
+
//OK, a new drawing so do your calculations
|
20513
|
+
var cornerTiles = tiledImage._getCornerTiles(level, topLeftBound, bottomRightBound);
|
20514
|
+
var topLeftTile = cornerTiles.topLeft;
|
20515
|
+
var bottomRightTile = cornerTiles.bottomRight;
|
20516
|
+
var numberOfTiles = tiledImage.source.getNumTiles(level);
|
20517
|
+
|
20518
|
+
var viewportCenter = tiledImage.viewport.pixelFromPoint(
|
20519
|
+
tiledImage.viewport.getCenter());
|
20520
|
+
for (var x = topLeftTile.x; x <= bottomRightTile.x; x++) {
|
20521
|
+
for (var y = topLeftTile.y; y <= bottomRightTile.y; y++) {
|
20522
|
+
|
20523
|
+
// Optimisation disabled with wrapping because getTileBounds does not
|
20524
|
+
// work correctly with x and y outside of the number of tiles
|
20525
|
+
if (!tiledImage.wrapHorizontal && !tiledImage.wrapVertical) {
|
20526
|
+
var tileBounds = tiledImage.source.getTileBounds(level, x, y);
|
20527
|
+
if (drawArea.intersection(tileBounds) === null) {
|
20528
|
+
// This tile is outside of the viewport, no need to draw it
|
20529
|
+
continue;
|
20530
|
+
}
|
20531
|
+
}
|
19573
20532
|
|
19574
20533
|
best = updateTile(
|
19575
20534
|
tiledImage,
|
@@ -19591,11 +20550,29 @@ function updateLevel( tiledImage, haveDrawn, drawLevel, level, levelOpacity, lev
|
|
19591
20550
|
return best;
|
19592
20551
|
}
|
19593
20552
|
|
19594
|
-
|
20553
|
+
/**
|
20554
|
+
* @private
|
20555
|
+
* @inner
|
20556
|
+
* Update a single tile at a particular resolution level.
|
20557
|
+
* @param {OpenSeadragon.TiledImage} tiledImage - Which TiledImage is being drawn.
|
20558
|
+
* @param {Boolean} haveDrawn
|
20559
|
+
* @param {Boolean} drawLevel
|
20560
|
+
* @param {Number} x
|
20561
|
+
* @param {Number} y
|
20562
|
+
* @param {Number} level
|
20563
|
+
* @param {Number} levelOpacity
|
20564
|
+
* @param {Number} levelVisibility
|
20565
|
+
* @param {OpenSeadragon.Point} viewportCenter
|
20566
|
+
* @param {Number} numberOfTiles
|
20567
|
+
* @param {Number} currentTime
|
20568
|
+
* @param {OpenSeadragon.Tile} best - The current "best" tile to draw.
|
20569
|
+
*/
|
20570
|
+
function updateTile( tiledImage, haveDrawn, drawLevel, x, y, level, levelOpacity, levelVisibility, viewportCenter, numberOfTiles, currentTime, best){
|
19595
20571
|
|
19596
20572
|
var tile = getTile(
|
19597
20573
|
x, y,
|
19598
20574
|
level,
|
20575
|
+
tiledImage,
|
19599
20576
|
tiledImage.source,
|
19600
20577
|
tiledImage.tilesMatrix,
|
19601
20578
|
currentTime,
|
@@ -19625,6 +20602,9 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|
19625
20602
|
|
19626
20603
|
setCoverage( tiledImage.coverage, level, x, y, false );
|
19627
20604
|
|
20605
|
+
var loadingCoverage = tile.loaded || tile.loading || isCovered(tiledImage.loadingCoverage, level, x, y);
|
20606
|
+
setCoverage(tiledImage.loadingCoverage, level, x, y, loadingCoverage);
|
20607
|
+
|
19628
20608
|
if ( !tile.exists ) {
|
19629
20609
|
return best;
|
19630
20610
|
}
|
@@ -19654,7 +20634,7 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|
19654
20634
|
if (tile.context2D) {
|
19655
20635
|
setTileLoaded(tiledImage, tile);
|
19656
20636
|
} else {
|
19657
|
-
var imageRecord = tiledImage._tileCache.getImageRecord(tile.
|
20637
|
+
var imageRecord = tiledImage._tileCache.getImageRecord(tile.cacheKey);
|
19658
20638
|
if (imageRecord) {
|
19659
20639
|
var image = imageRecord.getImage();
|
19660
20640
|
setTileLoaded(tiledImage, tile, image);
|
@@ -19677,20 +20657,47 @@ function updateTile( tiledImage, drawLevel, haveDrawn, x, y, level, levelOpacity
|
|
19677
20657
|
}
|
19678
20658
|
} else if ( tile.loading ) {
|
19679
20659
|
// the tile is already in the download queue
|
19680
|
-
|
19681
|
-
} else {
|
20660
|
+
tiledImage._tilesLoading++;
|
20661
|
+
} else if (!loadingCoverage) {
|
19682
20662
|
best = compareTiles( best, tile );
|
19683
20663
|
}
|
19684
20664
|
|
19685
20665
|
return best;
|
19686
20666
|
}
|
19687
20667
|
|
19688
|
-
|
20668
|
+
/**
|
20669
|
+
* @private
|
20670
|
+
* @inner
|
20671
|
+
* Obtains a tile at the given location.
|
20672
|
+
* @param {Number} x
|
20673
|
+
* @param {Number} y
|
20674
|
+
* @param {Number} level
|
20675
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20676
|
+
* @param {OpenSeadragon.TileSource} tileSource
|
20677
|
+
* @param {Object} tilesMatrix - A '3d' dictionary [level][x][y] --> Tile.
|
20678
|
+
* @param {Number} time
|
20679
|
+
* @param {Number} numTiles
|
20680
|
+
* @param {Number} worldWidth
|
20681
|
+
* @param {Number} worldHeight
|
20682
|
+
* @returns {OpenSeadragon.Tile}
|
20683
|
+
*/
|
20684
|
+
function getTile(
|
20685
|
+
x, y,
|
20686
|
+
level,
|
20687
|
+
tiledImage,
|
20688
|
+
tileSource,
|
20689
|
+
tilesMatrix,
|
20690
|
+
time,
|
20691
|
+
numTiles,
|
20692
|
+
worldWidth,
|
20693
|
+
worldHeight
|
20694
|
+
) {
|
19689
20695
|
var xMod,
|
19690
20696
|
yMod,
|
19691
20697
|
bounds,
|
19692
20698
|
exists,
|
19693
20699
|
url,
|
20700
|
+
ajaxHeaders,
|
19694
20701
|
context2D,
|
19695
20702
|
tile;
|
19696
20703
|
|
@@ -19707,6 +20714,18 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|
19707
20714
|
bounds = tileSource.getTileBounds( level, xMod, yMod );
|
19708
20715
|
exists = tileSource.tileExists( level, xMod, yMod );
|
19709
20716
|
url = tileSource.getTileUrl( level, xMod, yMod );
|
20717
|
+
|
20718
|
+
// Headers are only applicable if loadTilesWithAjax is set
|
20719
|
+
if (tiledImage.loadTilesWithAjax) {
|
20720
|
+
ajaxHeaders = tileSource.getTileAjaxHeaders( level, xMod, yMod );
|
20721
|
+
// Combine tile AJAX headers with tiled image AJAX headers (if applicable)
|
20722
|
+
if ($.isPlainObject(tiledImage.ajaxHeaders)) {
|
20723
|
+
ajaxHeaders = $.extend({}, tiledImage.ajaxHeaders, ajaxHeaders);
|
20724
|
+
}
|
20725
|
+
} else {
|
20726
|
+
ajaxHeaders = null;
|
20727
|
+
}
|
20728
|
+
|
19710
20729
|
context2D = tileSource.getContext2D ?
|
19711
20730
|
tileSource.getContext2D(level, xMod, yMod) : undefined;
|
19712
20731
|
|
@@ -19720,7 +20739,9 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|
19720
20739
|
bounds,
|
19721
20740
|
exists,
|
19722
20741
|
url,
|
19723
|
-
context2D
|
20742
|
+
context2D,
|
20743
|
+
tiledImage.loadTilesWithAjax,
|
20744
|
+
ajaxHeaders
|
19724
20745
|
);
|
19725
20746
|
}
|
19726
20747
|
|
@@ -19730,13 +20751,24 @@ function getTile( x, y, level, tileSource, tilesMatrix, time, numTiles, worldWid
|
|
19730
20751
|
return tile;
|
19731
20752
|
}
|
19732
20753
|
|
20754
|
+
/**
|
20755
|
+
* @private
|
20756
|
+
* @inner
|
20757
|
+
* Dispatch a job to the ImageLoader to load the Image for a Tile.
|
20758
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20759
|
+
* @param {OpenSeadragon.Tile} tile
|
20760
|
+
* @param {Number} time
|
20761
|
+
*/
|
19733
20762
|
function loadTile( tiledImage, tile, time ) {
|
19734
20763
|
tile.loading = true;
|
19735
20764
|
tiledImage._imageLoader.addJob({
|
19736
20765
|
src: tile.url,
|
20766
|
+
loadWithAjax: tile.loadWithAjax,
|
20767
|
+
ajaxHeaders: tile.ajaxHeaders,
|
19737
20768
|
crossOriginPolicy: tiledImage.crossOriginPolicy,
|
19738
|
-
|
19739
|
-
|
20769
|
+
ajaxWithCredentials: tiledImage.ajaxWithCredentials,
|
20770
|
+
callback: function( image, errorMsg, tileRequest ){
|
20771
|
+
onTileLoad( tiledImage, tile, time, image, errorMsg, tileRequest );
|
19740
20772
|
},
|
19741
20773
|
abort: function() {
|
19742
20774
|
tile.loading = false;
|
@@ -19744,7 +20776,18 @@ function loadTile( tiledImage, tile, time ) {
|
|
19744
20776
|
});
|
19745
20777
|
}
|
19746
20778
|
|
19747
|
-
|
20779
|
+
/**
|
20780
|
+
* @private
|
20781
|
+
* @inner
|
20782
|
+
* Callback fired when a Tile's Image finished downloading.
|
20783
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20784
|
+
* @param {OpenSeadragon.Tile} tile
|
20785
|
+
* @param {Number} time
|
20786
|
+
* @param {Image} image
|
20787
|
+
* @param {String} errorMsg
|
20788
|
+
* @param {XMLHttpRequest} tileRequest
|
20789
|
+
*/
|
20790
|
+
function onTileLoad( tiledImage, tile, time, image, errorMsg, tileRequest ) {
|
19748
20791
|
if ( !image ) {
|
19749
20792
|
$.console.log( "Tile %s failed to load: %s - error: %s", tile, tile.url, errorMsg );
|
19750
20793
|
/**
|
@@ -19757,8 +20800,15 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|
19757
20800
|
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image the tile belongs to.
|
19758
20801
|
* @property {number} time - The time in milliseconds when the tile load began.
|
19759
20802
|
* @property {string} message - The error message.
|
20803
|
+
* @property {XMLHttpRequest} tileRequest - The XMLHttpRequest used to load the tile if available.
|
19760
20804
|
*/
|
19761
|
-
tiledImage.viewer.raiseEvent("tile-load-failed", {
|
20805
|
+
tiledImage.viewer.raiseEvent("tile-load-failed", {
|
20806
|
+
tile: tile,
|
20807
|
+
tiledImage: tiledImage,
|
20808
|
+
time: time,
|
20809
|
+
message: errorMsg,
|
20810
|
+
tileRequest: tileRequest
|
20811
|
+
});
|
19762
20812
|
tile.loading = false;
|
19763
20813
|
tile.exists = false;
|
19764
20814
|
return;
|
@@ -19771,9 +20821,8 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|
19771
20821
|
}
|
19772
20822
|
|
19773
20823
|
var finish = function() {
|
19774
|
-
var cutoff =
|
19775
|
-
|
19776
|
-
setTileLoaded(tiledImage, tile, image, cutoff);
|
20824
|
+
var cutoff = tiledImage.source.getClosestLevel();
|
20825
|
+
setTileLoaded(tiledImage, tile, image, cutoff, tileRequest);
|
19777
20826
|
};
|
19778
20827
|
|
19779
20828
|
// Check if we're mid-update; this can happen on IE8 because image load events for
|
@@ -19786,7 +20835,15 @@ function onTileLoad( tiledImage, tile, time, image, errorMsg ) {
|
|
19786
20835
|
}
|
19787
20836
|
}
|
19788
20837
|
|
19789
|
-
|
20838
|
+
/**
|
20839
|
+
* @private
|
20840
|
+
* @inner
|
20841
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20842
|
+
* @param {OpenSeadragon.Tile} tile
|
20843
|
+
* @param {Image} image
|
20844
|
+
* @param {Number} cutoff
|
20845
|
+
*/
|
20846
|
+
function setTileLoaded(tiledImage, tile, image, cutoff, tileRequest) {
|
19790
20847
|
var increment = 0;
|
19791
20848
|
|
19792
20849
|
function getCompletionCallback() {
|
@@ -19821,6 +20878,7 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|
19821
20878
|
* @property {Image} image - The image of the tile.
|
19822
20879
|
* @property {OpenSeadragon.TiledImage} tiledImage - The tiled image of the loaded tile.
|
19823
20880
|
* @property {OpenSeadragon.Tile} tile - The tile which has been loaded.
|
20881
|
+
* @property {XMLHttpRequest} tiledImage - The AJAX request that loaded this tile (if applicable).
|
19824
20882
|
* @property {function} getCompletionCallback - A function giving a callback to call
|
19825
20883
|
* when the asynchronous processing of the image is done. The image will be
|
19826
20884
|
* marked as entirely loaded when the callback has been called once for each
|
@@ -19829,6 +20887,7 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|
19829
20887
|
tiledImage.viewer.raiseEvent("tile-loaded", {
|
19830
20888
|
tile: tile,
|
19831
20889
|
tiledImage: tiledImage,
|
20890
|
+
tileRequest: tileRequest,
|
19832
20891
|
image: image,
|
19833
20892
|
getCompletionCallback: getCompletionCallback
|
19834
20893
|
});
|
@@ -19836,6 +20895,16 @@ function setTileLoaded(tiledImage, tile, image, cutoff) {
|
|
19836
20895
|
getCompletionCallback()();
|
19837
20896
|
}
|
19838
20897
|
|
20898
|
+
/**
|
20899
|
+
* @private
|
20900
|
+
* @inner
|
20901
|
+
* @param {OpenSeadragon.Tile} tile
|
20902
|
+
* @param {Boolean} overlap
|
20903
|
+
* @param {OpenSeadragon.Viewport} viewport
|
20904
|
+
* @param {OpenSeadragon.Point} viewportCenter
|
20905
|
+
* @param {Number} levelVisibility
|
20906
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20907
|
+
*/
|
19839
20908
|
function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility, tiledImage ){
|
19840
20909
|
var boundsTL = tile.bounds.getTopLeft();
|
19841
20910
|
|
@@ -19849,12 +20918,12 @@ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility,
|
|
19849
20918
|
boundsSize.x *= tiledImage._scaleSpring.current.value;
|
19850
20919
|
boundsSize.y *= tiledImage._scaleSpring.current.value;
|
19851
20920
|
|
19852
|
-
var positionC
|
19853
|
-
positionT
|
19854
|
-
sizeC
|
19855
|
-
sizeT
|
19856
|
-
tileCenter
|
19857
|
-
|
20921
|
+
var positionC = viewport.pixelFromPointNoRotate(boundsTL, true),
|
20922
|
+
positionT = viewport.pixelFromPointNoRotate(boundsTL, false),
|
20923
|
+
sizeC = viewport.deltaPixelsFromPointsNoRotate(boundsSize, true),
|
20924
|
+
sizeT = viewport.deltaPixelsFromPointsNoRotate(boundsSize, false),
|
20925
|
+
tileCenter = positionT.plus( sizeT.divide( 2 ) ),
|
20926
|
+
tileSquaredDistance = viewportCenter.squaredDistanceTo( tileCenter );
|
19858
20927
|
|
19859
20928
|
if ( !overlap ) {
|
19860
20929
|
sizeC = sizeC.plus( new $.Point( 1, 1 ) );
|
@@ -19862,11 +20931,27 @@ function positionTile( tile, overlap, viewport, viewportCenter, levelVisibility,
|
|
19862
20931
|
|
19863
20932
|
tile.position = positionC;
|
19864
20933
|
tile.size = sizeC;
|
19865
|
-
tile.
|
20934
|
+
tile.squaredDistance = tileSquaredDistance;
|
19866
20935
|
tile.visibility = levelVisibility;
|
19867
20936
|
}
|
19868
20937
|
|
19869
|
-
|
20938
|
+
/**
|
20939
|
+
* @private
|
20940
|
+
* @inner
|
20941
|
+
* Updates the opacity of a tile according to the time it has been on screen
|
20942
|
+
* to perform a fade-in.
|
20943
|
+
* Updates coverage once a tile is fully opaque.
|
20944
|
+
* Returns whether the fade-in has completed.
|
20945
|
+
*
|
20946
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
20947
|
+
* @param {OpenSeadragon.Tile} tile
|
20948
|
+
* @param {Number} x
|
20949
|
+
* @param {Number} y
|
20950
|
+
* @param {Number} level
|
20951
|
+
* @param {Number} levelOpacity
|
20952
|
+
* @param {Number} currentTime
|
20953
|
+
* @returns {Boolean}
|
20954
|
+
*/
|
19870
20955
|
function blendTile( tiledImage, tile, x, y, level, levelOpacity, currentTime ){
|
19871
20956
|
var blendTimeMillis = 1000 * tiledImage.blendTime,
|
19872
20957
|
deltaTime,
|
@@ -19907,6 +20992,12 @@ function blendTile( tiledImage, tile, x, y, level, levelOpacity, currentTime ){
|
|
19907
20992
|
* Note that out-of-bounds tiles provide coverage in this sense, since
|
19908
20993
|
* there's no content that they would need to cover. Tiles at non-existent
|
19909
20994
|
* levels that are within the image bounds, however, do not.
|
20995
|
+
*
|
20996
|
+
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
20997
|
+
* @param {Number} level - The resolution level of the tile.
|
20998
|
+
* @param {Number} x - The X position of the tile.
|
20999
|
+
* @param {Number} y - The Y position of the tile.
|
21000
|
+
* @returns {Boolean}
|
19910
21001
|
*/
|
19911
21002
|
function providesCoverage( coverage, level, x, y ) {
|
19912
21003
|
var rows,
|
@@ -19946,6 +21037,12 @@ function providesCoverage( coverage, level, x, y ) {
|
|
19946
21037
|
* Returns true if the given tile is completely covered by higher-level
|
19947
21038
|
* tiles of higher resolution representing the same content. If neither x
|
19948
21039
|
* nor y is given, returns true if the entire visible level is covered.
|
21040
|
+
*
|
21041
|
+
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
21042
|
+
* @param {Number} level - The resolution level of the tile.
|
21043
|
+
* @param {Number} x - The X position of the tile.
|
21044
|
+
* @param {Number} y - The Y position of the tile.
|
21045
|
+
* @returns {Boolean}
|
19949
21046
|
*/
|
19950
21047
|
function isCovered( coverage, level, x, y ) {
|
19951
21048
|
if ( x === undefined || y === undefined ) {
|
@@ -19964,6 +21061,12 @@ function isCovered( coverage, level, x, y ) {
|
|
19964
21061
|
* @private
|
19965
21062
|
* @inner
|
19966
21063
|
* Sets whether the given tile provides coverage or not.
|
21064
|
+
*
|
21065
|
+
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
21066
|
+
* @param {Number} level - The resolution level of the tile.
|
21067
|
+
* @param {Number} x - The X position of the tile.
|
21068
|
+
* @param {Number} y - The Y position of the tile.
|
21069
|
+
* @param {Boolean} covers - Whether the tile provides coverage.
|
19967
21070
|
*/
|
19968
21071
|
function setCoverage( coverage, level, x, y, covers ) {
|
19969
21072
|
if ( !coverage[ level ] ) {
|
@@ -19987,6 +21090,9 @@ function setCoverage( coverage, level, x, y, covers ) {
|
|
19987
21090
|
* Resets coverage information for the given level. This should be called
|
19988
21091
|
* after every draw routine. Note that at the beginning of the next draw
|
19989
21092
|
* routine, coverage for every visible tile should be explicitly set.
|
21093
|
+
*
|
21094
|
+
* @param {Object} coverage - A '3d' dictionary [level][x][y] --> Boolean.
|
21095
|
+
* @param {Number} level - The resolution level of tiles to completely reset.
|
19990
21096
|
*/
|
19991
21097
|
function resetCoverage( coverage, level ) {
|
19992
21098
|
coverage[ level ] = {};
|
@@ -19997,6 +21103,10 @@ function resetCoverage( coverage, level ) {
|
|
19997
21103
|
* @inner
|
19998
21104
|
* Determines whether the 'last best' tile for the area is better than the
|
19999
21105
|
* tile in question.
|
21106
|
+
*
|
21107
|
+
* @param {OpenSeadragon.Tile} previousBest
|
21108
|
+
* @param {OpenSeadragon.Tile} tile
|
21109
|
+
* @returns {OpenSeadragon.Tile} The new best tile.
|
20000
21110
|
*/
|
20001
21111
|
function compareTiles( previousBest, tile ) {
|
20002
21112
|
if ( !previousBest ) {
|
@@ -20006,7 +21116,7 @@ function compareTiles( previousBest, tile ) {
|
|
20006
21116
|
if ( tile.visibility > previousBest.visibility ) {
|
20007
21117
|
return tile;
|
20008
21118
|
} else if ( tile.visibility == previousBest.visibility ) {
|
20009
|
-
if ( tile.
|
21119
|
+
if ( tile.squaredDistance < previousBest.squaredDistance ) {
|
20010
21120
|
return tile;
|
20011
21121
|
}
|
20012
21122
|
}
|
@@ -20014,8 +21124,15 @@ function compareTiles( previousBest, tile ) {
|
|
20014
21124
|
return previousBest;
|
20015
21125
|
}
|
20016
21126
|
|
21127
|
+
/**
|
21128
|
+
* @private
|
21129
|
+
* @inner
|
21130
|
+
* Draws a TiledImage.
|
21131
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
21132
|
+
* @param {OpenSeadragon.Tile[]} lastDrawn - An unordered list of Tiles drawn last frame.
|
21133
|
+
*/
|
20017
21134
|
function drawTiles( tiledImage, lastDrawn ) {
|
20018
|
-
if (lastDrawn.length === 0) {
|
21135
|
+
if (tiledImage.opacity === 0 || lastDrawn.length === 0) {
|
20019
21136
|
return;
|
20020
21137
|
}
|
20021
21138
|
var tile = lastDrawn[0];
|
@@ -20030,7 +21147,12 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|
20030
21147
|
|
20031
21148
|
var zoom = tiledImage.viewport.getZoom(true);
|
20032
21149
|
var imageZoom = tiledImage.viewportToImageZoom(zoom);
|
20033
|
-
|
21150
|
+
|
21151
|
+
if (lastDrawn.length > 1 &&
|
21152
|
+
imageZoom > tiledImage.smoothTileEdgesMinZoom &&
|
21153
|
+
!tiledImage.iOSDevice &&
|
21154
|
+
tiledImage.getRotation(true) % 360 === 0 && // TODO: support tile edge smoothing with tiled image rotation.
|
21155
|
+
$.supportsCanvas) {
|
20034
21156
|
// When zoomed in a lot (>100%) the tile edges are visible.
|
20035
21157
|
// So we have to composite them at ~100% and scale them up together.
|
20036
21158
|
// Note: Disabled on iOS devices per default as it causes a native crash
|
@@ -20054,10 +21176,23 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|
20054
21176
|
tiledImage._drawer._clear(true, bounds);
|
20055
21177
|
}
|
20056
21178
|
|
20057
|
-
// When scaling, we must rotate only when blending the sketch canvas to
|
20058
|
-
// interpolation
|
20059
|
-
if (
|
20060
|
-
|
21179
|
+
// When scaling, we must rotate only when blending the sketch canvas to
|
21180
|
+
// avoid interpolation
|
21181
|
+
if (!sketchScale) {
|
21182
|
+
if (tiledImage.viewport.degrees !== 0) {
|
21183
|
+
tiledImage._drawer._offsetForRotation({
|
21184
|
+
degrees: tiledImage.viewport.degrees,
|
21185
|
+
useSketch: useSketch
|
21186
|
+
});
|
21187
|
+
}
|
21188
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
21189
|
+
tiledImage._drawer._offsetForRotation({
|
21190
|
+
degrees: tiledImage.getRotation(true),
|
21191
|
+
point: tiledImage.viewport.pixelFromPointNoRotate(
|
21192
|
+
tiledImage._getRotationPoint(true), true),
|
21193
|
+
useSketch: useSketch
|
21194
|
+
});
|
21195
|
+
}
|
20061
21196
|
}
|
20062
21197
|
|
20063
21198
|
var usedClip = false;
|
@@ -20065,6 +21200,7 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|
20065
21200
|
tiledImage._drawer.saveContext(useSketch);
|
20066
21201
|
|
20067
21202
|
var box = tiledImage.imageToViewportRectangle(tiledImage._clip, true);
|
21203
|
+
box = box.rotate(-tiledImage.getRotation(true), tiledImage._getRotationPoint(true));
|
20068
21204
|
var clipRect = tiledImage._drawer.viewportToDrawerRectangle(box);
|
20069
21205
|
if (sketchScale) {
|
20070
21206
|
clipRect = clipRect.times(sketchScale);
|
@@ -20125,14 +21261,31 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|
20125
21261
|
tiledImage._drawer.restoreContext( useSketch );
|
20126
21262
|
}
|
20127
21263
|
|
20128
|
-
if (
|
20129
|
-
tiledImage.
|
21264
|
+
if (!sketchScale) {
|
21265
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
21266
|
+
tiledImage._drawer._restoreRotationChanges(useSketch);
|
21267
|
+
}
|
21268
|
+
if (tiledImage.viewport.degrees !== 0) {
|
21269
|
+
tiledImage._drawer._restoreRotationChanges(useSketch);
|
21270
|
+
}
|
20130
21271
|
}
|
20131
21272
|
|
20132
21273
|
if (useSketch) {
|
20133
|
-
|
20134
|
-
|
20135
|
-
|
21274
|
+
if (sketchScale) {
|
21275
|
+
if (tiledImage.viewport.degrees !== 0) {
|
21276
|
+
tiledImage._drawer._offsetForRotation({
|
21277
|
+
degrees: tiledImage.viewport.degrees,
|
21278
|
+
useSketch: false
|
21279
|
+
});
|
21280
|
+
}
|
21281
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
21282
|
+
tiledImage._drawer._offsetForRotation({
|
21283
|
+
degrees: tiledImage.getRotation(true),
|
21284
|
+
point: tiledImage.viewport.pixelFromPointNoRotate(
|
21285
|
+
tiledImage._getRotationPoint(true), true),
|
21286
|
+
useSketch: false
|
21287
|
+
});
|
21288
|
+
}
|
20136
21289
|
}
|
20137
21290
|
tiledImage._drawer.blendSketch({
|
20138
21291
|
opacity: tiledImage.opacity,
|
@@ -20141,19 +21294,32 @@ function drawTiles( tiledImage, lastDrawn ) {
|
|
20141
21294
|
compositeOperation: tiledImage.compositeOperation,
|
20142
21295
|
bounds: bounds
|
20143
21296
|
});
|
20144
|
-
if (
|
20145
|
-
tiledImage.
|
21297
|
+
if (sketchScale) {
|
21298
|
+
if (tiledImage.getRotation(true) % 360 !== 0) {
|
21299
|
+
tiledImage._drawer._restoreRotationChanges(false);
|
21300
|
+
}
|
21301
|
+
if (tiledImage.viewport.degrees !== 0) {
|
21302
|
+
tiledImage._drawer._restoreRotationChanges(false);
|
21303
|
+
}
|
20146
21304
|
}
|
20147
21305
|
}
|
20148
21306
|
drawDebugInfo( tiledImage, lastDrawn );
|
20149
21307
|
}
|
20150
21308
|
|
21309
|
+
/**
|
21310
|
+
* @private
|
21311
|
+
* @inner
|
21312
|
+
* Draws special debug information for a TiledImage if in debug mode.
|
21313
|
+
* @param {OpenSeadragon.TiledImage} tiledImage
|
21314
|
+
* @param {OpenSeadragon.Tile[]} lastDrawn - An unordered list of Tiles drawn last frame.
|
21315
|
+
*/
|
20151
21316
|
function drawDebugInfo( tiledImage, lastDrawn ) {
|
20152
21317
|
if( tiledImage.debugMode ) {
|
20153
21318
|
for ( var i = lastDrawn.length - 1; i >= 0; i-- ) {
|
20154
21319
|
var tile = lastDrawn[ i ];
|
20155
21320
|
try {
|
20156
|
-
tiledImage._drawer.drawDebugInfo(
|
21321
|
+
tiledImage._drawer.drawDebugInfo(
|
21322
|
+
tile, lastDrawn.length, i, tiledImage);
|
20157
21323
|
} catch(e) {
|
20158
21324
|
$.console.error(e);
|
20159
21325
|
}
|
@@ -20305,6 +21471,7 @@ $.TileCache.prototype = {
|
|
20305
21471
|
* may temporarily surpass that number, but should eventually come back down to the max specified.
|
20306
21472
|
* @param {Object} options - Tile info.
|
20307
21473
|
* @param {OpenSeadragon.Tile} options.tile - The tile to cache.
|
21474
|
+
* @param {String} options.tile.cacheKey - The unique key used to identify this tile in the cache.
|
20308
21475
|
* @param {Image} options.image - The image of the tile to cache.
|
20309
21476
|
* @param {OpenSeadragon.TiledImage} options.tiledImage - The TiledImage that owns that tile.
|
20310
21477
|
* @param {Number} [options.cutoff=0] - If adding this tile goes over the cache max count, this
|
@@ -20314,16 +21481,16 @@ $.TileCache.prototype = {
|
|
20314
21481
|
cacheTile: function( options ) {
|
20315
21482
|
$.console.assert( options, "[TileCache.cacheTile] options is required" );
|
20316
21483
|
$.console.assert( options.tile, "[TileCache.cacheTile] options.tile is required" );
|
20317
|
-
$.console.assert( options.tile.
|
21484
|
+
$.console.assert( options.tile.cacheKey, "[TileCache.cacheTile] options.tile.cacheKey is required" );
|
20318
21485
|
$.console.assert( options.tiledImage, "[TileCache.cacheTile] options.tiledImage is required" );
|
20319
21486
|
|
20320
21487
|
var cutoff = options.cutoff || 0;
|
20321
21488
|
var insertionIndex = this._tilesLoaded.length;
|
20322
21489
|
|
20323
|
-
var imageRecord = this._imagesLoaded[options.tile.
|
21490
|
+
var imageRecord = this._imagesLoaded[options.tile.cacheKey];
|
20324
21491
|
if (!imageRecord) {
|
20325
21492
|
$.console.assert( options.image, "[TileCache.cacheTile] options.image is required to create an ImageRecord" );
|
20326
|
-
imageRecord = this._imagesLoaded[options.tile.
|
21493
|
+
imageRecord = this._imagesLoaded[options.tile.cacheKey] = new ImageRecord({
|
20327
21494
|
image: options.image
|
20328
21495
|
});
|
20329
21496
|
|
@@ -20397,9 +21564,9 @@ $.TileCache.prototype = {
|
|
20397
21564
|
},
|
20398
21565
|
|
20399
21566
|
// private
|
20400
|
-
getImageRecord: function(
|
20401
|
-
$.console.assert(
|
20402
|
-
return this._imagesLoaded[
|
21567
|
+
getImageRecord: function(cacheKey) {
|
21568
|
+
$.console.assert(cacheKey, '[TileCache.getImageRecord] cacheKey is required');
|
21569
|
+
return this._imagesLoaded[cacheKey];
|
20403
21570
|
},
|
20404
21571
|
|
20405
21572
|
// private
|
@@ -20411,11 +21578,11 @@ $.TileCache.prototype = {
|
|
20411
21578
|
tile.unload();
|
20412
21579
|
tile.cacheImageRecord = null;
|
20413
21580
|
|
20414
|
-
var imageRecord = this._imagesLoaded[tile.
|
21581
|
+
var imageRecord = this._imagesLoaded[tile.cacheKey];
|
20415
21582
|
imageRecord.removeTile(tile);
|
20416
21583
|
if (!imageRecord.getTileCount()) {
|
20417
21584
|
imageRecord.destroy();
|
20418
|
-
delete this._imagesLoaded[tile.
|
21585
|
+
delete this._imagesLoaded[tile.cacheKey];
|
20419
21586
|
this._imagesLoadedCount--;
|
20420
21587
|
}
|
20421
21588
|
|
@@ -20533,6 +21700,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|
20533
21700
|
this._needsDraw = true;
|
20534
21701
|
|
20535
21702
|
item.addHandler('bounds-change', this._delegatedFigureSizes);
|
21703
|
+
item.addHandler('clip-change', this._delegatedFigureSizes);
|
20536
21704
|
|
20537
21705
|
/**
|
20538
21706
|
* Raised when an item is added to the World.
|
@@ -20633,6 +21801,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|
20633
21801
|
}
|
20634
21802
|
|
20635
21803
|
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
21804
|
+
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
20636
21805
|
item.destroy();
|
20637
21806
|
this._items.splice( index, 1 );
|
20638
21807
|
this._figureSizes();
|
@@ -20649,9 +21818,11 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|
20649
21818
|
// We need to make sure any pending images are canceled so the world items don't get messed up
|
20650
21819
|
this.viewer._cancelPendingImages();
|
20651
21820
|
var item;
|
20652
|
-
|
21821
|
+
var i;
|
21822
|
+
for (i = 0; i < this._items.length; i++) {
|
20653
21823
|
item = this._items[i];
|
20654
21824
|
item.removeHandler('bounds-change', this._delegatedFigureSizes);
|
21825
|
+
item.removeHandler('clip-change', this._delegatedFigureSizes);
|
20655
21826
|
item.destroy();
|
20656
21827
|
}
|
20657
21828
|
|
@@ -20822,7 +21993,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|
20822
21993
|
var item = this._items[0];
|
20823
21994
|
var bounds = item.getBounds();
|
20824
21995
|
this._contentFactor = item.getContentSize().x / bounds.width;
|
20825
|
-
var clippedBounds = item.getClippedBounds();
|
21996
|
+
var clippedBounds = item.getClippedBounds().getBoundingBox();
|
20826
21997
|
var left = clippedBounds.x;
|
20827
21998
|
var top = clippedBounds.y;
|
20828
21999
|
var right = clippedBounds.x + clippedBounds.width;
|
@@ -20832,7 +22003,7 @@ $.extend( $.World.prototype, $.EventSource.prototype, /** @lends OpenSeadragon.W
|
|
20832
22003
|
bounds = item.getBounds();
|
20833
22004
|
this._contentFactor = Math.max(this._contentFactor,
|
20834
22005
|
item.getContentSize().x / bounds.width);
|
20835
|
-
clippedBounds = item.getClippedBounds();
|
22006
|
+
clippedBounds = item.getClippedBounds().getBoundingBox();
|
20836
22007
|
left = Math.min(left, clippedBounds.x);
|
20837
22008
|
top = Math.min(top, clippedBounds.y);
|
20838
22009
|
right = Math.max(right, clippedBounds.x + clippedBounds.width);
|