Merge branch 'main' of gitea.iwm-tuebingen.de:IWMBrowser/iwmlib into main
* 'main' of gitea.iwm-tuebingen.de:IWMBrowser/iwmlib: Removed console.logs Fixed timestamp name mismatch. Updated iwmlib and removed log statement. Added pluggable throw behavior. Replaced requestAnimationFrame with setInterval Moved throws to a single loop. Added cancelAnimationFrame update code block to reflect current state Fixed html double code Fixed problem with scrolling text in card drawers. added fix for viewBox rotation bug fixed rollup documented/ solved svg rotation bug # Conflicts: # package.json
This commit is contained in:
commit
57d6e8b461
0
bin/browser.sh
Executable file → Normal file
0
bin/browser.sh
Executable file → Normal file
1258
browser/menu.js
1258
browser/menu.js
File diff suppressed because it is too large
Load Diff
196
dist/iwmlib.js
vendored
196
dist/iwmlib.js
vendored
@ -3213,6 +3213,40 @@
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
|
||||
class RequestFrameThrower {
|
||||
/** Implemenents the standard throw behavior. */
|
||||
animateThrow(throwable) {
|
||||
/*** Calls the animateThrow method in sync with the display link. */
|
||||
requestAnimationFrame(throwable.animateThrow.bind(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
class TimeoutThrower {
|
||||
|
||||
constructor(delay=20) {
|
||||
this.throwables = new Set();
|
||||
this.delay = delay;
|
||||
setTimeout(this.animateStep.bind(this), this.delay);
|
||||
}
|
||||
|
||||
animateThrow(throwable) {
|
||||
this.throwables.add(throwable);
|
||||
}
|
||||
|
||||
animateStep() {
|
||||
let active = [...this.throwables];
|
||||
this.throwables.clear();
|
||||
for(let throwable of active) {
|
||||
throwable.animateThrow();
|
||||
}
|
||||
setTimeout(this.animateStep.bind(this), this.delay);
|
||||
}
|
||||
}
|
||||
|
||||
let thrower = new RequestFrameThrower();
|
||||
|
||||
class Throwable {
|
||||
constructor({
|
||||
movableX = true,
|
||||
@ -3220,7 +3254,7 @@
|
||||
throwVisibility = 44,
|
||||
throwDamping = 0.95,
|
||||
autoThrow = true,
|
||||
onThrowFinished = null,
|
||||
onThrowFinished = null
|
||||
} = {}) {
|
||||
this.movableX = movableX;
|
||||
this.movableY = movableY;
|
||||
@ -3229,9 +3263,16 @@
|
||||
this.autoThrow = autoThrow;
|
||||
this.velocities = [];
|
||||
this.velocity = null;
|
||||
this.timestamp = null;
|
||||
this.lastframe = null;
|
||||
this.onThrowFinished = onThrowFinished;
|
||||
//console.log("onThrowFinished", onThrowFinished)
|
||||
}
|
||||
|
||||
static defaultThrow() {
|
||||
thrower = new RequestFrameThrower();
|
||||
}
|
||||
|
||||
static timeoutThrow() {
|
||||
thrower = new TimeoutThrower();
|
||||
}
|
||||
|
||||
observeVelocity() {
|
||||
@ -3253,7 +3294,7 @@
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x / number,
|
||||
dy: delta.y / number,
|
||||
dy: delta.y / number
|
||||
};
|
||||
this.velocities.push(velocity);
|
||||
while (this.velocities.length > buffer) {
|
||||
@ -3262,8 +3303,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
addTestVelocity(delta, dt=20, buffer = 5) {
|
||||
let t = performance.now();
|
||||
this.lastframe = t;
|
||||
let velocity = {
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x ,
|
||||
dy: delta.y
|
||||
};
|
||||
for(let i=0; i<buffer; i++) {
|
||||
velocity.t += dt;
|
||||
this.velocities.push(velocity);
|
||||
}
|
||||
}
|
||||
|
||||
meanVelocity(milliseconds = 30) {
|
||||
this.addVelocity({ x: 0, y: 0, number: 1 });
|
||||
// this.addVelocity({ x: 0, y: 0, number: 1 })
|
||||
let sum = { x: 0, y: 0 };
|
||||
let count = 0;
|
||||
let t = 0;
|
||||
@ -3284,6 +3340,7 @@
|
||||
killAnimation() {
|
||||
this.velocity = null;
|
||||
this.velocities = [];
|
||||
this.lastframe = null;
|
||||
}
|
||||
|
||||
startThrow() {
|
||||
@ -3305,6 +3362,10 @@
|
||||
return dt
|
||||
}
|
||||
|
||||
recurseAnimateThrow() {
|
||||
ThrowableObjects.add(this);
|
||||
}
|
||||
|
||||
animateThrow(time) {
|
||||
if (this.velocity != null) {
|
||||
let dt = this._throwDeltaTime();
|
||||
@ -3315,7 +3376,7 @@
|
||||
if (nextLength > prevLength) {
|
||||
let factor = nextLength / prevLength;
|
||||
next = Points$1.multiplyScalar(next, 1 / factor);
|
||||
console.log('Prevent acceleration', factor, this.velocity, next);
|
||||
// console.log('Prevent acceleration', factor, this.velocity, next)
|
||||
}
|
||||
this.velocity = next;
|
||||
let d = Points$1.multiplyScalar(this.velocity, dt);
|
||||
@ -3323,11 +3384,11 @@
|
||||
|
||||
this.onDragUpdate(d);
|
||||
if (dt == 0 || this.needsAnimation()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this));
|
||||
thrower.animateThrow(this);
|
||||
return
|
||||
} else {
|
||||
if (this.isOutside()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this));
|
||||
thrower.animateThrow(this);
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -3351,7 +3412,7 @@
|
||||
let next = Points$1.multiplyScalar(velocity, this.throwDamping);
|
||||
return {
|
||||
x: this.movableX ? next.x : 0,
|
||||
y: this.movableY ? next.y : 0,
|
||||
y: this.movableY ? next.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -3396,7 +3457,7 @@
|
||||
scaleCloseBuffer = 0.05,
|
||||
maxRotation = Angle.degree2radian(5),
|
||||
minInteractionDistance = 0,
|
||||
useLowPassFilter = false,
|
||||
useLowPassFilter = false
|
||||
} = {}) {
|
||||
if (rotationDegrees != null && rotation != null) {
|
||||
throw new Error('Use rotationDegrees or rotation but not both')
|
||||
@ -3411,7 +3472,7 @@
|
||||
throwVisibility,
|
||||
throwDamping,
|
||||
autoThrow,
|
||||
onThrowFinished,
|
||||
onThrowFinished
|
||||
});
|
||||
|
||||
/**
|
||||
@ -3486,7 +3547,7 @@
|
||||
|
||||
_callCloseCallbacks() {
|
||||
if (this.onClose) {
|
||||
this.onClose.forEach((callback) => callback(this));
|
||||
this.onClose.forEach(callback => callback(this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3506,6 +3567,9 @@
|
||||
let delta = interaction.delta();
|
||||
|
||||
if (delta != null) {
|
||||
/* uo: Is this the best place to add velocity? It works with scrollable text in card drawers but
|
||||
has to be tested */
|
||||
this.addVelocity(delta);
|
||||
let rotate = delta.rotate;
|
||||
let zoom = delta.zoom;
|
||||
if (this.maxRotation != null) {
|
||||
@ -3524,9 +3588,10 @@
|
||||
zoomDelta *= ratio;
|
||||
zoom = 1 + zoomDelta;
|
||||
}
|
||||
|
||||
this.transform(delta, zoom, rotate, delta.about);
|
||||
this.addVelocity(delta); // uo: reverted commit fa0256d782dd498c6d3e51321260ca375ca9f855
|
||||
/* uo: This is too late an dangerous. transform sometimes modifies delta
|
||||
this.addVelocity(delta) // uo: reverted commit fa0256d782dd498c6d3e51321260ca375ca9f855
|
||||
*/
|
||||
|
||||
if (zoom != 1) this.interactionAnchor = delta.about;
|
||||
}
|
||||
@ -3637,11 +3702,11 @@
|
||||
if (this.scale < this.minScale + this.scaleCloseThreshold - this.scaleCloseBuffer) {
|
||||
this.zoom(this.minScale, {
|
||||
animate: 0.2,
|
||||
onComplete: this.close.bind(this),
|
||||
onComplete: this.close.bind(this)
|
||||
});
|
||||
} else if (this.scale < this.minScale + this.scaleCloseThreshold) {
|
||||
this.zoom(this.minScale + this.scaleCloseThreshold, {
|
||||
animate: 0.4,
|
||||
animate: 0.4
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -3663,12 +3728,12 @@
|
||||
x: '+=' + d.x,
|
||||
y: '+=' + d.y,
|
||||
/* scale: scale, uo: not defined, why was this here? */
|
||||
onUpdate: (e) => {
|
||||
onUpdate: e => {
|
||||
let p = this.position;
|
||||
let dx = p.x - startPos.x;
|
||||
let dy = p.x - startPos.y;
|
||||
this.onMoved(dx, dy);
|
||||
},
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._move(d);
|
||||
@ -3697,7 +3762,7 @@
|
||||
scale: scale,
|
||||
delay: delay,
|
||||
onComplete: onComplete,
|
||||
onUpdate: this.onZoomed.bind(this),
|
||||
onUpdate: this.onZoomed.bind(this)
|
||||
});
|
||||
} else {
|
||||
this.scale = scale;
|
||||
@ -3715,7 +3780,7 @@
|
||||
transform(translate, zoom, rotate, anchor) {
|
||||
let delta = {
|
||||
x: this.movableX ? translate.x : 0,
|
||||
y: this.movableY ? translate.y : 0,
|
||||
y: this.movableY ? translate.y : 0
|
||||
};
|
||||
if (this.resizable) var vzoom = zoom;
|
||||
if (!this.translatable) delta = { x: 0, y: 0 };
|
||||
@ -3730,9 +3795,9 @@
|
||||
rotate: 0,
|
||||
about: anchor,
|
||||
fast: false,
|
||||
type: UPDATE,
|
||||
type: UPDATE
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3761,9 +3826,9 @@
|
||||
translate: delta,
|
||||
scale: newScale,
|
||||
rotate: rotate,
|
||||
about: anchor,
|
||||
about: anchor
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3829,7 +3894,7 @@
|
||||
if (this.scale > this.maxScale) zoom = 1 - amount;
|
||||
if (zoom != 1) {
|
||||
this.transform({ x: 0, y: 0 }, zoom, 0, this.zoomAnchor);
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.animateZoomBounce(dt);
|
||||
});
|
||||
return
|
||||
@ -3886,9 +3951,9 @@
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: START,
|
||||
type: START
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3904,13 +3969,13 @@
|
||||
}
|
||||
|
||||
onEnd(event, interaction) {
|
||||
console.log('Scatter.onEnd', this.dragging);
|
||||
//console.log('Scatter.onEnd', this.dragging)
|
||||
if (interaction.isFinished()) {
|
||||
this.endGesture(interaction);
|
||||
this.dragging = false;
|
||||
for (let key of interaction.ended.keys()) {
|
||||
if (interaction.isTap(key)) {
|
||||
console.log('Scatter.isTap');
|
||||
//console.log('Scatter.isTap')
|
||||
let point = interaction.ended.get(key);
|
||||
this.onTap(event, interaction, point);
|
||||
}
|
||||
@ -3922,9 +3987,9 @@
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: END,
|
||||
type: END
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3938,7 +4003,7 @@
|
||||
//onTap(event, interaction, point) {}
|
||||
|
||||
onTap(event, interaction, point) {
|
||||
console.log('AbstractScatter.onTap', this.tapDelegate, interaction);
|
||||
//console.log('AbstractScatter.onTap', this.tapDelegate, interaction)
|
||||
if (this.tapDelegate) {
|
||||
Events.stop(event);
|
||||
this.tapDelegate.tap(event, 'scatter');
|
||||
@ -3952,9 +4017,9 @@
|
||||
translate: delta,
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3966,9 +4031,9 @@
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3980,9 +4045,9 @@
|
||||
translate: { x: dx, y: dy },
|
||||
about: about,
|
||||
fast: true,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -3993,9 +4058,9 @@
|
||||
let event = new ScatterEvent(this, {
|
||||
scale: this.scale,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -4009,9 +4074,9 @@
|
||||
scale: this.scale,
|
||||
about: about,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -4043,7 +4108,7 @@
|
||||
useCapture = true,
|
||||
capturePointerEvents = true,
|
||||
touchAction = 'none',
|
||||
debugCanvas = null,
|
||||
debugCanvas = null
|
||||
} = {}
|
||||
) {
|
||||
this.onCapture = null;
|
||||
@ -4055,7 +4120,7 @@
|
||||
movement of scatter objects, the touchmove event has to be bound again.
|
||||
*/
|
||||
if (Capabilities.isSafari) {
|
||||
document.addEventListener('touchmove', (event) => this.preventPinch(event), false);
|
||||
document.addEventListener('touchmove', event => this.preventPinch(event), false);
|
||||
stopEvents = false;
|
||||
} else {
|
||||
stopEvents = true;
|
||||
@ -4070,11 +4135,11 @@
|
||||
this.delegate = new InteractionMapper$1(element, this, {
|
||||
useCapture,
|
||||
capturePointerEvents,
|
||||
mouseWheelElement: window,
|
||||
mouseWheelElement: window
|
||||
});
|
||||
|
||||
if (debugCanvas !== null) {
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.showTouches(dt, debugCanvas);
|
||||
});
|
||||
}
|
||||
@ -4096,7 +4161,7 @@
|
||||
context.fill();
|
||||
context.stroke();
|
||||
}
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.showTouches(dt, canvas);
|
||||
});
|
||||
}
|
||||
@ -4238,7 +4303,7 @@
|
||||
scaleCloseBuffer = 0.05,
|
||||
useLowPassFilter = false,
|
||||
maxRotation = Angle.degree2radian(15),
|
||||
minInteractionDistance = 200,
|
||||
minInteractionDistance = 200
|
||||
} = {}
|
||||
) {
|
||||
super({
|
||||
@ -4265,7 +4330,7 @@
|
||||
onClose,
|
||||
useLowPassFilter,
|
||||
maxRotation,
|
||||
minInteractionDistance,
|
||||
minInteractionDistance
|
||||
});
|
||||
if (container == null || width == null || height == null) {
|
||||
throw new Error('Invalid value: null')
|
||||
@ -4293,7 +4358,7 @@
|
||||
height: height,
|
||||
scale: startScale,
|
||||
rotation: this.startRotationDegrees,
|
||||
transformOrigin: transformOrigin,
|
||||
transformOrigin: transformOrigin
|
||||
};
|
||||
this.tapNodes = new Map();
|
||||
|
||||
@ -4315,15 +4380,15 @@
|
||||
button.className = 'interactiveElement';
|
||||
this.element.appendChild(button);
|
||||
|
||||
button.addEventListener('pointerdown', (e) => {
|
||||
button.addEventListener('pointerdown', e => {
|
||||
this.startResize(e);
|
||||
});
|
||||
|
||||
button.addEventListener('pointermove', (e) => {
|
||||
button.addEventListener('pointermove', e => {
|
||||
this.resize(e);
|
||||
});
|
||||
|
||||
button.addEventListener('pointerup', (e) => {
|
||||
button.addEventListener('pointerup', e => {
|
||||
this.stopResize(e);
|
||||
});
|
||||
this.resizeButton = button;
|
||||
@ -4340,7 +4405,7 @@
|
||||
scale: this.scale,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
rotation: this.rotation,
|
||||
rotation: this.rotation
|
||||
}
|
||||
}
|
||||
|
||||
@ -4391,7 +4456,7 @@
|
||||
top: rect.top - stage.top,
|
||||
left: rect.left - stage.left,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
height: rect.height
|
||||
}
|
||||
}
|
||||
|
||||
@ -4432,7 +4497,7 @@
|
||||
set scale(scale) {
|
||||
TweenLite.set(this.element, {
|
||||
scale: scale,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
});
|
||||
this._scale = scale;
|
||||
}
|
||||
@ -4464,9 +4529,9 @@
|
||||
hide() {
|
||||
TweenLite.to(this.element, 0.1, {
|
||||
display: 'none',
|
||||
onComplete: (e) => {
|
||||
onComplete: e => {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -4480,7 +4545,7 @@
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
rotation: rotationDegrees,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
});
|
||||
}
|
||||
|
||||
@ -4541,7 +4606,7 @@
|
||||
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
this.bringToFront();
|
||||
|
||||
@ -4549,7 +4614,7 @@
|
||||
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
|
||||
let offset = Points$1.subtract(oldPostition, newPostition);
|
||||
@ -4594,7 +4659,7 @@
|
||||
)
|
||||
TweenLite.to(this.element, 0, {
|
||||
width: this.element.offsetWidth + resizeW / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale
|
||||
});
|
||||
|
||||
this.oldX = e.clientX;
|
||||
@ -4611,12 +4676,12 @@
|
||||
let event = new CustomEvent('resizeEnded');
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
this.element.style.transformOrigin = '50% 50%';
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
let offset = Points$1.subtract(oldPostition, newPostition);
|
||||
|
||||
@ -4789,7 +4854,6 @@
|
||||
tap(event, calledBy = 'unknown') {
|
||||
if (event.isTrusted) {
|
||||
let node = this.nearestActive(event);
|
||||
console.log('tap', node);
|
||||
this.nodeTapped(node, event);
|
||||
|
||||
/* let node = document.elementFromPoint(event.clientX, event.clientY)
|
||||
@ -8195,7 +8259,6 @@
|
||||
image,
|
||||
});
|
||||
let center = this._calculateCenterRelativeTo(target, image);
|
||||
console.log('_calculateCenterRelativeTo', center);
|
||||
TweenLite.set(maskImage, {
|
||||
transformOrigin: `${center.x} ${center.y}`,
|
||||
});
|
||||
@ -9099,7 +9162,6 @@
|
||||
}
|
||||
|
||||
static _calculateCenterRelativeTo(target, image) {
|
||||
// console.log('_calculateCenterRelativeTo', target, image)
|
||||
let bbox = image.getBBox();
|
||||
let width = bbox.width;
|
||||
let height = bbox.height;
|
||||
|
184
dist/iwmlib.pixi.js
vendored
184
dist/iwmlib.pixi.js
vendored
@ -6778,6 +6778,40 @@
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
|
||||
class RequestFrameThrower {
|
||||
/** Implemenents the standard throw behavior. */
|
||||
animateThrow(throwable) {
|
||||
/*** Calls the animateThrow method in sync with the display link. */
|
||||
requestAnimationFrame(throwable.animateThrow.bind(throwable));
|
||||
}
|
||||
}
|
||||
|
||||
class TimeoutThrower {
|
||||
|
||||
constructor(delay=20) {
|
||||
this.throwables = new Set();
|
||||
this.delay = delay;
|
||||
setTimeout(this.animateStep.bind(this), this.delay);
|
||||
}
|
||||
|
||||
animateThrow(throwable) {
|
||||
this.throwables.add(throwable);
|
||||
}
|
||||
|
||||
animateStep() {
|
||||
let active = [...this.throwables];
|
||||
this.throwables.clear();
|
||||
for(let throwable of active) {
|
||||
throwable.animateThrow();
|
||||
}
|
||||
setTimeout(this.animateStep.bind(this), this.delay);
|
||||
}
|
||||
}
|
||||
|
||||
let thrower = new RequestFrameThrower();
|
||||
|
||||
class Throwable {
|
||||
constructor({
|
||||
movableX = true,
|
||||
@ -6785,7 +6819,7 @@
|
||||
throwVisibility = 44,
|
||||
throwDamping = 0.95,
|
||||
autoThrow = true,
|
||||
onThrowFinished = null,
|
||||
onThrowFinished = null
|
||||
} = {}) {
|
||||
this.movableX = movableX;
|
||||
this.movableY = movableY;
|
||||
@ -6794,9 +6828,16 @@
|
||||
this.autoThrow = autoThrow;
|
||||
this.velocities = [];
|
||||
this.velocity = null;
|
||||
this.timestamp = null;
|
||||
this.lastframe = null;
|
||||
this.onThrowFinished = onThrowFinished;
|
||||
//console.log("onThrowFinished", onThrowFinished)
|
||||
}
|
||||
|
||||
static defaultThrow() {
|
||||
thrower = new RequestFrameThrower();
|
||||
}
|
||||
|
||||
static timeoutThrow() {
|
||||
thrower = new TimeoutThrower();
|
||||
}
|
||||
|
||||
observeVelocity() {
|
||||
@ -6818,7 +6859,7 @@
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x / number,
|
||||
dy: delta.y / number,
|
||||
dy: delta.y / number
|
||||
};
|
||||
this.velocities.push(velocity);
|
||||
while (this.velocities.length > buffer) {
|
||||
@ -6827,8 +6868,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
addTestVelocity(delta, dt=20, buffer = 5) {
|
||||
let t = performance.now();
|
||||
this.lastframe = t;
|
||||
let velocity = {
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x ,
|
||||
dy: delta.y
|
||||
};
|
||||
for(let i=0; i<buffer; i++) {
|
||||
velocity.t += dt;
|
||||
this.velocities.push(velocity);
|
||||
}
|
||||
}
|
||||
|
||||
meanVelocity(milliseconds = 30) {
|
||||
this.addVelocity({ x: 0, y: 0, number: 1 });
|
||||
// this.addVelocity({ x: 0, y: 0, number: 1 })
|
||||
let sum = { x: 0, y: 0 };
|
||||
let count = 0;
|
||||
let t = 0;
|
||||
@ -6849,6 +6905,7 @@
|
||||
killAnimation() {
|
||||
this.velocity = null;
|
||||
this.velocities = [];
|
||||
this.lastframe = null;
|
||||
}
|
||||
|
||||
startThrow() {
|
||||
@ -6870,6 +6927,10 @@
|
||||
return dt
|
||||
}
|
||||
|
||||
recurseAnimateThrow() {
|
||||
ThrowableObjects.add(this);
|
||||
}
|
||||
|
||||
animateThrow(time) {
|
||||
if (this.velocity != null) {
|
||||
let dt = this._throwDeltaTime();
|
||||
@ -6880,7 +6941,7 @@
|
||||
if (nextLength > prevLength) {
|
||||
let factor = nextLength / prevLength;
|
||||
next = Points.multiplyScalar(next, 1 / factor);
|
||||
console.log('Prevent acceleration', factor, this.velocity, next);
|
||||
// console.log('Prevent acceleration', factor, this.velocity, next)
|
||||
}
|
||||
this.velocity = next;
|
||||
let d = Points.multiplyScalar(this.velocity, dt);
|
||||
@ -6888,11 +6949,11 @@
|
||||
|
||||
this.onDragUpdate(d);
|
||||
if (dt == 0 || this.needsAnimation()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this));
|
||||
thrower.animateThrow(this);
|
||||
return
|
||||
} else {
|
||||
if (this.isOutside()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this));
|
||||
thrower.animateThrow(this);
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -6916,7 +6977,7 @@
|
||||
let next = Points.multiplyScalar(velocity, this.throwDamping);
|
||||
return {
|
||||
x: this.movableX ? next.x : 0,
|
||||
y: this.movableY ? next.y : 0,
|
||||
y: this.movableY ? next.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -6961,7 +7022,7 @@
|
||||
scaleCloseBuffer = 0.05,
|
||||
maxRotation = Angle.degree2radian(5),
|
||||
minInteractionDistance = 0,
|
||||
useLowPassFilter = false,
|
||||
useLowPassFilter = false
|
||||
} = {}) {
|
||||
if (rotationDegrees != null && rotation != null) {
|
||||
throw new Error('Use rotationDegrees or rotation but not both')
|
||||
@ -6976,7 +7037,7 @@
|
||||
throwVisibility,
|
||||
throwDamping,
|
||||
autoThrow,
|
||||
onThrowFinished,
|
||||
onThrowFinished
|
||||
});
|
||||
|
||||
/**
|
||||
@ -7051,7 +7112,7 @@
|
||||
|
||||
_callCloseCallbacks() {
|
||||
if (this.onClose) {
|
||||
this.onClose.forEach((callback) => callback(this));
|
||||
this.onClose.forEach(callback => callback(this));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7071,6 +7132,9 @@
|
||||
let delta = interaction.delta();
|
||||
|
||||
if (delta != null) {
|
||||
/* uo: Is this the best place to add velocity? It works with scrollable text in card drawers but
|
||||
has to be tested */
|
||||
this.addVelocity(delta);
|
||||
let rotate = delta.rotate;
|
||||
let zoom = delta.zoom;
|
||||
if (this.maxRotation != null) {
|
||||
@ -7089,9 +7153,10 @@
|
||||
zoomDelta *= ratio;
|
||||
zoom = 1 + zoomDelta;
|
||||
}
|
||||
|
||||
this.transform(delta, zoom, rotate, delta.about);
|
||||
this.addVelocity(delta); // uo: reverted commit fa0256d782dd498c6d3e51321260ca375ca9f855
|
||||
/* uo: This is too late an dangerous. transform sometimes modifies delta
|
||||
this.addVelocity(delta) // uo: reverted commit fa0256d782dd498c6d3e51321260ca375ca9f855
|
||||
*/
|
||||
|
||||
if (zoom != 1) this.interactionAnchor = delta.about;
|
||||
}
|
||||
@ -7202,11 +7267,11 @@
|
||||
if (this.scale < this.minScale + this.scaleCloseThreshold - this.scaleCloseBuffer) {
|
||||
this.zoom(this.minScale, {
|
||||
animate: 0.2,
|
||||
onComplete: this.close.bind(this),
|
||||
onComplete: this.close.bind(this)
|
||||
});
|
||||
} else if (this.scale < this.minScale + this.scaleCloseThreshold) {
|
||||
this.zoom(this.minScale + this.scaleCloseThreshold, {
|
||||
animate: 0.4,
|
||||
animate: 0.4
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -7228,12 +7293,12 @@
|
||||
x: '+=' + d.x,
|
||||
y: '+=' + d.y,
|
||||
/* scale: scale, uo: not defined, why was this here? */
|
||||
onUpdate: (e) => {
|
||||
onUpdate: e => {
|
||||
let p = this.position;
|
||||
let dx = p.x - startPos.x;
|
||||
let dy = p.x - startPos.y;
|
||||
this.onMoved(dx, dy);
|
||||
},
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._move(d);
|
||||
@ -7262,7 +7327,7 @@
|
||||
scale: scale,
|
||||
delay: delay,
|
||||
onComplete: onComplete,
|
||||
onUpdate: this.onZoomed.bind(this),
|
||||
onUpdate: this.onZoomed.bind(this)
|
||||
});
|
||||
} else {
|
||||
this.scale = scale;
|
||||
@ -7280,7 +7345,7 @@
|
||||
transform(translate, zoom, rotate, anchor) {
|
||||
let delta = {
|
||||
x: this.movableX ? translate.x : 0,
|
||||
y: this.movableY ? translate.y : 0,
|
||||
y: this.movableY ? translate.y : 0
|
||||
};
|
||||
if (this.resizable) var vzoom = zoom;
|
||||
if (!this.translatable) delta = { x: 0, y: 0 };
|
||||
@ -7295,9 +7360,9 @@
|
||||
rotate: 0,
|
||||
about: anchor,
|
||||
fast: false,
|
||||
type: UPDATE,
|
||||
type: UPDATE
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7326,9 +7391,9 @@
|
||||
translate: delta,
|
||||
scale: newScale,
|
||||
rotate: rotate,
|
||||
about: anchor,
|
||||
about: anchor
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7394,7 +7459,7 @@
|
||||
if (this.scale > this.maxScale) zoom = 1 - amount;
|
||||
if (zoom != 1) {
|
||||
this.transform({ x: 0, y: 0 }, zoom, 0, this.zoomAnchor);
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.animateZoomBounce(dt);
|
||||
});
|
||||
return
|
||||
@ -7451,9 +7516,9 @@
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: START,
|
||||
type: START
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7469,13 +7534,13 @@
|
||||
}
|
||||
|
||||
onEnd(event, interaction) {
|
||||
console.log('Scatter.onEnd', this.dragging);
|
||||
//console.log('Scatter.onEnd', this.dragging)
|
||||
if (interaction.isFinished()) {
|
||||
this.endGesture(interaction);
|
||||
this.dragging = false;
|
||||
for (let key of interaction.ended.keys()) {
|
||||
if (interaction.isTap(key)) {
|
||||
console.log('Scatter.isTap');
|
||||
//console.log('Scatter.isTap')
|
||||
let point = interaction.ended.get(key);
|
||||
this.onTap(event, interaction, point);
|
||||
}
|
||||
@ -7487,9 +7552,9 @@
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: END,
|
||||
type: END
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7503,7 +7568,7 @@
|
||||
//onTap(event, interaction, point) {}
|
||||
|
||||
onTap(event, interaction, point) {
|
||||
console.log('AbstractScatter.onTap', this.tapDelegate, interaction);
|
||||
//console.log('AbstractScatter.onTap', this.tapDelegate, interaction)
|
||||
if (this.tapDelegate) {
|
||||
Events$1.stop(event);
|
||||
this.tapDelegate.tap(event, 'scatter');
|
||||
@ -7517,9 +7582,9 @@
|
||||
translate: delta,
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7531,9 +7596,9 @@
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7545,9 +7610,9 @@
|
||||
translate: { x: dx, y: dy },
|
||||
about: about,
|
||||
fast: true,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7558,9 +7623,9 @@
|
||||
let event = new ScatterEvent(this, {
|
||||
scale: this.scale,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7574,9 +7639,9 @@
|
||||
scale: this.scale,
|
||||
about: about,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
});
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event);
|
||||
});
|
||||
}
|
||||
@ -7623,7 +7688,7 @@
|
||||
scaleCloseBuffer = 0.05,
|
||||
useLowPassFilter = false,
|
||||
maxRotation = Angle.degree2radian(15),
|
||||
minInteractionDistance = 200,
|
||||
minInteractionDistance = 200
|
||||
} = {}
|
||||
) {
|
||||
super({
|
||||
@ -7650,7 +7715,7 @@
|
||||
onClose,
|
||||
useLowPassFilter,
|
||||
maxRotation,
|
||||
minInteractionDistance,
|
||||
minInteractionDistance
|
||||
});
|
||||
if (container == null || width == null || height == null) {
|
||||
throw new Error('Invalid value: null')
|
||||
@ -7678,7 +7743,7 @@
|
||||
height: height,
|
||||
scale: startScale,
|
||||
rotation: this.startRotationDegrees,
|
||||
transformOrigin: transformOrigin,
|
||||
transformOrigin: transformOrigin
|
||||
};
|
||||
this.tapNodes = new Map();
|
||||
|
||||
@ -7700,15 +7765,15 @@
|
||||
button.className = 'interactiveElement';
|
||||
this.element.appendChild(button);
|
||||
|
||||
button.addEventListener('pointerdown', (e) => {
|
||||
button.addEventListener('pointerdown', e => {
|
||||
this.startResize(e);
|
||||
});
|
||||
|
||||
button.addEventListener('pointermove', (e) => {
|
||||
button.addEventListener('pointermove', e => {
|
||||
this.resize(e);
|
||||
});
|
||||
|
||||
button.addEventListener('pointerup', (e) => {
|
||||
button.addEventListener('pointerup', e => {
|
||||
this.stopResize(e);
|
||||
});
|
||||
this.resizeButton = button;
|
||||
@ -7725,7 +7790,7 @@
|
||||
scale: this.scale,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
rotation: this.rotation,
|
||||
rotation: this.rotation
|
||||
}
|
||||
}
|
||||
|
||||
@ -7776,7 +7841,7 @@
|
||||
top: rect.top - stage.top,
|
||||
left: rect.left - stage.left,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
height: rect.height
|
||||
}
|
||||
}
|
||||
|
||||
@ -7817,7 +7882,7 @@
|
||||
set scale(scale) {
|
||||
TweenLite.set(this.element, {
|
||||
scale: scale,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
});
|
||||
this._scale = scale;
|
||||
}
|
||||
@ -7849,9 +7914,9 @@
|
||||
hide() {
|
||||
TweenLite.to(this.element, 0.1, {
|
||||
display: 'none',
|
||||
onComplete: (e) => {
|
||||
onComplete: e => {
|
||||
this.element.parentNode.removeChild(this.element);
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -7865,7 +7930,7 @@
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
rotation: rotationDegrees,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
});
|
||||
}
|
||||
|
||||
@ -7926,7 +7991,7 @@
|
||||
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
this.bringToFront();
|
||||
|
||||
@ -7934,7 +7999,7 @@
|
||||
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
|
||||
let offset = Points.subtract(oldPostition, newPostition);
|
||||
@ -7979,7 +8044,7 @@
|
||||
)
|
||||
TweenLite.to(this.element, 0, {
|
||||
width: this.element.offsetWidth + resizeW / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale
|
||||
});
|
||||
|
||||
this.oldX = e.clientX;
|
||||
@ -7996,12 +8061,12 @@
|
||||
let event = new CustomEvent('resizeEnded');
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
this.element.style.transformOrigin = '50% 50%';
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
};
|
||||
let offset = Points.subtract(oldPostition, newPostition);
|
||||
|
||||
@ -8174,7 +8239,6 @@
|
||||
tap(event, calledBy = 'unknown') {
|
||||
if (event.isTrusted) {
|
||||
let node = this.nearestActive(event);
|
||||
console.log('tap', node);
|
||||
this.nodeTapped(node, event);
|
||||
|
||||
/* let node = document.elementFromPoint(event.clientX, event.clientY)
|
||||
|
0
lib/_menu.js
Executable file → Normal file
0
lib/_menu.js
Executable file → Normal file
@ -766,7 +766,6 @@ export default class Card {
|
||||
}
|
||||
|
||||
static _calculateCenterRelativeTo(target, image) {
|
||||
// console.log('_calculateCenterRelativeTo', target, image)
|
||||
let bbox = image.getBBox()
|
||||
let width = bbox.width
|
||||
let height = bbox.height
|
||||
|
@ -213,7 +213,6 @@ export default class Highlight extends Object {
|
||||
image,
|
||||
})
|
||||
let center = this._calculateCenterRelativeTo(target, image)
|
||||
console.log('_calculateCenterRelativeTo', center)
|
||||
TweenLite.set(maskImage, {
|
||||
transformOrigin: `${center.x} ${center.y}`,
|
||||
})
|
||||
|
@ -158,7 +158,6 @@ export default class CardWrapper extends Object {
|
||||
tap(event, calledBy = 'unknown') {
|
||||
if (event.isTrusted) {
|
||||
let node = this.nearestActive(event)
|
||||
console.log('tap', node)
|
||||
this.nodeTapped(node, event)
|
||||
|
||||
/* let node = document.elementFromPoint(event.clientX, event.clientY)
|
||||
|
@ -17,44 +17,60 @@
|
||||
<div class="flipFace back" style="visibility: hidden"></div>
|
||||
</div>
|
||||
<!-- Very tricky problem to scale svgs: see https://css-tricks.com/scale-svg/ -->
|
||||
<svg
|
||||
class="flipButton backBtn"
|
||||
style="visibility: hidden"
|
||||
viewBox="0 0 100 100"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
>
|
||||
<!-- SVG viewPort interferes with DOMMatrix calculations: see
|
||||
https://stackoverflow.com/questions/70696387/how-to-get-transform-matrix-of-a-dom-element-->
|
||||
<div class="flipButton backBtn" style="visibility:hidden;">
|
||||
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" style="width:inherit; height:inherit;">
|
||||
<g stroke-width="8" stroke="white">
|
||||
<circle cx="50" cy="50" r="44" fill="gray" />
|
||||
<line x1="30" y1="30" x2="70" y2="70" />
|
||||
<line x1="30" y1="70" x2="70" y2="30" />
|
||||
<circle cx="50" cy="50" r="44" fill="gray" />
|
||||
<line x1="30" y1="30" x2="70" y2="70" />
|
||||
<line x1="30" y1="70" x2="70" y2="30" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
|
||||
<svg class="flipButton infoBtn" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
|
||||
<div class="flipButton infoBtn">
|
||||
<svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" style="width:inherit; height:inherit;">
|
||||
<circle cx="50" cy="50" r="44" stroke="white" stroke-width="8" fill="gray" />
|
||||
<circle cx="50" cy="32" r="7" fill="white" />
|
||||
<line x1="50" y1="46" x2="50" y2="78" stroke="white" stroke-width="12" />
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
</head>
|
||||
<body onload="Doctest.run()">
|
||||
<h1><a href="index.html">lib.</a>Flippable</h1>
|
||||
<p>
|
||||
The flip effect simulates a flip between a front and back view of an object by means of a 3D rotation. The
|
||||
DOMFlippable class implements this effect for two DOM nodes, one as the front view, the other as the back
|
||||
view. Both views are connected via a HTML template that defines the placeholders for front and back views.
|
||||
The style file "css/flipeffect.css" holds reasonable default styles for this kind of templates.
|
||||
</p>
|
||||
<pre><code>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</head>
|
||||
<body onload="Doctest.run()">
|
||||
<h1>
|
||||
Flippable
|
||||
</h1>
|
||||
<p>
|
||||
The flip effect simulates a flip between a front and back view of an object
|
||||
by means of a 3D rotation. The DOMFlippable class implements this effect for two
|
||||
DOM nodes, one as the front view, the other as the back view. Both views are connected
|
||||
via a HTML template that defines the placeholders for front and back views. The
|
||||
style file "css/flipeffect.css" holds reasonable default styles for this kind of
|
||||
templates.
|
||||
</p>
|
||||
<p>
|
||||
The SVG buttons have to be wrapped in an HTML DOM element which handles events. Otherwise,
|
||||
the viewbox of the SVG will interfere with the coordinate transformation.
|
||||
</p>
|
||||
<pre><code>
|
||||
<template id="flipTemplate">
|
||||
<div class="flipWrapper">
|
||||
<div class="flipCard">
|
||||
<div class="flipFace front"></div>
|
||||
<div class="flipFace back" style="visibility:hidden;"></div>
|
||||
</div>
|
||||
<svg class="flipButton backBtn" .../>
|
||||
<svg class="flipButton infoBtn" .../>
|
||||
<div class="flipButton backBtn" .../>
|
||||
<svg .../>
|
||||
</div>
|
||||
<div class="flipButton infoBtn" .../>
|
||||
<svg .../>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</code>
|
||||
|
191
lib/scatter.js
191
lib/scatter.js
@ -88,6 +88,40 @@ export class ResizeEvent extends BaseEvent {
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
|
||||
class RequestFrameThrower {
|
||||
/** Implemenents the standard throw behavior. */
|
||||
animateThrow(throwable) {
|
||||
/*** Calls the animateThrow method in sync with the display link. */
|
||||
requestAnimationFrame(throwable.animateThrow.bind(throwable))
|
||||
}
|
||||
}
|
||||
|
||||
class TimeoutThrower {
|
||||
|
||||
constructor(delay=20) {
|
||||
this.throwables = new Set()
|
||||
this.delay = delay
|
||||
setTimeout(this.animateStep.bind(this), this.delay)
|
||||
}
|
||||
|
||||
animateThrow(throwable) {
|
||||
this.throwables.add(throwable)
|
||||
}
|
||||
|
||||
animateStep() {
|
||||
let active = [...this.throwables]
|
||||
this.throwables.clear()
|
||||
for(let throwable of active) {
|
||||
throwable.animateThrow()
|
||||
}
|
||||
setTimeout(this.animateStep.bind(this), this.delay)
|
||||
}
|
||||
}
|
||||
|
||||
let thrower = new RequestFrameThrower()
|
||||
|
||||
class Throwable {
|
||||
constructor({
|
||||
movableX = true,
|
||||
@ -95,7 +129,7 @@ class Throwable {
|
||||
throwVisibility = 44,
|
||||
throwDamping = 0.95,
|
||||
autoThrow = true,
|
||||
onThrowFinished = null,
|
||||
onThrowFinished = null
|
||||
} = {}) {
|
||||
this.movableX = movableX
|
||||
this.movableY = movableY
|
||||
@ -104,9 +138,16 @@ class Throwable {
|
||||
this.autoThrow = autoThrow
|
||||
this.velocities = []
|
||||
this.velocity = null
|
||||
this.timestamp = null
|
||||
this.lastframe = null
|
||||
this.onThrowFinished = onThrowFinished
|
||||
//console.log("onThrowFinished", onThrowFinished)
|
||||
}
|
||||
|
||||
static defaultThrow() {
|
||||
thrower = new RequestFrameThrower()
|
||||
}
|
||||
|
||||
static timeoutThrow() {
|
||||
thrower = new TimeoutThrower()
|
||||
}
|
||||
|
||||
observeVelocity() {
|
||||
@ -128,7 +169,7 @@ class Throwable {
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x / number,
|
||||
dy: delta.y / number,
|
||||
dy: delta.y / number
|
||||
}
|
||||
this.velocities.push(velocity)
|
||||
while (this.velocities.length > buffer) {
|
||||
@ -137,8 +178,23 @@ class Throwable {
|
||||
}
|
||||
}
|
||||
|
||||
addTestVelocity(delta, dt=20, buffer = 5) {
|
||||
let t = performance.now()
|
||||
this.lastframe = t
|
||||
let velocity = {
|
||||
t: t,
|
||||
dt: dt,
|
||||
dx: delta.x ,
|
||||
dy: delta.y
|
||||
}
|
||||
for(let i=0; i<buffer; i++) {
|
||||
velocity.t += dt
|
||||
this.velocities.push(velocity)
|
||||
}
|
||||
}
|
||||
|
||||
meanVelocity(milliseconds = 30) {
|
||||
this.addVelocity({ x: 0, y: 0, number: 1 })
|
||||
// this.addVelocity({ x: 0, y: 0, number: 1 })
|
||||
let sum = { x: 0, y: 0 }
|
||||
let count = 0
|
||||
let t = 0
|
||||
@ -159,6 +215,7 @@ class Throwable {
|
||||
killAnimation() {
|
||||
this.velocity = null
|
||||
this.velocities = []
|
||||
this.lastframe = null
|
||||
}
|
||||
|
||||
startThrow() {
|
||||
@ -180,6 +237,10 @@ class Throwable {
|
||||
return dt
|
||||
}
|
||||
|
||||
recurseAnimateThrow() {
|
||||
ThrowableObjects.add(this)
|
||||
}
|
||||
|
||||
animateThrow(time) {
|
||||
if (this.velocity != null) {
|
||||
let dt = this._throwDeltaTime()
|
||||
@ -190,7 +251,7 @@ class Throwable {
|
||||
if (nextLength > prevLength) {
|
||||
let factor = nextLength / prevLength
|
||||
next = Points.multiplyScalar(next, 1 / factor)
|
||||
console.log('Prevent acceleration', factor, this.velocity, next)
|
||||
// console.log('Prevent acceleration', factor, this.velocity, next)
|
||||
}
|
||||
this.velocity = next
|
||||
let d = Points.multiplyScalar(this.velocity, dt)
|
||||
@ -198,11 +259,11 @@ class Throwable {
|
||||
|
||||
this.onDragUpdate(d)
|
||||
if (dt == 0 || this.needsAnimation()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this))
|
||||
thrower.animateThrow(this)
|
||||
return
|
||||
} else {
|
||||
if (this.isOutside()) {
|
||||
requestAnimationFrame(this.animateThrow.bind(this))
|
||||
thrower.animateThrow(this)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -226,7 +287,7 @@ class Throwable {
|
||||
let next = Points.multiplyScalar(velocity, this.throwDamping)
|
||||
return {
|
||||
x: this.movableX ? next.x : 0,
|
||||
y: this.movableY ? next.y : 0,
|
||||
y: this.movableY ? next.y : 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +332,7 @@ export class AbstractScatter extends Throwable {
|
||||
scaleCloseBuffer = 0.05,
|
||||
maxRotation = Angle.degree2radian(5),
|
||||
minInteractionDistance = 0,
|
||||
useLowPassFilter = false,
|
||||
useLowPassFilter = false
|
||||
} = {}) {
|
||||
if (rotationDegrees != null && rotation != null) {
|
||||
throw new Error('Use rotationDegrees or rotation but not both')
|
||||
@ -286,7 +347,7 @@ export class AbstractScatter extends Throwable {
|
||||
throwVisibility,
|
||||
throwDamping,
|
||||
autoThrow,
|
||||
onThrowFinished,
|
||||
onThrowFinished
|
||||
})
|
||||
|
||||
/**
|
||||
@ -361,7 +422,7 @@ export class AbstractScatter extends Throwable {
|
||||
|
||||
_callCloseCallbacks() {
|
||||
if (this.onClose) {
|
||||
this.onClose.forEach((callback) => callback(this))
|
||||
this.onClose.forEach(callback => callback(this))
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,6 +442,9 @@ export class AbstractScatter extends Throwable {
|
||||
let delta = interaction.delta()
|
||||
|
||||
if (delta != null) {
|
||||
/* uo: Is this the best place to add velocity? It works with scrollable text in card drawers but
|
||||
has to be tested */
|
||||
this.addVelocity(delta)
|
||||
let rotate = delta.rotate
|
||||
let zoom = delta.zoom
|
||||
if (this.maxRotation != null) {
|
||||
@ -399,9 +463,10 @@ export class AbstractScatter extends Throwable {
|
||||
zoomDelta *= ratio
|
||||
zoom = 1 + zoomDelta
|
||||
}
|
||||
|
||||
this.transform(delta, zoom, rotate, delta.about)
|
||||
/* uo: This is too late an dangerous. transform sometimes modifies delta
|
||||
this.addVelocity(delta) // uo: reverted commit fa0256d782dd498c6d3e51321260ca375ca9f855
|
||||
*/
|
||||
|
||||
if (zoom != 1) this.interactionAnchor = delta.about
|
||||
}
|
||||
@ -512,11 +577,11 @@ export class AbstractScatter extends Throwable {
|
||||
if (this.scale < this.minScale + this.scaleCloseThreshold - this.scaleCloseBuffer) {
|
||||
this.zoom(this.minScale, {
|
||||
animate: 0.2,
|
||||
onComplete: this.close.bind(this),
|
||||
onComplete: this.close.bind(this)
|
||||
})
|
||||
} else if (this.scale < this.minScale + this.scaleCloseThreshold) {
|
||||
this.zoom(this.minScale + this.scaleCloseThreshold, {
|
||||
animate: 0.4,
|
||||
animate: 0.4
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -538,12 +603,12 @@ export class AbstractScatter extends Throwable {
|
||||
x: '+=' + d.x,
|
||||
y: '+=' + d.y,
|
||||
/* scale: scale, uo: not defined, why was this here? */
|
||||
onUpdate: (e) => {
|
||||
onUpdate: e => {
|
||||
let p = this.position
|
||||
let dx = p.x - startPos.x
|
||||
let dy = p.x - startPos.y
|
||||
this.onMoved(dx, dy)
|
||||
},
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this._move(d)
|
||||
@ -572,7 +637,7 @@ export class AbstractScatter extends Throwable {
|
||||
scale: scale,
|
||||
delay: delay,
|
||||
onComplete: onComplete,
|
||||
onUpdate: this.onZoomed.bind(this),
|
||||
onUpdate: this.onZoomed.bind(this)
|
||||
})
|
||||
} else {
|
||||
this.scale = scale
|
||||
@ -590,7 +655,7 @@ export class AbstractScatter extends Throwable {
|
||||
transform(translate, zoom, rotate, anchor) {
|
||||
let delta = {
|
||||
x: this.movableX ? translate.x : 0,
|
||||
y: this.movableY ? translate.y : 0,
|
||||
y: this.movableY ? translate.y : 0
|
||||
}
|
||||
if (this.resizable) var vzoom = zoom
|
||||
if (!this.translatable) delta = { x: 0, y: 0 }
|
||||
@ -605,9 +670,9 @@ export class AbstractScatter extends Throwable {
|
||||
rotate: 0,
|
||||
about: anchor,
|
||||
fast: false,
|
||||
type: UPDATE,
|
||||
type: UPDATE
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -636,9 +701,9 @@ export class AbstractScatter extends Throwable {
|
||||
translate: delta,
|
||||
scale: newScale,
|
||||
rotate: rotate,
|
||||
about: anchor,
|
||||
about: anchor
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -704,7 +769,7 @@ export class AbstractScatter extends Throwable {
|
||||
if (this.scale > this.maxScale) zoom = 1 - amount
|
||||
if (zoom != 1) {
|
||||
this.transform({ x: 0, y: 0 }, zoom, 0, this.zoomAnchor)
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.animateZoomBounce(dt)
|
||||
})
|
||||
return
|
||||
@ -761,9 +826,9 @@ export class AbstractScatter extends Throwable {
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: START,
|
||||
type: START
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -779,13 +844,13 @@ export class AbstractScatter extends Throwable {
|
||||
}
|
||||
|
||||
onEnd(event, interaction) {
|
||||
console.log('Scatter.onEnd', this.dragging)
|
||||
//console.log('Scatter.onEnd', this.dragging)
|
||||
if (interaction.isFinished()) {
|
||||
this.endGesture(interaction)
|
||||
this.dragging = false
|
||||
for (let key of interaction.ended.keys()) {
|
||||
if (interaction.isTap(key)) {
|
||||
console.log('Scatter.isTap')
|
||||
//console.log('Scatter.isTap')
|
||||
let point = interaction.ended.get(key)
|
||||
this.onTap(event, interaction, point)
|
||||
}
|
||||
@ -797,9 +862,9 @@ export class AbstractScatter extends Throwable {
|
||||
rotate: 0,
|
||||
about: null,
|
||||
fast: false,
|
||||
type: END,
|
||||
type: END
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -813,7 +878,7 @@ export class AbstractScatter extends Throwable {
|
||||
//onTap(event, interaction, point) {}
|
||||
|
||||
onTap(event, interaction, point) {
|
||||
console.log('AbstractScatter.onTap', this.tapDelegate, interaction)
|
||||
//console.log('AbstractScatter.onTap', this.tapDelegate, interaction)
|
||||
if (this.tapDelegate) {
|
||||
Events.stop(event)
|
||||
this.tapDelegate.tap(event, 'scatter')
|
||||
@ -827,9 +892,9 @@ export class AbstractScatter extends Throwable {
|
||||
translate: delta,
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
type: null,
|
||||
type: null
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -841,9 +906,9 @@ export class AbstractScatter extends Throwable {
|
||||
scale: this.scale,
|
||||
about: this.currentAbout,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -855,9 +920,9 @@ export class AbstractScatter extends Throwable {
|
||||
translate: { x: dx, y: dy },
|
||||
about: about,
|
||||
fast: true,
|
||||
type: null,
|
||||
type: null
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -868,9 +933,9 @@ export class AbstractScatter extends Throwable {
|
||||
let event = new ScatterEvent(this, {
|
||||
scale: this.scale,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -884,9 +949,9 @@ export class AbstractScatter extends Throwable {
|
||||
scale: this.scale,
|
||||
about: about,
|
||||
fast: false,
|
||||
type: null,
|
||||
type: null
|
||||
})
|
||||
this.onTransform.forEach(function (f) {
|
||||
this.onTransform.forEach(function(f) {
|
||||
f(event)
|
||||
})
|
||||
}
|
||||
@ -918,7 +983,7 @@ export class DOMScatterContainer {
|
||||
useCapture = true,
|
||||
capturePointerEvents = true,
|
||||
touchAction = 'none',
|
||||
debugCanvas = null,
|
||||
debugCanvas = null
|
||||
} = {}
|
||||
) {
|
||||
this.onCapture = null
|
||||
@ -930,7 +995,7 @@ export class DOMScatterContainer {
|
||||
movement of scatter objects, the touchmove event has to be bound again.
|
||||
*/
|
||||
if (Capabilities.isSafari) {
|
||||
document.addEventListener('touchmove', (event) => this.preventPinch(event), false)
|
||||
document.addEventListener('touchmove', event => this.preventPinch(event), false)
|
||||
stopEvents = false
|
||||
} else {
|
||||
stopEvents = true
|
||||
@ -945,11 +1010,11 @@ export class DOMScatterContainer {
|
||||
this.delegate = new InteractionMapper(element, this, {
|
||||
useCapture,
|
||||
capturePointerEvents,
|
||||
mouseWheelElement: window,
|
||||
mouseWheelElement: window
|
||||
})
|
||||
|
||||
if (debugCanvas !== null) {
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.showTouches(dt, debugCanvas)
|
||||
})
|
||||
}
|
||||
@ -971,7 +1036,7 @@ export class DOMScatterContainer {
|
||||
context.fill()
|
||||
context.stroke()
|
||||
}
|
||||
requestAnimationFrame((dt) => {
|
||||
requestAnimationFrame(dt => {
|
||||
this.showTouches(dt, canvas)
|
||||
})
|
||||
}
|
||||
@ -1113,7 +1178,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
scaleCloseBuffer = 0.05,
|
||||
useLowPassFilter = false,
|
||||
maxRotation = Angle.degree2radian(15),
|
||||
minInteractionDistance = 200,
|
||||
minInteractionDistance = 200
|
||||
} = {}
|
||||
) {
|
||||
super({
|
||||
@ -1140,7 +1205,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
onClose,
|
||||
useLowPassFilter,
|
||||
maxRotation,
|
||||
minInteractionDistance,
|
||||
minInteractionDistance
|
||||
})
|
||||
if (container == null || width == null || height == null) {
|
||||
throw new Error('Invalid value: null')
|
||||
@ -1168,7 +1233,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
height: height,
|
||||
scale: startScale,
|
||||
rotation: this.startRotationDegrees,
|
||||
transformOrigin: transformOrigin,
|
||||
transformOrigin: transformOrigin
|
||||
}
|
||||
this.tapNodes = new Map()
|
||||
|
||||
@ -1190,15 +1255,15 @@ export class DOMScatter extends AbstractScatter {
|
||||
button.className = 'interactiveElement'
|
||||
this.element.appendChild(button)
|
||||
|
||||
button.addEventListener('pointerdown', (e) => {
|
||||
button.addEventListener('pointerdown', e => {
|
||||
this.startResize(e)
|
||||
})
|
||||
|
||||
button.addEventListener('pointermove', (e) => {
|
||||
button.addEventListener('pointermove', e => {
|
||||
this.resize(e)
|
||||
})
|
||||
|
||||
button.addEventListener('pointerup', (e) => {
|
||||
button.addEventListener('pointerup', e => {
|
||||
this.stopResize(e)
|
||||
})
|
||||
this.resizeButton = button
|
||||
@ -1215,7 +1280,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
scale: this.scale,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
rotation: this.rotation,
|
||||
rotation: this.rotation
|
||||
}
|
||||
}
|
||||
|
||||
@ -1266,7 +1331,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
top: rect.top - stage.top,
|
||||
left: rect.left - stage.left,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
height: rect.height
|
||||
}
|
||||
}
|
||||
|
||||
@ -1307,7 +1372,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
set scale(scale) {
|
||||
TweenLite.set(this.element, {
|
||||
scale: scale,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
})
|
||||
this._scale = scale
|
||||
}
|
||||
@ -1339,9 +1404,9 @@ export class DOMScatter extends AbstractScatter {
|
||||
hide() {
|
||||
TweenLite.to(this.element, 0.1, {
|
||||
display: 'none',
|
||||
onComplete: (e) => {
|
||||
onComplete: e => {
|
||||
this.element.parentNode.removeChild(this.element)
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -1355,7 +1420,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
rotation: rotationDegrees,
|
||||
transformOrigin: this.transformOrigin,
|
||||
transformOrigin: this.transformOrigin
|
||||
})
|
||||
}
|
||||
|
||||
@ -1416,7 +1481,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
}
|
||||
this.bringToFront()
|
||||
|
||||
@ -1424,7 +1489,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
}
|
||||
|
||||
let offset = Points.subtract(oldPostition, newPostition)
|
||||
@ -1469,7 +1534,7 @@ export class DOMScatter extends AbstractScatter {
|
||||
)
|
||||
TweenLite.to(this.element, 0, {
|
||||
width: this.element.offsetWidth + resizeW / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale,
|
||||
height: this.element.offsetHeight + resizeH / this.scale
|
||||
})
|
||||
|
||||
this.oldX = e.clientX
|
||||
@ -1486,12 +1551,12 @@ export class DOMScatter extends AbstractScatter {
|
||||
let event = new CustomEvent('resizeEnded')
|
||||
let oldPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
}
|
||||
this.element.style.transformOrigin = '50% 50%'
|
||||
let newPostition = {
|
||||
x: this.element.getBoundingClientRect().left,
|
||||
y: this.element.getBoundingClientRect().top,
|
||||
y: this.element.getBoundingClientRect().top
|
||||
}
|
||||
let offset = Points.subtract(oldPostition, newPostition)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user