'use strict'; /** * */ function Mesh(width, height, side) { // Length of a side this.side = side; this.width = width; this.height = height; // How far a seed will extend its reach this.seedWeight = 5; // Color seed coordinants // this.addSeed(new MeshSeed(0, 0, '#ff0000', this.seedWeight), faces); // this.addSeed(new MeshSeed(0, this.height - 1, '#0000ff', this.seedWeight), faces); // this.addSeed(new MeshSeed(this.width - 1, 0, '#00ff00', this.seedWeight), faces); // this.addSeed(new MeshSeed(this.width - 1, this.height - 1, '#ffff00', this.seedWeight), faces); // this.calculateFills(faces); // var svg = d3.select("body").append("svg").attr('width', this.width).attr('height', this.height); // d3.select(id).attr('fill', seed.fill); // for (var i = 0, len = seeds.length; i < len; i++) { // d3.select(seeds[i].faceId).attr('fill', seeds[i].fill); // } }; /** * */ Mesh.prototype = { /** * Faces must be a one dimensional array to pass to D3. */ initFaces: function(width, height, side) { var countW = Math.ceil(width / side); var countH = Math.ceil(height / side); var all = []; for (var w = 0; w < countW; w++) { for (var h = 0; h < countH; h++) { all.push(new MeshFace( `f-${w}-${h}-${all.length}`, w * side, h * side, side )); } } return all; }, /** * */ calculateFills: function(faces) { var len = faces.length; var hexes, colors; var populate = function(color) { var arr = []; for (var k = 0; k < color.weight; k++) { arr.push(color.hex); } return arr; }; for (var i = 0; i < len; i++) { hexes = []; for (var j = 0; j < faces[i].colors.length; j++) { colors = faces[i].colors[j]; hexes = hexes.concat(populate(colors)); } while (hexes.length < this.seedWeight) { hexes.push('#ffffff'); } faces[i].fill = this.averageHexCollection(hexes); } }, /** * */ addSeed: function(seed, faces) { var faceX = Math.floor(seed.x / this.side); var faceY = Math.floor(seed.y / this.side); var countX = this.width / this.side; var countY = this.height / this.side; var n = this.seedWeight; var len = faces.length; var delta, index, weight; for (var x = (faceX - n + 1); x < faceX + n; x++) { if (x < 0 || x >= countX) { continue; } for (var y = (faceY - n + 1); y < faceY + n; y++) { if (y < 0 || y >= countY) { continue; } // Weights decrement outwards from source in a given shape: // Diamonds: // delta = Math.abs(faceX - x) + Math.abs(faceY - y); // weight = Math.max(0, n - delta); // Squares: var weight = n - Math.max(Math.abs(faceX - x), Math.abs(faceY - y)); index = x * countY + y; if (weight > 0 && index >= 0 && index < len) { faces[index].colors.push({ hex: seed.fill, weight: weight }); } } } }, /** * */ averageComponentCollection: function(collection) { var len = collection.length; var total = 0; for (var i = 0; i < len; i++) { total += parseInt(collection[i], 16); } var avg = Math.round(total / len); avg = avg.toString(16); avg = ('00' + avg).slice(-2); return avg; }, /** * */ averageHexCollection: function(collection) { // check hex against regex var allR = []; var allG = []; var allB = []; var len = collection.length; var tmp, hex; for (var i = 0; i < len; i++) { tmp = collection[i].substr(1); allR.push(tmp.substr(0, 2)); allG.push(tmp.substr(2, 2)); allB.push(tmp.substr(4, 2)); } var r = this.averageComponentCollection(allR); var g = this.averageComponentCollection(allG); var b = this.averageComponentCollection(allB); return '#' + r + g + b; } };