var width = 960; height = 500; var points = [], radius = 30; var cos30 = Math.sqrt(3)/2; var sin30 = 1/2; var rows = Math.ceil(height/(3/2*radius)); var columns = Math.ceil(width/(cos30*radius*2)); var gridHeight = sin30*radius*3; var gridWidth = cos30*radius*2; var c = sin30 * radius; var m = c / (gridWidth/2); for (i = 0; i < rows; i++) { for (j = 0; j < columns; j++) { points.push({"i": i, "j": j}); } } var getHexagon = function (point) { point[0] = point[0] + cos30*radius; point[1] = point[1] + radius; var row = Math.floor(point[1] / gridHeight); var column; var rowIsOdd = (row % 2 == 1); if (rowIsOdd) column = Math.floor((point[0] - gridWidth/2) / gridWidth); else column = Math.floor(point[0] / gridWidth); var relY = point[1] - (row * gridHeight); var relX; if (rowIsOdd) relX = (point[0] - (column * gridWidth)) - gridWidth/2; else relX = point[0] - (column * gridWidth); // Work out if the point is above either of the hexagon's top edges if (relY < (-m * relX) + c) {// LEFT edge row--; if (!rowIsOdd) column--; } else if (relY < (m * relX) - c) {// RIGHT edge row--; if (rowIsOdd) column++; } return [row, column]; }; var vis = d3.select("body").append("svg") .attr("width", width) .attr("height", height); var cursor = vis.append("path") .attr("class", "cursor") .attr("d", function(r) {return "M0,"+radius+" L"+(cos30*radius)+","+(sin30*radius)+" L"+(cos30*radius)+","+(-sin30*radius)+" L0,"+(-radius)+" L"+(-cos30*radius)+","+(-sin30*radius)+" L"+(-cos30*radius)+","+(sin30*radius)+" Z";}); var get_coordinates = function(d, i) { h = getHexagon(d3.mouse(this)); if (h[0] % 2 === 0) cursor.attr("transform", "translate(" + (h[1]*cos30*radius*2) + "," + (h[0]*3/2*radius) + ")"); else cursor.attr("transform", "translate(" + (h[1]*(cos30*radius*2)+(cos30*radius)) + "," + (h[0]*3/2*radius) + ")"); }; var hexagon_layer = vis.insert("g", ":last-child").on('mouseover', get_coordinates); var hexagon = hexagon_layer.selectAll(".hexagon") .data(points); var enter_hexagon = hexagon.enter().append("g") .attr("class", "hexagon") .attr("transform", function(d) { if (d.i % 2 === 0) return "translate(" + (d.j*cos30*radius*2) + "," + (d.i*3/2*radius) + ")"; else return "translate(" + (d.j*(cos30*radius*2)+(cos30*radius)) + "," + (d.i*3/2*radius) + ")"; }); enter_hexagon.append("path") .attr("d", function(r) {return "M0,"+radius+" L"+(cos30*radius)+","+(sin30*radius)+" L"+(cos30*radius)+","+(-sin30*radius)+" L0,"+(-radius)+" L"+(-cos30*radius)+","+(-sin30*radius)+" L"+(-cos30*radius)+","+(sin30*radius)+" Z";}); enter_hexagon.append("text") .attr("class", "label") .attr("dy", "0.35em") .text(function(d) {return d.i + "," + d.j;});