function matrixGrid(matrix,width,height,margin) { var rows = matrix.length, cols = matrix[0].length, margin = margin || {top:10,left:10,bottom:10,right:10}, width = width || 960 - margin.left - margin.right, height = height || 500 - margin.top - margin.bottom, data = [], cells = {}; var output = { setCellMargin:setCellMargin, info:info, draw:draw, getCell:getCell } matrix.forEach(function(row,i){ row.forEach(function(cell,j) { var check = data.filter(function(d) { return d.id == cell}); if(check.length == 0) { data.push({id:cell, row:i+1, col:j+1, height:1, width:1}); } else { data.forEach(function(d){ if(d.id == cell) { if(d.width + d.col - 1 < j+1) { d.width++; } if(d.height + d.row - 1 < i+1) { d.height++; } } }) } }) }); data.forEach(function(d) { d.margin = {top:10,left:10,bottom:10,right:10}; d.width = width/cols*d.width - d.margin.left - d.margin.right; d.height = height/rows*d.height - d.margin.top - d.margin.bottom; d.translate = [((d.col - 1)*width/cols + d.margin.left),((d.row-1)*height/rows + d.margin.top)]; }); function setCellMargin(cell,top,left,bottom,right) { data.filter(function(d) { return d.id == cell}).forEach(function(d) { d.width = d.width + d.margin.left + d.margin.right - left - right; d.height = d.height + d.margin.top + d.margin.bottom - top - bottom; d.translate[0] = d.translate[0] - d.margin.left + left; d.translate[1] = d.translate[1] - d.margin.top + top; d.margin = {top:top,bottom:bottom,left:left,right:right}; }); return output; } function info(cell) { return data.filter(function(d) { return d.id == cell;})[0]; } function draw(elementId, resize, inCanvas, zoomable) { var svg; d3.select("#" + elementId).selectAll("*").remove(); if(inCanvas) { var canvas = d3.select("#" + elementId) .append("canvas") .attr("width", width/height*100) .attr("height", 100) .style("visibility","hidden") .style("display","block") .style("height","100%") .style("width", "100%") } if(resize) { svg = d3.select("#" + elementId) .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("viewBox","0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom)) .attr("preserveAspectRatio","xMinYMin meet") .style("-webkit-user-select","none") .style("cursor","default") .append("g") .attr("transform","translate(" + margin.left + "," + margin.top +")"); } else { svg = d3.select("#" + elementId) .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .style("-webkit-user-select","none") .style("cursor","default") .append("g") .attr("transform","translate(" + margin.left + "," + margin.top +")"); } if(inCanvas) { d3.select(svg.node().parentNode) .style("position","absolute") .style("top",0) .style("left",0) } var allCells = svg.selectAll(".cell") .data(data) .enter() .append("g") .attr("transform", function(d) {return 'translate('+ d.translate[0] + "," + d.translate[1] + ")"}) .each(function(d) { cells["cell" + d.id] = d3.select(this)}); if(zoomable) { allCells.on("dblclick", zoom); } return output; var zoomed = false; function zoom(d) { if(zoomed) { if(inCanvas) { canvas.transition() .duration(1000) .attr("width", width/height*100) .attr("height", 100) } d3.select(this.parentNode.parentNode) .transition() .duration(1000) .attr("viewBox","0 0 " + (width + margin.left + margin.right) + " " + (height + margin.top + margin.bottom)) allCells.transition() .duration(1000) .style("opacity",1) } else { var bb = this.getBBox() var vb = [0,0,0,0]; vb[0] = d.translate[0] - margin.left - d.margin.left - 10; vb[1] = d.translate[1] - margin.top - d.margin.top - 10; vb[2] = d.width + d.margin.left + d.margin.right + 30; vb[3] = d.height + d.margin.top + d.margin.bottom + 30; d3.select(this.parentNode.parentNode) .transition() .duration(1000) .attr("viewBox", vb[0] + " " + vb[1] + " " + vb[2] + " " + vb[3]) allCells.transition() .duration(1000) .style("opacity",function(e) { return e.id == d.id ? 1 : .1;}) if(inCanvas) { canvas.transition() .duration(1000) .attr("width", (vb[2])/(vb[3])*100) .attr("height", 100) } } zoomed = !zoomed; } } function getCell(id) { return cells["cell" + id]; } return output; }