diff --git a/src/cartographer.js b/src/cartographer.js index 528d4f3..8cf3a14 100644 --- a/src/cartographer.js +++ b/src/cartographer.js @@ -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) { diff --git a/src/sketch.js b/src/sketch.js index d99b64d..6e74b3b 100644 --- a/src/sketch.js +++ b/src/sketch.js @@ -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; diff --git a/src/tessellate.js b/src/tessellate.js index 2b0d7e2..3a2b7db 100644 --- a/src/tessellate.js +++ b/src/tessellate.js @@ -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); + } } diff --git a/src/utils.js b/src/utils.js index 0694256..0ece316 100644 --- a/src/utils.js +++ b/src/utils.js @@ -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));