diff --git a/src/drawCircle.js b/src/drawCircle.js index c66f338..83a73b6 100644 --- a/src/drawCircle.js +++ b/src/drawCircle.js @@ -3,16 +3,16 @@ export default class DrawCircle { constructor(settings) { } - filled(context, cell) { + filled(context, scale, x, y, cell) { context.beginPath(); - context.arc(cell.x, cell.y, cell.scale, 0, 2*Math.PI, false); + context.arc(x, y, scale * cell.scale, 0, 2*Math.PI, false); context.fillStyle = cell.getColor(); context.fill(); } - outline(context, cell) { + outline(context, scale, x, y, cell) { context.beginPath(); - context.arc(cell.x, cell.y, cell.scale, 0, 2*Math.PI, false); + context.arc(x, y, scale * cell.scale, 0, 2*Math.PI, false); context.lineWidth = cell.width; context.strokeStyle = cell.getColor(); context.stroke(); diff --git a/src/drawHexagon.js b/src/drawHexagon.js index 4576909..f1277c1 100644 --- a/src/drawHexagon.js +++ b/src/drawHexagon.js @@ -31,10 +31,8 @@ export default class DrawHexagon { } } - outline(context, cell) { - let x = cell.x; - let y = cell.y; - let scale = cell.scale; + outline(context, scale, x, y, cell) { + scale = scale * cell.scale; let hexCornerX = cell.pointyTop ? this.pointyTopCornerX : this.flatTopCornerX; let hexCornerY = cell.pointyTop ? this.pointyTopCornerY : this.flatTopCornerY; @@ -52,10 +50,8 @@ export default class DrawHexagon { context.stroke(); } - filled(context, cell) { - let x = cell.x; - let y = cell.y; - let scale = cell.scale; + filled(context, scale, x, y, cell) { + scale = scale * cell.scale; let hexCornerX = cell.pointyTop ? this.pointyTopCornerX : this.flatTopCornerX; let hexCornerY = cell.pointyTop ? this.pointyTopCornerY : this.flatTopCornerY; diff --git a/src/drawSquare.js b/src/drawSquare.js index 455f726..6977ddd 100644 --- a/src/drawSquare.js +++ b/src/drawSquare.js @@ -9,10 +9,8 @@ export default class DrawSquare { this.diamondY = [0, -sqrt2, 0, sqrt2]; } - filled(context, cell) { - let x = cell.x; - let y = cell.y; - let scale = cell.scale; + filled(context, scale, x, y, cell) { + scale = scale * cell.scale; let squareCornerX = cell.pointyTop ? this.diamondX : this.squareX; let squareCornerY = cell.pointyTop ? this.diamondY : this.squareY; @@ -26,10 +24,8 @@ export default class DrawSquare { context.fill(); } - outline(context, cell) { - let x = cell.x; - let y = cell.y; - let scale = cell.scale; + outline(context, scale, x, y, cell) { + scale = scale * cell.scale; let squareCornerX = cell.pointyTop ? this.diamondX : this.squareX; let squareCornerY = cell.pointyTop ? this.diamondY : this.squareY; diff --git a/src/exWhyZee.js b/src/exWhyZee.js index 85aa9de..c759744 100644 --- a/src/exWhyZee.js +++ b/src/exWhyZee.js @@ -20,7 +20,9 @@ export default class ExWhyZee { 'getVertDistance', 'hexToPixel', 'pixelToHex', - 'boundingBox' + 'boundingBox', + 'move', + 'zoom' ].map(method => this[method] = this[method].bind(this)); this.pointyTop = false; @@ -31,7 +33,7 @@ export default class ExWhyZee { // in pixels this.scale = 25; - this.scaleMin = 5; + this.scaleMin = 10; this.scaleMax = 250; // in cells @@ -150,6 +152,41 @@ export default class ExWhyZee { return hexagons; } + + move(event) { + if (event.deltaX) { + + this.originX = Math.floor((this.originX*1000) + (event.deltaX*1000)) / 1000; + } + + if (event.deltaY) { + + this.originY = Math.floor((this.originY*1000) + (event.deltaY*1000)) / 1000; + } + } + + zoom(event) { + let scaleOrig = this.scale; + + let scaleTemp = parseInt((scaleOrig + (event.deltaY / -10)) * 1000) / 1000; + + // make sure 'scale' doesn't get too small nor too big + if (scaleTemp < this.scaleMin) + scaleTemp = this.scaleMin; + else if (scaleTemp > this.scaleMax) + scaleTemp = this.scaleMax; + + if (scaleOrig != scaleTemp) { + + this.scale = scaleTemp; + + // zoom to the current mouse location + this.move({ + deltaX: (((event.offsetX - this.originX) / scaleOrig) * (scaleOrig - scaleTemp)), + deltaY: (((event.offsetY - this.originY) / scaleOrig) * (scaleOrig - scaleTemp)) + }); + } + } } // function getCoordinates(canvasX, canvasY) { diff --git a/src/main.js b/src/main.js index 506f9c0..faf411d 100644 --- a/src/main.js +++ b/src/main.js @@ -46,7 +46,8 @@ class Demo { } draw(context) { - this.map.forEach(cell => this[cell.tile][cell.style](context, cell)); + let scale = 1; + this.map.forEach(cell => this[cell.tile][cell.style](context, scale, cell.x, cell.y, cell)); } } diff --git a/src/onTap.js b/src/onTap.js index f09fd0f..d433c51 100644 --- a/src/onTap.js +++ b/src/onTap.js @@ -1,24 +1,113 @@ +import {noop} from './utils.js'; + export default class OnTap { constructor(settings) { this.element = settings.element || document.body; - this.callbacks = {}; + this.state = { + clickStartX: null, + clickStartY: null, + clickStartTime: null + }; - this.events = ['click']; + this.actions = { + tap: { + callback: settings.tap || noop + }, + move: { + threshold: settings.moveThreshold || 5, // greater than in pixels + callback: settings.move || noop + }, + doubletap: { + threshold: settings.doubletapThreshold || 500, // less than in milliseconds + callback: settings.doubletap || noop + }, + press: { + threshold: settings.pressThreshold || 1000, // greater than or equal to in milliseconds + callback: settings.press || noop + }, + zoom: { + callback: settings.zoom || noop + } + }; + + this.events = ['mousedown', 'mouseup', 'mousemove', 'touchstart', 'touchend', 'touchmove', 'touchcancel', 'wheel']; this.events.map(method => { this[method] = this[method].bind(this); - - if (typeof settings[method] === 'function') { - this.element.addEventListener(method, this[method]); - this.callbacks[method] = settings[method]; - } + this.element.addEventListener(method, this[method]); }); } - click(event) { - this.callbacks.click(event); + mousedown(event) { + if (!this.state.clickStartTime) { + this.state.clickStartX = event.pageX; + this.state.clickStartY = event.pageY; + this.state.clickStartTime = event.timeStamp; + } + + console.log('mousedown', event); + } + + mouseup(event) { + if (this.state.clickStartTime) { + console.log({ + duration: event.timeStamp - this.state.clickStartTime, + deltaX: event.pageX - this.state.clickStartX, + deltaY: event.pageY - this.state.clickStartY + }); + + this.state.clickStartX = null; + this.state.clickStartY = null; + this.state.clickStartTime = null; + } + + console.log('mouseup', event); + this.actions.tap.callback(event); + } + + mousemove(event) { +// console.log('mousemove', event); + } + + touchstart(event) { + if (!this.state.clickStartTime) { + this.state.clickStartX = event.pageX; + this.state.clickStartY = event.pageY; + this.state.clickStartTime = event.timeStamp; + } + + console.log('touchstart', event); + } + + touchend(event) { + if (this.state.clickStartTime) { + console.log({ + duration: event.timeStamp - this.state.clickStartTime, + deltaX: event.pageX - this.state.clickStartX, + deltaY: event.pageY - this.state.clickStartY + }); + + this.state.clickStartX = null; + this.state.clickStartY = null; + this.state.clickStartTime = null; + } + + console.log('touchend', event); + this.actions.tap.callback(event); + } + + touchmove(event) { +// console.log('touchmove', event); + } + + touchcancel(event) { + console.log('touchcancel', event); + } + + wheel(event) { + this.actions.zoom.callback(event); } } diff --git a/src/tessellate.js b/src/tessellate.js index afd891c..eef5afd 100644 --- a/src/tessellate.js +++ b/src/tessellate.js @@ -18,7 +18,7 @@ import ExWhyZee from './exWhyZee.js'; export default class Tessellate { constructor(settings) { - ['click', 'draw', 'drawMap'].map(method => {this[method] = this[method].bind(this)}); + ['tap', 'draw', 'drawMap', 'zoom'].map(method => {this[method] = this[method].bind(this)}); this.drawCB = settings.draw || utils.noop; this.clickCB = settings.click || utils.noop; @@ -31,7 +31,8 @@ export default class Tessellate { this.onTap = new OnTap({ element: this.element, - click: this.click + tap: this.tap, + zoom: this.zoom }); this.map = []; @@ -45,10 +46,14 @@ export default class Tessellate { this.hexagon = new DrawHexagon(); } - click(event) { + tap(event) { this.clickCB(event); } + zoom(event) { + this.xyz.zoom(event); + } + drawMap(context) { let scale = this.xyz.getScale(); let upperLeft = new Point(0, 0); @@ -67,18 +72,18 @@ export default class Tessellate { if (!this.map[hex.getX()][hex.getY()]) { this.map[hex.getX()][hex.getY()] = new Cell({ - x: hexPoint.getX(), - y: hexPoint.getY(), + x: hex.getX(), + y: hex.getY(), pointyTop: true, red: utils.random(255), green: utils.random(255), blue: utils.random(255), alpha: utils.random(25, 75) / 100, - scale: scale * utils.random(5,9)/10 + scale: utils.random(5,9)/10 }); } - this.hexagon.filled(context, this.map[hex.getX()][hex.getY()]); + this.hexagon.filled(context, scale, hexPoint.getX(), hexPoint.getY(), this.map[hex.getX()][hex.getY()]); // let cell = map.getXY(hex.getX(), hex.getY()); //