D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
VisDockHub
Full window
Github gist
Matrix Visualization with animation
Animation-enabled matrix visualization.
<html> <style> .rowLabel { -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Safari */ -khtml-user-select: none; /* Konqueror HTML */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* Internet Explorer/Edge */ user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */ } .columnLabel { -webkit-touch-callout: none; /* iOS Safari */ -webkit-user-select: none; /* Safari */ -khtml-user-select: none; /* Konqueror HTML */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* Internet Explorer/Edge */ user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */ } </style> <body> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var w_cell = 75; var h_cell = 75; var ind; var celldata; var mat = []; var drawBoxC, drawBoxR; var mouseEvt = 1; var userlog = []; var svg = d3.select('body').append('svg') .attr('height', '600px') .attr('width', '600px'); d3.csv("data.csv", function(error, data){ celldata = data; var j = 0; ind = Object.keys(data[0]); /*for (var i = 0; i < data.length; i ++){ }*/ var canvas = svg.append('g').attr('class', 'canvas'); for (var i = 0; i < data.length; i++){ // Create column g var column = canvas.append('g').attr('id', 'gc' + i) .attr('class', 'column_g') .attr('transform', function(){ var x = w_cell*(i+1); var y = h_cell*0; return 'translate(' + x + ',' + y + ')'; }); column.append('rect').attr('class', 'columnLabel') .attr('width', w_cell).attr('height', h_cell) //.attr('x', w_cell*(i+1)) .attr('y', h_cell*(0)) .attr('style', 'stroke:white; fill:white; opacity: 0.5'); column.append('text').attr('class', 'columnLabel') //.attr('x', w_cell*(i+1)+w_cell*1/10).attr('y', h_cell*(9)/10) .attr('transform', function(){ var x = 0*w_cell*(i+1)+w_cell*1/10; var y = h_cell*9/10; return 'translate(' + x + ',' + y + ')rotate(-45)'; }) .text(function(){return data.columns[i];}); mat[i] = []; for (var j = 0; j < data.length; j++){ mat[i][j] = data[i][ind[j]]; column.append('rect').attr('class', 'cell') .attr('id', 'cell' + j) .attr('width', w_cell).attr('height', h_cell) //.attr('x', w_cell*(i+1)) .attr('y', h_cell*(j+1)) .attr('style', function(){ var str; if (data[i][ind[j]] == '1'){ str = 'black'; } else { str = 'white'; } return 'stroke: none; stroke-width: none; opacity: 0.5; fill:' + str; }); } // Create row g var row = canvas.append('g').attr('id', 'gr' + i) .attr('class', 'row_g') .attr('transform', function(){ var x = 0*w_cell; var y = h_cell*(i+1); return 'translate(' + x + ',' + y + ')'; }); row.append('rect').attr('class', 'rowLabel') .attr('width', w_cell).attr('height', h_cell) .attr('x', w_cell*(0)) //.attr('y', h_cell*(i+1)) .attr('style', 'stroke:white; fill:white; opacity:0.5'); row.append('text').attr('class', 'rowLabel') //.attr('x', w_cell*(i+1)+w_cell*1/10).attr('y', h_cell*(9)/10) .attr('transform', function(){ var x = w_cell*0/10; var y = 0*h_cell*(i+1) + 1/2*h_cell; return 'translate(' + x + ',' + y + ')'; }) .text(function(){return data.columns[i];}); for (var j = 0; j < data.length; j++){ row.append('rect').attr('class', 'cell') .attr('id', 'cell' + j) .attr('width', w_cell).attr('height', h_cell) .attr('x', w_cell*(j+1)) //.attr('y', h_cell*(i+1)) .attr('style', function(){ var str; if (data[i][ind[j]] == '1'){ str = 'black'; } else { str = 'white'; } return 'stroke: none; stroke-width: none; opacity: 0.5; fill:' + str; }); } } for (var i = 0; i < data.length; i++){ for (var j = 0; j < data.length; j ++){ canvas.append('rect').attr('class', 'backgroundCell') .attr('width', w_cell).attr('height', h_cell) .attr('x', w_cell*(i+1)) .attr('y', h_cell*(j+1)) .attr('style', 'opacity: 0.5; stroke: black; stroke-width: 2px; fill: none;'); } } var dx, dy; var mousedrag; d3.selectAll('.columnLabel') .on('mousedown', function(){ if (mouseEvt == 1){ var logtime = timeCount/100; var logStr = 'Column ' + this.parentNode.getAttribute('id'); var parent = this.parentNode; var temp = parent.cloneNode(true); d3.select(temp).selectAll('.cell') .attr('style', function() { var style = this.getAttribute('style').split(';'); var str = 'stroke: red; stroke-width: 5px;'; for (var s = 2; s < style.length; s++){ if (s == style.length - 1){ if (style[s] == ' fill:black') str = str + ' fill:red'; else str = str + ' fill:white'; } else { str = str + style[s]+ ';'; } } return str; }); //d3.select(temp).selectAll('.columnLabel') // .attr('style', 'fill: white; opacity: 0.5'); d3.select(temp).selectAll('text') .attr('fill', 'red'); document.getElementsByClassName('canvas')[0].appendChild(temp); mousedrag = 1; dx = event.clientX - parent.getAttribute('transform').split('(')[1].split(',')[0]; d3.select('.canvas') .on('mousemove', function(){ var x = event.clientX-dx; var y = parent.getAttribute('transform').split(')')[0].split(',')[1]; if (x < w_cell){ x = w_cell; } else if (x > w_cell * data.length){ x = w_cell * data.length; } if (mousedrag == 1) temp.setAttribute('transform', 'translate(' + x + ',' + y + ')'); }) .on('mouseup', function(){ //var x = event.clientX; var x = parseFloat(temp.getAttribute('transform').split(',')[0].split('(')[1]); var id = temp.getAttribute('id'); temp.remove(); mousedrag = 0; var newColumn = swapColumn(id, x); logStr = logStr + ' to gc' + newColumn; userlog.push([logStr, logtime]); d3.select('.canvas').on('mousemove', null); d3.select('.canvas').on('mouseup', null); }); } //var c = 0; }); d3.selectAll('.rowLabel') .on('mousedown', function(){ if (mouseEvt == 1){ var logtime = timeCount/100; var logStr = 'Row ' + this.parentNode.getAttribute('id'); var parent = this.parentNode; mousedrag = 1; var temp = parent.cloneNode(true); d3.select(temp).selectAll('.cell') .attr('style', function() { var style = this.getAttribute('style').split(';'); var str = 'stroke: red; stroke-width: 5px;'; for (var s = 2; s < style.length; s++){ if (s == style.length - 1){ if (style[s] == ' fill:black') str = str + ' fill:red'; else str = str + ' fill:white'; } else { str = str + style[s]+ ';'; } } return str; }); d3.select(temp).selectAll('.rowLabel') //.attr('style', 'fill: white; opacity: 0.5'); d3.select(temp).selectAll('text') .attr('fill', 'red'); document.getElementsByClassName('canvas')[0].appendChild(temp); mousedrag = 1; dy = event.clientY - parent.getAttribute('transform').split(')')[0].split(',')[1]; d3.select('.canvas') //.attr('style', 'fill: white; stroke: red; stroke-width: 5px; opacity: 0.5') .on('mousemove', function(){ var y = event.clientY-dy; //var y = this.getAttribute('transform').split(')')[0].split(',')[1]; if (y < h_cell){ y = h_cell; } else if (y > h_cell * data.length){ y = h_cell * data.length; } if (mousedrag == 1) temp.setAttribute('transform', 'translate(' + 0 + ',' + y + ')'); }) .on('mouseup', function(){ mousedrag = 0; var id = temp.getAttribute('id'); var y = parseFloat(temp.getAttribute('transform').split(',')[1].split(')')[0]); temp.remove(); var newRow = swapRow(id, y); logStr = logStr + ' to gr' + newRow; userlog.push([logStr, logtime]); d3.select('.canvas').on('mouseup', null); d3.select('.canvas').on('mousemove', null); }); } }); d3.selectAll('.cell').on('mousedown', function(){ var str = this.getAttribute('id') + ' in ' + this.parentNode.getAttribute('id'); document.getElementById('myText2').value = str; userlog.push(['mousedown', str]); }); }); function swapRow(id, y){ var row = parseInt(id.split('gr')[1]); var newRow; for (var i = 0; i < celldata.length; i++){ if (y <= (i+1)*h_cell && y > (i+0.5)*h_cell){ newRow = i; } else if (y <= (i+1)*h_cell && y > (i)*h_cell){ newRow = i-1; } } if (row == newRow) return row; rearrangeCell(row, newRow); // change position var trans1 = document.getElementById('gr'+row).getAttribute('transform'); var trans2 = document.getElementById('gr'+newRow).getAttribute('transform'); var x1 = parseFloat(trans1.split(',')[0].split('(')[1]); var y1 = parseFloat(trans1.split(',')[1].split(')')[0]); var x2 = parseFloat(trans2.split(',')[0].split('(')[1]); var y2 = parseFloat(trans2.split(',')[1].split(')')[0]); var cap = 75 * Math.abs(row-newRow); var timing = setInterval(frame, 5); var count = 1; var int_x_1 = (x2-x1)/cap; var int_x_2 = -int_x_1; var int_y_1 = (y2-y1)/cap; var int_y_2 = -int_y_1; return newRow; function frame(){ if (count > cap) { clearInterval(timing); mouseEvt = 1; rest(); //return newRow; } else { // deactivate any re-ordering mouseEvt = 0; var x = x1 + int_x_1*count; var y = y1 + int_y_1*count; document.getElementById('gr'+row).setAttribute('transform', 'translate(' + x + ',' + y + ')'); document.getElementById('gc'+row).setAttribute('transform', 'translate(' + y + ',' + x + ')'); var x = x2 + int_x_2*count; var y = y2 + int_y_2*count; document.getElementById('gr'+newRow).setAttribute('transform', 'translate(' + x + ',' + y + ')'); document.getElementById('gc'+newRow).setAttribute('transform', 'translate(' + y + ',' + x + ')'); count++; } } function rest(){ swapCellc(row, newRow); var trans1 = document.getElementById('gc'+row).getAttribute('transform'); var trans2 = document.getElementById('gc'+newRow).getAttribute('transform'); swapCellr(row, newRow); document.getElementById('gr'+newRow).setAttribute('id', 'gr_'+ row); document.getElementById('gr'+row).setAttribute('id', 'gr_'+newRow); document.getElementById('gc'+newRow).setAttribute('id', 'gc_' + row); document.getElementById('gc'+row).setAttribute('id', 'gc_' + newRow); document.getElementById('gr_'+ row).setAttribute('id', 'gr'+ row); document.getElementById('gr_'+ newRow).setAttribute('id', 'gr'+newRow); document.getElementById('gc_' + row).setAttribute('id', 'gc' + row); document.getElementById('gc_' + newRow).setAttribute('id', 'gc' + newRow); } //var c; } function findCell(groups, id, ind){ for (var i = 0; i < groups.length; i++){ if (groups[i].getAttribute('id') == id + ind){ groups[i].setAttribute('id', id + '_' + ind); return groups[i]; } } } function rearrangeCell(column, newColumn){ document.getElementById('gr'+newColumn) .appendChild(findCell(document.getElementById('gr'+column).childNodes, 'cell', newColumn)); document.getElementById('gr'+newColumn) .appendChild(findCell(document.getElementById('gr'+column).childNodes, 'cell', column)); document.getElementById('gr'+column) .appendChild(findCell(document.getElementById('gr'+newColumn).childNodes, 'cell', newColumn)); document.getElementById('gr'+column) .appendChild(findCell(document.getElementById('gr'+newColumn).childNodes, 'cell', column)); d3.selectAll('#cell_' + newColumn).attr('id', 'cell' + newColumn); d3.selectAll('#cell_' + column).attr('id', 'cell' + column); document.getElementById('gc'+newColumn) .appendChild(findCell(document.getElementById('gc'+column).childNodes, 'cell', newColumn)); document.getElementById('gc'+newColumn) .appendChild(findCell(document.getElementById('gc'+column).childNodes, 'cell', column)); document.getElementById('gc'+column) .appendChild(findCell(document.getElementById('gc'+newColumn).childNodes, 'cell', newColumn)); document.getElementById('gc'+column) .appendChild(findCell(document.getElementById('gc'+newColumn).childNodes, 'cell', column)); d3.selectAll('#cell_' + newColumn).attr('id', 'cell' + newColumn); d3.selectAll('#cell_' + column).attr('id', 'cell' + column); } function swapColumn(id, x){ var column = parseInt(id.split('gc')[1]); var newColumn; for (var i = 0; i < celldata.length; i++){ if (x <= (i+1)*w_cell && x > (i+0.5)*w_cell){ newColumn = i; } else if (x <= (i+1)*w_cell && x > (i)*w_cell){ newColumn = i-1; } } if (column == newColumn) return column; // change position var trans1 = document.getElementById('gr'+column).getAttribute('transform'); var trans2 = document.getElementById('gr'+newColumn).getAttribute('transform'); var x1 = parseFloat(trans1.split(',')[0].split('(')[1]); var y1 = parseFloat(trans1.split(',')[1].split(')')[0]); var x2 = parseFloat(trans2.split(',')[0].split('(')[1]); var y2 = parseFloat(trans2.split(',')[1].split(')')[0]); rearrangeCell(column, newColumn); //document.getElementById('gr'+column).setAttribute('transform', trans2); //document.getElementById('gr'+newColumn).setAttribute('transform', trans1); var cap = 75*Math.abs(column-newColumn); var timing = setInterval(frame, 5); var count = 1; var int_x_1 = (x2-x1)/cap; var int_x_2 = -int_x_1; var int_y_1 = (y2-y1)/cap; var int_y_2 = -int_y_1; return newColumn; function frame(){ if (count > cap) { clearInterval(timing); mouseEvt = 1; rest(); } else { // deactivate any re-ordering mouseEvt = 0; var x = x1 + int_x_1*count; var y = y1 + int_y_1*count; document.getElementById('gr'+column).setAttribute('transform', 'translate(' + x + ',' + y + ')'); document.getElementById('gc'+column).setAttribute('transform', 'translate(' + y + ',' + x + ')'); var x = x2 + int_x_2*count; var y = y2 + int_y_2*count; document.getElementById('gr'+newColumn).setAttribute('transform', 'translate(' + x + ',' + y + ')'); document.getElementById('gc'+newColumn).setAttribute('transform', 'translate(' + y + ',' + x + ')'); count++; } } function rest(){ swapCellr(column, newColumn); var trans1 = document.getElementById('gc'+column).getAttribute('transform'); var trans2 = document.getElementById('gc'+newColumn).getAttribute('transform'); //document.getElementById('gc'+column).setAttribute('transform', trans2); //document.getElementById('gc'+newColumn).setAttribute('transform', trans1); swapCellc(column, newColumn); // change index document.getElementById('gr'+newColumn).setAttribute('id', 'gr_'+ column); document.getElementById('gr'+column).setAttribute('id', 'gr_'+newColumn); document.getElementById('gc'+newColumn).setAttribute('id', 'gc_' + column); document.getElementById('gc'+column).setAttribute('id', 'gc_' + newColumn); document.getElementById('gr_'+ column).setAttribute('id', 'gr'+ column); document.getElementById('gr_'+ newColumn).setAttribute('id', 'gr'+newColumn); document.getElementById('gc_' + column).setAttribute('id', 'gc' + column); document.getElementById('gc_' + newColumn).setAttribute('id', 'gc' + newColumn); } //var c; } function swapCellc(ind1, ind2){ for (var i = 0; i < celldata.length; i++){ if (i != ind1 && i != ind2){ var column = d3.select(document.getElementById('gc' + i)) .selectAll('.cell'); for (var j = 0; j < celldata.length; j++){ if (column._groups[0][j].getAttribute('id') == 'cell' + ind1){ var y1 = column._groups[0][j].getAttribute('y'); column._groups[0][j].setAttribute('id', 'cell_' + ind1); } else if (column._groups[0][j].getAttribute('id') == 'cell' + ind2){ var y2 = column._groups[0][j].getAttribute('y'); column._groups[0][j].setAttribute('id', 'cell_' + ind2); } } d3.select('#cell_' + ind1).attr('id', 'cell' + ind2).attr('y', y2); d3.select('#cell_' + ind2).attr('id', 'cell' + ind1).attr('y', y1); } } } function swapCellr(ind1, ind2){ for (var i = 0; i < celldata.length; i++){ if (i != ind1 && i != ind2){ var column = d3.select(document.getElementById('gr' + i)) .selectAll('.cell'); for (var j = 0; j < celldata.length; j++){ if (column._groups[0][j].getAttribute('id') == 'cell' + ind1){ var x1 = column._groups[0][j].getAttribute('x'); column._groups[0][j].setAttribute('id', 'cell_' + ind1); } else if (column._groups[0][j].getAttribute('id') == 'cell' + ind2){ var x2 = column._groups[0][j].getAttribute('x'); column._groups[0][j].setAttribute('id', 'cell_' + ind2); } } d3.select('#cell_' + ind1).attr('id', 'cell' + ind2).attr('x', x2); d3.select('#cell_' + ind2).attr('id', 'cell' + ind1).attr('x', x1); } } } var timeCount = 0; var timer = setInterval(frame, 10); function frame(){ timeCount++; document.getElementById('myText').value = timeCount/100; } </script> </body> </html>
https://d3js.org/d3.v4.min.js