|
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; |
|
|
|
} |
|
|