ol-games/source/HexMap.js
2019-11-17 21:35:59 +01:00

182 lines
5.6 KiB
JavaScript

/* Copyright (c) 2017 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
@classdesc
ol_source_HexMap is a source for drawing hex map.
Inherits from:
<ol_source_ImageCanvas>
*/
import ol_ext_inherits from 'ol-ext/util/ext'
import ol_source_ImageCanvas from 'ol/source/ImageCanvas'
/**
* @constructor ol_source_HexMap
* @extends {ol.source.ImageCanvas}
* @param {*} options
* @todo
*/
var ol_source_HexMap = function(options){
options = options || {};
this.canvas = document.createElement('canvas');
this.context = this.canvas.getContext('2d');
this.grid = options.hexGrid;
this.grid.on('change', this.changed.bind(this));
ol_source_ImageCanvas.call (this, { canvasFunction: this.drawHex });
};
ol_ext_inherits (ol_source_HexMap, ol_source_ImageCanvas);
/** draw an hexagon
* @param {Canvas context2D} ctx
* @param {ol.pixel}
* @param {Number} size (in pixel)
* @param {bool} fill to fill the polygon
* @param {Number} min, default 0
* @param {Number} max, default 6
* @param {Number} dl offset, default 0
*/
ol_source_HexMap.prototype.drawHexagon = function (ctx, p, size, fill, min, max, dl) {
var p0;
ctx.beginPath();
min = min || 0;
max = max || 6;
dl = dl || 0;
for (var i=min; i<=max; i++) {
p0 = this.grid.hex_corner(p, size-dl, i);
if (i!=min) ctx.lineTo(p0[0], p0[1]);
else ctx.moveTo(p0[0], p0[1]);
}
ctx.stroke();
if (fill) ctx.fill();
};
/** Display coordinates on hexagon
* @param { false | axial | offset | cube } what coord type
*/
ol_source_HexMap.prototype.showCoordiantes = function (what) {
this.coordinates_ = what;
this.changed();
};
/** Draw the hex map
* @param {ol.extent} extent map extent
* @param {number} res current resolution
* @param {number} ratio current ratio
* @param {ol.size} size map size (px)
* @param {ol.proj.Projection} current projection
* @API stable
*/
ol_source_HexMap.prototype.drawHex = function (extent, res, ratio, size /*, proj*/) {
var w = this.canvas.width = size[0];
var h = this.canvas.height = size[1];
this.extent = extent;
// Hexagon radius in pixel
var ctx, x, y, p, c;
var pxSize = this.grid.getSize()/res;
if (pxSize < 8) {
var pattern = document.createElement('canvas');
// $("#pattern").html(pattern)
ctx = pattern.getContext('2d');
// pattern size
var psize = 10;
var dw = 2*Math.sqrt(3)*pxSize*ratio*psize;
var dh = 3*pxSize*ratio*psize
pattern.width = Math.round(dw);
pattern.height = Math.round(dh);
ctx.scale(ratio,ratio)
ctx.lineWidth = 1.5;
ctx.fillStyle="transparent"
var h0 = this.grid.coord2hex([extent[0],extent[3]])
for (x=-psize; x<2*psize+2; x++) {
for (y=-3; y<2*psize+2; y++) {
p = this.grid.hex2coord([h0[0]+x,h0[1]+y]);
p[0] = (p[0]-extent[0])/res;
p[1] = pattern.height - (p[1]-extent[3])/res;
// Draw
ctx.strokeStyle = "rgba(0,0,0,0.5)";
this.drawHexagon(ctx, p, pxSize, 0, 3);
ctx.strokeStyle = "rgba(255,255,255,0.8)";
this.drawHexagon(ctx, p, pxSize, false, 2, 5, 2 );
ctx.strokeStyle = "rgba(0,0,0,0.3)";
this.drawHexagon(ctx, p, pxSize, false, 5, 8, 2 );
}
}
// Prevent coord rounding
var cache = document.createElement('canvas');
ctx = cache.getContext('2d');
cache.width = Math.round(w + (dw-pattern.width) * Math.floor(w/pattern.width));
cache.height = Math.round(h + (dh-pattern.height) * Math.floor(h/pattern.height));
ctx.fillStyle = ctx.createPattern(pattern,"repeat");
ctx.fillRect(0,0,cache.width,cache.height);
this.context.drawImage (cache, 0, 0, w, h, 0, 0, cache.width, cache.height);
} else {
ctx = this.context;
ctx.save();
var o0 = this.grid.hex2offset ( this.grid.coord2hex ([extent[0] , extent[1]]));
var o1 = this.grid.hex2offset ( this.grid.coord2hex ([extent[2] , extent[3]]));
ctx.scale(ratio,ratio)
ctx.lineWidth = 1.5;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.font = "bold 12px Arial"
// draw
for (x=o0[0]-1; x<=o1[0]+1; x++) {
for (y=o0[1]-1; y<=o1[1]+1; y++) {
var hex = this.grid.offset2hex([x,y], this.layout_);
p = this.grid.hex2coord(hex);
// Coord to pixel
p[0] = (p[0] - extent[0])/res;
p[1] = h/ratio - (p[1] - extent[1])/res;
// Draw
ctx.strokeStyle = "rgba(0,0,0,0.25)";
this.drawHexagon(ctx, p, pxSize);
ctx.strokeStyle = "rgba(255,255,255,0.8)";
this.drawHexagon(ctx, p, pxSize, false, 2, 5, 2 );
ctx.strokeStyle = "rgba(0,0,0,0.3)";
this.drawHexagon(ctx, p, pxSize, false, 5, 8, 2 );
// Show coords
if (pxSize > 20) {
switch (this.coordinates_) {
case 'axial': {
ctx.fillText(hex[0]+","+hex[1], p[0], p[1]);
break;
}
case 'cube': {
c = this.grid.hex2cube(hex);
//c=["x","y","z"]
for (var a=0; a<3; a++) {
var angle_rad = - Math.PI / 180 * (a*120 + 30);
ctx.fillText(c[a], p[0] + Math.cos(angle_rad)*pxSize*0.5, p[1] + Math.sin(angle_rad)*pxSize*0.5);
}
break;
}
case 'offset': {
c = this.grid.hex2offset(hex);
ctx.fillText(c[0]+","+c[1], p[0], p[1]);
break;
}
default: break;
}
}
}
}
ctx.restore();
}
return this.canvas;
};
export default ol_source_HexMap