in web/src/drawing.js [1:195]
(function() {
var LABEL_SIZE = 20;
var UPSAMPLE = 2;
var LINE_WIDTH = 0.05;
var CENTERED_PAD = 0.9;
function DrawingCell(size) {
this.onChange = function() {};
this.size = size;
this.element = document.createElement('div');
this.element.className = 'few-shot-cell';
this._canvas = document.createElement('canvas');
this._canvas.className = 'few-shot-cell-canvas';
this._canvas.width = size * UPSAMPLE;
this._canvas.height = size * UPSAMPLE;
this.element.appendChild(this._canvas);
this._emptyLabel = document.createElement('label');
this._emptyLabel.className = 'few-shot-cell-empty-label';
this._emptyLabel.textContent = 'Draw Here';
this.element.appendChild(this._emptyLabel);
this._paths = [];
this._redraw();
this._enabled = false;
}
DrawingCell.prototype.enableInteraction = function() {
if (!this._enabled) {
this._enabled = true;
this._registerMouse();
if ('ontouchstart' in document.documentElement) {
this._registerTouch();
}
}
};
DrawingCell.prototype.setPaths = function(paths) {
this._paths = paths;
this._redraw();
};
DrawingCell.prototype.empty = function() {
return this._paths.length === 0;
};
DrawingCell.prototype.clear = function() {
this.setPaths([]);
};
DrawingCell.prototype.tensor = function(size) {
var canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
var ctx = canvas.getContext('2d');
ctx.strokeStyle = 'black';
ctx.lineWidth = LINE_WIDTH * size;
ctx.lineCap = 'square';
ctx.lineJoin = 'square';
drawPaths(ctx, size, this._centeredPaths());
var data = ctx.getImageData(0, 0, size, size).data;
var grayscale = [];
for (var i = 3; i < data.length; i += 4) {
if (data[i] > 128) {
grayscale.push(0);
} else {
grayscale.push(1);
}
}
return new jsnet.Tensor([size, size, 1], grayscale);
};
DrawingCell.prototype._redraw = function() {
if (this._paths.length === 0) {
this._emptyLabel.style.display = 'block';
} else {
this._emptyLabel.style.display = 'none';
}
var ctx = this._canvas.getContext('2d');
var size = this.size * UPSAMPLE;
ctx.clearRect(0, 0, size, size);
ctx.strokeStyle = '#777';
ctx.lineWidth = LINE_WIDTH * size;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
drawPaths(ctx, size, this._paths);
};
DrawingCell.prototype._registerMouse = function() {
this._canvas.addEventListener('mousedown', function(e) {
var mouseUp = function() {
this.onChange();
removeEvents();
}.bind(this);
var mouseMove = function(e) {
this._paths[this._paths.length - 1].push(this._mousePosition(e));
this._redraw();
}.bind(this);
var removeEvents = function() {
window.removeEventListener('mouseup', mouseUp);
window.removeEventListener('mousemove', mouseMove);
};
window.addEventListener('mouseup', mouseUp);
window.addEventListener('mouseleave', mouseUp);
window.addEventListener('mousemove', mouseMove);
this._paths.push([this._mousePosition(e)]);
this._redraw();
}.bind(this));
};
DrawingCell.prototype._registerTouch = function() {
this._canvas.addEventListener('touchstart', function(e) {
e.preventDefault();
this._paths.push([this._touchPosition(e)]);
}.bind(this));
this._canvas.addEventListener('touchmove', function(e) {
e.preventDefault();
this._paths[this._paths.length - 1].push(this._touchPosition(e));
this._redraw();
}.bind(this));
var onEnd = function() {
this.onChange();
}.bind(this);
this._canvas.addEventListener('touchend', onEnd);
this._canvas.addEventListener('touchcancel', onEnd);
};
DrawingCell.prototype._mousePosition = function(e) {
var rect = this._canvas.getBoundingClientRect();
return [(e.clientX - rect.left) / this._canvas.offsetWidth,
(e.clientY - rect.top) / this._canvas.offsetHeight];
};
DrawingCell.prototype._touchPosition = function(e) {
var rect = this._canvas.getBoundingClientRect();
var touch = e.changedTouches[0];
return [(touch.clientX - rect.left) / this._canvas.offsetWidth,
(touch.clientY - rect.top) / this._canvas.offsetHeight];
};
DrawingCell.prototype._centeredPaths = function() {
var minX = Infinity, maxX = -Infinity;
var minY = Infinity, maxY = -Infinity;
for (var i = 0; i < this._paths.length; ++i) {
var path = this._paths[i];
for (var j = 0; j < path.length; ++j) {
var point = path[j];
minX = Math.min(minX, point[0]);
maxX = Math.max(maxX, point[0]);
minY = Math.min(minY, point[1]);
maxY = Math.max(maxY, point[1]);
}
}
var sideLength = Math.max(maxX-minX, maxY-minY) * (1 + CENTERED_PAD);
var topX = (maxX+minX)/2 - sideLength/2;
var topY = (maxY+minY)/2 - sideLength/2;
var result = [];
for (var i = 0; i < this._paths.length; ++i) {
var path = this._paths[i];
var newPath = [];
for (var j = 0; j < path.length; ++j) {
var point = path[j];
newPath.push([(point[0] - topX) / sideLength, (point[1] - topY) / sideLength]);
}
result.push(newPath);
}
return result;
};
function drawPaths(ctx, size, paths) {
for (var i = 0; i < paths.length; ++i) {
var path = paths[i];
if (path.length < 2) {
path = [path[0], [path[0][0] + 0.001, path[0][1] + 0.001]];
}
ctx.beginPath();
ctx.moveTo(path[0][0] * size, path[0][1] * size);
for (var j = 1; j < path.length; ++j) {
ctx.lineTo(path[j][0] * size, path[j][1] * size);
}
ctx.stroke();
}
}
window.DrawingCell = DrawingCell;
})();