project files added

This commit is contained in:
mhalfmann
2021-06-15 16:00:08 +02:00
parent e156e2f053
commit db46afa351
13928 changed files with 1569902 additions and 0 deletions
+351
View File
@@ -0,0 +1,351 @@
import Theme from './theme.js'
/**
* Class that represents a PixiJS AbstractPopup.
* The class is used for various other Popup-like classes
* like Popup, Message, Tooltip...
*
* @class
* @abstract
* @extends PIXI.Graphics
* @see {@link http://pixijs.download/dev/docs/PIXI.Graphics.html|PIXI.Graphics}
*/
export default class AbstractPopup extends PIXI.Graphics {
/**
* Creates an instance of an AbstractPopup (only for internal use).
*
* @constructor
* @param {object} [opts] - An options object to specify to style and behaviour of the popup.
* @param {number} [opts.id=auto generated] - The id of the popup.
* @param {number} [opts.x=0] - The x position of the popup. Can be also set after creation with popup.x = 0.
* @param {number} [opts.y=0] - The y position of the popup. Can be also set after creation with popup.y = 0.
* @param {string|Theme} [opts.theme=dark] - The theme to use for this popup. Possible values are dark, light, red
* or a Theme object.
* @param {string|number|PIXI.Text} [opts.header] - The heading inside the popup as a string, a number (will be
* converted to a text) or as a PIXI.Text object.
* @param {string|number|PIXI.DisplayObject} [opts.content] - A text, a number (will be converted to a text) or
* an PIXI.DisplayObject as the content of the popup.
* @param {number} [opts.minWidth=320] - The minimum width of the popup.
* @param {number} [opts.minHeight=130] - The minimum height of the popup.
* @param {number} [opts.padding=Theme.padding] - The inner spacing (distance from header and content) the the border.
* @param {number} [opts.fill=Theme.fill] - The color of the button background as a hex value.
* @param {number} [opts.fillAlpha=Theme.fillAlpha] - The alpha value of the background.
* @param {number} [opts.stroke=Theme.stroke] - The color of the border as a hex value.
* @param {number} [opts.strokeWidth=Theme.strokeWidth] - The width of the border in pixel.
* @param {number} [opts.strokeAlpha=Theme.strokeAlpha] - The alpha value of the border.
* @param {object} [opts.headerStyle=Theme.textStyleLarge] - A textstyle object for the styling of the header. See PIXI.TextStyle
* for possible options.
* @param {object} [opts.textStyle=Theme.textStyleSmall] - A textstyle object for the styling of the text. See PIXI.TextStyle
* for possible options.
* @param {number} [opts.radius=Theme.radius] - The radius of the four corners of the popup (which is a rounded rectangle).
* @param {hiddenCallback} [opts.onHidden] - Executed when the popup gets hidden.
* @param {boolean} [opts.visible=true] - Is the popup initially visible (property visible)?
* @param {string} [opts.orientation] - When set to portrait, the popup cannot be displayed in landscape mode. When set
* to landscape, the popup cannot be displayed in portrait mode.
*/
constructor(opts = {}) {
super()
const theme = Theme.fromString(opts.theme)
this.theme = theme
this.opts = Object.assign(
{},
{
id: PIXI.utils.uid(),
x: 0,
y: 0,
header: null, // null or null
content: null, // null or String or PIXI.DisplayObject
minWidth: 320,
minHeight: 130,
maxWidth: null,
padding: theme.padding,
fill: theme.fill,
fillAlpha: theme.fillAlpha,
stroke: theme.stroke,
strokeWidth: theme.strokeWidth,
strokeAlpha: theme.strokeAlpha,
headerStyle: theme.textStyleLarge,
textStyle: theme.textStyleSmall,
radius: theme.radius,
onHidden: null,
visible: true,
orientation: null
},
opts
)
this.id = this.opts.id
this.headerStyle = new PIXI.TextStyle(this.opts.headerStyle)
this.textStyle = new PIXI.TextStyle(this.opts.textStyle)
if (this.opts.maxWidth) {
this.headerStyle.wordWrap = true
this.headerStyle.wordWrapWidth = this.opts.maxWidth - 2 * this.opts.padding
this.textStyle.wordWrap = true
this.textStyle.wordWrapWidth = this.opts.maxWidth - 2 * this.opts.padding
}
this.alpha = 0
this.visible = this.opts.visible
this._header = null
this._content = null
// position
this.x = this.opts.x
this.y = this.opts.y
// padding
this.innerPadding = this.opts.padding * 1.5
// interaction
//-----------------
this.interactive = true
this.on('added', e => {
this.show()
})
}
/**
* Creates the framework and instantiates everything.
*
* @private
* @return {AbstractPopup} A reference to the popup for chaining.
*/
setup() {
// position
//-----------------
this.sy = this.opts.padding
// header
//-----------------
if (this.opts.header != null) {
let header = null
if (this.opts.header instanceof PIXI.Text) {
header = this.opts.header
} else if (typeof this.opts.header === 'number') {
header = new PIXI.Text(this.opts.header.toString(), this.headerStyle)
} else {
header = new PIXI.Text(this.opts.header, this.headerStyle)
}
header.x = this.opts.padding
header.y = this.sy
this.addChild(header)
this.sy += header.height
this._header = header
}
if (this.opts.header && this.opts.content) {
this.sy += this.innerPadding
}
// content
//-----------------
if (this.opts.content != null) {
let content = null
if (typeof this.opts.content === 'string') {
content = new PIXI.Text(this.opts.content, this.textStyle)
} else if (typeof this.opts.content === 'number') {
content = new PIXI.Text(this.opts.content.toString(), this.textStyle)
} else {
content = this.opts.content
}
content.x = this.opts.padding
content.y = this.sy
this.sy += content.height
this.addChild(content)
this._content = content
}
return this
}
/**
* Should be called to refresh the layout of the popup. Can be used after resizing.
*
* @return {AbstractPopup} A reference to the popup for chaining.
*/
layout() {
// wanted width & wanted height
//-----------------
const padding = this.opts.padding
const size = this.getInnerSize()
const width = size.width + 2 * padding
const height = size.height + 2 * padding
this.wantedWidth = Math.max(width, this.opts.minWidth)
this.wantedHeight = Math.max(height, this.opts.minHeight)
if (this.opts.maxWidth) {
this.wantedWidth = Math.min(this.wantedWidth, this.opts.maxWidth)
}
if (this.opts.radius * 2 > this.wantedWidth) {
this.wantedWidth = this.opts.radius * 2
}
if (this.opts.radius * 2 > this.wantedHeight) {
this.wantedHeight = this.opts.radius * 2
}
switch (this.opts.orientation) {
case 'portrait':
if (this.wantedWidth > this.wantedHeight) {
this.wantedHeight = this.wantedWidth
}
break
case 'landscape':
if (this.wantedHeight > this.wantedWidth) {
this.wantedWidth = this.wantedHeight
}
break
}
this.draw()
return this
}
/**
* Draws the canvas.
*
* @private
* @return {AbstractPopup} A reference to the popup for chaining.
*/
draw() {
const square = Math.round(this.wantedWidth) === Math.round(this.wantedHeight)
const diameter = Math.round(this.opts.radius * 2)
this.clear()
this.lineStyle(this.opts.strokeWidth, this.opts.stroke, this.opts.strokeAlpha)
this.beginFill(this.opts.fill, this.opts.fillAlpha)
if (square && diameter === this.wantedWidth) {
this.drawCircle(this.wantedWidth / 2, this.wantedHeight / 2, this.opts.radius)
} else {
this.drawRoundedRect(0, 0, this.wantedWidth, this.wantedHeight, this.opts.radius)
}
this.endFill()
return this
}
/**
* Calculates the size of the children of the AbstractPopup.
* Cannot use getBounds() because it is not updated when children
* are removed.
*
* @private
* @returns {object} An JavaScript object width the keys width and height.
*/
getInnerSize() {
let width = 0
let height = 0
if (this._header) {
width = this._header.width
height = this._header.height
}
if (this._header && this._content) {
height += this.innerPadding
}
if (this._content) {
width = Math.max(width, this._content.width)
height += this._content.height
}
return { width, height }
}
/**
* Shows the popup (sets his alpha values to 1).
*
* @param {callback} [cb] - Executed when show animation was completed.
* @return {AbstractPopup} A reference to the popup for chaining.
*/
show(cb) {
TweenLite.to(this, this.theme.fast, {
alpha: 1,
onComplete: () => {
if (cb) {
cb.call(this)
}
}
})
return this
}
/**
* Hides the popup (sets his alpha values to 0).
*
* @param {callback} [cb] - Executed when hide animation was completed.
* @return {AbstractPopup} A reference to the popup for chaining.
*/
hide(cb) {
TweenLite.to(this, this.theme.fast, {
alpha: 0,
onComplete: () => {
this.visible = false
if (cb) {
cb.call(this)
}
}
})
if (this.opts.onHidden) {
this.opts.onHidden.call(this, this)
}
return this
}
/**
* Sets or gets the header. The getter always returns a PIXI.Text object. The setter can receive
* a string, a number or a PIXI.Text object.
*
* @member {string|number|PIXI.Text}
*/
get header() {
return this._header
}
set header(value) {
if (this._header) {
this._header.destroy()
}
this.opts.header = value
this.setup().layout()
}
/**
* Sets or gets the content. The getter always returns an PIXI.DisplayObject. The setter can receive
* a string, a number or a PIXI.DisplayObject.
*
* @member {string|number|PIXI.DisplayObject}
*/
get content() {
return this._content
}
set content(value) {
if (this._content) {
this._content.destroy()
}
this.opts.content = value
this.setup().layout()
}
}
+117
View File
@@ -0,0 +1,117 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PIXI Application Resolution Doctest</title>
<link rel="stylesheet" href=".././3rdparty/highlight/styles/default.css">
<link rel="stylesheet" href="../../css/doctest.css">
<script src=".././3rdparty/highlight/highlight.pack.js"></script>
<script src=".././3rdparty/all.js"></script>
<script src=".../../dist/iwmlib.pixi.js"></script>
<script src="../../dist/iwmlib.pixi.js"></script>
<style>
#dpi {
height: 1in;
left: -100%;
position: absolute;
top: -100%;
width: 1in;
}
</style>
</head>
<body onload="Doctest.run()">
<h1>Application Resolution</h1>
<p>
This is a doc test page to examine the width and height of canvas elements at different resolutions.
</p>
<p>Further documentation:</p>
<ul>
<li><a href="https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html">WebGL Fundamentals</a></li>
<li><a href="https://www.khronos.org/webgl/wiki/HandlingHighDPI">Handling High DPI</a></li>
</ul>
<p>Device properties:</p>
<ul>
<li id="dpi-result">Your screen has <span></span> dpi.</li>
<li id="dpr-result">Your screen has a device-pixel-ratio of <span></span>.</li>
</ul>
<p>
Set width and height per CSS: <input type="checkbox" />
</p>
<script>
let scaled = false
$('input[type="checkbox"]').click(function(e) {
if ($(this).prop('checked')) {
$('#canvas1').css({width: '100px', height: '100px'})
$('#canvas2').css({width: '100px', height: '100px'})
$('#canvas3').css({width: '100px', height: '100px'})
$('#canvas4').css({width: '100px', height: '100px'})
} else {
$('#canvas1').css({width: 'auto', height: 'auto'})
$('#canvas2').css({width: 'auto', height: 'auto'})
$('#canvas3').css({width: 'auto', height: 'auto'})
$('#canvas4').css({width: 'auto', height: 'auto'})
}
})
</script>
<p>Let's look at some canvas resolution examples:</p>
<div id="dpi"></div>
<script>
$('#dpi-result span').text(document.getElementById("dpi").offsetHeight)
$('#dpr-result span').text(window.devicePixelRatio)
</script>
<script>
const style = new PIXI.TextStyle({
fontStyle: 'italic',
fontWeight: 'bold',
fill: ['#ffffff', '#00ff99'],
stroke: '#4a1850',
strokeThickness: 5,
wordWrap: true,
wordWrapWidth: 440
})
</script>
<canvas id="canvas1" class="interactive"></canvas>
<script class="doctest">
const app1 = new PIXI.Application({width: 100, height: 100, resolution: 1, backgroundColor : 0xf8ce2d, view: canvas1})
const text11 = new PIXI.Text('AaBb12')
const text12 = new PIXI.Text('IWM', style)
text12.y = 30
app1.stage.addChild(text11, text12)
</script>
<canvas id="canvas2" class="interactive"></canvas>
<script class="doctest">
const app2 = new PIXI.Application({width: 100, height: 100, resolution: 2, backgroundColor : 0xfd6b6a, view: canvas2})
const text21 = new PIXI.Text('AaBb12')
const text22 = new PIXI.Text('IWM', style)
text22.y = 30
app2.stage.addChild(text21, text22)
</script>
<canvas id="canvas3" class="interactive"></canvas>
<script class="doctest">
const app3 = new PIXI.Application({width: 100, height: 100, resolution: 3, backgroundColor : 0x40c3f2, view: canvas3})
const text31 = new PIXI.Text('AaBb12')
const text32 = new PIXI.Text('IWM', style)
text32.y = 30
app3.stage.addChild(text31, text32)
</script>
<canvas id="canvas4" class="interactive"></canvas>
<script class="doctest">
const app4 = new PIXI.Application({width: 100, height: 100, resolution: window.devicePixelRatio, backgroundColor : 0xd7a3f9, view: canvas4})
const text41 = new PIXI.Text('AaBb12')
const text42 = new PIXI.Text('IWM', style)
text42.y = 30
app4.stage.addChild(text41, text42)
</script>
</body>
+70
View File
@@ -0,0 +1,70 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PIXI Application Doctest</title>
<link rel="stylesheet" href=".././3rdparty/highlight/styles/default.css">
<link rel="stylesheet" href="../../css/doctest.css">
<script src=".././3rdparty/highlight/highlight.pack.js"></script>
<script src="../../dist/iwmlib.3rdparty.js"></script>
<script src="../../dist/iwmlib.js"></script>
<script src="../../dist/iwmlib.pixi.js"></script>
</head>
<body onload="Doctest.run()">
<h1>Application</h1>
<p>
The class PIXIApp is the main entry point to create a new PIXI Application.
It inherits from PIXI.Application, set meaningfull defaults, creates a scene and
a stage and provides some helper methods to load resources, get the size of
the app...
</p>
<p>
The pattern to create a new application is:
<ol>
<li>Create a new PIXIApp Object</li>
<li>Call the setup() method</li>
<li>Call the run() method</li>
</ol>
These three steps are required. The constructor has been split into these three parts in order to have the greatest possible flexibility in complex applications.
The setup() method creates a default scene. This can be overwritten with a spezialized setup() method to create a scatter container, for example.
</p>
<p><a href="../../doc/out/PIXIApp.html">JavaScript API</a></p>
<p>Let's look at an example of creating a new application:</p>
<canvas id="canvas" class="interactive"></canvas>
<p>
What you should see: There should be a green circle on a dark background. In the upper left corner, the refresh rate should be approximately 60 fps.
</p>
<script class="doctest">
const app = new PIXIApp({
view: canvas,
width: 450,
height: 150,
fpsLogging: true,
transparent: false
})
app.setup()
app.run()
let highlightBtn = new PIXI.Graphics();
highlightBtn.lineStyle(2, 0x033792);
highlightBtn.drawRoundedRect(15, 40, 30, 30, 10);
highlightBtn.endFill();
app.stage.addChild(highlightBtn);
// app.loadSprites("assets/app-circle.png", sprites => {
// let circle = sprites.get("assets/app-circle.png")
// circle.anchor.set(0.5)
// circle.x = app.screen.width / 2
// circle.y = app.screen.height / 2
// circle.width = 80
// circle.height = 80
// app.scene.addChild(circle)
// app.run()
// })
</script>
</body>
+731
View File
@@ -0,0 +1,731 @@
/* global apollo, subscriptions, gql */
import Theme from './theme.js'
import Progress from './progress.js'
import Modal from './modal.js'
import Message from './message.js'
import { debounce } from '../utils.js'
/**
* A special InteractionManager for fullscreen apps, which may
* go beyond the limits of WebGL drawing buffers. On Safari and Chrome
* the drawing buffers are limited to 4096 in width (Safari) or 4096x4096
* in total buffer size (Chrome). The original InteractionManager.mapPositionToPoint
* does not work with these extreme sizes which mainly occur if large
* retina displays (>= 4K) are used with devicePixelRatio > 1.
*
* @private
* @class
* @extends PIXI.interaction.InteractionManager
* @see {@link http://pixijs.download/dev/docs/PIXI.interaction.InteractionManager.html|PIXI.interaction.InteractionManager}
* @see {@link https://stackoverflow.com/questions/29710696/webgl-drawing-buffer-size-does-not-equal-canvas-size}
*/
class FullscreenInteractionManager extends PIXI.interaction.InteractionManager {
mapPositionToPoint(point, x, y) {
let resolution = this.renderer.resolution
let extendWidth = 1.0
let extendHeight = 1.0
let dy = 0
let canvas = this.renderer.view
let context = canvas.getContext('webgl')
if (context.drawingBufferWidth < canvas.width || context.drawingBufferHeight < canvas.height) {
extendWidth = context.drawingBufferWidth / canvas.width
extendHeight = context.drawingBufferHeight / canvas.height
//dx = wantedWidth - context.drawingBufferWidth
dy = (canvas.height - context.drawingBufferHeight) / resolution
}
x *= extendWidth
y *= extendHeight
super.mapPositionToPoint(point, x, y + dy)
}
}
/**
* The class PixiApp extends the class PIXI.Application
* by several functions and makes meaningful pre-assumptions.
*
* @example
* // Create the app
* const app = new PIXIApp({
* view: canvas,
* width: 450,
* height: 150,
* fpsLogging: true,
* theme: 'light',
* transparent: false
* }).setup().run()
*
* @class
* @extends PIXI.Application
* @see {@link http://pixijs.download/dev/docs/PIXI.Application.html|PIXI.Application}
*/
export default class PIXIApp extends PIXI.Application {
/**
* Creates an instance of a PixiApp.
*
* @constructor
* @param {object} [opts={}] - An options object. The following options can be set:
* @param {number} [opts.width] - The width of the renderer. If no set, the application will run in fullscreen.
* @param {number} [opts.height] - The height of the renderer. If no set, the application will run in fullscreen.
* @param {HTMLElement} [opts.view] - The canvas HTML element. If not set, a render-element is added inside the body.
* @param {boolean} [opts.transparent=true] - Should the render view be transparent?
* @param {boolean} [opts.antialias=true] - Sets antialias (only applicable in chrome at the moment).
* @param {number} [opts.resolution=window.devicePixelRatio | 1] - The resolution / device pixel ratio of the renderer, retina would be 2.
* @param {boolean} [opts.autoResize=true] - Should the canvas-element be resized automatically if the resolution was set?
* @param {number} [opts.backgroundColor=0x282828] - The color of the background.
* @param {string|Theme} [opts.theme=dark] - The name of the theme (dark, light, red) or a Theme object to use for styling.
* @param {boolean} [opts.fpsLogging=false] - If set to true, the current frames per second are displayed in the upper left corner.
* @param {object} [opts.progress={}] - Can be used to add options to the progress bar. See class Progress for more informations.
* @param {boolean} [opts.forceCanvas=false] - Prevents selection of WebGL renderer, even if such is present.
* @param {boolean} [opts.roundPixels=true] - Align PIXI.DisplayObject coordinates to screen resolution.
* @param {boolean} [opts.monkeyPatchMapping=true] - Monkey patch for canvas fullscreen support on large displays.
* @param {boolean} [opts.adaptive=true] - Adds Graphics adaptive calculation of quadratic curve and arc subdivision.
*/
constructor({
width = null,
height = null,
view = null,
transparent = true,
backgroundColor = 0x282828,
theme = 'dark',
antialias = true,
resolution = window.devicePixelRatio || 1,
autoResize = true,
fpsLogging = false,
progress = {},
forceCanvas = false,
roundPixels = true,
monkeyPatchMapping = true,
adaptive = true,
graphql = false
}) {
const fullScreen = !width || !height
if (fullScreen) {
width = window.innerWidth
height = window.innerHeight
}
super({
view,
width,
height,
transparent,
antialias,
resolution,
autoResize,
backgroundColor,
forceCanvas
})
this.width = width
this.height = height
this.theme = Theme.fromString(theme)
this.fpsLogging = fpsLogging
this.progressOpts = progress
this.fullScreen = fullScreen
this.orient = null
this.originalMapPositionToPoint = null
this.monkeyPatchMapping = monkeyPatchMapping
if (parseInt(PIXI.VERSION) >= 5) {
PIXI.settings.ROUND_PIXELS = roundPixels
PIXI.GRAPHICS_CURVES.adaptive = adaptive
} else {
PIXI.Graphics.CURVES.adaptive = adaptive
}
this.graphql = graphql
if (fullScreen || autoResize) {
console.log('App is in fullScreen mode or autoResize mode')
const resizeDebounced = debounce(event => this.resize(event), 50)
window.addEventListener('resize', resizeDebounced)
document.body.addEventListener('orientationchange', this.checkOrientation.bind(this))
}
if (monkeyPatchMapping) {
console.log('Using monkey patched coordinate mapping')
// Pluggin the specializtion does not work. Monkey patching does
// this.renderer.plugins.interaction = new FullscreenInteractionManager(this.renderer)
this.monkeyPatchPixiMapping()
}
}
/**
* Extra setup method to construct complex scenes, etc...
* Overwrite this method if you need additonal views and components.
*
* @return {PIXIApp} A reference to the PIXIApp for chaining.
*/
setup() {
this.scene = this.sceneFactory()
this.stage.addChild(this.scene)
// fpsLogging
if (this.fpsLogging) {
this.addFpsDisplay()
}
// GraphQL
if (this.graphql && typeof apollo !== 'undefined') {
const networkInterface = apollo.createNetworkInterface({
uri: '/graphql'
})
const wsClient = new subscriptions.SubscriptionClient(`wss://${location.hostname}/subscriptions`, {
reconnect: true,
connectionParams: {}
})
const networkInterfaceWithSubscriptions = subscriptions.addGraphQLSubscriptions(networkInterface, wsClient)
this.apolloClient = new apollo.ApolloClient({
networkInterface: networkInterfaceWithSubscriptions
})
}
// progress
this._progress = new Progress(
Object.assign({ theme: this.theme }, this.progressOpts, {
app: this
})
)
this._progress.visible = false
this.stage.addChild(this._progress)
return this
}
/**
* Tests whether the width is larger than the height of the application.
*
* @return {boolean} Returns true if app is in landscape mode.
*/
orientation() {
return this.width > this.height
}
/**
* Checks orientation and adapts view size if necessary. Implements a
* handler for the orientationchange event.
*
* @param {event=} - orientationchange event
*/
checkOrientation(event) {
var value = this.orientation()
if (value != this.orient) {
setTimeout(
100,
function() {
this.orientationChanged(true)
}.bind(this)
)
this.orient = value
}
}
/**
* Called if checkOrientation detects an orientation change event.
*
* @param {boolean=} [force=false] - Called if checkOrientation detects an orientation change event.
*/
orientationChanged(force = false) {
if (this.expandRenderer() || force) {
this.layout()
}
}
/**
* Called after a resize. Empty method but can be overwritten to
* adapt their layout to the new app size.
*
* @param {number} [width] - The width of the app.
* @param {number} [height] - The height of the app.
*/
layout(width, height) {}
/**
* Draws the display tree of the app. Typically this can be delegated
* to the layout method.
*
*/
draw() {
this.layout(this.width, this.height)
}
/*
* Run the application. Override this method with everything
* that is needed to maintain your App, e.g. setup calls, main loops, etc.
*
*/
run() {
return this
}
/*
* Overwrite this factory method if your application needs a special
* scene object.
*
* @returns {PIXI.Container} - A new PIXI Container for use as a scene.
*/
sceneFactory() {
return new PIXI.Container()
}
/**
* Adds the display of the frames per second to the renderer in the upper left corner.
*
* @return {PIXIApp} - Returns the PIXIApp for chaining.
*/
addFpsDisplay() {
const fpsDisplay = new FpsDisplay(this)
this.stage.addChild(fpsDisplay)
return this
}
/**
* Returns the size of the renderer as an object with the keys width and height.
*
* @readonly
* @member {object}
*/
get size() {
return { width: this.width, height: this.height }
}
/**
* Returns the center of the renderer as an object with the keys x and y.
*
* @readonly
* @member {object}
*/
get center() {
return { x: this.width / 2, y: this.height / 2 }
}
/**
* Resizes the renderer to fit into the window or given width and height.
*
* @param {object} [event] - The event.
* @param {object=} [opts={}] - The event.
* @param {number} [opts.width=window.innerWidth] - The width of the app to resize to.
* @param {number} [opts.height=window.innerHeight] - The height of the app to resize to.
* @return {PIXIApp} - Returns the PIXIApp for chaining.
*/
resize(event, { width = window.innerWidth, height = window.innerHeight } = {}) {
this.width = width
this.height = height
this.expandRenderer()
this.layout(width, height)
//console.log("App.resize", width, height, window.innerWidth, window.innerHeight )
// if (this.scene) {
// console.log("gl.drawingBufferWidth", this.renderer.view.getContext('webgl').drawingBufferWidth)
// console.log("scene", this.scene.scale, this.renderer, this.renderer.autoResize, this.renderer.resolution)
// }
return this
}
/**
* @todo Write the documentation.
*
* @private
*/
monkeyPatchPixiMapping() {
if (this.originalMapPositionToPoint === null) {
let interactionManager = this.renderer.plugins.interaction
this.originalMapPositionToPoint = interactionManager.mapPositionToPoint
interactionManager.mapPositionToPoint = (point, x, y) => {
return this.fixedMapPositionToPoint(point, x, y)
}
}
}
/**
* In some browsers the canvas is distorted if the screen resolution and
* overall size of the canvas exceeds the internal limits (e.g. 4096 x 4096 pixels).
* To compensate these distortions we need to fix the mapping to the actual
* drawing buffer coordinates.
* @private
* @param {any} local
* @param {number} x
* @param {number} y
* @return {} interactionManager.mapPositionToPoint
*/
fixedMapPositionToPoint(local, x, y) {
let resolution = this.renderer.resolution
let interactionManager = this.renderer.plugins.interaction
let extendWidth = 1.0
let extendHeight = 1.0
let dy = 0
let canvas = this.renderer.view
let context = canvas.getContext('webgl')
if (
context !== null &&
(context.drawingBufferWidth < canvas.width || context.drawingBufferHeight < canvas.height)
) {
extendWidth = context.drawingBufferWidth / canvas.width
extendHeight = context.drawingBufferHeight / canvas.height
//dx = wantedWidth - context.drawingBufferWidth
dy = (canvas.height - context.drawingBufferHeight) / resolution
}
x *= extendWidth
y *= extendHeight
return this.originalMapPositionToPoint.call(interactionManager, local, x, y + dy)
}
/**
* Expand the renderer step-wise on resize.
*
* @param {number} [expand] - The amount of additional space for the renderer [px].
* @return {boolean} true if the renderer was resized.
*/
expandRenderer(expand = 256) {
let renderer = this.renderer
let resolution = this.renderer.resolution
let ww = this.width
let hh = this.height
let sw = this.screen.width
let sh = this.screen.height
if (ww > sw || hh > sh) {
//console.log('App.expandRenderer')
renderer.resize(ww + expand, hh + expand)
return true
}
renderer.resize(ww, hh)
return false
}
/**
* Set the loading progress of the application. If called for the first time, display the progress bar.
*
* @param {number} [value] - Should be a value between 0 and 100. If 100, the progress bar will disappear.
* @return {PIXIApp|Progress} The PixiApp object for chaining or the Progress object when the method was
* called without a parameter.
*/
progress(value) {
if (typeof value === 'undefined') {
return this._progress
}
this._progress.visible = true
this._progress.progress = value
return this
}
/**
* Opens a new Modal object binded to this app.
*
* @param {object} [opts] - An options object for the Modal object.
* @return {Modal} Returns the Modal object.
*/
modal(opts = {}) {
let modal = new Modal(Object.assign({ theme: this.theme }, opts, { app: this }))
this.scene.addChild(modal)
return modal
}
/**
* Opens a new Message object binded to this app.
*
* @param {object} [opts] - An options object for the Message object.
* @return {Message} Returns the Message object.
*/
message(opts = {}) {
let message = new Message(Object.assign({ theme: this.theme }, opts, { app: this }))
this.scene.addChild(message)
return message
}
/**
* Loads sprites, e.g. images into the PIXI TextureCache.
*
* @param {string|string[]} resources - A String or an Array of urls to the images to load.
* @param {function} [loaded] - A callback which is executed after all resources has been loaded.
* Receives one paramter, a Map of sprites where the key is the path of the image which was
* loaded and the value is the PIXI.Sprite object.
* @param {object} [opts] - An options object for more specific parameters.
* @param {boolean} [opts.resolutionDependent=true] - Should the sprites be loaded dependent of the
* renderer resolution?
* @param {boolean} [opts.progress=false] - Should a progress bar display the loading status?
* @return {PIXIApp} The PIXIApp object for chaining.
*/
loadSprites(resources, loaded = null, { resolutionDependent = true, progress = false } = {}) {
this.loadTextures(
resources,
textures => {
let sprites = new Map()
for (let [key, texture] of textures) {
sprites.set(key, new PIXI.Sprite(texture))
}
if (loaded) {
loaded.call(this, sprites)
}
},
{ resolutionDependent, progress }
)
return this
}
/**
* Loads textures, e.g. images into the PIXI TextureCache.
*
* @param {string|string[]} resources - A String or an Array of urls to the images to load.
* @param {function} [loaded] - A callback which is executed after all resources has been loaded.
* Receives one paramter, a Map of textures where the key is the path of the image which was
* loaded and the value is the PIXI.Texture object.
* @param {object} [opts] - An options object for more specific parameters.
* @param {boolean} [opts.resolutionDependent=true] - Should the textures be loaded dependent of the
* renderer resolution?
* @param {boolean} [opts.progress=false] - Should a progress bar display the loading status?
* @return {PIXIApp} The PIXIApp object for chaining.
*/
loadTextures(resources, loaded = null, { resolutionDependent = true, progress = false } = {}) {
if (!Array.isArray(resources)) {
resources = [resources]
}
const loader = this.loader
for (let resource of resources) {
if (!loader.resources[resource]) {
if (resolutionDependent) {
let resolution = Math.round(this.renderer.resolution)
switch (resolution) {
case 2:
loader.add(resource, resource.replace(/\.([^.]*)$/, '@2x.$1'))
break
case 3:
loader.add(resource, resource.replace(/\.([^.]*)$/, '@3x.$1'))
break
default:
loader.add(resource)
break
}
} else {
loader.add(resource)
}
}
}
if (progress) {
loader.on('progress', e => {
this.progress(e.progress)
})
}
loader.load((loader, resources) => {
const textures = new Map()
for (let key in resources) {
textures.set(key, resources[key].texture)
}
if (loaded) {
loaded.call(this, textures)
}
})
return this
}
/**
* Queries the GraphQL endpoint.
*
* @param {string} [query] - The GraphQL query string.
* @param {object} [opts={}] - An options object. The following options can be set:
* http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient.query
* @return {Promise} Returns a Promise which is either resolved with the resulting data or
* rejected with an error.
*/
query(query, opts = {}) {
if (typeof query === 'string') {
opts = Object.assign({}, opts, { query })
} else {
opts = Object.assign({}, query)
}
opts.query = opts.query.trim()
if (!opts.query.startsWith('query')) {
if (opts.query.startsWith('{')) {
opts.query = `query ${opts.query}`
} else {
opts.query = `query {${opts.query}}`
}
}
opts.query = gql(opts.query)
return this.apolloClient.query(opts)
}
/**
* Mutate the GraphQL endpoint.
*
* @param {string} [mutation] - The GraphQL mutation string.
* @param {object} [opts={}] - An options object. The following options can be set:
* http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient.mutate
* @return {Promise} Returns a Promise which is either resolved with the resulting data or
* rejected with an error.
*/
mutate(mutation, opts = {}) {
if (typeof mutation === 'string') {
opts = Object.assign({}, opts, { mutation })
} else {
opts = Object.assign({}, mutation)
}
opts.mutation = opts.mutation.trim()
if (!opts.mutation.startsWith('mutation')) {
if (opts.mutation.startsWith('{')) {
opts.mutation = `mutation ${opts.mutation}`
} else {
opts.mutation = `mutation {${opts.mutation}}`
}
}
opts.mutation = gql(opts.mutation)
return this.apolloClient.mutate(opts)
}
/**
* Subscribe the GraphQL endpoint.
*
* @param {string} [subscription] - The GraphQL subscription.
* @param {object} [opts={}] - An options object. The following options can be set:
* http://dev.apollodata.com/core/apollo-client-api.html#ApolloClient.query
* @return {Promise} Returns a Promise which is either resolved with the resulting data or
* rejected with an error.
*/
subscribe(subscription, opts = {}) {
if (typeof subscription === 'string') {
opts = Object.assign({}, opts, { subscription })
} else {
opts = Object.assign({}, subscription)
}
opts.subscription = opts.subscription.trim()
if (!opts.subscription.startsWith('subscription')) {
if (opts.subscription.startsWith('{')) {
opts.subscription = `subscription ${opts.subscription}`
} else {
opts.subscription = `subscription {${opts.subscription}}`
}
}
opts.query = gql(opts.subscription)
delete opts.subscription
return this.apolloClient.subscribe(opts)
}
/**
* Supports the page as a global coordinate system and converts browser page coordinates
* to local DisplayObject coordinates.
*
* @param {DisplayObject} displayObject - The PIXI displayObject.
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
*
* @return {PIXI.Point} Returns a PIXI.Point.
*/
convertPointFromPageToNode(displayObject, x, y) {
let resolution = this.renderer.resolution
console.log('resolution', resolution)
let pixiGlobal = window.convertPointFromPageToNode(app.view, x, y)
pixiGlobal.x /= resolution
pixiGlobal.y /= resolution
return displayObject.toLocal(new PIXI.Point(pixiGlobal.x, pixiGlobal.y))
}
/**
* Supports the page as a global coordinate system and converts local DisplayObject coordinates
* to browser page coordinates.
*
* @param {DisplayObject} displayObject - The PIXI displayObject.
* @param {number} x - The x coordinate.
* @param {number} y - The y coordinate.
*
* @return {Point} Returns a DOM Point.
*/
convertPointFromNodeToPage(displayObject, x, y) {
let resolution = this.renderer.resolution
let pixiGlobal = displayObject.toGlobal(new PIXI.Point(x, y))
pixiGlobal.x *= resolution
pixiGlobal.y *= resolution
// console.log("app.convertPointFromNodeToPage", pixiGlobal)
return window.convertPointFromNodeToPage(app.view, pixiGlobal.x, pixiGlobal.y)
}
}
/**
* The class fpsdisplay shows in the upper left corner
* of the renderer the current image refresh rate.
*
* @private
* @class
* @extends PIXI.Graphics
* @see {@link http://pixijs.download/dev/docs/PIXI.Graphics.html|PIXI.Graphics}
*/
class FpsDisplay extends PIXI.Graphics {
/**
* Creates an instance of a FpsDisplay.
*
* @constructor
* @param {PIXIApp} app - The PIXIApp where the frames per second should be displayed.
*/
constructor(app) {
super()
this.app = app
this.lineStyle(3, 0x434f4f, 1)
.beginFill(0x434f4f, 0.6)
.drawRoundedRect(0, 0, 68, 32, 5)
.endFill()
.position.set(20, 20)
this.text = new PIXI.Text(
this.fps,
new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 14,
fontWeight: 'bold',
fill: '#f6f6f6',
stroke: '#434f4f',
strokeThickness: 3
})
)
this.text.position.set(6, 6)
this.addChild(this.text)
this.refreshFps()
window.setInterval(this.refreshFps.bind(this), 1000)
}
/**
* Refreshes fps numer.
*
* @return {PIXIApp} Returns the PIXIApp object for chaining.
*/
refreshFps() {
this.text.text = `${this.app.ticker.FPS.toFixed(1)} fps`
return this
}
}
+36
View File
@@ -0,0 +1,36 @@
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>PIXI.Application Doctest</title>
<script src="../../dist/iwmlib.3rdparty.js"></script>
<script src="../../dist/iwmlib.js"></script>
<script src="../../dist/iwmlib.pixi.js"></script>
</head>
<body>
<h1>PIXI.Application with nothing!</h1>
<script>
const app = new PIXI.Application({
width: 450,
height: 150
})
// Add the view to the DOM
document.body.appendChild(app.view)
// ex, add display objects
const sprite = PIXI.Sprite.from('./assets/app-circle.png')
sprite.scale.set(.3, .3)
app.stage.addChild(sprite)
sprite.interactive = true
sprite.buttonMode = true
sprite.on('click', e => {
console.log('sprite clicked')
})
</script>
</body>
Binary file not shown.
+171
View File
@@ -0,0 +1,171 @@
<?xml version='1.0'?>
<font>
<info aa='1' size='50' smooth='1' stretchH='100' bold='0' padding='0,0,0,0' spacing='0,0' charset='' italic='0' unicode='0' face='Arial'/>
<common scaleW='384' packed='0' pages='1' lineHeight='56' scaleH='320' base='46'/>
<pages>
<page id='0' file='Arial.png'/>
</pages>
<chars count='95'>
<char xadvance='14' x='46' chnl='0' yoffset='45' y='96' xoffset='0' id='32' page='0' height='0' width='0'/>
<char xadvance='14' x='42' chnl='0' yoffset='9' y='140' xoffset='5' id='33' page='0' height='40' width='10'/>
<char xadvance='18' x='254' chnl='0' yoffset='9' y='152' xoffset='3' id='34' page='0' height='16' width='18'/>
<char xadvance='28' x='94' chnl='0' yoffset='7' y='180' xoffset='1' id='35' page='0' height='42' width='30'/>
<char xadvance='28' x='94' chnl='0' yoffset='6' y='88' xoffset='2' id='36' page='0' height='48' width='28'/>
<char xadvance='45' x='2' chnl='0' yoffset='8' y='96' xoffset='3' id='37' page='0' height='42' width='42'/>
<char xadvance='34' x='54' chnl='0' yoffset='7' y='256' xoffset='3' id='38' page='0' height='42' width='34'/>
<char xadvance='10' x='296' chnl='0' yoffset='9' y='152' xoffset='3' id='39' page='0' height='16' width='10'/>
<char xadvance='17' x='242' chnl='0' yoffset='9' y='170' xoffset='4' id='40' page='0' height='50' width='16'/>
<char xadvance='17' x='214' chnl='0' yoffset='9' y='246' xoffset='4' id='41' page='0' height='50' width='16'/>
<char xadvance='20' x='318' chnl='0' yoffset='7' y='170' xoffset='2' id='42' page='0' height='20' width='20'/>
<char xadvance='30' x='332' chnl='0' yoffset='15' y='44' xoffset='3' id='43' page='0' height='28' width='28'/>
<char xadvance='14' x='284' chnl='0' yoffset='40' y='152' xoffset='5' id='44' page='0' height='16' width='10'/>
<char xadvance='17' x='94' chnl='0' yoffset='30' y='308' xoffset='2' id='45' page='0' height='8' width='18'/>
<char xadvance='14' x='330' chnl='0' yoffset='39' y='152' xoffset='5' id='46' page='0' height='10' width='10'/>
<char xadvance='14' x='260' chnl='0' yoffset='7' y='246' xoffset='0' id='47' page='0' height='42' width='18'/>
<char xadvance='28' x='308' chnl='0' yoffset='9' y='76' xoffset='3' id='48' page='0' height='40' width='28'/>
<char xadvance='28' x='280' chnl='0' yoffset='9' y='202' xoffset='6' id='49' page='0' height='40' width='18'/>
<char xadvance='28' x='278' chnl='0' yoffset='9' y='76' xoffset='2' id='50' page='0' height='40' width='28'/>
<char xadvance='28' x='248' chnl='0' yoffset='9' y='76' xoffset='3' id='51' page='0' height='40' width='28'/>
<char xadvance='28' x='218' chnl='0' yoffset='9' y='76' xoffset='1' id='52' page='0' height='40' width='28'/>
<char xadvance='28' x='188' chnl='0' yoffset='9' y='76' xoffset='3' id='53' page='0' height='40' width='28'/>
<char xadvance='28' x='158' chnl='0' yoffset='9' y='76' xoffset='2' id='54' page='0' height='40' width='28'/>
<char xadvance='28' x='128' chnl='0' yoffset='9' y='244' xoffset='3' id='55' page='0' height='40' width='28'/>
<char xadvance='28' x='128' chnl='0' yoffset='9' y='202' xoffset='3' id='56' page='0' height='40' width='28'/>
<char xadvance='28' x='128' chnl='0' yoffset='9' y='160' xoffset='3' id='57' page='0' height='40' width='28'/>
<char xadvance='14' x='366' chnl='0' yoffset='19' y='76' xoffset='5' id='58' page='0' height='30' width='10'/>
<char xadvance='14' x='42' chnl='0' yoffset='18' y='186' xoffset='5' id='59' page='0' height='38' width='10'/>
<char xadvance='30' x='302' chnl='0' yoffset='15' y='44' xoffset='3' id='60' page='0' height='28' width='28'/>
<char xadvance='30' x='288' chnl='0' yoffset='20' y='170' xoffset='3' id='61' page='0' height='18' width='28'/>
<char xadvance='30' x='272' chnl='0' yoffset='15' y='44' xoffset='3' id='62' page='0' height='28' width='28'/>
<char xadvance='28' x='128' chnl='0' yoffset='9' y='118' xoffset='3' id='63' page='0' height='40' width='28'/>
<char xadvance='51' x='2' chnl='0' yoffset='9' y='2' xoffset='3' id='64' page='0' height='50' width='50'/>
<char xadvance='34' x='54' chnl='0' yoffset='9' y='2' xoffset='0' id='65' page='0' height='40' width='38'/>
<char xadvance='34' x='94' chnl='0' yoffset='9' y='138' xoffset='4' id='66' page='0' height='40' width='32'/>
<char xadvance='37' x='54' chnl='0' yoffset='7' y='44' xoffset='3' id='67' page='0' height='42' width='36'/>
<char xadvance='37' x='130' chnl='0' yoffset='9' y='2' xoffset='4' id='68' page='0' height='40' width='34'/>
<char xadvance='34' x='94' chnl='0' yoffset='9' y='224' xoffset='4' id='69' page='0' height='40' width='30'/>
<char xadvance='31' x='128' chnl='0' yoffset='9' y='76' xoffset='5' id='70' page='0' height='40' width='28'/>
<char xadvance='39' x='2' chnl='0' yoffset='7' y='230' xoffset='3' id='71' page='0' height='42' width='38'/>
<char xadvance='37' x='336' chnl='0' yoffset='9' y='2' xoffset='5' id='72' page='0' height='40' width='32'/>
<char xadvance='14' x='370' chnl='0' yoffset='9' y='2' xoffset='5' id='73' page='0' height='40' width='8'/>
<char xadvance='25' x='186' chnl='0' yoffset='9' y='244' xoffset='2' id='74' page='0' height='40' width='24'/>
<char xadvance='34' x='94' chnl='0' yoffset='9' y='2' xoffset='4' id='75' page='0' height='40' width='34'/>
<char xadvance='28' x='186' chnl='0' yoffset='9' y='202' xoffset='4' id='76' page='0' height='40' width='26'/>
<char xadvance='42' x='2' chnl='0' yoffset='9' y='274' xoffset='4' id='77' page='0' height='40' width='38'/>
<char xadvance='37' x='302' chnl='0' yoffset='9' y='2' xoffset='4' id='78' page='0' height='40' width='32'/>
<char xadvance='39' x='2' chnl='0' yoffset='7' y='186' xoffset='3' id='79' page='0' height='42' width='38'/>
<char xadvance='34' x='268' chnl='0' yoffset='9' y='2' xoffset='4' id='80' page='0' height='40' width='32'/>
<char xadvance='39' x='2' chnl='0' yoffset='7' y='140' xoffset='3' id='81' page='0' height='44' width='38'/>
<char xadvance='37' x='54' chnl='0' yoffset='9' y='214' xoffset='4' id='82' page='0' height='40' width='36'/>
<char xadvance='34' x='94' chnl='0' yoffset='7' y='44' xoffset='3' id='83' page='0' height='42' width='32'/>
<char xadvance='31' x='234' chnl='0' yoffset='9' y='2' xoffset='2' id='84' page='0' height='40' width='32'/>
<char xadvance='37' x='200' chnl='0' yoffset='9' y='2' xoffset='4' id='85' page='0' height='40' width='32'/>
<char xadvance='34' x='54' chnl='0' yoffset='9' y='172' xoffset='1' id='86' page='0' height='40' width='36'/>
<char xadvance='48' x='2' chnl='0' yoffset='9' y='54' xoffset='1' id='87' page='0' height='40' width='50'/>
<char xadvance='34' x='54' chnl='0' yoffset='9' y='130' xoffset='1' id='88' page='0' height='40' width='36'/>
<char xadvance='34' x='54' chnl='0' yoffset='9' y='88' xoffset='1' id='89' page='0' height='40' width='36'/>
<char xadvance='31' x='166' chnl='0' yoffset='9' y='2' xoffset='2' id='90' page='0' height='40' width='32'/>
<char xadvance='14' x='300' chnl='0' yoffset='8' y='202' xoffset='4' id='91' page='0' height='50' width='14'/>
<char xadvance='14' x='260' chnl='0' yoffset='7' y='202' xoffset='0' id='92' page='0' height='42' width='18'/>
<char xadvance='14' x='280' chnl='0' yoffset='8' y='244' xoffset='1' id='93' page='0' height='50' width='14'/>
<char xadvance='24' x='158' chnl='0' yoffset='8' y='288' xoffset='2' id='94' page='0' height='24' width='24'/>
<char xadvance='28' x='344' chnl='0' yoffset='50' y='152' xoffset='0' id='95' page='0' height='8' width='34'/>
<char xadvance='17' x='314' chnl='0' yoffset='9' y='152' xoffset='3' id='96' page='0' height='10' width='14'/>
<char xadvance='28' x='314' chnl='0' yoffset='17' y='118' xoffset='2' id='97' page='0' height='32' width='28'/>
<char xadvance='28' x='186' chnl='0' yoffset='9' y='160' xoffset='4' id='98' page='0' height='40' width='26'/>
<char xadvance='25' x='214' chnl='0' yoffset='17' y='170' xoffset='2' id='99' page='0' height='32' width='26'/>
<char xadvance='28' x='186' chnl='0' yoffset='9' y='118' xoffset='2' id='100' page='0' height='40' width='26'/>
<char xadvance='28' x='284' chnl='0' yoffset='17' y='118' xoffset='2' id='101' page='0' height='32' width='28'/>
<char xadvance='14' x='214' chnl='0' yoffset='9' y='204' xoffset='1' id='102' page='0' height='40' width='20'/>
<char xadvance='28' x='158' chnl='0' yoffset='17' y='118' xoffset='2' id='103' page='0' height='42' width='26'/>
<char xadvance='28' x='158' chnl='0' yoffset='9' y='246' xoffset='4' id='104' page='0' height='40' width='26'/>
<char xadvance='12' x='42' chnl='0' yoffset='9' y='274' xoffset='4' id='105' page='0' height='40' width='8'/>
<char xadvance='12' x='242' chnl='0' yoffset='9' y='222' xoffset='-2' id='106' page='0' height='50' width='14'/>
<char xadvance='25' x='158' chnl='0' yoffset='9' y='204' xoffset='4' id='107' page='0' height='40' width='26'/>
<char xadvance='12' x='42' chnl='0' yoffset='9' y='230' xoffset='4' id='108' page='0' height='40' width='8'/>
<char xadvance='42' x='170' chnl='0' yoffset='19' y='44' xoffset='4' id='109' page='0' height='30' width='40'/>
<char xadvance='28' x='260' chnl='0' yoffset='19' y='170' xoffset='4' id='110' page='0' height='30' width='26'/>
<char xadvance='28' x='254' chnl='0' yoffset='17' y='118' xoffset='2' id='111' page='0' height='32' width='28'/>
<char xadvance='28' x='158' chnl='0' yoffset='18' y='162' xoffset='4' id='112' page='0' height='40' width='26'/>
<char xadvance='28' x='338' chnl='0' yoffset='18' y='76' xoffset='2' id='113' page='0' height='40' width='26'/>
<char xadvance='17' x='362' chnl='0' yoffset='19' y='44' xoffset='4' id='114' page='0' height='30' width='18'/>
<char xadvance='25' x='344' chnl='0' yoffset='17' y='118' xoffset='2' id='115' page='0' height='32' width='26'/>
<char xadvance='14' x='242' chnl='0' yoffset='9' y='274' xoffset='1' id='116' page='0' height='40' width='16'/>
<char xadvance='28' x='186' chnl='0' yoffset='19' y='286' xoffset='4' id='117' page='0' height='30' width='26'/>
<char xadvance='25' x='242' chnl='0' yoffset='19' y='44' xoffset='1' id='118' page='0' height='30' width='28'/>
<char xadvance='37' x='128' chnl='0' yoffset='19' y='44' xoffset='1' id='119' page='0' height='30' width='40'/>
<char xadvance='25' x='212' chnl='0' yoffset='19' y='44' xoffset='1' id='120' page='0' height='30' width='28'/>
<char xadvance='25' x='94' chnl='0' yoffset='19' y='266' xoffset='1' id='121' page='0' height='40' width='28'/>
<char xadvance='25' x='128' chnl='0' yoffset='19' y='286' xoffset='1' id='122' page='0' height='30' width='26'/>
<char xadvance='17' x='234' chnl='0' yoffset='9' y='118' xoffset='2' id='123' page='0' height='50' width='18'/>
<char xadvance='13' x='232' chnl='0' yoffset='9' y='246' xoffset='5' id='124' page='0' height='50' width='8'/>
<char xadvance='17' x='214' chnl='0' yoffset='9' y='118' xoffset='2' id='125' page='0' height='50' width='18'/>
<char xadvance='30' x='54' chnl='0' yoffset='23' y='300' xoffset='3' id='126' page='0' height='12' width='28'/>
</chars>
<kernings count="64">
<kerning first="86" second="117" amount="-1"/>
<kerning first="84" second="97" amount="-5"/>
<kerning first="84" second="99" amount="-5"/>
<kerning first="87" second="65" amount="-1"/>
<kerning first="80" second="65" amount="-3"/>
<kerning first="86" second="101" amount="-2"/>
<kerning first="89" second="111" amount="-4"/>
<kerning first="87" second="44" amount="-2"/>
<kerning first="84" second="111" amount="-5"/>
<kerning first="89" second="112" amount="-3"/>
<kerning first="84" second="65" amount="-3"/>
<kerning first="80" second="44" amount="-6"/>
<kerning first="87" second="46" amount="-2"/>
<kerning first="89" second="113" amount="-4"/>
<kerning first="76" second="84" amount="-3"/>
<kerning first="80" second="46" amount="-6"/>
<kerning first="76" second="121" amount="-1"/>
<kerning first="76" second="86" amount="-3"/>
<kerning first="84" second="114" amount="-1"/>
<kerning first="76" second="87" amount="-3"/>
<kerning first="84" second="58" amount="-5"/>
<kerning first="84" second="44" amount="-5"/>
<kerning first="84" second="115" amount="-5"/>
<kerning first="76" second="89" amount="-3"/>
<kerning first="84" second="46" amount="-5"/>
<kerning first="89" second="117" amount="-2"/>
<kerning first="89" second="97" amount="-3"/>
<kerning first="119" second="44" amount="-2"/>
<kerning first="84" second="117" amount="-1"/>
<kerning first="89" second="118" amount="-2"/>
<kerning first="114" second="44" amount="-2"/>
<kerning first="89" second="101" amount="-4"/>
<kerning first="49" second="49" amount="-3"/>
<kerning first="86" second="121" amount="-1"/>
<kerning first="119" second="46" amount="-2"/>
<kerning first="84" second="119" amount="-2"/>
<kerning first="84" second="101" amount="-5"/>
<kerning first="114" second="46" amount="-2"/>
<kerning first="86" second="97" amount="-3"/>
<kerning first="89" second="65" amount="-3"/>
<kerning first="89" second="105" amount="-1"/>
<kerning first="118" second="44" amount="-3"/>
<kerning first="65" second="84" amount="-3"/>
<kerning first="84" second="105" amount="-1"/>
<kerning first="65" second="86" amount="-3"/>
<kerning first="65" second="87" amount="-1"/>
<kerning first="118" second="46" amount="-3"/>
<kerning first="65" second="89" amount="-3"/>
<kerning first="70" second="65" amount="-2"/>
<kerning first="89" second="58" amount="-2"/>
<kerning first="89" second="44" amount="-6"/>
<kerning first="86" second="65" amount="-3"/>
<kerning first="86" second="111" amount="-2"/>
<kerning first="89" second="46" amount="-6"/>
<kerning first="121" second="44" amount="-3"/>
<kerning first="87" second="97" amount="-1"/>
<kerning first="70" second="44" amount="-5"/>
<kerning first="84" second="121" amount="-2"/>
<kerning first="86" second="114" amount="-1"/>
<kerning first="86" second="58" amount="-1"/>
<kerning first="86" second="44" amount="-4"/>
<kerning first="70" second="46" amount="-5"/>
<kerning first="121" second="46" amount="-3"/>
<kerning first="86" second="46" amount="-4"/>
</kernings>
</font>
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 984 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

@@ -0,0 +1,14 @@
{
"projection": "mercator",
"type": "deepzoom",
"tiles": {
"tileSize": 256,
"format": "png",
"overlap": 0,
"type": "map",
"height": 1024,
"width": 1024,
"path": "../../examples/osm",
"urlTileTemplate": "{path}/{level}/{row}/{column}.{format}"
}
}
@@ -0,0 +1,20 @@
author: Hans Braxmeier (https://pixabay.com/de/users/hans-2/)
url: https://pixabay.com/de/illustrations/karte-mitteleuropa-zentraleuropa-1804891/
license:
Vereinfachte Pixabay Lizenz:
Unsere Lizenz gibt Nutzern umfassende Freiheiten und Sicherheit - und gleichzeitig schützt sie die Bildautoren und unsere Community vor Mißbrauch. Die rechtliche Seite halten wir dabei so einfach wie möglich und fassen alle wichtigen Punkte hier zusammen.
Was ist erlaubt?
- Du darfst alle Pixabay Inhalte kostenlos nutzen, für kommerzielle und nicht-kommerzielle Anwendungen, gedruckt und digital. Beachte dabei die Einschränkungen unter "Was ist nicht erlaubt".
- Du musst weder vom Bildautor noch von Pixabay eine Genehmigung einholen und auch eine Quellenangabe ist nicht erforderlich, wobei wir uns über eine freiwillige Nennung freuen.
- Du darfst Pixabay Inhalte verändern.
Was ist nicht erlaubt?
Dieser Abschnitt betrifft ausschließlich Bildnutzer und nicht die jeweiligen Bildautoren.
- Verbreite oder verkaufe die Werke nicht auf anderen Bilder-, Wallpaper- bzw. Vertriebsseiten.
- Verkaufe keine unveränderten Kopien von Bildern, z.B. auf einer Stockfoto-Seite, als Poster oder als Ausdruck auf einem physischen Produkt.
- Erkennbare Personen dürfen nicht in einer anstößigen Weise dargestellt werden.
- Suggeriere nicht, dass Bildautor oder erkennbare Personen bzw. Marken auf den Bildern Dein Produkt empfehlen oder befürworten.
Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

@@ -0,0 +1,12 @@
{
"clip": {
"min": {
"x": 32.863294,
"y": -18.58
},
"max": {
"x": 57.467973,
"y": 44.277158
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Some files were not shown because too many files have changed in this diff Show More