325 lines
7.2 KiB
JavaScript
325 lines
7.2 KiB
JavaScript
import * as utils from './utils';
|
|
import * as funky from './funky';
|
|
|
|
import OnTap from './onTap.js';
|
|
import Point from './point.js';
|
|
import Sketch from './sketch.js';
|
|
|
|
import DrawShapes from './drawShapes.js';
|
|
import DrawCircle from './drawCircle.js';
|
|
import DrawSquare from './drawSquare.js';
|
|
import DrawHexagon from './drawHexagon.js';
|
|
|
|
import Cell from './cell.js';
|
|
|
|
import CartographerFlatXY from './cartographerFlatXY.js';
|
|
import CartographerPointyXY from './cartographerPointyXY.js';
|
|
import CartographerFlatXYZ from './cartographerFlatXYZ.js';
|
|
import CartographerPointyXYZ from './cartographerPointyXYZ.js';
|
|
|
|
import {
|
|
HEX, CIRCLE, SQUARE,
|
|
TILE_STYLES,
|
|
BOARD_STYLES,
|
|
FLAT, POINTY,
|
|
ORIENTATION_STYLES,
|
|
FILL, OUTLINE,
|
|
DRAW_STYLES,
|
|
} from './consts.js';
|
|
|
|
const TILES = {
|
|
[HEX]: new DrawHexagon(),
|
|
[CIRCLE]: new DrawCircle(),
|
|
[SQUARE]: new DrawSquare(),
|
|
};
|
|
|
|
const Shapes = new DrawShapes();
|
|
|
|
const DEFAULTS = {
|
|
tile: HEX,
|
|
board: HEX,
|
|
orientation: FLAT,
|
|
negativeTiles: true,
|
|
|
|
tap: utils.noop,
|
|
pressStart: utils.noop,
|
|
press: utils.noop,
|
|
|
|
draw: utils.noop,
|
|
};
|
|
|
|
function selectCartographer(board, orientation) {
|
|
switch (board) {
|
|
case HEX:
|
|
switch (orientation) {
|
|
case FLAT: return CartographerFlatXYZ;
|
|
case POINTY: return CartographerPointyXYZ;
|
|
}
|
|
case SQUARE:
|
|
switch (orientation) {
|
|
case FLAT: return CartographerFlatXY;
|
|
case POINTY: return CartographerPointyXY;
|
|
}
|
|
}
|
|
}
|
|
|
|
export class Tessellate {
|
|
static get TILE_STYLES() {return TILE_STYLES}
|
|
static get BOARD_STYLES() {return BOARD_STYLES}
|
|
static get ORIENTATION_STYLES() {return ORIENTATION_STYLES}
|
|
static get DRAW_STYLES() {return DRAW_STYLES}
|
|
|
|
static get TILES() {return TILES}
|
|
static get Cell() {return Cell}
|
|
static get Shapes() {return Shapes}
|
|
|
|
static get utils() {return utils}
|
|
static get funky() {return funky}
|
|
|
|
constructor (settings) {
|
|
[
|
|
'checkSettings',
|
|
'tap',
|
|
'doubletap',
|
|
'pressStart',
|
|
'press',
|
|
'move',
|
|
'zoom',
|
|
'pixelToTile',
|
|
'tileToPixel',
|
|
'getLocationSets',
|
|
'draw',
|
|
'resize',
|
|
'remap',
|
|
].map(method => {this[method] = this[method].bind(this)});
|
|
|
|
this.checkSettings(settings);
|
|
|
|
this.sketch = new Sketch({
|
|
element: this.settings.element,
|
|
draw: this.draw,
|
|
resize: this.resize,
|
|
});
|
|
|
|
this.onTap = new OnTap(Object.assign({
|
|
element: this.settings.element,
|
|
tap: this.tap,
|
|
doubletap: this.doubletap,
|
|
pressStart: this.pressStart,
|
|
press: this.press,
|
|
move: this.move,
|
|
zoom: this.zoom,
|
|
}, funky.pick(this.settings, ['desktopPress', 'moveThreshold', 'doubletapThreshold', 'pressThreshold', 'wheelFactor'])));
|
|
|
|
const cartographer = selectCartographer(this.settings.board, this.settings.orientation);
|
|
this.cartographer = new cartographer(Object.assign(this.sketch.getSize(), funky.pick(this.settings, [
|
|
'adjustScaleMin',
|
|
'centerX',
|
|
'centerY',
|
|
'height',
|
|
'negativeTiles',
|
|
'radius',
|
|
'scale',
|
|
'width',
|
|
'wrap',
|
|
])));
|
|
}
|
|
|
|
checkSettings (settings) {
|
|
|
|
this.settings = Object.assign({}, DEFAULTS, settings);
|
|
this.settings.element = this.settings.element instanceof HTMLElement ? this.settings.element :
|
|
document.querySelector(this.settings.element);
|
|
|
|
if (this.settings.radius) {
|
|
this.settings.height = this.settings.radius * 2 + 1;
|
|
this.settings.width = this.settings.radius * 2 + 1;
|
|
}
|
|
|
|
if (this.settings.negativeTiles) {
|
|
if (this.settings.height && (this.settings.height % 2 === 0)) {
|
|
this.settings.height++;
|
|
}
|
|
|
|
if (this.settings.width && (this.settings.width % 2 === 0)) {
|
|
this.settings.width++;
|
|
}
|
|
}
|
|
}
|
|
|
|
tap (event) {
|
|
const point = new Point(event.offsetX, event.offsetY);
|
|
const tile = this.cartographer.pixelToTile(point);
|
|
const mapTile = this.cartographer.teleport(tile);
|
|
|
|
this.interacted = true;
|
|
|
|
this.settings.tap({
|
|
event,
|
|
mapTile,
|
|
point,
|
|
tile,
|
|
});
|
|
}
|
|
|
|
doubletap (event) {
|
|
console.log('DOUBLETAP', event);
|
|
const point = new Point(event.offsetX, event.offsetY);
|
|
const tile = this.cartographer.pixelToTile(point);
|
|
const mapTile = this.cartographer.teleport(tile);
|
|
|
|
this.interacted = true;
|
|
|
|
let tap = {
|
|
event,
|
|
map,
|
|
mapTile,
|
|
point,
|
|
tile
|
|
};
|
|
|
|
console.log(tap);
|
|
}
|
|
|
|
pressStart (event) {
|
|
const point = new Point(event.offsetX, event.offsetY);
|
|
const tile = this.cartographer.pixelToTile(point);
|
|
const mapTile = this.cartographer.teleport(tile);
|
|
|
|
this.interacted = true;
|
|
|
|
this.settings.pressStart({
|
|
event,
|
|
mapTile,
|
|
point,
|
|
tile,
|
|
});
|
|
}
|
|
|
|
press (event) {
|
|
const point = new Point(event.offsetX, event.offsetY);
|
|
const tile = this.cartographer.pixelToTile(point);
|
|
const mapTile = this.cartographer.teleport(tile);
|
|
|
|
this.interacted = true;
|
|
|
|
this.settings.press({
|
|
event,
|
|
mapTile,
|
|
point,
|
|
tile,
|
|
});
|
|
}
|
|
|
|
move (event) {
|
|
return this.cartographer.move(event);
|
|
}
|
|
|
|
zoom (event) {
|
|
this.cartographer.zoom(event);
|
|
}
|
|
|
|
pixelToTile (x, y) {
|
|
return this.cartographer.pixelToTile(x, y);
|
|
}
|
|
|
|
tileToPixel (tilePoint) {
|
|
return this.cartographer.tileToPixel(tilePoint);
|
|
}
|
|
|
|
newLocation (corners) {
|
|
this.lastLocation = this.lastLocation || {};
|
|
|
|
const currentLocation = utils.extend({
|
|
originX: this.cartographer.getOriginX(),
|
|
originY: this.cartographer.getOriginY(),
|
|
scaleOrig: this.cartographer.getScale(),
|
|
}, corners);
|
|
|
|
const changed = funky.reduce(currentLocation, (same, val, key) => same || this.lastLocation[key] !== val, false);
|
|
|
|
this.lastLocation = currentLocation;
|
|
|
|
return changed;
|
|
}
|
|
|
|
getLocationSets (corners) {
|
|
const {upperLeftX, upperLeftY, lowerRightX, lowerRightY} = corners;
|
|
|
|
const upperLeft = new Point(upperLeftX, upperLeftY);
|
|
const upperRight = new Point(lowerRightX, 0);
|
|
const lowerLeft = new Point(0, lowerRightY);
|
|
const lowerRight = new Point(lowerRightX, lowerRightY);
|
|
|
|
return this.cartographer.boundingBox(upperLeft, upperRight, lowerLeft, lowerRight);
|
|
}
|
|
|
|
draw (context) {
|
|
const canvas = context.canvas;
|
|
const height = canvas.height;
|
|
const width = canvas.width;
|
|
|
|
const corners = {
|
|
upperLeftX: 0,
|
|
upperLeftY: 0,
|
|
lowerRightX: width,
|
|
lowerRightY: height
|
|
};
|
|
|
|
const interacted = this.interacted;
|
|
this.interacted = false;
|
|
|
|
const moved = this.newLocation(corners);
|
|
this.locationSets = moved ? this.getLocationSets(corners) : this.locationSets;
|
|
|
|
return this.settings.draw({
|
|
context,
|
|
|
|
height, width,
|
|
scale: this.cartographer.getScale(),
|
|
|
|
lastNow: context.lastUTC,
|
|
now: context.utc,
|
|
|
|
interacted,
|
|
moved,
|
|
locationSets: this.locationSets,
|
|
});
|
|
}
|
|
|
|
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)),
|
|
height: event.height,
|
|
width: event.width,
|
|
};
|
|
|
|
this.move(moveForScale);
|
|
}
|
|
|
|
remap ({height, width}) {
|
|
this.cartographer.remap(Object.assign({
|
|
height,
|
|
width,
|
|
}, this.sketch.getSize()));
|
|
}
|
|
}
|