responsive matrix design - using string with 0 & 1 for dynamic visualization
This fiddle does automatically fit boxes inside a equilateral grid - you can adjust the number of boxes with changing the maxDots variable (just make sure to stay with 2x2, 3x3, ...). The grid reads a string with 1's and 0's and transform it accordingly to the grid with boxes being a 1 and dots being a 0. Works with all current Browser, IE10+ (because of flexbox).
by Ercan Cicek
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<!-- using jquery -->
<!-- using angular -->
<body ng-app="symApp" ng-controller="symCtrl" class="flex-display flex-center">
<div class="matrix-wrapper flex-display flex-center">
<div class="matrix-container flex-display flex-spaceA flex-flow">
<div id="dot-{{dot.id}}" ng-repeat="dot in dots" ng-class="dot.state ? '' : 'noBg'" class="dot dot-expanded flex-display flex-center">
<div ng-class="dot.state ? 'noBg' : ''" class="dot-default"></div>
</div>
</div>
</div>
</body>
CSS
html, body {
position: relative;
width: 100%;
height: 100%;
}
.matrix-wrapper {
width: 100%;
height: 100%;
position: relative;
}
.matrix-container {
position: relative;
width: 100%; /* placeholder */
height: 100%; /* placeholder */
border: 1px solid #69F0AE;
}
.dot-expanded {
border-radius: 1px;
background-color: #69F0AE;
}
.dot-default {
width: 25%;
height: 25%;
border-radius: 50%;
background-color: #69F0AE;
}
/* --- utilities --- */
.softHide {
visibility: hidden;
}
.noBg {
background-color: transparent;
}
.flex-display {
display: -webkit-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
}
.flex-center {
-webkit-box-align: center;
-moz-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-moz-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.flex-spaceA {
-webkit-box-pack: justify;
-webkit-justify-content: space-around;
-ms-flex-pack: distribute;
justify-content: space-around;
-webkit-align-content: space-around;
align-content: space-around;
}
.flex-flow {
-webkit-flex-flow: row wrap;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
JavaScript
angular.module('symApp',[]).controller('symCtrl', ['$scope', '$timeout', function($scope, $timeout) {
// --- vars
var maxDots = 64; // --- has to be 2*2, 3*3, ...
// --- angular vars
$scope.dots = [];
// ------ fill $scope.dots with default values
for(var i = 1; i <= maxDots; i++) {
$scope.dots.push({ id: i, state: false });
}
// --- functions
$(init);
function init() {
// --- maxboxsize 52%, margin 40% (defined by me ;))
var dotSize = 52 / Math.sqrt(maxDots),
dotMargin = 40 / (Math.sqrt(maxDots) * 2);
// --- set dot sizes suitable for maxDots
$("body").append("<style type='text/css'>.dot { width: " + dotSize + "%; height: " + dotSize + "%; margin-left: " + dotMargin + "%; margin-right: " + dotMargin + "%; }</style>");
// --- responsivity
$(window).resize(setElements);
setElements();
// ---
$timeout(getMatrix);
}
function getMatrix() {
// --- generate string with 0 & 1 randomly with count equally to maxDots - every 1 will be shown as expanded dot
var testItem = "";
for(var i = 0; i < maxDots; i++) {
testItem += getRandomInt(0,1);
}
for(var j = 0; j < maxDots; j++) {
$scope.dots[j].state = (testItem[j] === '1');
}
console.log($scope.dots);
}
function setElements() {
var $gaCont = $(".matrix-wrapper"),
wndw = { w: $gaCont.width(), h: $gaCont.height() },
distSize = isPortrait() ? wndw.w * 0.75 : wndw.h * 0.75;
$(".matrix-container").css({ width: distSize + "px", height: distSize + "px" });
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function isPortrait() {
return window.matchMedia("(orientation: portrait)").matches;
}
}]);