Added doctest for flippable images with different sizes.

This commit is contained in:
Uwe Oestermeier 2024-02-12 14:08:24 +01:00
parent c8f7e39235
commit 8d8090cdde
8 changed files with 176 additions and 81 deletions

View File

@ -1,4 +1,3 @@
.flipWrapper {
position: absolute;
top: 0;
@ -48,6 +47,7 @@
width: 44px;
height: 44px;
padding: 4px;
border: 1px solid red;
right: 0;
top: 0;
}
@ -58,6 +58,7 @@
width: 44px;
height: 44px;
padding: 4px;
border: 1px solid red;
right: 0;
bottom: 0;
}
@ -68,6 +69,7 @@
width: 44px;
height: 44px;
padding: 4px;
border: 1px solid red;
right: 0;
bottom: 0;
}

89
dist/iwmlib.js vendored
View File

@ -1020,7 +1020,7 @@
/** Static methods to compute 2D points with x and y coordinates.
*/
class Points$1 {
let Points$1 = class Points {
static length(a) {
return Math.sqrt(a.x * a.x + a.y * a.y)
}
@ -1114,7 +1114,7 @@
// }
return window.convertPointFromNodeToPage(element, p.x, p.y)
}
}
};
/**
* A helper class for common set operations.
@ -1238,7 +1238,7 @@
}
}
class Elements$1 {
let Elements$1 = class Elements {
static setStyle(element, styles) {
for (let key in styles) {
element.style[key] = styles[key];
@ -1260,7 +1260,7 @@
static hasClass(element, cssClass) {
return element.classList.contains(cssClass)
}
}
};
class MapProxy {
/* This class is needed if we want to use the interaction classes
@ -1578,7 +1578,7 @@
/**
* Util functions to deal with DOMRects.
*/
class Rect$1 {
let Rect$1 = class Rect {
/**
* Test if a given point is contained by the provided Rect.
*
@ -1603,7 +1603,7 @@
static getPosition(rect) {
return { x: rect.x, y: rect.y }
}
}
};
/** String utility functions */
@ -1741,7 +1741,7 @@
* The logging handlers can be overwritten by calling the static
* setup method.
*/
class Logging$1 {
let Logging$1 = class Logging {
/** Static log function.
* @param {*} message
*/
@ -1778,9 +1778,12 @@
logHandlers.warn = warn;
logHandlers.error = error;
}
}
};
/* eslint-disable no-unused-vars */
/* globals Hammer, propagating */
/*eslint no-console: ["error", { allow: ["log", "warn", "info", "error"] }]*/
/** Interaction patterns
@ -2728,7 +2731,7 @@
* @class InteractionMapper
* @extends {InteractionDelegate}
*/
class InteractionMapper$1 extends InteractionDelegate {
let InteractionMapper$1 = class InteractionMapper extends InteractionDelegate {
constructor(
element,
target,
@ -2950,7 +2953,7 @@
}
}
}
}
};
window.InteractionMapper = InteractionMapper$1;
@ -3126,6 +3129,8 @@
window.CapabilitiesTests = CapabilitiesTests;
/* eslint-disable no-unused-vars */
/* eslint-disable no-console */
/* globals debugCanvas */
/** This interface allows scatters to delegate tap events to other objects. */
class ITapDelegate extends Interface {
@ -4193,7 +4198,7 @@
}
}
class DOMScatter$1 extends AbstractScatter {
let DOMScatter$1 = class DOMScatter extends AbstractScatter {
constructor(
element,
container,
@ -4482,7 +4487,7 @@
bringToFront() {
// this.element.parentNode.appendChild(this.element)
// uo: On Chome and Electon appendChild leads to flicker
TweenLite.set(this.element, { zIndex: DOMScatter$1.zIndex++ });
TweenLite.set(this.element, { zIndex: DOMScatter.zIndex++ });
}
isDescendant(parent, child) {
@ -4622,11 +4627,13 @@
this.element.dispatchEvent(event);
}
}
};
DOMScatter$1.zIndex = 1000;
/* eslint-disable no-console */
/* global TweenLite */
class CardWrapper extends Object {
constructor(domNode, { triggerSVGClicks = true, allowClickDistance = 44 } = {}) {
@ -4803,6 +4810,7 @@
}
/* eslint-disable no-unused-vars */
/* global PDFJS Power1 */
class CardLoader {
constructor(
@ -4817,7 +4825,7 @@
scale = 1,
minScale = 0.5,
maxScale = 1.5,
rotation = 0,
rotation = 0
} = {}
) {
this.src = src;
@ -4867,7 +4875,7 @@
// Render PDF page into canvas context.
let renderContext = {
canvasContext: context,
viewport: viewport,
viewport: viewport
};
page.render(renderContext);
domNode.appendChild(canvas);
@ -5009,7 +5017,7 @@
onClose = null,
onUpdate = null,
onRemoved = null,
onLoaded = null,
onLoaded = null
} = {}
) {
this.domScatterContainer = domScatterContainer;
@ -5076,7 +5084,7 @@
scalable: this.scalable,
rotatable: this.rotatable,
overdoScaling: this.overdoScaling,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null
});
if (this.center) {
@ -5152,7 +5160,7 @@
opacity: 0,
onComplete: () => {
this.cardWrapper.remove();
},
}
});
}
@ -5200,7 +5208,7 @@
TweenLite.set(this.back, { rotationY: -180 });
TweenLite.set([this.back, this.front], {
backfaceVisibility: 'hidden',
perspective: 5000,
perspective: 5000
});
TweenLite.set(this.front, { visibility: 'visible' });
this.infoBtn = element.querySelector('.infoBtn');
@ -5247,7 +5255,7 @@
if (this.onRemoved) {
this.onRemoved.call(this);
}
},
}
});
}
}
@ -5276,7 +5284,7 @@
scaleButtons() {
TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
scale: this.buttonScale,
scale: this.buttonScale
});
}
@ -5418,10 +5426,11 @@
this.scatter.translatable = translatable;
this.scatter.rotatable = rotatable;
},
force3D: true,
force3D: true
});
// See https://greensock.com/forums/topic/7997-rotate-the-shortest-way/
TweenLite.to(this.element, this.flipDuration / 2, {
const duration = this.flipDuration / 2;
TweenLite.to(this.element, duration, {
scale: targetScale,
ease: Power1.easeOut,
rotationZ: targetZ + '_short',
@ -5438,8 +5447,26 @@
this.hide(this.back);
// this.show(this.infoBtn)
}
},
}
});
//uo: check for special case that the front image must be adapted to the back size
let frontImage = this.front.querySelector('img');
if (frontImage) {
let scaleX = this.flipped ? w / this.scatterStartWidth : this.scatterStartWidth / w;
let scaleY = this.flipped ? h / this.scatterStartHeight : this.scatterStartHeight / h;
let ratio = this.scatterStartWidth / this.scatterStartHeight;
if (this.flipped) {
TweenLite.to(frontImage, duration, {
ease: Power1.easeOut,
scaleY: scaleY * targetScale * ratio,
scaleX: scaleX * targetScale,
onComplete: (e) => {
TweenLite.set(frontImage, { scale: 1.0 });
}
});
}
}
}
}
@ -5582,10 +5609,12 @@
Poppable.registrations = new Map();
/* eslint-disable no-console */
/* eslint-disable no-case-declarations */
/* eslint-disable no-unused-vars */
/** A Popup that shows text labels, images, or html
*/
class Popup$1 extends Poppable {
let Popup$1 = class Popup extends Poppable {
/**
* Creates an instance of Popup.
* @param {any} [{
@ -6439,7 +6468,7 @@
} = {}
) {
let notchPosition = switchPos && point.y < 50 ? 'topCenter' : 'bottomCenter';
let popup = new Popup$1({
let popup = new Popup({
parent,
context,
fontFamily,
@ -6527,14 +6556,14 @@
event.target;
let x = event.pageX;
let y = event.pageY;
let rect = Popup$1.targetRect(event);
let rect = Popup.targetRect(event);
if (rect != null) {
x = rect.left + rect.width / 2;
y = rect.top + rect.height / 2;
}
return { x, y }
}
}
};
/** A Popup Menu that shows text labels in a vertical row.
*/
@ -7870,7 +7899,7 @@
* @ignore
* @class
*/
class Event$1 {
let Event$1 = class Event {
/**
* Creates an event object.
*
@ -7949,7 +7978,7 @@
return new MouseEvent(type, Object.assign({}, eventOpts, uiEventOpts, mouseEventOpts, opts))
}
}
}
};
/* eslint-disable no-console */

102
dist/iwmlib.pixi.js vendored
View File

@ -1179,7 +1179,7 @@
}
}
class Events$1 {
let Events$1 = class Events {
static stop(event) {
event.preventDefault();
// I removed this, as it destroys all the Hammer.js events.
@ -1301,8 +1301,8 @@
data.pointerId = event.pointerId;
data.pointerType = event.pointerType;
}
if (Events$1.debug) {
Events$1.extracted.push(this.toLine(event));
if (Events.debug) {
Events.extracted.push(this.toLine(event));
}
return infos
}
@ -1331,8 +1331,8 @@
if (data.target != null) {
data.target.dispatchEvent(clone);
}
if (Events$1.debug) {
Events$1.simulated.push(this.toLine(clone));
if (Events.debug) {
Events.simulated.push(this.toLine(clone));
}
}
@ -1408,7 +1408,7 @@
top: event.clientY + 'px',
});
}
}
};
Events$1.popup = null;
Events$1.debug = true;
@ -1818,7 +1818,7 @@
}
}
class Elements$1 {
let Elements$1 = class Elements {
static setStyle(element, styles) {
for (let key in styles) {
element.style[key] = styles[key];
@ -1840,7 +1840,7 @@
static hasClass(element, cssClass) {
return element.classList.contains(cssClass)
}
}
};
class MapProxy {
/* This class is needed if we want to use the interaction classes
@ -2280,7 +2280,7 @@
* @see {@link http://pixijs.download/dev/docs/PIXI.Container.html|PIXI.Container}
* @see {@link https://www.iwm-tuebingen.de/iwmbrowser/lib/pixi/button.html|DocTest}
*/
class Button$1 extends PIXI.Container {
let Button$1 = class Button extends PIXI.Container {
/**
* Creates an instance of a Button.
*
@ -2904,7 +2904,7 @@
size = this.opts.minHeight - 2 * this.opts.padding;
}
const url = Button$1.iconIsUrl(icon) ? icon : `../../assets/icons/${icon}.png`;
const url = Button.iconIsUrl(icon) ? icon : `../../assets/icons/${icon}.png`;
const iconTexture = PIXI.Texture.from(url);
const sprite = new PIXI.Sprite(iconTexture);
@ -2952,10 +2952,11 @@
overwrite: 'none',
});
}
}
};
/* globals ThrowPropsPlugin, Strong */
/**
* Class that represents a PixiJS ButtonGroup.
*
@ -4240,6 +4241,7 @@
/* global apollo, subscriptions, gql */
/**
* A special InteractionManager for fullscreen apps, which may
* go beyond the limits of WebGL drawing buffers. On Safari and Chrome
@ -5313,7 +5315,7 @@
* The logging handlers can be overwritten by calling the static
* setup method.
*/
class Logging$1 {
let Logging$1 = class Logging {
/** Static log function.
* @param {*} message
*/
@ -5350,9 +5352,12 @@
logHandlers.warn = warn;
logHandlers.error = error;
}
}
};
/* eslint-disable no-unused-vars */
/* globals Hammer, propagating */
/*eslint no-console: ["error", { allow: ["log", "warn", "info", "error"] }]*/
/** Interaction patterns
@ -6300,7 +6305,7 @@
* @class InteractionMapper
* @extends {InteractionDelegate}
*/
class InteractionMapper$1 extends InteractionDelegate {
let InteractionMapper$1 = class InteractionMapper extends InteractionDelegate {
constructor(
element,
target,
@ -6522,7 +6527,7 @@
}
}
}
}
};
window.InteractionMapper = InteractionMapper$1;
@ -6698,6 +6703,8 @@
window.CapabilitiesTests = CapabilitiesTests;
/* eslint-disable no-unused-vars */
/* eslint-disable no-console */
/* globals debugCanvas */
/**
* A base class for scatter specific events.
@ -8010,6 +8017,8 @@
DOMScatter.zIndex = 1000;
/* eslint-disable no-console */
/* global TweenLite */
class CardWrapper extends Object {
constructor(domNode, { triggerSVGClicks = true, allowClickDistance = 44 } = {}) {
@ -8186,6 +8195,7 @@
}
/* eslint-disable no-unused-vars */
/* global PDFJS Power1 */
class CardLoader {
constructor(
@ -8200,7 +8210,7 @@
scale = 1,
minScale = 0.5,
maxScale = 1.5,
rotation = 0,
rotation = 0
} = {}
) {
this.src = src;
@ -8248,7 +8258,7 @@
onClose = null,
onUpdate = null,
onRemoved = null,
onLoaded = null,
onLoaded = null
} = {}
) {
this.domScatterContainer = domScatterContainer;
@ -8315,7 +8325,7 @@
scalable: this.scalable,
rotatable: this.rotatable,
overdoScaling: this.overdoScaling,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null
});
if (this.center) {
@ -8391,7 +8401,7 @@
opacity: 0,
onComplete: () => {
this.cardWrapper.remove();
},
}
});
}
@ -8439,7 +8449,7 @@
TweenLite.set(this.back, { rotationY: -180 });
TweenLite.set([this.back, this.front], {
backfaceVisibility: 'hidden',
perspective: 5000,
perspective: 5000
});
TweenLite.set(this.front, { visibility: 'visible' });
this.infoBtn = element.querySelector('.infoBtn');
@ -8486,7 +8496,7 @@
if (this.onRemoved) {
this.onRemoved.call(this);
}
},
}
});
}
}
@ -8515,7 +8525,7 @@
scaleButtons() {
TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
scale: this.buttonScale,
scale: this.buttonScale
});
}
@ -8657,10 +8667,11 @@
this.scatter.translatable = translatable;
this.scatter.rotatable = rotatable;
},
force3D: true,
force3D: true
});
// See https://greensock.com/forums/topic/7997-rotate-the-shortest-way/
TweenLite.to(this.element, this.flipDuration / 2, {
const duration = this.flipDuration / 2;
TweenLite.to(this.element, duration, {
scale: targetScale,
ease: Power1.easeOut,
rotationZ: targetZ + '_short',
@ -8677,8 +8688,26 @@
this.hide(this.back);
// this.show(this.infoBtn)
}
},
}
});
//uo: check for special case that the front image must be adapted to the back size
let frontImage = this.front.querySelector('img');
if (frontImage) {
let scaleX = this.flipped ? w / this.scatterStartWidth : this.scatterStartWidth / w;
let scaleY = this.flipped ? h / this.scatterStartHeight : this.scatterStartHeight / h;
let ratio = this.scatterStartWidth / this.scatterStartHeight;
if (this.flipped) {
TweenLite.to(frontImage, duration, {
ease: Power1.easeOut,
scaleY: scaleY * targetScale * ratio,
scaleX: scaleX * targetScale,
onComplete: (e) => {
TweenLite.set(frontImage, { scale: 1.0 });
}
});
}
}
}
}
@ -14542,6 +14571,7 @@
}
/* eslint-disable no-undef */
/* eslint-disable no-console */
class StylusCommand extends Object {
constructor() {
@ -15602,6 +15632,7 @@
/* global Quad */
/**
* Class that represents a PixiJS Volatile.
*
@ -15759,6 +15790,7 @@
/* globals ThrowPropsPlugin, Strong */
/**
* Class that represents a PixiJS List.
*
@ -16954,6 +16986,8 @@
}
/* ES Lint */
/* globals PIXI, requestAnimationFrame, performance, app*/
/**
* The AdvancedScatterContainer extends the ScatterContainer, but
@ -17769,7 +17803,7 @@
* @see {@link maps.html}
*/
class GeoMap$1 {
let GeoMap$1 = class GeoMap {
/**
* Creates instance of GeoMap
*
@ -17797,7 +17831,7 @@
onTransform = null
} = {}
) {
this._id = GeoMap$1.counter++;
this._id = GeoMap.counter++;
this.onLoad = new EventHandler('loaded', { listeners: onLoad });
this.onTransform = new EventHandler('transform', { listeners: onTransform });
@ -18209,10 +18243,10 @@
static allFromJson(json, root = './') {
let error = { message: '' };
let maps = {};
if (GeoMap$1._validateJson(json, error)) {
if (GeoMap._validateJson(json, error)) {
for (let [mapname, data] of Object.entries(json)) {
data.tiles.path = root + data.tiles.path;
maps[mapname] = GeoMap$1._createMap(data);
maps[mapname] = GeoMap._createMap(data);
maps[mapname].name = mapname;
}
} else console.error('Could not validate JSON: ' + error.message);
@ -18232,7 +18266,7 @@
static mapFromJson(map, json) {
if (json[map]) {
const data = json[map];
if (this._validJsonMap(data)) return GeoMap$1._createMap(data)
if (this._validJsonMap(data)) return GeoMap._createMap(data)
else console.error('Map was not in a valid format.');
} else console.error('Map was not in data.');
@ -18258,7 +18292,7 @@
error.message += 'The provided JSON object did not contain any items.';
}
for (let [name, data] of Object.entries(json)) {
if (!GeoMap$1._validJsonMap(data)) {
if (!GeoMap._validJsonMap(data)) {
error.message += `${name} was not valid. `;
isValid = false;
}
@ -18305,14 +18339,14 @@
static _createMap(data) {
switch (data.type.toLowerCase()) {
case 'deepzoom':
return GeoMap$1._createDeepZoomMap(data)
return GeoMap._createDeepZoomMap(data)
default:
console.error(`Datatype is invalid or not implemented yet: ${data.type}`);
}
}
static _createDeepZoomMap(data) {
const projection = GeoMap$1._getProjectionByName(data.projection);
const projection = GeoMap._getProjectionByName(data.projection);
const tilesConfig = data.tiles;
const options = data.options;
@ -18329,7 +18363,7 @@
return null
}
}
}
};
GeoMap$1.counter = 0;

BIN
lib/examples/queen.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -64,16 +64,27 @@
<script class="doctest">
let scatterContainer = new DOMScatterContainer(main, { stopEvents: false })
if (Capabilities.supportsTemplate()) {
let flip = new DOMFlip(
let flip1 = new DOMFlip(
scatterContainer,
flipTemplate,
new ImageLoader('./examples/king.jpeg'),
new ImageLoader('./examples/women.jpeg'),
{ tapDelegateFactory: CardWrapper, preloadBack: true }
{ /*tapDelegateFactory: CardWrapper,*/ preloadBack: true }
)
flip.load().then((flip) => {
flip1.load().then((flip) => {
flip.centerAt({ x: 150, y: 120 })
})
let flip2 = new DOMFlip(
scatterContainer,
flipTemplate,
new ImageLoader('./examples/king.jpeg'),
new ImageLoader('./examples/queen.jpeg'),
{ /*tapDelegateFactory: CardWrapper,*/ preloadBack: true }
)
flip2.load().then((flip) => {
flip.centerAt({ x: 650, y: 120 })
})
} else {
alert('Templates not supported, use Edge, Chrome, Safari or Firefox.')
}

View File

@ -17,7 +17,7 @@ export class CardLoader {
scale = 1,
minScale = 0.5,
maxScale = 1.5,
rotation = 0,
rotation = 0
} = {}
) {
this.src = src
@ -67,7 +67,7 @@ export class PDFLoader extends CardLoader {
// Render PDF page into canvas context.
let renderContext = {
canvasContext: context,
viewport: viewport,
viewport: viewport
}
page.render(renderContext)
domNode.appendChild(canvas)
@ -209,7 +209,7 @@ export class DOMFlip {
onClose = null,
onUpdate = null,
onRemoved = null,
onLoaded = null,
onLoaded = null
} = {}
) {
this.domScatterContainer = domScatterContainer
@ -276,7 +276,7 @@ export class DOMFlip {
scalable: this.scalable,
rotatable: this.rotatable,
overdoScaling: this.overdoScaling,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null,
tapDelegate: this.tapDelegateFactory ? new this.tapDelegateFactory(this.cardWrapper) : null
})
if (this.center) {
@ -352,7 +352,7 @@ export class DOMFlip {
opacity: 0,
onComplete: () => {
this.cardWrapper.remove()
},
}
})
}
@ -400,7 +400,7 @@ export class DOMFlippable {
TweenLite.set(this.back, { rotationY: -180 })
TweenLite.set([this.back, this.front], {
backfaceVisibility: 'hidden',
perspective: 5000,
perspective: 5000
})
TweenLite.set(this.front, { visibility: 'visible' })
this.infoBtn = element.querySelector('.infoBtn')
@ -447,7 +447,7 @@ export class DOMFlippable {
if (this.onRemoved) {
this.onRemoved.call(this)
}
},
}
})
}
}
@ -476,7 +476,7 @@ export class DOMFlippable {
scaleButtons() {
TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
scale: this.buttonScale,
scale: this.buttonScale
})
}
@ -618,10 +618,11 @@ export class DOMFlippable {
this.scatter.translatable = translatable
this.scatter.rotatable = rotatable
},
force3D: true,
force3D: true
})
// See https://greensock.com/forums/topic/7997-rotate-the-shortest-way/
TweenLite.to(this.element, this.flipDuration / 2, {
const duration = this.flipDuration / 2
TweenLite.to(this.element, duration, {
scale: targetScale,
ease: Power1.easeOut,
rotationZ: targetZ + '_short',
@ -638,7 +639,25 @@ export class DOMFlippable {
this.hide(this.back)
// this.show(this.infoBtn)
}
},
}
})
//uo: check for special case that the front image must be adapted to the back size
let frontImage = this.front.querySelector('img')
if (frontImage) {
let scaleX = this.flipped ? w / this.scatterStartWidth : this.scatterStartWidth / w
let scaleY = this.flipped ? h / this.scatterStartHeight : this.scatterStartHeight / h
let ratio = this.scatterStartWidth / this.scatterStartHeight
if (this.flipped) {
TweenLite.to(frontImage, duration, {
ease: Power1.easeOut,
scaleY: scaleY * targetScale * ratio,
scaleX: scaleX * targetScale,
onComplete: (e) => {
TweenLite.set(frontImage, { scale: 1.0 })
}
})
}
}
}
}

View File

@ -14,8 +14,8 @@
"test-eventlistener-hammerjs-destroy": "node ./test/tests/eventlistener/hammerjs-destroy.js",
"test-eventlistener-interactionmapper": "node ./test/tests/eventlistener/interactionmapper.js",
"test-eventlistener-interactionmapper-off": "node ./test/tests/eventlistener/interactionmapper-off.js",
"build": "rollup --config ./rollup.config.js",
"watch": "rollup --watch --config ./rollup.config.js",
"build": "rollup --config ./rollup.config.mjs",
"watch": "rollup --watch --config ./rollup.config.mjs",
"3rdparty": "gulp",
"prettier": "gulp prettify",
"jsdoc": "jsdoc -c ./doc/conf.json"