diff --git a/coco/storage.py b/coco/storage.py index a98c94c..1208636 100644 --- a/coco/storage.py +++ b/coco/storage.py @@ -5,6 +5,7 @@ import pycocotools.coco import ast import copy import svgwrite +import uuid logger = logging.getLogger('coco.storage') @@ -81,6 +82,7 @@ class Annotation: data = self.__dict__.copy() del data['storage'] data['image'] = self.storage.getImage(data['image_id']) + data['category'] = self.storage.getCategory(self.category_id) return data def writeToDrawing(self, dwg, **pathSpecs): @@ -121,13 +123,20 @@ class Annotation: (viewbox[2], viewbox[3]), fill=bg)) if clip_image is not False: + clip_id = uuid.uuid4().hex + img = self.storage.getImage(self.image_id) rmpart = len("http://images.cocodataset.org/") href = img['coco_url'][rmpart:] if image_dir: href = os.path.join(image_dir, href) - dwg.add(dwg.image(href, insert=(0,0))) - self.writeToDrawing(dwg) + dwg.add(dwg.image(href, insert=(0,0), clip_path=f"url(#{clip_id})")) + + + clip_path = dwg.defs.add(dwg.clipPath(id=clip_id)) + self.writeToDrawing(clip_path) + else: + self.writeToDrawing(dwg) return dwg diff --git a/www/index.html b/www/index.html index 02a2b55..39df254 100644 --- a/www/index.html +++ b/www/index.html @@ -31,6 +31,14 @@ opacity:0; } + + svg .img{ + transition: stroke .2s; + } + svg .img.hide{ + opacity:0; + } + #crosshair line{ stroke: gray; stroke-dasharray: 5px 5px; diff --git a/www/js/game.js b/www/js/game.js index 832d88a..68a00b4 100644 --- a/www/js/game.js +++ b/www/js/game.js @@ -1,60 +1,107 @@ import { Flywheel } from "./effects.js"; import { getPathShapeBetweenPoints } from "./svg.js"; -export function init(svgEl, crosshairXEl, crosshairYEl) { - let flywheel = new Flywheel(); +export class Game { - // canvas position relative to mouse/screen - // TODO: update on resize: - svgEl.setAttribute('viewBox', '0 0 ' + window.innerWidth + ' ' + window.innerHeight); - let rect = svgEl.getBoundingClientRect(); + constructor(svgEl, crosshairXEl, crosshairYEl) { + this.flywheel = new Flywheel(); + this.svgEl = svgEl; - // move crosshairs - window.addEventListener('mousemove', function (mousemoveEv) { - let x = mousemoveEv.clientX - rect.left; - let y = mousemoveEv.clientY - rect.top; + // canvas position relative to mouse/screen + // TODO: update on resize: + svgEl.setAttribute('viewBox', '0 0 ' + window.innerWidth + ' ' + window.innerHeight); + this.rect = svgEl.getBoundingClientRect(); - crosshairXEl.setAttribute('x1', x) - crosshairXEl.setAttribute('x2', x) - crosshairYEl.setAttribute('y1', y) - crosshairYEl.setAttribute('y2', y) - }); + // move crosshairs + window.addEventListener('mousemove', function (mousemoveEv) { + let x = mousemoveEv.clientX - this.rect.left; + let y = mousemoveEv.clientY - this.rect.top; - svgEl.addEventListener('mousedown', function (mousedownEv) { - // create shape to draw - let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - shapeEl.classList.add('rect'); - let p1 = { 'x': mousedownEv.clientX - rect.left, 'y': mousedownEv.clientY - rect.top } - let corners = flywheel.effects.shape.getAngles(); - let d = getPathShapeBetweenPoints(p1, p1, corners); - svgEl.appendChild(shapeEl); - shapeEl.setAttribute('d', d); + crosshairXEl.setAttribute('x1', x) + crosshairXEl.setAttribute('x2', x) + crosshairYEl.setAttribute('y1', y) + crosshairYEl.setAttribute('y2', y) + }.bind(this)); + this.loadAnnotation(); + } - let mouseMoveEv = function (mousemoveEv) { - let p2 = { 'x': mousemoveEv.clientX - rect.left, 'y': mousemoveEv.clientY - rect.top } - let d = getPathShapeBetweenPoints(p1, p2, corners); + loadAnnotation() { + let json_request = new Request('/annotation.json'); + + fetch(json_request).then(function (response) { + return response.json(); + }).then((annotation) => { + let svg_request = new Request('/annotation.svg?id='+annotation.id); + + fetch(svg_request).then(function (response) { + return response.text() + }).then((text) => { + this.addAnnotation(annotation, text); + }) + }).catch((e) => console.error(e)); + } + + addAnnotation(annotation, svgText) { + + //determine position + const maxX = this.rect.width - annotation.bbox[2]; + const maxY = this.rect.height - annotation.bbox[3]; + const posX = Math.random() * maxX; + const posY = Math.random() * maxY; + + let imgEl = document.createElementNS('http://www.w3.org/2000/svg', 'g'); + imgEl.innerHTML = svgText; + imgEl.classList.add('img'); + imgEl.setAttribute('transform', `translate(${posX} ${posY})`); + this.svgEl.appendChild(imgEl); + + let startTrace = function (mousedownEv) { + // create shape to draw + let shapeEl = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + shapeEl.classList.add('rect'); + let p1 = { 'x': mousedownEv.clientX - this.rect.left, 'y': mousedownEv.clientY - this.rect.top } + let corners = this.flywheel.effects.shape.getAngles(); + let d = getPathShapeBetweenPoints(p1, p1, corners); + this.svgEl.appendChild(shapeEl); shapeEl.setAttribute('d', d); - }; - let mouseUpEv = function () { - console.log('up'); - window.removeEventListener('mousemove', mouseMoveEv); // remove itself. - window.removeEventListener('mouseup', mouseUpEv); // remove itself. - shapeEl.classList.add('locked'); - //TODO: calculate points - flywheel.add(); - // fade out - setTimeout(function () { - shapeEl.classList.add('hide'); - // remove shape + let mouseMoveEv = function (mousemoveEv) { + let p2 = { 'x': mousemoveEv.clientX - this.rect.left, 'y': mousemoveEv.clientY - this.rect.top } + let d = getPathShapeBetweenPoints(p1, p2, corners); + shapeEl.setAttribute('d', d); + }.bind(this); + let mouseUpEv = function () { + console.log('up'); + window.removeEventListener('mousemove', mouseMoveEv); // remove itself. + window.removeEventListener('mouseup', mouseUpEv); // remove itself. + this.svgEl.removeEventListener('mousedown', startTrace); // remove itself. + shapeEl.classList.add('locked'); + //TODO: calculate points + this.flywheel.add(); + this.loadAnnotation(); + + // fade out box setTimeout(function () { - shapeEl.parentNode.removeChild(shapeEl); + shapeEl.classList.add('hide'); + // remove shape + setTimeout(function () { + shapeEl.parentNode.removeChild(shapeEl); + }, 1000); }, 1000); - }, 1000); - }; - window.addEventListener('mousemove', mouseMoveEv); - window.addEventListener('mouseup', mouseUpEv); - }) + // fade out img + setTimeout(function () { + imgEl.classList.add('hide'); + // remove shape + setTimeout(function () { + imgEl.parentNode.removeChild(imgEl); + }, 500); + }, 500); + }.bind(this); + window.addEventListener('mousemove', mouseMoveEv); + window.addEventListener('mouseup', mouseUpEv); + }.bind(this); - return this; + this.svgEl.addEventListener('mousedown', startTrace) + + } } \ No newline at end of file diff --git a/www/js/main.js b/www/js/main.js index 07fe509..f0ad13d 100644 --- a/www/js/main.js +++ b/www/js/main.js @@ -1,9 +1,9 @@ -import { init } from "./game.js"; +import { Game } from "./game.js"; let svgEl = document.getElementById('canvas'); let crosshairXEl = document.getElementById('crosshair_x'); let crosshairYEl = document.getElementById('crosshair_y'); -var game = init(svgEl, crosshairXEl, crosshairYEl); +var game = new Game(svgEl, crosshairXEl, crosshairYEl); console.log('Initialised game', game); \ No newline at end of file