2019-03-29 08:49:53 +01:00
<!DOCTYPE html>
< html >
< head >
< meta charset = "utf-8" >
< title > iwmlib API Documentation< / title >
< meta name = "description" content = "The IWM Browser: One Browser for all apps." / >
< meta property = "og:title" content = "iwmlib API Documentation" / >
< meta property = "og:type" content = "website" / >
< meta property = "og:image" content = "" / >
< meta property = "og:url" content = "https://www.iwm-tuebingen.de" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
< script src = "scripts/prettify/prettify.js" > < / script >
< script src = "scripts/prettify/lang-css.js" > < / script >
< script src = "scripts/jquery.min.js" > < / script >
<!-- [if lt IE 9]>
< script src = "//html5shiv.googlecode.com/svn/trunk/html5.js" > < / script >
<![endif]-->
< link href = "https://fonts.googleapis.com/css?family=Libre+Franklin:400,700" rel = "stylesheet" >
< link type = "text/css" rel = "stylesheet" href = "styles/prettify-tomorrow.css" >
< link type = "text/css" rel = "stylesheet" href = "styles/bootstrap.min.css" >
< link type = "text/css" rel = "stylesheet" href = "styles/main.css" >
< script >
var config = {"monospaceLinks":false,"cleverLinks":false,"applicationName":"iwmlib","disqus":"","googleAnalytics":"","openGraph":{"title":"iwmlib API Documentation","type":"website","image":"","site_name":"","url":"https://www.iwm-tuebingen.de"},"meta":{"title":"iwmlib API Documentation","description":"The IWM Browser: One Browser for all apps.","keyword":""},"linenums":true,"cleverlinks":true,"default":{"outputSourceFiles":true,"useLongnameInNav":false}};
< / script >
< / head >
< body >
< div id = "wrap" class = "clearfix" >
< div class = "navigation" >
< h3 class = "applicationName" > < a href = "index.html" > iwmlib< / a > < / h3 >
< button id = "menuToggle" class = "btn btn-link btn-lg menu-toggle" >
< span class = "glyphicon glyphicon-menu-hamburger" > < / span >
< / button >
< div class = "search" >
< input id = "search" type = "text" class = "form-control input-md" placeholder = "Search..." >
< / div >
< ul class = "list" >
< li class = "item" data-name = "global" >
< span class = "title namespace " >
< span class = "namespaceTag" >
< span class = "glyphicon glyphicon-globe" > < / span >
< / span >
< a href = "global.html" > Global< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< span class = "subtitle" > Typedefs< / span >
< li class = "parent" data-name = "actionActiveCallback" > < a href = "global.html#actionActiveCallback" > actionActiveCallback< / a > < / li >
< li class = "parent" data-name = "actionCallback" > < a href = "global.html#actionCallback" > actionCallback< / a > < / li >
< li class = "parent" data-name = "actionCallback" > < a href = "global.html#actionCallback" > actionCallback< / a > < / li >
< li class = "parent" data-name = "afterActionCallback" > < a href = "global.html#afterActionCallback" > afterActionCallback< / a > < / li >
< li class = "parent" data-name = "afterActionCallback" > < a href = "global.html#afterActionCallback" > afterActionCallback< / a > < / li >
< li class = "parent" data-name = "beforeActionCallback" > < a href = "global.html#beforeActionCallback" > beforeActionCallback< / a > < / li >
< li class = "parent" data-name = "beforeActionCallback" > < a href = "global.html#beforeActionCallback" > beforeActionCallback< / a > < / li >
< li class = "parent" data-name = "onCompleteCallback" > < a href = "global.html#onCompleteCallback" > onCompleteCallback< / a > < / li >
< li class = "parent" data-name = "onCompleteCallback" > < a href = "global.html#onCompleteCallback" > onCompleteCallback< / a > < / li >
< li class = "parent" data-name = "onStartCallback" > < a href = "global.html#onStartCallback" > onStartCallback< / a > < / li >
< li class = "parent" data-name = "onStartCallback" > < a href = "global.html#onStartCallback" > onStartCallback< / a > < / li >
< li class = "parent" data-name = "onUpdateCallback" > < a href = "global.html#onUpdateCallback" > onUpdateCallback< / a > < / li >
< li class = "parent" data-name = "onUpdateCallback" > < a href = "global.html#onUpdateCallback" > onUpdateCallback< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "AbstractPopup" >
< span class = "title " >
< a href = "AbstractPopup.html" > AbstractPopup< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "AbstractPopup#content" > < a href = "AbstractPopup.html#content" > content< / a > < / li >
< li class = "parent " data-name = "AbstractPopup#header" > < a href = "AbstractPopup.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "AbstractPopup#hide" > < a href = "AbstractPopup.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "AbstractPopup#layout" > < a href = "AbstractPopup.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "AbstractPopup#show" > < a href = "AbstractPopup.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Badge" >
< span class = "title " >
< a href = "Badge.html" > Badge< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = " " data-name = "Badge#content" > < a href = "Badge.html#content" > content< / a > < / li >
< li class = " " data-name = "Badge#header" > < a href = "Badge.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = " " data-name = "Badge#hide" > < a href = "Badge.html#hide" > hide< / a > < / li >
< li class = " " data-name = "Badge#layout" > < a href = "Badge.html#layout" > layout< / a > < / li >
< li class = " " data-name = "Badge#show" > < a href = "Badge.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "BlurFilter" >
< span class = "title " >
< a href = "BlurFilter.html" > BlurFilter< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "BlurFilter#blur" > < a href = "BlurFilter.html#blur" > blur< / a > < / li >
< li class = "parent " data-name = "BlurFilter#shape" > < a href = "BlurFilter.html#shape" > shape< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Button" >
< span class = "title " >
< a href = "Button.html" > Button< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Button#active" > < a href = "Button.html#active" > active< / a > < / li >
< li class = "parent " data-name = "Button#disabled" > < a href = "Button.html#disabled" > disabled< / a > < / li >
< li class = "parent " data-name = "Button#iconColor" > < a href = "Button.html#iconColor" > iconColor< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Button#capture" > < a href = "Button.html#capture" > capture< / a > < / li >
< li class = "parent " data-name = "Button#hide" > < a href = "Button.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "Button#layout" > < a href = "Button.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "Button#show" > < a href = "Button.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "ButtonGroup" >
< span class = "title " >
< a href = "ButtonGroup.html" > ButtonGroup< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "ButtonGroup#disabled" > < a href = "ButtonGroup.html#disabled" > disabled< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "ButtonGroup#hide" > < a href = "ButtonGroup.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "ButtonGroup#layout" > < a href = "ButtonGroup.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "ButtonGroup#show" > < a href = "ButtonGroup.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "DeepZoomImage" >
< span class = "title " >
< a href = "DeepZoomImage.html" > DeepZoomImage< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "DeepZoomImage#baseSize" > < a href = "DeepZoomImage.html#baseSize" > baseSize< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#foreground" > < a href = "DeepZoomImage.html#foreground" > foreground< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#height" > < a href = "DeepZoomImage.html#height" > height< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#maxScale" > < a href = "DeepZoomImage.html#maxScale" > maxScale< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#pixelSize" > < a href = "DeepZoomImage.html#pixelSize" > pixelSize< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#width" > < a href = "DeepZoomImage.html#width" > width< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "DeepZoomImage#_calculateBounds" > < a href = "DeepZoomImage.html#_calculateBounds" > _calculateBounds< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#_createTiles" > < a href = "DeepZoomImage.html#_createTiles" > _createTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#activate" > < a href = "DeepZoomImage.html#activate" > activate< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#addTiles" > < a href = "DeepZoomImage.html#addTiles" > addTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#allTiles" > < a href = "DeepZoomImage.html#allTiles" > allTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#bringTilesToFront" > < a href = "DeepZoomImage.html#bringTilesToFront" > bringTilesToFront< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#calculateBounds" > < a href = "DeepZoomImage.html#calculateBounds" > calculateBounds< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#changedTiles" > < a href = "DeepZoomImage.html#changedTiles" > changedTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#deactivate" > < a href = "DeepZoomImage.html#deactivate" > deactivate< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#destroyObsoleteTiles" > < a href = "DeepZoomImage.html#destroyObsoleteTiles" > destroyObsoleteTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#destroyTiles" > < a href = "DeepZoomImage.html#destroyTiles" > destroyTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#destroyTilesAboveLevel" > < a href = "DeepZoomImage.html#destroyTilesAboveLevel" > destroyTilesAboveLevel< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#destroyUnneededTiles" > < a href = "DeepZoomImage.html#destroyUnneededTiles" > destroyUnneededTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#ensureAllTiles" > < a href = "DeepZoomImage.html#ensureAllTiles" > ensureAllTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#ensureTiles" > < a href = "DeepZoomImage.html#ensureTiles" > ensureTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#levelAndAlphaForScale" > < a href = "DeepZoomImage.html#levelAndAlphaForScale" > levelAndAlphaForScale< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#levelForScale" > < a href = "DeepZoomImage.html#levelForScale" > levelForScale< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#neededTiles" > < a href = "DeepZoomImage.html#neededTiles" > neededTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#populateAllTiles" > < a href = "DeepZoomImage.html#populateAllTiles" > populateAllTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#populateTiles" > < a href = "DeepZoomImage.html#populateTiles" > populateTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#setup" > < a href = "DeepZoomImage.html#setup" > setup< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#setupTiles" > < a href = "DeepZoomImage.html#setupTiles" > setupTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#thumbnail" > < a href = "DeepZoomImage.html#thumbnail" > thumbnail< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#tintObsoleteTiles" > < a href = "DeepZoomImage.html#tintObsoleteTiles" > tintObsoleteTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomImage#transformed" > < a href = "DeepZoomImage.html#transformed" > transformed< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "DeepZoomInfo" >
< span class = "title " >
< a href = "DeepZoomInfo.html" > DeepZoomInfo< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "DeepZoomInfo#dimensions" > < a href = "DeepZoomInfo.html#dimensions" > dimensions< / a > < / li >
< li class = "parent " data-name = "DeepZoomInfo#getDimensions" > < a href = "DeepZoomInfo.html#getDimensions" > getDimensions< / a > < / li >
< li class = "parent " data-name = "DeepZoomInfo#getNumTiles" > < a href = "DeepZoomInfo.html#getNumTiles" > getNumTiles< / a > < / li >
< li class = "parent " data-name = "DeepZoomInfo#getScale" > < a href = "DeepZoomInfo.html#getScale" > getScale< / a > < / li >
< li class = "parent " data-name = "DeepZoomInfo#imageForURL" > < a href = "DeepZoomInfo.html#imageForURL" > imageForURL< / a > < / li >
< li class = "parent " data-name = "DeepZoomInfo#urlForTile" > < a href = "DeepZoomInfo.html#urlForTile" > urlForTile< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Flippable" >
< span class = "title " >
< a href = "Flippable.html" > Flippable< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Flippable#flipped" > < a href = "Flippable.html#flipped" > flipped< / a > < / li >
< li class = "parent " data-name = "Flippable#frontSideInFront" > < a href = "Flippable.html#frontSideInFront" > frontSideInFront< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Flippable#layout" > < a href = "Flippable.html#layout" > layout< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "FontInfo" >
< span class = "title " >
< a href = "FontInfo.html" > FontInfo< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Hypenate" >
< span class = "title " >
< a href = "Hypenate.html" > Hypenate< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Hypenate.splitLines" > < a href = "Hypenate.html#.splitLines" > splitLines< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "InteractivePopup" >
< span class = "title " >
< a href = "InteractivePopup.html" > InteractivePopup< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = " " data-name = "InteractivePopup#content" > < a href = "InteractivePopup.html#content" > content< / a > < / li >
< li class = " " data-name = "InteractivePopup#header" > < a href = "InteractivePopup.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = " " data-name = "InteractivePopup#hide" > < a href = "InteractivePopup.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "InteractivePopup#layout" > < a href = "InteractivePopup.html#layout" > layout< / a > < / li >
< li class = " " data-name = "InteractivePopup#show" > < a href = "InteractivePopup.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "LabeledGraphics" >
< span class = "title " >
< a href = "LabeledGraphics.html" > LabeledGraphics< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "LabeledGraphics#clear" > < a href = "LabeledGraphics.html#clear" > clear< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#debugInfos" > < a href = "LabeledGraphics.html#debugInfos" > debugInfos< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#ensureLabel" > < a href = "LabeledGraphics.html#ensureLabel" > ensureLabel< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#getLabel" > < a href = "LabeledGraphics.html#getLabel" > getLabel< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#hideLabel" > < a href = "LabeledGraphics.html#hideLabel" > hideLabel< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#removeLabel" > < a href = "LabeledGraphics.html#removeLabel" > removeLabel< / a > < / li >
< li class = "parent " data-name = "LabeledGraphics#truncateLabel" > < a href = "LabeledGraphics.html#truncateLabel" > truncateLabel< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "LabeledGraphics.exports.LabeledGraphics" >
< span class = "title " >
< a href = "LabeledGraphics.exports.LabeledGraphics.html" > LabeledGraphics.exports.LabeledGraphics< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "List" >
< span class = "title " >
< a href = "List.html" > List< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "List#innerHeight" > < a href = "List.html#innerHeight" > innerHeight< / a > < / li >
< li class = "parent " data-name = "List#innerWidth" > < a href = "List.html#innerWidth" > innerWidth< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "List#capture" > < a href = "List.html#capture" > capture< / a > < / li >
< li class = "parent " data-name = "List#layout" > < a href = "List.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "List#resize" > < a href = "List.html#resize" > resize< / a > < / li >
< li class = "parent " data-name = "List#setItems" > < a href = "List.html#setItems" > setItems< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Message" >
< span class = "title " >
< a href = "Message.html" > Message< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Message#layout" > < a href = "Message.html#layout" > layout< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Modal" >
< span class = "title " >
< a href = "Modal.html" > Modal< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Modal#content" > < a href = "Modal.html#content" > content< / a > < / li >
< li class = "parent " data-name = "Modal#header" > < a href = "Modal.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Modal#hide" > < a href = "Modal.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "Modal#layout" > < a href = "Modal.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "Modal#show" > < a href = "Modal.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "PIXIApp" >
< span class = "title " >
< a href = "PIXIApp.html" > PIXIApp< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "PIXIApp#center" > < a href = "PIXIApp.html#center" > center< / a > < / li >
< li class = "parent " data-name = "PIXIApp#size" > < a href = "PIXIApp.html#size" > size< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "PIXIApp#addFpsDisplay" > < a href = "PIXIApp.html#addFpsDisplay" > addFpsDisplay< / a > < / li >
< li class = "parent " data-name = "PIXIApp#checkOrientation" > < a href = "PIXIApp.html#checkOrientation" > checkOrientation< / a > < / li >
< li class = "parent " data-name = "PIXIApp#convertPointFromNodeToPage" > < a href = "PIXIApp.html#convertPointFromNodeToPage" > convertPointFromNodeToPage< / a > < / li >
< li class = "parent " data-name = "PIXIApp#convertPointFromPageToNode" > < a href = "PIXIApp.html#convertPointFromPageToNode" > convertPointFromPageToNode< / a > < / li >
< li class = "parent " data-name = "PIXIApp#draw" > < a href = "PIXIApp.html#draw" > draw< / a > < / li >
< li class = "parent " data-name = "PIXIApp#expandRenderer" > < a href = "PIXIApp.html#expandRenderer" > expandRenderer< / a > < / li >
< li class = "parent " data-name = "PIXIApp#layout" > < a href = "PIXIApp.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "PIXIApp#loadSprites" > < a href = "PIXIApp.html#loadSprites" > loadSprites< / a > < / li >
< li class = "parent " data-name = "PIXIApp#loadTextures" > < a href = "PIXIApp.html#loadTextures" > loadTextures< / a > < / li >
< li class = "parent " data-name = "PIXIApp#message" > < a href = "PIXIApp.html#message" > message< / a > < / li >
< li class = "parent " data-name = "PIXIApp#modal" > < a href = "PIXIApp.html#modal" > modal< / a > < / li >
< li class = "parent " data-name = "PIXIApp#mutate" > < a href = "PIXIApp.html#mutate" > mutate< / a > < / li >
< li class = "parent " data-name = "PIXIApp#orientation" > < a href = "PIXIApp.html#orientation" > orientation< / a > < / li >
< li class = "parent " data-name = "PIXIApp#orientationChanged" > < a href = "PIXIApp.html#orientationChanged" > orientationChanged< / a > < / li >
< li class = "parent " data-name = "PIXIApp#progress" > < a href = "PIXIApp.html#progress" > progress< / a > < / li >
< li class = "parent " data-name = "PIXIApp#query" > < a href = "PIXIApp.html#query" > query< / a > < / li >
< li class = "parent " data-name = "PIXIApp#resize" > < a href = "PIXIApp.html#resize" > resize< / a > < / li >
< li class = "parent " data-name = "PIXIApp#setup" > < a href = "PIXIApp.html#setup" > setup< / a > < / li >
< li class = "parent " data-name = "PIXIApp#subscribe" > < a href = "PIXIApp.html#subscribe" > subscribe< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Popup" >
< span class = "title " >
< a href = "Popup.html" > Popup< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = " " data-name = "Popup#content" > < a href = "Popup.html#content" > content< / a > < / li >
< li class = " " data-name = "Popup#header" > < a href = "Popup.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = " " data-name = "Popup#hide" > < a href = "Popup.html#hide" > hide< / a > < / li >
< li class = " " data-name = "Popup#layout" > < a href = "Popup.html#layout" > layout< / a > < / li >
< li class = " " data-name = "Popup#show" > < a href = "Popup.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "PopupMenu" >
< span class = "title " >
< a href = "PopupMenu.html" > PopupMenu< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = " " data-name = "PopupMenu#content" > < a href = "PopupMenu.html#content" > content< / a > < / li >
< li class = " " data-name = "PopupMenu#header" > < a href = "PopupMenu.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = " " data-name = "PopupMenu#hide" > < a href = "PopupMenu.html#hide" > hide< / a > < / li >
< li class = " " data-name = "PopupMenu#layout" > < a href = "PopupMenu.html#layout" > layout< / a > < / li >
< li class = " " data-name = "PopupMenu#show" > < a href = "PopupMenu.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Progress" >
< span class = "title " >
< a href = "Progress.html" > Progress< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Progress#progress" > < a href = "Progress.html#progress" > progress< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Progress#hide" > < a href = "Progress.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "Progress#layout" > < a href = "Progress.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "Progress#show" > < a href = "Progress.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Slider" >
< span class = "title " >
< a href = "Slider.html" > Slider< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Slider#disabled" > < a href = "Slider.html#disabled" > disabled< / a > < / li >
< li class = "parent " data-name = "Slider#value" > < a href = "Slider.html#value" > value< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Slider#hide" > < a href = "Slider.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "Slider#layout" > < a href = "Slider.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "Slider#show" > < a href = "Slider.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Switch" >
< span class = "title " >
< a href = "Switch.html" > Switch< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "Switch#active" > < a href = "Switch.html#active" > active< / a > < / li >
< li class = "parent " data-name = "Switch#disabled" > < a href = "Switch.html#disabled" > disabled< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Switch#hide" > < a href = "Switch.html#hide" > hide< / a > < / li >
< li class = "parent " data-name = "Switch#layout" > < a href = "Switch.html#layout" > layout< / a > < / li >
< li class = "parent " data-name = "Switch#show" > < a href = "Switch.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "TextLabel.TextLabel" >
< span class = "title " >
< a href = "TextLabel.TextLabel.html" > TextLabel.TextLabel< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Theme" >
< span class = "title " >
< a href = "Theme.html" > Theme< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Theme.fromString" > < a href = "Theme.html#.fromString" > fromString< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "ThemeDark" >
< span class = "title " >
< a href = "ThemeDark.html" > ThemeDark< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "ThemeLight" >
< span class = "title " >
< a href = "ThemeLight.html" > ThemeLight< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "ThemeRed" >
< span class = "title " >
< a href = "ThemeRed.html" > ThemeRed< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "TileQuadNode" >
< span class = "title " >
< a href = "TileQuadNode.html" > TileQuadNode< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "TileQuadNode#link" > < a href = "TileQuadNode.html#link" > link< / a > < / li >
< li class = "parent " data-name = "TileQuadNode#noQuads" > < a href = "TileQuadNode.html#noQuads" > noQuads< / a > < / li >
< li class = "parent " data-name = "TileQuadNode#unlink" > < a href = "TileQuadNode.html#unlink" > unlink< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Tooltip" >
< span class = "title " >
< a href = "Tooltip.html" > Tooltip< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = " " data-name = "Tooltip#content" > < a href = "Tooltip.html#content" > content< / a > < / li >
< li class = " " data-name = "Tooltip#header" > < a href = "Tooltip.html#header" > header< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = " " data-name = "Tooltip#hide" > < a href = "Tooltip.html#hide" > hide< / a > < / li >
< li class = " " data-name = "Tooltip#layout" > < a href = "Tooltip.html#layout" > layout< / a > < / li >
< li class = " " data-name = "Tooltip#show" > < a href = "Tooltip.html#show" > show< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "UITest" >
< span class = "title " >
< a href = "UITest.html" > UITest< / a >
< / span >
< ul class = "members itemMembers" >
< span class = "subtitle" > Members< / span >
< li class = "parent " data-name = "UITest#timeline" > < a href = "UITest.html#timeline" > timeline< / a > < / li >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "UITest#clear" > < a href = "UITest.html#clear" > clear< / a > < / li >
< li class = "parent " data-name = "UITest#pan" > < a href = "UITest.html#pan" > pan< / a > < / li >
< li class = "parent " data-name = "UITest#pinch" > < a href = "UITest.html#pinch" > pinch< / a > < / li >
< li class = "parent " data-name = "UITest#restart" > < a href = "UITest.html#restart" > restart< / a > < / li >
< li class = "parent " data-name = "UITest#start" > < a href = "UITest.html#start" > start< / a > < / li >
< li class = "parent " data-name = "UITest#stop" > < a href = "UITest.html#stop" > stop< / a > < / li >
< li class = "parent " data-name = "UITest#tap" > < a href = "UITest.html#tap" > tap< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< li class = "item" data-name = "Volatile" >
< span class = "title " >
< a href = "Volatile.html" > Volatile< / a >
< / span >
< ul class = "members itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "typedefs itemMembers" >
< / ul >
< ul class = "methods itemMembers" >
< span class = "subtitle" > Methods< / span >
< li class = "parent " data-name = "Volatile#layout" > < a href = "Volatile.html#layout" > layout< / a > < / li >
< / ul >
< ul class = "events itemMembers" >
< / ul >
< / li >
< / ul >
< / div >
< div class = "main" >
< h1 class = "page-title" data-filename = "pixi_deepzoom_image.js.html" > Source: pixi/deepzoom/image.js< / h1 >
< section >
< header >
< div class = "header content-size" >
< h2 > pixi/deepzoom/image.js< / h2 >
< / div >
< / header >
< article >
< pre id = "source-code" class = "prettyprint source linenums" > < code > import { Capabilities } from '../../capabilities.js'
import { Points } from '../../utils.js'
import { deepZoomTileCache } from './tile.js'
import { Tiles } from './tiles.js'
function isEven(n) {
return n % 2 == 0
}
function printTileCacheInfos() {
let references = new Map()
let multiples = 0
for (let [url, tiles] of deepZoomTileCache.entries()) {
let count = tiles.size
references.set(url, count)
if (count > 1) {
multiples += 1
}
}
console.log({ multiples, references })
}
/**
* A utility class that holds information typically provided by DZI files, i.e.
* height and width of the overall image, overlap, and image type.
*
* @constructor
* @param {obj} attrs - A JSON-Object holding the listed keys and values
* @example
* {
* "tileSize": 1024,
* "format": "jpeg",
* "overlap": 1,
* "height": 4794,
* "width": 4095,
* "clip": { "minLevel": 12, "maxLevel": 20, "startCol": 301436, "startRow": 354060 },
* // optional: minLevel and maxLevel define the level bounds
* // startCol: first col at maxLevel
* // startRow: first row at maxLevel
* "path": "var/Vermeer/Vermeer_files",
* "type": "dzi", // optional: dzi (default) or map
* "urlTileTemplate": "{path}/{level}/{column}/{row}.{format}"
* // optional: {path}/{level}/{column}_{row}.{format} (default) or
* // a template String with the format of the URL
* }
*/
export class DeepZoomInfo {
constructor(attrs) {
for (let key in attrs) {
this[key] = attrs[key]
}
this.maxLevel = 0 // The highest level number, typically corresponds to the
// number in the file system for the folder with tiles
this.clip = this.clip || null // e.g. { level: 12, col: 301436, row: 354060 }
this.type = this.type || 'dzi'
this.urlTileTemplate =
this.urlTileTemplate || '{path}/{level}/{column}_{row}.{format}'
this.setupDimensions()
}
/* Computes the needed number of layers from the width and height
* of the image. Note that this includes the level 0, i.e. 0 ... 4
* means that 5 levels exist.
**/
numLevels() {
let maxDimension = Math.max(this.width, this.height)
let boundary = this.type === 'dzi' ? 1 : this.tileSize
let numLevels = 0
while (maxDimension >= boundary) {
maxDimension /= 2
numLevels++
}
return numLevels
}
/** Computes the scale at the given level.
* @param {number} level - The level of the wanted layer
* @returns {number} scale
**/
getScale(level) {
let scale = 1
if (this.type === 'dzi') {
scale = Math.pow(0.5, this.maxLevel - level + 1)
} else {
scale = Math.pow(0.5, this.maxLevel - level)
}
return scale
}
/** Computes the scaled width and height of the given level.
* @param {number} level - The level of the wanted layer
* @returns {array} size - The width and height
**/
getDimensions(level) {
let scale = this.getScale(level)
let w = Math.ceil(this.width * scale)
let h = Math.ceil(this.height * scale)
return [w, h]
}
/** Computes the number of cols and rows of tiles.
* @param {number} level - The level of the wanted layer
* @returns {array} size - The cols and rows
**/
getNumTiles(level) {
let dim = this.getDimensions(level)
let cols = Math.ceil(dim[0] / this.tileSize)
let rows = Math.ceil(dim[1] / this.tileSize)
if (this.clip) {
let rest = this.rests[level]
if (rest) {
if (rest.restCol) {
cols += 1
}
if (rest.restRows) {
rows += 1
}
}
}
return [cols, rows]
}
setupDimensions(loadBaseImage = false) {
/** Setup instance variables and load the base image, i.e. the largest
image that can be represented as a single tile.
@private
**/
let ww = this.width
let hh = this.height
let scale = 1.0
let level = 0
let single = 0
const tsize = this.tileSize
if (this.clip) {
this.baseLevel = this.clip.minLevel
this.maxLevel = this.clip.maxLevel
this.baseImage = null
this.size = this.getDimensions(this.baseLevel)
this.offsets = {}
this.rests = {}
let startCol = this.clip.startCol
let startRow = this.clip.startRow
let floatStartCol = startCol
let floatStartRow = startRow
for (let i = this.maxLevel; i >= this.baseLevel; i--) {
this.offsets[i] = { startCol, startRow }
let restCol = floatStartCol % 1
let restRow = floatStartRow % 1
this.rests[i] = { restCol, restRow }
startCol = Math.floor(startCol / 2)
startRow = Math.floor(startRow / 2)
floatStartCol /= 2
floatStartRow /= 2
}
} else {
const boundary = this.type === 'dzi' ? 1.0 : tsize
while (ww > boundary & & hh > boundary) {
if (ww >= tsize & & hh >= tsize) {
single += 1
}
scale = scale / 2.0
ww = Math.ceil(this.width * scale)
hh = Math.ceil(this.height * scale)
level += 1
}
this.baseLevel = level - single
this.maxLevel = this.numLevels() - 1
this.baseURL = this.urlForTile(this.baseLevel, 0, 0, false)
if (loadBaseImage) {
this.imageForURL(this.baseURL, e => {
this.size = [e.target.naturalWidth, e.target.naturalHeight]
this.baseImage = e.target
})
} else {
this.baseImage = null
this.size = this.getDimensions(this.baseLevel)
}
}
}
get maxLoadableLevel() {
if (this.clip) {
return this.maxLevel
}
return this.type === 'dzi' ? this.maxLevel : this.maxLevel
}
/** Computes the url for the given level, column and and row.
* @param {number} level - The level of the wanted layer
* @param {number} column - The column of the tile
* @param {number} row - The row of the tile
* @returns {string} url
**/
urlForTile(level, column, row, compressed = true) {
let format = this.format
if (compressed & & this.compression) {
let supported = Capabilities.isIOS ? 'pvr' : 'dds'
if (this.compression.indexOf(supported) >= 0) {
format = supported
}
}
if (this.clip) {
let offset = this.offsets[level]
if (offset) {
let { startCol, startRow } = offset
column += startCol
row += startRow
}
}
let url = this.urlTileTemplate
.replace(/\{path\}/g, this.path)
.replace(/\{level\}/g, level)
.replace(/\{row\}/g, row)
.replace(/\{column\}/g, column)
.replace(/\{format\}/g, format)
return url
}
/** Loads the image for the given url and executes a callback function
on completion.
* @param {string} url - The url of the tile
* @param {function} complete - The callback function
* @returns {Image} obj
**/
imageForURL(url, complete) {
let img = new Image()
img.onload = complete.bind(this)
img.src = url
return img
}
/** Computes the columns and rows as well as scaled width and height.
* @param {number} level - The level of the wanted layer
* @returns {array} [cols, rows, width, height]
**/
dimensions(level) {
let dim = this.getDimensions(level)
let tiles = this.getNumTiles(level)
return [tiles[0], tiles[1], dim[0], dim[1]]
}
test() {
//console.log("w=" + this.width + " h=" + this.height + " maxlevel=" + this.maxLevel + " base=" + this.baseLevel)
for (let i = 0; i < = this.maxLevel; i++) {
console.log(
' ' +
i +
' -> ' +
this.getScale(i) +
' [' +
this.dimensions(i) +
']'
)
}
console.log(this.urlForTile(this.baseLevel, 0, 0))
}
}
/**
* A utility class that describes a quad tree of tiles. Each tile on a given
* level has up to four corresponding tiles on the next level. A TileQuadNode
* uses the attributes nw (i.e. northwest), ne, sw, se to link to the
* quad nodes on the next level. The previous attributes links to the quad
* one level below that holds the given quad as nw, ne, sw, or se.
* We use this node class because we need a representation of tiles that are
* needed but not loaded yet to compute tiles which can be abandoned to reduce
* the memory pressure.
*
* @constructor
* @param {level} Number - The level the quad node belongs to
* @param {col} Number - The col of the quad
* @param {row} Number - The level the quad node belongs to
* @param {url} String - The level the quad node belongs to
*/
class TileQuadNode {
constructor(level, col, row, url) {
this.level = level
this.col = col
this.row = row
this.url = url
this.nw = null
this.ne = null
this.sw = null
this.se = null
this.previous = null
}
/** Return True if this node has no successors and can be used as
an indicator of tiles to free.
**/
noQuads() {
if (this.previous === null) return false
return (
this.nw === null & &
this.ne === null & &
this.sw === null & &
this.se === null
)
}
/** Unlink the given quad node
* @param {node} TileQuadNode - The TileQuadNode to remove
**/
unlink(node) {
if (this.nw === node) this.nw = null
if (this.ne === node) this.ne = null
if (this.sw === node) this.sw = null
if (this.se === node) this.se = null
}
/** Link this quad node to the given previous node. Use the north
* and west flags to address nw, ne, sw, and se.
* @param {node} TileQuadNode - The TileQuadNode to remove
* @param {north} Boolean - Link to north (true) or south (false)
* @param {west} Boolean - Link to west (true) or east (false)
**/
link(north, west, previous) {
this.previous = previous
if (north) {
if (west) {
previous.nw = this
} else {
previous.ne = this
}
} else {
if (west) {
previous.sw = this
} else {
previous.se = this
}
}
}
}
/**
* The main class of a deeply zoomable image that is represented by a hierarchy
* of tile layers for each zoom level. This gives the user the impression that
* even huge pictures (up to gigapixel-images) can be zoomed instantaneously,
* since the tiles at smaller levels are scaled immediately and overloaded by
* more detailed tiles at the larger level as fast as possible.
* @constructor
* @param {DeepZoomInfo} deepZoomInfo - Information extracted from a JSON-Object
*/
export class DeepZoomImage extends PIXI.Container {
constructor(
deepZoomInfo,
{
debug = false,
shadow = false,
center = false,
world = null, // Defines the world bounds the images lives in
highResolution = true,
autoLoadTiles = true,
preferWorker = false,
minimumLevel = 0,
alpha = 1,
app = window.app
} = {}
) {
super()
this.app = app
this.debug = debug
this.shadow = shadow
this.world = world
this.preferWorker = preferWorker
this.resolution = highResolution
? Math.round(window.devicePixelRatio)
: 1
this.alpha = alpha
this.fastLoads = 0
this.autoLoadTiles = autoLoadTiles
this.minimumLevel = minimumLevel
this.quadTrees = new Map() // url as keys, TileQuadNodes as values
this.setup(deepZoomInfo, center)
}
get point() {
if (this._point == null) {
let graphics = new PIXI.Graphics()
graphics.lineStyle(2, 0x00ff00)
graphics.drawCircle(0, 0, 2)
graphics.interactive = false
this._point = graphics
}
return this._point
}
/** Reads the DeepZoomInfo object and initializes all tile layers.
* Called by the constructor.
* Creates the sprite for the loaded texture and add the sprite to the tile
* layer.
* @param {Object} deepZoomInfo - the DeepZoomInfo instance
* @param {boolean} center - If true ensures that the pivot is set to the center
**/
setup(deepZoomInfo, center) {
this.info = deepZoomInfo
this.interactive = true
this.tileLayers = {}
this._foreground = null
this.tileContainer = new PIXI.Container()
this.tileContainer.interactive = false
let [w, h] = this.baseSize
if (this.shadow) {
this.filters = [new PIXI.filters.DropShadowFilter(45, 3)]
}
this.addChild(this.tileContainer)
if (deepZoomInfo.clip) {
let mask = new PIXI.Graphics()
mask.beginFill(1, 1)
mask.drawRect(0, 0, w, h)
mask.endFill()
this.mask = mask
mask.alpha = 0
this.addChild(mask)
this.minimumLevel = deepZoomInfo.baseLevel
}
this.currentLevel = Math.max(this.minimumLevel, deepZoomInfo.baseLevel)
console.log("autoLoadTiles", this.autoLoadTiles)
if (this.autoLoadTiles) {
this.setupTiles(center)
}
}
/** Default setup method for tiles. Loads all tiles of the current level.
Can be overwritten in subclasses.
@param {boolean} center - If true ensures that the pivot is set to the center
**/
setupTiles(center = false) {
// First load background tile
let tiles = this.ensureAllTiles(this.currentLevel)
if (center) {
this.pivot.set(w / 2, h / 2)
}
let scaleLevel = this.levelForScale(1)
this.ensureAllTiles(scaleLevel)
}
removeTileQuadNode(level, col, row, url) {
if (this.quadTrees.has(url)) {
let quad = this.quadTrees.get(url)
this.tileQuadRemoved(quad)
this.quadTrees.delete(url)
}
}
addTileQuadNode(level, col, row, url) {
if (this.quadTrees.has(url)) return this.quadTrees.get(url)
let quad = new TileQuadNode(level, col, row, url)
this.quadTrees.set(url, quad)
this.tileQuadAdded(quad)
return quad
}
tileQuadRemoved(quad) {
let below = quad.previous
// if (this.debug) console.log("tileQuadRemoved", quad)
if (below) {
below.unlink(quad)
if (below.noQuads()) {
if (this.debug) console.log('Removed tile below')
let levelBelow = quad.level - 1
if (levelBelow < this.minimumLevel) return
let c = Math.floor(quad.col / 2)
let r = Math.floor(quad.row / 2)
let urlBelow = this.info.urlForTile(levelBelow, c, r)
if (this.quadTrees.has(urlBelow)) {
this.removeTileQuadNode(levelBelow, c, r, urlBelow)
}
}
}
}
tileQuadAdded(quad) {
let levelBelow = quad.level - 1
if (levelBelow < this.minimumLevel) return
//if (this.debug) console.log("tileQuadAdded", quad)
let c = Math.floor(quad.col / 2)
let r = Math.floor(quad.row / 2)
let urlBelow = this.info.urlForTile(levelBelow, c, r)
let below = null
if (!this.quadTrees.has(urlBelow)) {
below = this.addTileQuadNode(levelBelow, c, r, urlBelow)
quad.link(isEven(quad.row), isEven(quad.col), below)
}
}
/** Returns the tile layer level that corresponds to the given scale.
* @param {number} scale - the scale factor
**/
levelForScale(scale) {
let level = Math.round(Math.log2(scale * this.resolution)) // Math.floor(Math.log2(event.scale))+1
let newLevel = this.info.baseLevel + Math.max(level, 0)
return Math.min(newLevel, this.info.maxLoadableLevel)
}
/** Returns the tile layer level that corresponds to the given scale.
* @param {number} scale - the scale factor
**/
levelAndAlphaForScale(scale) {
let value = Math.log2(scale * this.resolution)
let level = Math.round(value)
let newLevel = this.info.baseLevel + Math.max(level, 0)
return { level: Math.min(newLevel, this.info.maxLoadableLevel), alpha: value - level }
}
/** Adds a tile layer to the DeepZoomImage.
* @param {string} key - the access key
* @param {Tiles} tiles - the tile layer object
**/
addTiles(key, tiles) {
if (key in this.tileLayers) {
console.warn('Tiles already availabl', key)
}
this.tileContainer.addChild(tiles)
this.tileLayers[key] = tiles
}
destroyTiles(key) {
let tiles = this.tileLayers[key]
this.tileContainer.removeChild(tiles)
tiles.destroy()
delete this.tileLayers[key]
}
/** Getter for PIXI.Container foreground layer.
* Adds a PIXI.Container if necessary.
**/
get foreground() {
if (this._foreground == null) {
this._foreground = new PIXI.Container()
this.addChild(this._foreground)
}
return this._foreground
}
/** Getter for the DeepZoomInfo base level size.
**/
get baseSize() {
return this.info.getDimensions(this.info.baseLevel)
}
/** Getter for the current scaled size in pixels.
**/
get pixelSize() {
let [w, h] = this.baseSize
return [w * this.scale.x, h * this.scale.y]
}
/** Getter for the max scale factor.
**/
get maxScale() {
let delta = this.info.maxLevel - this.info.baseLevel
return Math.pow(2, delta) / this.resolution * 2
}
/** Getter for the current width.
**/
get width() {
return this.pixelSize[0]
}
/** Getter for the current height.
**/
get height() {
return this.pixelSize[1]
}
/* Overrides PIXI.Container.hitArea()
* Allows to optimize the hit testing. Container with hit areas are directly
* hit tested without consideration of children.
*/
get hitArea() {
// Defining the hitArea resulted hitting the scatter in masked area
// when a mask was used (@Tüsch[submaps]). Removing the hitArea() altogether
// broke the interaction in other projects (@googleart).
// Fix: When masked, the hitArea is ignored by returning null.
// TODO: test if childs are hittested, without setting interactiveChildren.
// Opel, 03-05-2018
if (this.mask) {
return null
}
return this
}
/* Overrides PIXI.Container.contains()
* Allows to optimize the hit testing.
*/
contains(x, y) {
let [w, h] = this.baseSize
return x >= 0 & & x < = w & & y >= 0 & & y < = h
}
/** Overrides PIXI.Container._calculateBounds()
* Only considers the base size and reduces the calculation to a single
* rect.
*/
_calculateBounds() {
let [w, h] = this.baseSize
this._bounds.addFrame(this.transform, 0, 0, w, h)
}
/** Overrides PIXI.Container.calculateBounds()
* Skips the children and only considers the deep zoom base size. Calls
* the also overwritten _calculateBounds method.
*/
calculateBounds() {
this._bounds.clear()
this._calculateBounds()
this._lastBoundsID = this._boundsID
}
/** Returns a single sprite that can be used a thumbnail representation of
* large images.
* @return {Sprite} sprite - A sprite with a single tile texture
*/
thumbnail() {
return new PIXI.Sprite.fromImage(this.info.baseURL)
}
/** Returns a list of all tiles of a given level.
* @param {Tiles} tiles - the grid of tiles
* @param {number} level - The zoom level of the grid
* @return {Array[]} - An array of [url, col, row] arrays
**/
allTiles(tiles, level) {
let result = []
for (let col = 0; col < tiles.cols; col++) {
for (let row = 0; row < tiles.rows; row++) {
let url = this.info.urlForTile(level, col, row)
result.push([url, col, row])
}
}
return result
}
worldBounds() {
let viewBounds = this.app.scene.bounds
// Using getBounds extends visible scope after loading tiles and leads
// to excessive loading
if (this.world != null) {
let bounds = this.world.bounds
let x = Math.max(-bounds.width, bounds.x)
let y = Math.max(-bounds.height, bounds.y)
let width = Math.min(viewBounds.width, bounds.width)
let height = Math.min(viewBounds.height, bounds.height)
//console.log("worldBounds new", { x, y, width, height })
return { x, y, width, height }
}
//console.log("worldBounds old", viewBounds)
return viewBounds
}
/** Loads all tiles that are needed to fill the app bounds.
* @param {Tiles} tiles - the grid of tiles
* @param {number} level - The zoom level of the grid
* @param {boolean} debug
* @return {Array[]} - An array of [url, col, row] arrays
*/
neededTiles(tiles, level, debug = false) {
let needed = []
let tsize = tiles.tileSize
let worldBounds = this.worldBounds()
let maxWidth = worldBounds.width
let maxHeight = worldBounds.height
let pointInWindow = new PIXI.Point()
let worldTopLeft = new PIXI.Point(worldBounds.x, worldBounds.y)
let worldBottomRight = new PIXI.Point(worldBounds.x + maxWidth, worldBounds.y + maxHeight)
let worldCenter = new PIXI.Point(worldBounds.x + maxWidth / 2, worldBounds.y + maxHeight / 2)
let tilesCenter = tiles.toLocal(worldCenter)
let topLeft = tiles.toLocal(worldTopLeft)
let bottomRight = tiles.toLocal(worldBottomRight)
tiles._centerPoint = tilesCenter
let bounds = new PIXI.Rectangle(
topLeft.x,
topLeft.y,
bottomRight.x - topLeft.x,
bottomRight.y - topLeft.y)
tiles._boundsRect = bounds
/* UO: we need a toLocal call here since the transform may need an update
which is guaranteed by the toLocal method. */
let centerCol = Math.floor(tilesCenter.x / tsize)
let centerRow = Math.floor(tilesCenter.y / tsize)
// Expand because we want to test for included centers
bounds.x -= tsize / 2
bounds.y -= tsize / 2
bounds.width += tsize
bounds.height += tsize
try {
let maxTilesWidth = Math.ceil(maxWidth / tsize)
let maxTilesHeight = Math.ceil(maxHeight / tsize)
maxTilesWidth += 2
maxTilesHeight += 2
let startCol = Math.max(0, centerCol - maxTilesWidth)
let endCol = Math.min(tiles.cols, centerCol + maxTilesWidth)
let startRow = Math.max(0, centerRow - maxTilesHeight)
let endRow = Math.min(tiles.rows, centerRow + maxTilesHeight)
for (let col = startCol; col < endCol; col++) {
let cx = (col + 0.5) * tsize
for (let row = startRow; row < endRow; row++) {
let cy = (row + 0.5) * tsize
let tileCenter = new PIXI.Point(cx, cy)
if (bounds.contains(tileCenter.x, tileCenter.y)) {
let url = this.info.urlForTile(level, col, row)
needed.push([url, col, row])
}
}
}
} catch (error) {
console.warn(error.message)
}
return { centerCol, centerRow, needed }
}
/** Returns all changed tiles for a given level.
* @param {Tiles} tiles - the grid of tiles
* @param {number} level - The zoom level of the grid
* @return {object} - An object with the keys added and removed which values are [url, col, row] arrays
*/
changedTiles(tiles, level) {
if (this.debug) console.time('changedTiles')
let changed = { added: [], removed: [] }
let newNeeded = new Map()
let { centerCol, centerRow, needed } = this.neededTiles(tiles, level)
needed.forEach(d => {
let [url, col, row] = d
newNeeded.set(url, [col, row])
if (!tiles.requested.has(url)) {
changed.added.push(d)
}
})
for (let url of tiles.needed.keys()) {
if (!newNeeded.has(url)) {
let [col, row] = tiles.needed.get(url)
changed.removed.push([url, col, row])
}
}
tiles.needed = newNeeded
if (this.debug) console.log(newNeeded)
if (this.debug) console.timeEnd('changedTiles')
return { centerCol, centerRow, changed }
}
/** Populates all tiles for a given level.
* @param {Tiles} tiles - the grid of tiles
* @param {number} level - The zoom level of the grid
*/
populateAllTiles(tiles, level) {
let all = this.allTiles(tiles, level)
for (let [url, col, row] of all) {
this.addTileQuadNode(level, col, row, url)
}
tiles.loadTiles(all, false, 0, 0)
}
/** Loads all tiles that are needed to fill the browser window.
* If the optional about parameter is provided (as a point with col as x,
* and row as y attr) the tiles are sorted by the distance to this point.
*
* @param {Tiles} tiles - the grid of tiles
* @param {number} level - The zoom level of the grid
* Optional parameter:
* @param {boolean} onlyone - if true only one tile is loaded
* @param {PIXI.Point} about - point of interaction
*/
populateTiles(tiles, level, { onlyone = false, about = null } = {}) {
if (tiles.isComplete())
return
let referenceCol = -1
let referenceRow = -1
let { centerCol, centerRow, changed } = this.changedTiles(tiles, level)
if (about != null) {
// We want to load tiles in the focus of the user first, therefore
// we sort according to the distance of the focus of interaction
let refPoint = this.toLocal(about)
let scaledTileSize = tiles.tileSize * tiles.tileScale
referenceCol = Math.floor(refPoint.x / scaledTileSize)
referenceRow = Math.floor(refPoint.y / scaledTileSize)
}
else {
referenceCol = centerCol
referenceRow = centerRow
}
referenceCol = centerCol
referenceRow = centerRow
let removed = changed.removed
for (let [url, col, row] of removed) {
this.removeTileQuadNode(level, col, row, url)
}
let added = changed.added
if (added.length == 0) return
for (let [url, col, row] of added) {
this.addTileQuadNode(level, col, row, url)
}
let ref = new PIXI.Point(referenceCol, referenceRow)
// Note: The array must be sorted in a way that the nearest tiles
// are at the end of the array since the load queue uses Array.push
// Array.pop
added.sort((a, b) => {
let aa = new PIXI.Point(a[1], a[2])
let bb = new PIXI.Point(b[1], b[2])
let da = Points.distance(aa, ref)
let db = Points.distance(bb, ref)
return db - da
})
tiles.loadTiles(added, onlyone, referenceCol, referenceRow)
}
/** Private method: creates all tiles for a given level.
* @param {number} level - The zoom level of the grid
* @return {Tiles} - tiles
*/
_createTiles(key, level) {
let [cols, rows, w, h] = this.info.dimensions(level)
let increasedLevels = level - this.info.baseLevel
let invScale = Math.pow(0.5, increasedLevels)
let tiles = new Tiles(
level,
this,
invScale,
cols,
rows,
w,
h,
this.info.tileSize,
this.info.overlap
)
this.addTiles(key, tiles)
if (this.info.clip) {
let rest = this.info.rests[level]
if (rest) {
let x = rest.restCol * this.info.tileSize * invScale
let y = rest.restRow * this.info.tileSize * invScale
tiles.x = -x
tiles.y = -y
}
}
return tiles
}
/** Ensures that all needed tiles of a given level are loaded. Creates
* a new Tiles layer if necessary
* @param {number} level - The zoom level of the grid
* @return {Tiles} tiles
*/
ensureTiles(level, about) {
let key = level.toString()
if (key in this.tileLayers) {
let tiles = this.tileLayers[key]
this.populateTiles(tiles, level, { about: about })
return tiles
}
let tiles = this._createTiles(key, level)
this.populateTiles(tiles, level, { about: about })
//console.log("ensureTiles", level)
return tiles
}
untintTiles(level) {
let key = level.toString()
if (key in this.tileLayers) {
let tiles = this.tileLayers[key]
}
}
/** Ensures that all tiles of a given level are loaded.
* @param {number} level - The zoom level of the grid
*/
ensureAllTiles(level) {
let key = level.toString()
if (key in this.tileLayers) {
let tiles = this.tileLayers[key]
this.populateAllTiles(tiles, level)
tiles.keep = true
return
}
let tiles = this._createTiles(key, level)
this.populateAllTiles(tiles, level)
tiles.keep = true
return tiles
}
hideTilesAboveLevel(level) {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (tiles.level > level) {
tiles.visible = false
}
})
}
/** Destroys all tiles above a given level to ensure that the memory can
* be reused.
* @param {number} level - The zoom level of the grid
*/
destroyTilesAboveLevel(level) {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (tiles.level > level & & !tiles.keep) {
for (let url of tiles.available.keys()) {
let quad = this.quadTrees.get(url)
if (quad) this.removeTileQuadNode(quad)
}
this.destroyTiles(key)
}
})
}
destroyAllTiles() {
Object.keys(this.tileLayers).forEach(key => {
this.destroyTiles(key)
})
}
/**
* Tint tiles in all layers that are no longer needed
*
* @memberof DeepZoomImage
*/
tintObsoleteTiles() {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
tiles.untintTiles()
if (!tiles.keep) {
tiles.tintObsoleteTiles()
}
})
}
/**
* Destroy tiles in all layers that are no longer needed
*
* @memberof DeepZoomImage
*/
destroyUnneededTiles() {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (!tiles.keep) {
tiles.destroyUnneededTiles()
}
})
}
/**
* Destroy tiles in all layers that are no longer needed
*
* @memberof DeepZoomImage
*/
destroyObsoleteTiles() {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (!tiles.keep) {
tiles.destroyObsoleteTiles()
}
})
}
/**
* Destroy tiles in all layers that are not part of the
* visible quadTrees
*
* @memberof DeepZoomImage
*/
destroyTiles() {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (!tiles.keep) {
tiles.destroyTiles(this.quadTrees)
}
})
}
/* Tint all tiles
* @param {number} level - The zoom level of the grid
*/
tintTilesBelowLevel(level) {
Object.keys(this.tileLayers).forEach(key => {
let tiles = this.tileLayers[key]
if (tiles.level < level) {
tiles.tintTiles(this.quadTrees)
}
})
}
/**
* Ensure that the given tiles layer is the topmost one and visible.
* @param {*} tiles
*/
bringTilesToFront(tiles) {
this.tileContainer.addChild(tiles)
tiles.visible = true
}
/** A callback function that can be used by a Scatter view to inform
* the zoomable image that it has been moved, rotated or scaled, and should
* load tiles accordingly.
* @param {PIXI.Point} translated - the movement of the scatter
* @param {number} scale - the zoom factor
* @param {PIXI.Point} about - the anchor point of the zoom
* @param {boolean} fast - informs the callback to return as fast as possible,
* i.e. after loading a single tile
* @param {boolean} debug - log debug infos
*/
transformed(event) {
let key = this.currentLevel.toString()
let currentTiles = this.tileLayers[key]
if (typeof currentTiles == 'undefined') {
return
}
if (event.fast) {
this.fastLoads += 1
this.populateTiles(currentTiles, this.currentLevel, {
onlyone: false,
about: event.about
})
if (this.fastLoads == 3) {
this.fastLoads = 0
}
else {
return
}
}
if (event.scale == null) {
this.ensureTiles(this.currentLevel, event.about)
return
}
let level = this.levelForScale(event.scale)
let newLevel = Math.max(level, this.minimumLevel)
if (newLevel != this.currentLevel) {
if (!currentTiles.keep) {
currentTiles.loader.cancel()
}
this.hideTilesAboveLevel(newLevel)
currentTiles = this.ensureTiles(newLevel, event.about)
this.currentLevel = newLevel
} else {
this.ensureTiles(this.currentLevel, event.about)
}
this.bringTilesToFront(currentTiles)
if (this._foreground) {
this.addChild(this._foreground)
}
}
/**
*Activates the textures on the DeepZoomImage.
*
* @memberof DeepZoomImage
*/
activate() {
this.destroyTilesAboveLevel(this.currentLevel)
this.ensureTiles(this.currentLevel, null)
//console.log("Activate Textures!", this.currentLevel)
}
/**
*Dectivates the textures on the DeepZoomImage.
*
* @memberof DeepZoomImage
*/
deactivate() {
this.destroyAllTiles()
Object.keys(this.tileLayers).forEach(key => {
this.destroyTiles(key)
})
this.tileContainer.destroy({ children: true })
printTileCacheInfos()
}
throwFinished() {
console.log("throwFinished")
let key = this.currentLevel.toString()
let currentTiles = this.tileLayers[key]
if (typeof currentTiles == 'undefined') {
return
}
this.ensureTiles(this.currentLevel)
// let all = new Set()
// for (let tile of currentTiles.children) {
// all.add(tile.url)
// }
// let { centerCol, centerRow, needed } = this.neededTiles(currentTiles, this.currentLevel)
// for (let [url, col, row] of needed) {
// all.delete(url)
// }
// for (let url of all) {
// currentTiles.destroyTileByUrl(url)
// }
// currentTiles.loader.loader.reset()
}
}
< / code > < / pre >
< / article >
< / section >
< footer class = "content-size" >
< div class = "footer" >
2019-03-29 11:44:34 +01:00
Documentation generated by < a href = "https://github.com/jsdoc3/jsdoc" > JSDoc 3.5.5< / a > on Fri Mar 29 2019 11:44:08 GMT+0100 (Mitteleuropäische Normalzeit)
2019-03-29 08:49:53 +01:00
< / div >
< / footer >
< / div >
< / div >
< script > prettyPrint ( ) ; < / script >
< script src = "scripts/main.js" > < / script >
< / body >
< / html >