diff --git a/static/annotator.html b/static/annotator.html index 3e1044c..3c6444d 100644 --- a/static/annotator.html +++ b/static/annotator.html @@ -7,6 +7,13 @@ font-family: sans-serif; } + .main { + position: fixed; + width: calc(90vw - 20px); + left: calc(10vw + 20px); + right: 0px; + } + .centered { margin-left: auto; margin-right: auto; @@ -20,6 +27,13 @@ box-sizing: border-box; } + .column10 { + display: inline-block; + width: 10vw; + padding: 5px; + box-sizing: border-box; + } + .row:after { content: ""; display: table; @@ -31,23 +45,78 @@ max-height: 100%; } + .selected { + border-style: solid; + border-width: 2px; + border-color: red; + } + + .notselected { + border-style: solid; + border-width: 2px; + border-color: rgba(0, 0, 0, 0); + } + #annotations { margin-left: 20px; + height: auto; + } + + #navbar { + position: fixed; + border-right: solid; + border-width: 1px; + height: 100vh; + left: 0; + overflow-y: scroll; + width: 10%; + padding: 10px; + } + + table, th, td { + border: 1px solid black; + } + + td { + text-align: center; + padding: 5px; + } + + p { + margin: 0px; + padding: 0px; } -

Annotator

-
-
-

Previous frame (1)

- + +
+

Annotator

+
+
+

Previous frame (1)

+ + +
+
+

Current frame (2)

+ +
-
-

Current frame (2)

- -

Annotations:

-
+
+
+

Shorcuts:

+ + + + + +
+
+
+

Annotations:

+
+
diff --git a/static/main.js b/static/main.js index f433b81..a307dd1 100644 --- a/static/main.js +++ b/static/main.js @@ -3,9 +3,9 @@ function findGetParameter(parameterName) { location.search .substr(1) - .split("&") + .split('&') .forEach(function(item) { - tmp = item.split("="); + tmp = item.split('='); if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]); }); return result; @@ -22,22 +22,68 @@ const Events = [ ]; class Annotator { - constructor(root, annotations, img1Id, img2Id, annotationId) { + constructor(root, annotations) { this.root = root; this.annotations = annotations; this.maxIndex = Object.keys(this.annotations).length - 1; + let img1Id = 'img-1'; + let img2Id = 'img-2' + let annotationsId = 'annotations'; + this.img1Element = document.getElementById(img1Id); this.img1IndexElement = document.getElementById(img1Id + '-index'); this.img2Element = document.getElementById(img2Id); this.img2IndexElement = document.getElementById(img2Id + '-index'); - this.annotationElement = document.getElementById(annotationId); + this.annotationElement = document.getElementById(annotationsId); + this.navbar = document.getElementById('navbar'); + this.shortcutsIndex = document.getElementById('shortcuts-index'); + this.shortcutsValue = document.getElementById('shortcuts-value'); + this.setNavbar(); + this.setShortcutsInfo(); this.setIndex(0); this.addShortcuts(); } + setShortcutsInfo() { + for (let index = 1; index <= Events.length; index++) { + let elt = document.createElement('td'); + elt.innerHTML = index; + this.shortcutsIndex.appendChild(elt); + + elt = document.createElement('td'); + elt.innerHTML = Events[index - 1]; + this.shortcutsValue.appendChild(elt); + } + } + + setNavbar() { + for (let frame in this.annotations) { + let div = document.createElement('div'); + div.classList.add('column10'); + div.classList.add('notselected'); + div.id = 'thumbnail-' + frame; + + let img = document.createElement('img'); + img.setAttribute('src', this.root + '/' + frame + '.jpg'); + + let text = document.createElement('p'); + text.classList.add('centered'); + text.innerHTML = frame; + + div.appendChild(img); + div.appendChild(text); + + div.addEventListener('click', () => { + this.setIndex(frame); + }); + + this.navbar.appendChild(div); + } + } + formatIndex(index) { index += ''; return index.padStart(4, '0'); @@ -64,10 +110,24 @@ class Annotator { this.img2IndexElement.innerHTML = this.index + 1 + '/' + this.maxIndex; } + let formattedIndex = this.formatIndex(this.index + 1); + + // Refresh navbar + for (let key of Object.keys(this.annotations)) { + document.getElementById('thumbnail-' + key).classList.remove('selected'); + document.getElementById('thumbnail-' + key).classList.add('notselected'); + } + + let current = document.getElementById('thumbnail-' + formattedIndex); + current.classList.add('selected'); + current.classList.remove('notselected'); + current.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'center' }); + // Refresh annotations list - let currentAnnotations = this.annotations[this.formatIndex(this.index + 1)]; + let currentAnnotations = this.annotations[formattedIndex]; + if (currentAnnotations.length === 0) { - this.annotationElement.innerHTML = "There is no annotation for this frame"; + this.annotationElement.innerHTML = 'There is no annotation for this frame'; } else { this.annotationElement.innerHTML = '
    '; for (let annotation of currentAnnotations) { @@ -87,7 +147,7 @@ class Annotator { } addShortcuts() { - document.addEventListener('keyup', (e) => { + document.addEventListener('keyup', async (e) => { switch (e.code) { case 'ArrowRight': this.increment(e.ctrlKey ? 10 : 1); break; case 'ArrowLeft': this.decrement(e.ctrlKey ? 10 : 1); break; @@ -95,12 +155,12 @@ class Annotator { if (e.code.startsWith('Numpad') || e.code.startsWith('Digit')) { let key = parseInt(e.code[e.code.length - 1], 10); - this.toggle(key); + await this.toggle(key); } }); } - toggle(key) { + async toggle(key) { let event = Events[key]; if (event === undefined) { return; @@ -115,12 +175,12 @@ class Annotator { events.splice(search, 1); } + await this.sync(); this.setIndex(); - this.sync(); } - sync() { - fetch('/data', { + async sync() { + await fetch('/data', { method: 'POST', headers: { 'Accept': 'application/json', @@ -137,7 +197,7 @@ async function main() { const root = findGetParameter('root'); let annotations = await fetch(root + '/annotations.json'); annotations = await annotations.json(); - const annotator = new Annotator(root, annotations, 'img-1', 'img-2', 'annotations'); + const annotator = new Annotator(root, annotations, ); } main();