diff --git a/index.html b/index.html index f22cb40..f1d8d1a 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,19 @@ - - - - - - - Online ArUco markers generator - - + + + + + + + + Online ArUco markers generator + + + + + + + + + + + \ No newline at end of file diff --git a/layouts.json b/layouts.json new file mode 100644 index 0000000..22927f2 --- /dev/null +++ b/layouts.json @@ -0,0 +1,246 @@ +{ + "layout1":{ + "name":"3 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 85 + }, + "marker2": { + "top": 0, + "left": 95, + "size": 85 + }, + "marker3": { + "top": 105, + "left": 3, + "size": 175 + } + }}, + + "layout2":{ + "name":"6 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 80 + }, + "marker2": { + "top": 100, + "left": 0, + "size": 80 + }, + "marker3": { + "top": 0, + "left": 100, + "size": 80 + }, + "marker4": { + "top": 100, + "left": 100, + "size": 80 + }, + "marker5": { + "top": 200, + "left": 0, + "size": 80 + }, + "marker6": { + "top": 200, + "left": 100, + "size": 80 + } + }}, + + "layout3":{ + "name":"4 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 110 + }, + "marker2": { + "top": 0, + "left": 130, + "size": 50 + }, + "marker4": { + "top": 70, + "left": 130, + "size": 50 + }, + "marker3": { + "top": 140, + "left": 0, + "size": 140 + } + + }}, + + + + "layout4":{ + "name":"13 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 35 + }, + "marker2": { + "top": 0, + "left": 50, + "size": 35 + }, + "marker3": { + "top": 0, + "left": 95, + "size": 35 + }, + "marker4": { + "top": 0, + "left": 145, + "size": 35 + }, + "marker5": { + "top": 50, + "left": 0, + "size": 55 + }, + "marker6": { + "top": 50, + "left": 60, + "size": 55 + }, + "marker7": { + "top": 50, + "left": 125, + "size": 55 + }, + "marker8": { + "top": 120, + "left": 0, + "size": 85 + }, + "marker9": { + "top": 120, + "left": 95, + "size": 85 + }, + "marker10": { + "top": 225, + "left": 0, + "size": 65 + }, + "marker11": { + "top": 225, + "left": 75, + "size": 65 + }, + "marker12": { + "top": 225, + "left": 150, + "size": 30 + }, + "marker13": { + "top": 265, + "left": 150, + "size": 30 + } + + } + }, + "layout5":{ + "name":"4 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 90 + }, + "marker2": { + "top": 0, + "left": 95, + "size": 90 + }, + "marker3": { + "top": 120, + "left": 0, + "size": 90 + }, + "marker4": { + "top": 120, + "left": 95, + "size": 90 + } + + + } + }, + "layout6":{ + "name":"6 split", + "width":200, + "height": 320, + "margin":1, + "markers": { + "marker1": { + "top": 0, + "left": 0, + "size": 120 + }, + "marker2": { + "top": 150, + "left": 0, + "size": 120 + }, + "marker 3": { + "top": 0, + "left": 125, + "size": 50 + }, + "marker 4": { + "top": 80, + "left": 125, + "size": 50 + }, + "marker 5": { + "top": 150, + "left": 125, + "size": 50 + }, + "marker 6": { + "top": 0, + "left": 125, + "size": 50 + }, + "marker 7": { + "top": 0, + "left": 125, + "size": 50 + }, + "marker 8": { + "top": 230, + "left": 125, + "size": 50 + } + } + } +} \ No newline at end of file diff --git a/main.css b/main.css index c7d4cd0..b20f791 100644 --- a/main.css +++ b/main.css @@ -2,6 +2,8 @@ body { font-family: sans-serif; padding: 0; margin: 0; + display: flex; + flex-direction: row; } h1 { @@ -31,7 +33,7 @@ a { vertical-align: -1px; } -.setup select { +.setup select, .setup textarea { font-weight: 300; margin: 0; margin-left: 20px; @@ -45,7 +47,8 @@ a { } .setup .field { - margin: 10px 0; + margin: 10px 20px 20px 20px; + display: flex; } .setup label { @@ -74,7 +77,7 @@ a { .marker { text-align: center; background: white; - margin: 40px; + margin: 0px; } .marker table { @@ -126,3 +129,90 @@ footer { display: block; } } + +#print-layouts { + width: 35mm; + border: 1 thin gray; + display: flex; + flex-direction: column; +} + +.print-layout { + width: 21.0mm; + height: 29.7mm; + border-style: solid; + border-color: gray; + margin: 1.5mm; + position: relative; +} + +.print-layout:hover { + transform: scale(1.05); + transition: all .2s ease; +} + +.marker-preview { + background-color: lightslategray; + position: absolute; +} + +.selected > .marker-preview { + background-color: rgb(50, 178, 201); +} + +.printPage { + border-style: dashed; + border-width: 2px; + border-color: rgb(243, 193, 142); + height:297mm; + width: 210mm; + margin: 4px; + position: relative; +} + +#printPages{ + display: flex; + flex-direction: column; +} + +.marker-container{ + position: absolute; + border-style: dashed; + border-color: whitesmoke; + border-width: 2px; + +} + +.marker { + /* padding: 6mm; */ + /* margin: 1mm; */ +} + +.page { + display: flex; + flex-direction: column; + height: 100%; +} + +@page { + size: A4; + margin: 0; +} + +@media print { + body * { + visibility: hidden; + } + #printPages, #printPages * { + visibility: visible; + } + #printPages { + position: absolute; + left: 0; + top: 0; + } + .printPage { + border-width: 0px; + margin: 0px; + } + } \ No newline at end of file diff --git a/main.js b/main.js index 247154f..39d7f9b 100644 --- a/main.js +++ b/main.js @@ -33,13 +33,14 @@ function generateMarkerSvg(width, height, bits) { } var dict; +var layouts; function generateArucoMarker(width, height, dictName, id) { console.log('Generate ArUco marker ' + dictName + ' ' + id); var bytes = dict[dictName][id]; var bits = []; - var bitsCount = width * height; + var bitsCount = width * height; // Parse marker's bytes for (var byte of bytes) { @@ -52,13 +53,17 @@ function generateArucoMarker(width, height, dictName, id) { return generateMarkerSvg(width, height, bits); } -var loadDict = $.getJSON('dict.json', function(data) { +var loadDict = $.getJSON('dict.json', function (data) { dict = data; }); -$(function() { +var loadLayouts = $.getJSON('layouts.json', function (data) { + layouts = data; +}); + +function renderMarkers() { var dictSelect = $('.setup select[name=dict]'); - var markerIdInput = $('.setup input[name=id]'); + var markerIdInput = $('.setup textarea[name=id]'); var sizeInput = $('.setup input[name=size]'); function updateMarker() { @@ -69,19 +74,18 @@ $(function() { var height = Number(dictSelect.find('option:selected').attr('data-height')); // Wait until dict data is loaded - loadDict.then(function() { - // Generate marker - var svg = generateArucoMarker(width, height, dictName, markerId, size); - svg.attr({ - width: size + 'mm', - height: size + 'mm' - }); - $('.marker').html(svg[0].outerHTML); - $('.save-button').attr({ - href: 'data:image/svg;base64,' + btoa(svg[0].outerHTML.replace('viewbox', 'viewBox')), - download: dictName + '-' + markerId + '.svg' - }); - $('.marker-id').html('ID ' + markerId); + loadDict.then(function () { + + var markers = document.getElementsByClassName('marker'); + var markerIDs = document.getElementsByClassName('marker-id'); + + for (i = 0; i< markers.length; i++){ + markerId = markerIDs[i].getAttribute('val'); //Math.floor(Math.random() * 1000); + svg = generateArucoMarker(width, height, dictName, markerId, size); + + markers[i].innerHTML = svg[0].outerHTML; + markerIDs[i].innerHTML = 'ID ' + markerId; + } }) } @@ -89,4 +93,135 @@ $(function() { dictSelect.change(updateMarker); $('.setup input').on('input', updateMarker); + +}; + +// resize and put marker in it's parent at the defined position +function positionMarker(realMarker, realParent, jsonMarker, jsonParent){ + // var style = getComputedStyle(realParent); + var left = jsonParent.margin + jsonMarker.left/(jsonParent.width - 2* jsonParent.margin) * 21.0; //* style.width; + var top = jsonParent.margin + jsonMarker.top/(jsonParent.height - 2* jsonParent.margin) * 29.7; //* style.width; + var width = jsonMarker.size/jsonParent.width * 21.0; //* style.width; + var height = jsonMarker.size/jsonParent.width * 21.0; //* style.height; + + realMarker.setAttribute('style','width:' + width + 'mm;' + ' height:' + height + 'mm;' + ' top:' + top + 'mm;' + ' left:' + left + 'mm;' ); + realMarker.setAttribute('markerLeft',left * 10); + realMarker.setAttribute('markerTop',top * 10); + realMarker.setAttribute('markerWidth',width * 10); + realMarker.setAttribute('markerHeight',height * 10); +}; + +// read json and display available print layouts in the left panel +$(document).ready(function showPrintLayouts() { + + // Wait until layouts data is loaded + loadLayouts.then(function () { + $.each (layouts, function(i, layout){ + + // create a div element in the left panel for each print layout + var element = document.createElement("div"); + element.setAttribute('class', 'print-layout'); + element.setAttribute('id', i); + element.setAttribute('markers-per-page',Object.keys(layout.markers).length); + + element.addEventListener("click", function(){ + var coll = document.getElementsByClassName('print-layout'); + + $.each(coll, function(i, elem){elem.setAttribute('class','print-layout');}) + this.setAttribute('class', 'print-layout selected'); + + showMarkers(); + }); + + $.each(layout.markers, function(i, marker){ + var markerPreview = document.createElement("div"); + markerPreview.setAttribute('class','marker-preview'); + positionMarker(markerPreview, element, marker,layout); + + element.appendChild(markerPreview); + }); + + if (element != null) { + document.getElementById('print-layouts').appendChild(element); + } + }); + + // select default page layout + if (document.getElementById('layout1') != null) { + document.getElementById('layout1').setAttribute('class', 'print-layout selected') + showMarkers(); + } + }); + + }); + +// refresh markers +function showMarkers() { + var sizeInput = $('.setup input[name=size]'); + + // clear previous + printPages = document.getElementById('printPages'); + printPages.innerHTML=''; + + // read number of markers per page + markersPerPage = 0; + markerPositions =null; + var coll = document.getElementsByClassName('print-layout selected'); + if (coll.length == 0) return; + + markersPerPage = coll[0].getAttribute('markers-per-page'); + markerPositions = coll[0].getElementsByClassName('marker-preview'); + + + var markerIdInput = $('.setup textarea[name=id]'); + var arrIDs = markerIdInput.val().trim().split(','); + markersCount =arrIDs.length; + if (markerIdInput.val().trim() == "") markersCount = 0; + + pagesCount = 0; + + // loop list of marker ids + xMarker = -1; + for (xi = 0; xi=0 && xID <=999) { + xMarker++; + + if (xMarker % Number(markersPerPage) == 0) { + // create new page + var printPage = document.createElement('div'); + printPage.setAttribute('class','printPage'); + + printPages.appendChild(printPage); + } + + var markerContainer = document.createElement('div'); + markerContainer.setAttribute('class', 'marker-container'); + printPage.appendChild(markerContainer); + + // add marker ID + var markerID = document.createElement('div'); + markerID.setAttribute('class','marker-id'); + markerID.setAttribute('val',arrIDs[xi]); + markerContainer.appendChild(markerID); + + // add marker + var marker = document.createElement('div'); + marker.setAttribute('class','marker'); + markerContainer.appendChild(marker); + + markerContainer.setAttribute('style','left: ' + markerPositions[xMarker % Number(markersPerPage)].getAttribute('markerLeft') + 'mm; ' + + 'top: ' + markerPositions[xMarker % Number(markersPerPage)].getAttribute('markerTop') + 'mm; ' + + 'width: ' + markerPositions[xMarker % Number(markersPerPage)].getAttribute('markerWidth') + 'mm; ' + + 'height: ' + markerPositions[xMarker % Number(markersPerPage)].getAttribute('markerHeight') + 'mm; '); + + + marker.setAttribute('style','margin:' + Number(sizeInput.val()) + 'mm;') + } + } + + renderMarkers(); +}; + +//TODO save as SVG all markers