JSFiddle - React, Tailwind, and code Playground
HTML
<div id="stage">
<canvas id="base" width="1000" height="500"></canvas>
<canvas id="overlay" width="1000" height="500"></canvas>
</div>
<style>
#stage {
width: 1000;
height: 500px;
position: relative;
border: 2px solid black;
}
canvas { position: absolute; }
#overlay { z-index: 2; }
#base { z-index: 1; }
</style>
JavaScript
const canvas = document.getElementById('base');
const ctx = canvas.getContext('2d');
const cWidth = canvas.width;
const cHeight = canvas.height;
const padding = 4;
const portSetCount = 96;
const portSetRows = 6;
const portsPerRow = portSetCount / portSetRows;
const drawablePortWidth = cWidth - ((portsPerRow+1)*padding);
const portWidth = drawablePortWidth / portsPerRow;
const portSixth = portWidth / 6;
let x=padding;
let y=padding;
for(let row=1; row<=portSetRows; row++){
x=padding;
for(let col=1; col<=portSetCount/portSetRows; col++){
ctx.fillStyle = 'green';
ctx.rect(x, y, portWidth, portWidth);
ctx.fill();
ctx.fillStyle='black';
ctx.beginPath();
ctx.moveTo(x+portSixth, y+(2*portSixth));
// left
ctx.lineTo(x+portSixth, y+(5*portSixth));
// bottom
ctx.lineTo(x+(5*portSixth), y+(5*portSixth));
// right
ctx.lineTo(x+(5*portSixth), y+(2*portSixth));
ctx.lineTo(x+(4*portSixth), y+(2*portSixth));
ctx.lineTo(x+(4*portSixth), y+(1*portSixth));
ctx.lineTo(x+(2*portSixth), y+(1*portSixth));
ctx.lineTo(x+(2*portSixth), y+(2*portSixth));
//ctx.lineTo(x+(1*portSixth), y+(2*portSixth));
ctx.closePath();
ctx.fill();
x += portWidth + padding;
}
y += portWidth + padding;
}