import Tone from 'tone' import keys from './lib/keys' import kalimba from './lib/kalimba' import colundi from './lib/colundi' import { mod, browser, requestAudioContext } from './lib/util' import { Grid, Views, HexFactory } from 'honeycomb-grid' const gridSize = browser.isMobile ? 25 : 50 const hexagon = polygon(6, gridSize) const grid = Grid({ size: gridSize, }) const Hex = HexFactory({ size: gridSize, template: function(hex) { return ` ` } }) const container = document.querySelector("#container") const origin = { x: container.offsetWidth / 2 - hexagon.width / 2, y: container.offsetHeight / 2 - hexagon.height / 2, } const view = Views.DOM({ container: container, origin: origin, }) let last = null, dragging = false let hexes requestAudioContext(init) function init () { if (browser.isMobile) { document.addEventListener('touchstart', touch(down)) document.addEventListener('touchmove', touch(move)) document.addEventListener('touchend', touch(up)) } else { document.addEventListener('mousedown', down) document.addEventListener('mousemove', move) document.addEventListener('mouseup', up) } build(colundi.list) keys.listen(function(index){ index += 20 const freq = colundi.index(index) kalimba.play(freq) }) } function build (list) { container.innerHTML = "" let perimeter = [ Hex(0, 0, 0) ] hexes = {} for (let i = 0, len = list.length; i < len;) { const hex = perimeter.shift() const id = hexToString(hex) if (hexes[id]) continue let pair = list[len - i - 1] const neighbors = [0,1,2,3,4,5].map((j) => Hex.neighbor(hex, j)) perimeter = perimeter.concat(neighbors) view.renderHexes([ hex ]) const el = container.lastChild el.querySelector('polygon').setAttribute('fill', pair.color) hexes[id] = { el: el, freq: pair.freq } i++ } } function down (e){ dragging = true const hex = grid.pointToHex({ x: e.pageX - origin.x - hexagon.width/2, y: e.pageY - origin.y - hexagon.height/2 }) const pair = find(hex) if (! pair) return pair.el.style.opacity = 0.5 kalimba.play( pair.freq ) } function move (e){ if (! dragging) return const hex = grid.pointToHex({ x: e.pageX - origin.x - hexagon.width/2, y: e.pageY - origin.y - hexagon.height/2 }) const pair = find(hex) if (last === pair) return if (last) last.el.style.opacity = 1 if (! pair) return pair.el.style.opacity = 0.5 kalimba.play( pair.freq ) last = pair } function up (e){ if (last) last.el.style.opacity = 1 last = null dragging = false } function find(hex){ const id = hexToString(hex) if (id in hexes) return hexes[id] return null } function touch(fn){ return (e) => fn(e.touches[0]) } function polygon(n, side){ const points = [] const xs = [], ys = [] let min_x = Infinity, max_x = -Infinity let min_y = Infinity, max_y = -Infinity let x, y for (let i = 0; i < n; i++) { x = side * Math.cos(Math.PI/n * (1 + 2*i)) y = side * Math.sin(Math.PI/n * (1 + 2*i)) min_x = Math.min(min_x, x) max_x = Math.max(max_x, x) min_y = Math.min(min_y, y) max_y = Math.max(max_y, y) xs.push(x) ys.push(y) } for (let i = 0; i < n; i++) { points.push(xs[i] - min_x, ys[i] - min_y) } return { points: points, pointString: points.map(p => p.toFixed(3)).join(" "), width: max_x - min_x, height: max_y - min_y } } function hexToString(hex) { return [hex.x, hex.y, hex.z].join("_") }