animationvideo
Version:
Javascript-Libary for animation and audio syncing
297 lines (279 loc) • 7.98 kB
JavaScript
import SceneNorm from "./Norm.mjs";
import calc from "../func/calc.mjs";
export default class SceneNormCamera extends SceneNorm {
constructor(...args) {
super(...args);
this.camConfig = Object.assign(
{},
{
zoomMax: 10,
zoomMin: 0.5,
zoomFactor: 1.2,
tween: 4,
registerEvents: true,
enabled: true,
click: (e, x, y) => {},
dblClick: undefined,
callResize: true
},
calc(this.configuration.cam) || {}
);
this.toCam = {
x: 0,
y: 0,
distance: undefined,
zoom: 1
};
this.mousePos = {
x: 0,
y: 0,
timestamp: 0,
isDown: false
};
}
camEnable() {
this.camConfig.enabled = true;
}
camDisable() {
this.camConfig.enabled = false;
}
camReset() {
this.toCam = {
x: 0,
y: 0,
zoom: 1
};
}
callInit(output, parameter, engine) {
if (this.camConfig.registerEvents) {
this.registerCamEvents(output.canvas);
}
return super.callInit(output, parameter, engine);
}
destroy(output) {
if (this.camConfig.registerEvents) {
this.destroyCamEvents(output.canvas);
}
return super.destroy(output);
}
_hasCamChanged() {
return (
this.toCam.x !== this.cam.x ||
this.toCam.y !== this.cam.y ||
this.toCam.zoom !== this.cam.zoom
);
}
fixedUpdate(output, timePassed, lastCall) {
const ret = super.fixedUpdate(output, timePassed);
if (this.camConfig.tween && this._hasCamChanged()) {
this.cam.x += (this.toCam.x - this.cam.x) / this.camConfig.tween;
this.cam.y += (this.toCam.y - this.cam.y) / this.camConfig.tween;
this.cam.zoom += (this.toCam.zoom - this.cam.zoom) / this.camConfig.tween;
if (lastCall) {
if (this.camConfig.callResize) {
this.resize(output);
} else {
this.transform = null;
this.transformInvert = null;
}
}
}
return ret;
}
move(output, timePassed) {
const ret = super.move(output, timePassed);
if (!this.camConfig.tween && this._hasCamChanged()) {
this.cam = Object.assign({}, this.toCam);
if (this.camConfig.callResize) {
this.resize(output);
} else {
this.transform = null;
this.transformInvert = null;
}
}
return ret;
}
registerCamEvents(element = this.engine._output.canvas) {
for (const eventName of ["touchstart", "mousedown"]) {
element.addEventListener(eventName, this._mouseDown.bind(this), true);
}
for (const eventName of ["touchend", "mouseup"]) {
element.addEventListener(eventName, this._mouseUp.bind(this), true);
}
for (const eventName of ["touchendoutside", "mouseout"]) {
element.addEventListener(eventName, this._mouseOut.bind(this), true);
}
for (const eventName of ["touchmove", "mousemove"]) {
element.addEventListener(eventName, this._mouseMove.bind(this), true);
}
element.addEventListener("mousewheel", this._mouseWheel.bind(this), true);
}
destroyCamEvents(element = this.engine._output.canvas) {
for (const eventName of ["touchstart", "mousedown"]) {
element.removeEventListener(eventName, this._mouseDown, true);
}
for (const eventName of ["touchend", "mouseup"]) {
element.removeEventListener(eventName, this._mouseUp, true);
}
for (const eventName of ["touchendoutside", "mouseout"]) {
element.removeEventListener(eventName, this._mouseOut, true);
}
for (const eventName of ["touchmove", "mousemove"]) {
element.removeEventListener(eventName, this._mouseMove, true);
}
element.removeEventListener("mousewheel", this._mouseWheel, true);
}
_getMousePosition(e) {
if (e && e.touches && e.touches.length > 0) {
const rect = e.target.getBoundingClientRect();
return [
e.targetTouches[0].pageX - rect.left,
e.targetTouches[0].pageY - rect.top
];
}
return [e.offsetX, e.offsetY];
}
_mouseDown(e) {
if (e && this.camConfig.enabled) {
const [mx, my] = this._getMousePosition(e);
this.mousePos.x = mx;
this.mousePos.y = my;
this.mousePos.cx = this.toCam.x;
this.mousePos.cy = this.toCam.y;
this.mousePos.isDown = true;
this.mousePos.distance = undefined;
this.mousePos.timestamp = Date.now();
}
}
_mouseUp(e) {
this.mousePos.isDown = false;
const [mx, my] = this._getMousePosition(e);
if (
Date.now() - this.mousePos.timestamp < 150 &&
Math.abs(this.mousePos.x - mx) < 5 &&
Math.abs(this.mousePos.y - my) < 5
) {
const [x, y] = this.transformPoint(mx, my);
this.camConfig.click(e, x, y);
}
}
_mouseOut(e) {
this.mousePos.isDown = false;
}
_mouseMove(e) {
if (e && this.camConfig.enabled && this.mousePos.isDown) {
if (e.touches && e.touches.length >= 2) {
const t = e.touches;
// Abstand der zwei Finger ausrechnen
const distance = Math.sqrt(
(t[0].pageX - t[1].pageX) * (t[0].pageX - t[1].pageX) +
(t[0].pageY - t[1].pageY) * (t[0].pageY - t[1].pageY)
);
if (this.mousePos.distance !== undefined) {
if (distance > this.mousePos.distance) {
this._zoomIn();
} else if (distance < this.mousePos.distance) {
this._zoomOut();
}
}
this.mousePos.distance = distance;
} else {
this.mousePos.distance = undefined;
const [mx, my] = this._getMousePosition(e);
const viewMatrix = this._getViewportByCam(this.toCam).invert();
const [ox, oy] = viewMatrix.transformPoint(
this.mousePos.x,
this.mousePos.y
);
const [nx, ny] = viewMatrix.transformPoint(mx, my);
this.toCam.x = this.mousePos.cx + ox - nx;
this.toCam.y = this.mousePos.cy + oy - ny;
this.clampView();
}
}
}
_mouseWheel(e) {
if (e && this.camConfig.enabled) {
e.preventDefault();
const [mx, my] = this._getMousePosition(e);
const [ox, oy] = this._getViewportByCam(this.toCam)
.invert()
.transformPoint(mx, my);
const wheelData = e.wheelDelta || e.deltaY * -1;
if (wheelData / 120 > 0) {
this._zoomIn();
const [nx, ny] = this._getViewportByCam(this.toCam)
.invert()
.transformPoint(mx, my);
this.toCam.x -= nx - ox;
this.toCam.y -= ny - oy;
this.clampView();
} else {
this._zoomOut();
}
}
}
_zoomIn() {
this.toCam.zoom = Math.min(
this.camConfig.zoomMax,
this.toCam.zoom * this.camConfig.zoomFactor
);
}
_zoomOut() {
this.toCam.zoom = Math.max(
this.camConfig.zoomMin,
this.toCam.zoom / this.camConfig.zoomFactor
);
this.clampView();
}
clampView = function() {
const invert = this._getViewportByCam(this.toCam).invert();
const [x1,y1] = invert.transformPoint(0, 0);
const [x2,y2] = invert.transformPoint(
this.engine._output.width,
this.engine._output.height
);
// check for x
// is there a zoom in?
if (x2 - x1 <= 2) {
if (x1 < -1) {
if (x2 <= 1) {
this.toCam.x += -1 - x1;
}
} else {
if (x2 > 1) {
this.toCam.x += 1 - x2;
}
}
} else {
if (x1 > -1) {
this.toCam.x += -1 - x1;
} else {
if (x2 < 1) {
this.toCam.x += 1 - x2;
}
}
}
// check for y
// zoom in?
if (y2 - y1 <= 2) {
if (y1 < -1) {
if (y2 <= 1) {
this.toCam.y += -1 - y1;
}
} else {
if (y2 > 1) {
this.toCam.y += 1 - y2;
}
}
} else {
if (y1 > -1) {
this.toCam.y += -1 - y1;
} else {
if (y2 < 1) {
this.toCam.y += 1 - y2;
}
}
}
};
}