Support viewport resizing (#16)

This commit is contained in:
gavin
2018-08-30 01:02:58 +00:00
committed by Gitea
parent a2d7402cfa
commit 2c83c47afc
4 changed files with 137 additions and 73 deletions

View File

@@ -1,6 +1,7 @@
import {has, toFixed} from './utils.js';
import {has} from './utils.js';
import {pick} from './funky';
const SETTINGS_DEFAULTS = {
const DEFAULTS = {
// in pixels
scale: 50,
scaleMin: 10,
@@ -17,18 +18,20 @@ export default class Cartographer {
'move',
'_checkMove',
'_setOriginX',
'_setOriginY',
'setOriginX',
'setOriginY',
'zoom',
].map(method => this[method] = this[method].bind(this));
Object.assign(this, SETTINGS_DEFAULTS, settings);
this.settings = Object.assign({}, DEFAULTS, settings);
this._checkScale(this.canvasHeight, this.canvasWidth);
Object.assign(this, pick(this.settings, ['height', 'width', 'negativeTiles']));
this._setOriginX();
this._setOriginY();
this.checkScale(this.settings.canvasHeight, this.settings.canvasWidth);
this.setOriginX(this.settings.canvasWidth, this.settings.centerX);
this.setOriginY(this.settings.canvasHeight, this.settings.centerY);
}
getOriginX() {return this.originX;}
@@ -36,41 +39,43 @@ export default class Cartographer {
getScale() {return this.scale;}
_checkScale(canvasHeight, canvasWidth) {
checkScale(canvasHeight, canvasWidth) {
const heightMin = this.height ? this.calculateVerticalScale(canvasHeight, this.height) : 0;
const widthMin = this.width ? this.calculateHorizontalScale(canvasWidth, this.width) : 0;
this.scaleMin = Math.max(this.scaleMin, heightMin, widthMin);
this.scale = this.scaleMin > this.scale ? this.scaleMin : this.scale;
this.scaleMax = this.settings.scaleMax;
this.scaleMin = Math.max(this.settings.scaleMin, heightMin, widthMin);
this.scale = this.scaleMin > this.settings.scale ? this.scaleMin : this.settings.scale;
}
_setOriginX () {
this.originX = has(this, 'originX') ? this.originX :
this.negativeTiles ? parseInt(this.canvasWidth / 2) :
this.width ? ((this.width * this.tileWidth()) / -2) + (this.canvasWidth / 2) + (this.tileWidth() / 2) :
setOriginX (canvasWidth, centerX) {
this.originX = centerX ? centerX - canvasWidth / 2 :
this.negativeTiles ? parseInt(canvasWidth / 2) :
this.width ? ((this.width * this.tileWidth()) / -2) + (canvasWidth / 2) + (this.tileWidth() / 2) :
this.tileWidth() / 2;
}
_setOriginY () {
setOriginY (canvasHeight, centerY) {
const boardHeight = this.height * this.tileHeight();
this.originY = has(this, 'originY') ? this.originY :
this.negativeTiles ? parseInt(this.canvasHeight / 2) :
this.height ? (boardHeight) - ((boardHeight - this.canvasHeight) / 2) - (this.tileHeight() / 2) :
this.canvasHeight - (this.tileHeight() / 2);
this.originY = centerY ? centerY + canvasHeight / 2 :
this.negativeTiles ? parseInt(canvasHeight / 2) :
this.height ? (boardHeight) - ((boardHeight - canvasHeight) / 2) - (this.tileHeight() / 2) :
canvasHeight - (this.tileHeight() / 2);
}
move(event) {
if (event.deltaX) {
const newX = this.originX + event.deltaX;
const newY = this.originY + event.deltaY;
this.originX = toFixed(this.originX + event.deltaX);
}
if (event.deltaY) {
this.originY = toFixed(this.originY + event.deltaY);
}
this.originX = newX;
this.originY = newY;
this._checkMove(event);
// return if the move succeeded or not
return this.originX === newX && this.originY === newY;
}
_checkMove(event) {

View File

@@ -1,17 +1,21 @@
import {noop} from './utils.js';
export default class Sketch {
constructor(settings) {
constructor (settings) {
this.lastNow = null;
['getContext', 'onResize', 'render'].map(method => this[method] = this[method].bind(this));
[
'getContext',
'onResize',
'render'
].map(method => this[method] = this[method].bind(this));
this.drawDelay = settings.drawDelay || 50;
this.draw = settings.draw || noop;
this.resize = settings.resize || noop;
this.drawDelay = settings.drawDelay || 50;
this.container = settings.element || document.body;
window.addEventListener('optimizedResize', this.onResize);
window.addEventListener('resize', this.onResize);
this.canvas = document.createElement('canvas');
this.canvas.width = this.container.offsetWidth;
@@ -24,13 +28,36 @@ export default class Sketch {
requestAnimationFrame(this.render);
}
getContext() { return this.context; }
onResize(event) {
console.log('sketch - onResize', arguments);
getContext () {
return this.context;
}
render(now) {
onResize (event) {
const width = this.container.offsetWidth;
const height = this.container.offsetHeight;
const oldWidth = this.canvas.width;
const oldHeight = this.canvas.height;
const deltaX = width - oldWidth;
const deltaY = height - oldHeight;
this.canvas.width = width;
this.canvas.height = height;
Object.assign(event, {
height, width,
oldHeight, oldWidth,
deltaX, deltaY,
});
this.resize(event);
}
render (now) {
this.canvas.width = this.container.offsetWidth;
this.canvas.height = this.container.offsetHeight;
this.context.now = now;
this.context.lastNow = this.lastNow;

View File

@@ -76,7 +76,7 @@ export class Tessellate {
static get utils() {return utils}
static get funky() {return funky}
constructor(settings) {
constructor (settings) {
[
'checkSettings',
'tap',
@@ -88,14 +88,16 @@ export class Tessellate {
'pixelToTile',
'tileToPixel',
'getTilePoints',
'draw'
'draw',
'resize',
].map(method => {this[method] = this[method].bind(this)});
this.checkSettings(settings);
this.sketch = new Sketch({
element: this.settings.element,
draw: this.draw
draw: this.draw,
resize: this.resize,
});
this.onTap = new OnTap(Object.assign({
@@ -112,10 +114,10 @@ export class Tessellate {
this.cartographer = new cartographer(Object.assign({
canvasWidth: this.sketch.getContext().canvas.width,
canvasHeight: this.sketch.getContext().canvas.height,
}, funky.pick(this.settings, ['originX', 'originY', 'height', 'width', 'scale', 'negativeTiles'])));
}, funky.pick(this.settings, ['centerX', 'centerY', 'height', 'width', 'scale', 'negativeTiles'])));
}
checkSettings(settings) {
checkSettings (settings) {
this.settings = Object.assign({}, DEFAULTS, settings);
this.settings.element = this.settings.element instanceof HTMLElement ? this.settings.element :
@@ -132,7 +134,7 @@ export class Tessellate {
}
}
tap(event) {
tap (event) {
let point = new Point(event.offsetX, event.offsetY);
let tile = this.cartographer.pixelToTile(point);
@@ -145,7 +147,7 @@ export class Tessellate {
this.settings.tap(tap);
}
doubletap(event) {
doubletap (event) {
console.log('DOUBLETAP', event);
let point = new Point(event.offsetX, event.offsetY);
let tile = this.cartographer.pixelToTile(point);
@@ -159,7 +161,7 @@ export class Tessellate {
console.log(tap);
}
pressStart(event) {
pressStart (event) {
let point = new Point(event.offsetX, event.offsetY);
let tile = this.cartographer.pixelToTile(point);
@@ -172,7 +174,7 @@ export class Tessellate {
this.settings.pressStart(tap);
}
press(event) {
press (event) {
let point = new Point(event.offsetX, event.offsetY);
let tile = this.cartographer.pixelToTile(point);
@@ -185,23 +187,23 @@ export class Tessellate {
this.settings.press(tap);
}
move(event) {
this.cartographer.move(event);
move (event) {
return this.cartographer.move(event);
}
zoom(event) {
zoom (event) {
this.cartographer.zoom(event);
}
pixelToTile(x, y) {
pixelToTile (x, y) {
return this.cartographer.pixelToTile(x, y);
}
tileToPixel(x, y, z) {
tileToPixel (x, y, z) {
return this.cartographer.tileToPixel(x, y, z);
}
getTilePoints({upperLeftX, upperLeftY, lowerRightX, lowerRightY}) {
getTilePoints ({upperLeftX, upperLeftY, lowerRightX, lowerRightY}) {
const upperLeft = new Point(upperLeftX, upperLeftY);
const upperRight = new Point(lowerRightX, 0);
const lowerLeft = new Point(0, lowerRightY);
@@ -210,7 +212,7 @@ export class Tessellate {
return funky.flatten(this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight));
}
draw(context) {
draw (context) {
const canvas = context.canvas;
const width = canvas.width;
const height = canvas.height;
@@ -230,4 +232,34 @@ export class Tessellate {
}),
});
}
resize (event) {
const originX = this.cartographer.getOriginX();
const originY = this.cartographer.getOriginY();
const scaleOrig = this.cartographer.getScale();
const moveForResize = Object.assign({}, event, {
deltaX: event.deltaX / 2,
deltaY: event.deltaY / 2,
});
this.move(moveForResize);
this.cartographer.checkScale(event.height, event.width);
const centerX = event.width / 2;
const centerY = event.height / 2;
const scaleNew = this.cartographer.getScale();
const moveForScale = {
deltaX: (((centerX - originX) / scaleOrig) * (scaleOrig - scaleNew)),
deltaY: (((centerY - originY) / scaleOrig) * (scaleOrig - scaleNew)),
target: {
offsetWidth: event.width,
offsetHeight: event.height,
},
};
this.move(moveForScale);
}
}

View File

@@ -9,25 +9,25 @@ export const sqrt2 = Math.sqrt(2);
// (2*S gives long width)
export const sqrt3 = Math.sqrt(3);
export function throttleEvent(type, name, obj) {
obj = obj || window;
let running = false;
let throttle = () => {
if (!running) {
running = true;
requestAnimationFrame(() => {
obj.dispatchEvent(new CustomEvent(name));
running = false;
});
}
}
obj.addEventListener(type, throttle);
}
throttleEvent('resize', 'optimizedResize');
//export function throttleEvent(type, name, obj) {
// obj = obj || window;
// let running = false;
//
// let throttle = () => {
// if (!running) {
// running = true;
//
// requestAnimationFrame(() => {
// obj.dispatchEvent(new CustomEvent(name));
// running = false;
// });
// }
// }
//
// obj.addEventListener(type, throttle);
//}
//
//throttleEvent('resize', 'optimizedResize');
export function clone(obj) {
return JSON.parse(JSON.stringify(obj));