coco/www/coco.js

235 lines
6.3 KiB
JavaScript

//////////////////////////
// use texture.js without d3 to create discerning patterns on the email blocks
/////////////////////////////////////
// some faked dom, see https://github.com/riccardoscalco/textures/issues/17
function dom(name) {
this.name = name;
this.els = [];
this.attrs = {};
}
dom.prototype.append = function(name) {
if (name === "defs") return this;
if (this.name === undefined) {
this.name = name;
return this;
}
var el = new dom(name);
this.els.push(el);
return el;
}
dom.prototype.attr = function(key, value) {
this.attrs[key] = value;
return this;
}
dom.prototype.toString = function() {
var attrs = [];
var k;
for (k in this.attrs) {
attrs += " " + k + "='" + this.attrs[k] + "'";
}
if (this.els.length) {
return "<"+this.name+attrs+">"+this.els.map(function(el) { return el.toString()}).join('\n')+"</"+this.name+">";
} else {
return "<"+this.name+attrs+"/>"
}
}
//////////// end of faked dom ///////////////////////////////
let categoryMap = {};
let textureMap = {};
function getColoredTexture(i, color) {
let j = i % 11; // update when adding items to switch:
switch(j) {
case 0:
return textures.lines().size(4).strokeWidth(1).stroke(color);
case 1:
return textures.circles().radius(2).size(5).fill('none').strokeWidth(1).stroke(color).complement();
case 2:
return textures.lines().size(10).orientation("3/8").stroke(color);
case 3:
return textures.lines().heavier(4).thinner(.8).stroke(color);
case 4:
return textures.paths().d("hexagons").size(3).strokeWidth(1).stroke(color);
case 5:
return textures.lines().orientation("vertical", "horizontal").size(4).strokeWidth(1).shapeRendering("crispEdges").stroke(color);
case 6:
return textures.paths().d("hexagons").size(5).strokeWidth(2).stroke("rgba(0,0,0,0)").fill(color);
case 7:
return textures.circles().size(4).stroke(color);
case 8:
return textures.circles().thicker().complement().stroke(color);
case 9:
return textures.paths().d("caps").lighter().thicker().size(5).stroke(color);
case 10:
return textures.paths().d("hexagons").size(4).strokeWidth(2).stroke(color);
// textures.lines().size(4).strokeWidth(1).orientation("-3/8"),
}
};
const categoryColors = {
"person": "#f00",
"vehicle": "#0f0",
"outdoor": "#006",
"animal": "#ff0",
"food": "#0ff",
"furniture": "#f0f",
"indoor": "#fff",
"electronic": "#390",
"kitchen": "#930",
"accessory": "#f90",
"sports": "#f09",
}
function getColorForSuperCategory(name) {
return categoryColors[name];
}
function getTextureForCategory(id) {
let hash = id;
if(!textureMap.hasOwnProperty(hash)) {
let color = categoryColors[categoryMap[id]['supercategory']];
textureMap[hash] = getColoredTexture(id, color);
}
return textureMap[hash];
}
class CocoCanvas {
start(){
this.catNavEl = document.getElementById('catNav');
this.canvas = document.getElementById('svgCanvas');
this.loadNav()
}
loadNav() {
let r = new Request('/categories.json');
fetch(r)
.then(response => response.json())
.then(categories => {
for(let cat of categories) {
categoryMap[cat['id']] = cat;
}
this.buildNav(categories);
}).catch(function(e){
console.error(e);
});
}
buildNav(categories) {
let ulEl = crel('ul');
for(let cat of categories) {
ulEl.appendChild(
crel('li', {
'id': 'category-' + cat['id'],
'on': {
'click': (e) => {
this.requestAnnotation(cat['id']);
}
}
}, cat['name'])
);
}
this.catNavEl.appendChild(ulEl);
let defsEl = document.createElementNS("http://www.w3.org/2000/svg", 'defs');
for(let cat of categories) {
let texture = getTextureForCategory(cat['id']);
let sel = new dom();
texture(sel);
defsEl.innerHTML += sel.toString();
}
this.canvas.appendChild(defsEl);
}
requestAnnotation(category_id) {
let r = new Request(`/annotation.json?category=${category_id}&normalise=100`);
fetch(r)
.then(response => response.json())
.then(annotation => {
this.addAnnotationAsShape(annotation);
}).catch(function(e){
console.error(e);
});;
}
pointsToD(points) {
let start = points.shift()
let d = `M${start[0].toPrecision(4)} ${start[1].toPrecision(4)} L `;
points = points.map((p) => `${p[0].toPrecision(4)} ${p[1].toPrecision(4)}`);
d += points.join(' ');
return d;
}
getMousePosition(evt) {
// from http://www.petercollingridge.co.uk/tutorials/svg/interactive/dragging/
let CTM = this.canvas.getScreenCTM();
return {
x: (evt.clientX - CTM.e) / CTM.a,
y: (evt.clientY - CTM.f) / CTM.d
};
}
addAnnotationAsShape(annotation) {
console.log('Add annotation', annotation);
let category = categoryMap[annotation['category_id']]
let texture = getTextureForCategory(category['id']);
let x = 500 - annotation['bbox'][2]/2;
let y = 500 - annotation['bbox'][3]/2;
let annEl = crel(document.createElementNS("http://www.w3.org/2000/svg", 'g'), {
'data-id': annotation['id'],
'transform': `translate(${x}, ${y})`,
'on': {
'mousedown': function(downE) {
console.log(downE);
console.log(this)
let offset = this.getMousePosition(downE);
// offset.x -= parseFloat(downE.target.getAttributeNS(null, "x"));
// offset.y -= parseFloat(downE.target.getAttributeNS(null, "y"));
// Get initial translation amount
console.log(annEl.transform.baseVal);
let transform = annEl.transform.baseVal.getItem(0);
offset.x -= transform.matrix.e;
offset.y -= transform.matrix.f;
let moveEvent = (moveE) => {
let coord = this.getMousePosition(moveE);
transform.matrix.e = coord.x - offset.x;
transform.matrix.f = coord.y - offset.y;
// annEl.setAttributeNS(null, "x", coord.x - offset.x);
// annEl.setAttributeNS(null, "y", coord.y - offset.y);
};
document.addEventListener('mousemove', moveEvent);
document.addEventListener('mouseup', (upE) => {
document.removeEventListener('mousemove', moveEvent);
});
}.bind(this)
}
});
for(let segment of annotation['segments']) {
let pathEl = crel(document.createElementNS("http://www.w3.org/2000/svg", 'path'), {
'fill': texture.url(),
'd': this.pointsToD(segment)
});
annEl.appendChild(pathEl);
}
console.log(annEl);
this.canvas.appendChild(annEl);
}
}
let cc = new CocoCanvas();
cc.start();