Web Dev Solutions

Catalin Mititiuc

const svgns = "http://www.w3.org/2000/svg"; function evenr_to_axial(x, y) { return { q: x - (y + (y & 1)) / 2, r: y }; } function axial_to_evenr(q, r) { return { x: q + (r + (r & 1)) / 2, y: r }; } function axial_distance(q1, r1, q2, r2) { return (Math.abs(q1 - q2) + Math.abs(q1 + r1 - q2 - r2) + Math.abs(r1 - r2)) / 2; } function offset_distance(x1, y1, x2, y2) { let { q: q1, r: r1 } = evenr_to_axial(x1, y1), { q: q2, r: r2 } = evenr_to_axial(x2, y2); return axial_distance(q1, r1, q2, r2); } function cube_to_axial(q, r, s) { return { q: q, r: r }; } function axial_to_cube(q, r) { return { q: q, r: r, s: -q - r }; } function cube_round(q, r, s) { rQ = Math.round(q); rR = Math.round(r); rS = Math.round(s); let q_diff = Math.abs(rQ - q), r_diff = Math.abs(rR - r), s_diff = Math.abs(rS - s); if (q_diff > r_diff && q_diff > s_diff) { rQ = -rR - rS; } else if (r_diff > s_diff) { rR = -rQ - rS; } else { rS = -rQ - rR; } return { q: rQ, r: rR, s: rS }; } function axial_round(q, r) { let cube = axial_to_cube(q, r), round = cube_round(cube.q, cube.r, cube.s), axial = cube_to_axial(round.q, round.r, round.s); return { q: axial.q, r: axial.r }; } function lerp(a, b, t) { return a + (b - a) * t; } function axial_lerp(q1, r1, q2, r2, t) { return { q: lerp(q1, q2, t), r: lerp(r1, r2, t) }; } function linedraw(x1, y1, x2, y2) { let axial1 = evenr_to_axial(x1, y1), axial2 = evenr_to_axial(x2, y2), n = offset_distance(x1, y1, x2, y2), results = []; for (let i = 0; i <= n; i++) { let lerp = axial_lerp(axial1.q, axial1.r, axial2.q, axial2.r, 1.0 / n * i), round = axial_round(lerp.q, lerp.r), { x, y } = axial_to_evenr(round.q, round.r); results.push([x, y]); } return results; } export default class SightLine { constructor(svg) { this.svg = svg; } getBoard() { return this.svg.querySelector('.board'); } getActiveHexes() { return this.svg.querySelectorAll('use[href="#hex"].active'); } clear() { const board = this.getBoard(), sl = board.querySelector('line.sight-line'), target = board.querySelector(`use[href="#hex"].sight-line-target`); if (sl) { sl.remove(); } if (target) { target.classList.remove('sight-line-target'); } this.clearHexes(); } clearHexes() { if (this.distanceCallback) { this.distanceCallback(); } this.getActiveHexes().forEach(el => el.classList.remove('active')); } draw(source, target) { this.clear(); let pt = new DOMPoint(0, 0), transform = getComputedStyle(source).transform.match(/-?\d+\.?\d*/g), mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); transform = getComputedStyle(source.parentElement).transform.match(/-?\d+\.?\d*/g); mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); let slX1 = pt.x, slY1 = pt.y; pt = new DOMPoint(0, 0); transform = getComputedStyle(target).transform.match(/-?\d+\.?\d*/g); mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); transform = getComputedStyle(target.parentElement).transform.match(/-?\d+\.?\d*/g); mtx = new DOMMatrix(transform); pt = pt.matrixTransform(mtx); let slX2 = pt.x, slY2 = pt.y; let sightLine = document.createElementNS(svgns, 'line'); sightLine.classList.add('sight-line'); sightLine.classList.add('active'); sightLine.setAttributeNS(null, 'x1', slX1); sightLine.setAttributeNS(null, 'y1', slY1); sightLine.setAttributeNS(null, 'x2', slX2); sightLine.setAttributeNS(null, 'y2', slY2); this.getBoard().appendChild(sightLine); let coords = [ source.dataset.x, source.parentElement.dataset.y, target.dataset.x, target.parentElement.dataset.y ].map(n => parseInt(n)); this.drawHexes(...coords); } update(cell, { x, y }) { const sl = this.svg.querySelector('.sight-line'), target = this.svg.querySelector('.sight-line-target').parentElement, x1 = cell.parentElement.dataset.x, y1 = cell.parentElement.parentElement.dataset.y, x2 = target.dataset.x, y2 = target.parentElement.dataset.y; sl.setAttributeNS(null, 'x1', x); sl.setAttributeNS(null, 'y1', y); this.drawHexes(...[x1, y1, x2, y2].map(n => parseInt(n))); } drawHexes(...coords) { this.clearHexes() if (this.distanceCallback) { this.distanceCallback(offset_distance(...coords)); } let lineCoords = linedraw(...coords); let s = lineCoords .map(([x, y]) => `g[data-y="${y}"] g[data-x="${x}"] use[href="#hex"]`) .join(', '); this.svg.querySelectorAll(s).forEach(p => p.classList.add('active')); } }