handwritten-mathematics-recogniser
Version:
Easy and abstracted way to recognise handwritten mathematics in a browser or in a web view.
121 lines (119 loc) • 4.82 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const mouse_1 = require("./mouse");
class Drawer {
constructor(selector, width, height) {
if (typeof selector === 'string') {
const elements = document.querySelectorAll(selector);
if (!document) {
throw new Error('No DOM found.');
}
if (elements.length === 0) {
throw new Error(`No HTMLElement found with selector ${selector}.`);
}
else if (elements.length > 1) {
throw new Error('Selector must explicitly identify a single canvas.');
}
this.feedbackCanvas = elements[0];
this.feedbackContext = this.feedbackCanvas.getContext('2d');
}
else {
this.feedbackCanvas = selector;
this.feedbackContext = this.feedbackCanvas.getContext('2d');
}
if (width) {
this.feedbackCanvas.width = width;
}
if (height) {
this.feedbackCanvas.height = height;
}
this.feedbackCanvas.style.cursor = 'crosshair';
this.mouse = new mouse_1.Mouse();
this.addListeners();
this.feedbackContext.globalCompositeOperation = 'source-over';
this.feedbackContext.globalAlpha = 1;
this.feedbackContext.strokeStyle = 'rgba(0,0,0,1)';
this.feedbackContext.lineCap = 'round';
this.feedbackContext.lineJoin = 'round';
this.feedbackContext.lineWidth = 4;
}
clear() {
const width = this.feedbackCanvas.width;
const height = this.feedbackCanvas.height;
this.feedbackContext.clearRect(-10, -10, width + 20, height + 20);
}
mouseDown(mousePosition) {
mousePosition.preventDefault();
this.mouseMove(mousePosition);
this.mouse.px = this.mouse.x;
this.mouse.py = this.mouse.y;
this.mouse.down = true;
this.feedbackContext.beginPath();
this.feedbackContext.moveTo(this.mouse.px, this.mouse.py);
}
mouseMove(e) {
e.preventDefault();
const rect = this.feedbackCanvas.getBoundingClientRect();
const position = e.changedTouches && e.changedTouches[0] || e;
let x = position.offsetX;
let y = position.offsetY;
if (typeof x === 'undefined') {
x = position.clientX
+ document.documentElement.scrollLeft
- rect.left;
}
if (typeof y === 'undefined') {
y = position.clientY
+ document.documentElement.scrollTop
- rect.top;
}
if (this.mouse.down) {
this.draw(x, y);
}
else {
this.mouse.x = x;
this.mouse.y = y;
}
}
mouseUp() {
this.mouse.down = false;
this.feedbackContext.closePath();
}
lineDistance(x1, y1, x2, y2) {
const xs = Math.pow(x2 - x1, 2);
const ys = Math.pow(y2 - y1, 2);
return Math.sqrt(xs + ys);
}
draw(mX, mY) {
const mouse = this.mouse;
const rawDist = this.lineDistance(mX, mY, mouse.px, mouse.py);
const smoothingFactor = Math.min(0.87, 0.85 + (rawDist - 60) / 3000);
mouse.x = mX - (mX - mouse.px) * smoothingFactor;
mouse.y = mY - (mY - mouse.py) * smoothingFactor;
this.feedbackContext.quadraticCurveTo(mouse.px, mouse.py, mouse.x, mouse.y);
this.feedbackContext.stroke();
mouse.px = mouse.x;
mouse.py = mouse.y;
}
addListeners() {
this.feedbackCanvas.style.msTouchAction = 'none';
this.feedbackCanvas.style.touchAction = 'none';
this.feedbackCanvas.addEventListener('mousedown', this.mouseDown.bind(this));
this.feedbackCanvas.addEventListener('touchstart', this.mouseDown.bind(this));
this.feedbackCanvas.addEventListener('mousemove', this.mouseMove.bind(this));
this.feedbackCanvas.addEventListener('touchmove', this.mouseMove.bind(this));
document.addEventListener('mouseup', this.mouseUp.bind(this));
this.feedbackCanvas.addEventListener('touchend', this.mouseUp.bind(this));
}
removeListeners() {
this.clear();
this.feedbackCanvas.addEventListener('mousedown', this.mouseDown.bind(this));
this.feedbackCanvas.addEventListener('touchstart', this.mouseDown.bind(this));
this.feedbackCanvas.addEventListener('mousemove', this.mouseMove.bind(this));
this.feedbackCanvas.addEventListener('touchmove', this.mouseMove.bind(this));
document.addEventListener('mouseup', this.mouseUp.bind(this));
this.feedbackCanvas.addEventListener('touchend', this.mouseUp.bind(this));
}
}
exports.Drawer = Drawer;
//# sourceMappingURL=drawer.js.map