react-drawing-board
Version:
Browser drawing board created with canvas and React.
191 lines (141 loc) • 6.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.matrix_invert = matrix_invert;
exports.isMobileDevice = exports.detectMobileDevice = exports.extract_scale_from_matrix = exports.matrix_multiply = exports.mapClientToCanvas = void 0;
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function matrix_invert(M) {
// I use Guassian Elimination to calculate the inverse:
// (1) 'augment' the matrix (left) by the identity (on the right)
// (2) Turn the matrix on the left into the identity by elemetry row ops
// (3) The matrix on the right is the inverse (was the identity matrix)
// There are 3 elemtary row ops: (I combine b and c in my code)
// (a) Swap 2 rows
// (b) Multiply a row by a scalar
// (c) Add 2 rows
//if the matrix isn't square: exit (error)
if (M.length !== M[0].length) {
return;
} //create the identity matrix (I), and a copy (C) of the original
var i = 0,
ii = 0,
j = 0,
dim = M.length,
e = 0,
t = 0;
var I = [],
C = [];
for (i = 0; i < dim; i += 1) {
// Create the row
I[I.length] = [];
C[C.length] = [];
for (j = 0; j < dim; j += 1) {
//if we're on the diagonal, put a 1 (for identity)
if (i == j) {
I[i][j] = 1;
} else {
I[i][j] = 0;
} // Also, make the copy of the original
C[i][j] = M[i][j];
}
} // Perform elementary row operations
for (i = 0; i < dim; i += 1) {
// get the element e on the diagonal
e = C[i][i]; // if we have a 0 on the diagonal (we'll need to swap with a lower row)
if (e == 0) {
//look through every row below the i'th row
for (ii = i + 1; ii < dim; ii += 1) {
//if the ii'th row has a non-0 in the i'th col
if (C[ii][i] != 0) {
//it would make the diagonal have a non-0 so swap it
for (j = 0; j < dim; j++) {
e = C[i][j]; //temp store i'th row
C[i][j] = C[ii][j]; //replace i'th row by ii'th
C[ii][j] = e; //repace ii'th by temp
e = I[i][j]; //temp store i'th row
I[i][j] = I[ii][j]; //replace i'th row by ii'th
I[ii][j] = e; //repace ii'th by temp
} //don't bother checking other rows since we've swapped
break;
}
} //get the new diagonal
e = C[i][i]; //if it's still 0, not invertable (error)
if (e == 0) {
return;
}
} // Scale this row down by e (so we have a 1 on the diagonal)
for (j = 0; j < dim; j++) {
C[i][j] = C[i][j] / e; //apply to original matrix
I[i][j] = I[i][j] / e; //apply to identity
} // Subtract this row (scaled appropriately for each row) from ALL of
// the other rows so that there will be 0's in this column in the
// rows above and below this one
for (ii = 0; ii < dim; ii++) {
// Only apply to other rows (we want a 1 on the diagonal)
if (ii == i) {
continue;
} // We want to change this element to 0
e = C[ii][i]; // Subtract (the row above(or below) scaled by e) from (the
// current row) but start at the i'th column and assume all the
// stuff left of diagonal is 0 (which it should be if we made this
// algorithm correctly)
for (j = 0; j < dim; j++) {
C[ii][j] -= e * C[i][j]; //apply to original matrix
I[ii][j] -= e * I[i][j]; //apply to identity
}
}
} //we've done all operations, C should be the identity
//matrix I should be the inverse:
return I;
}
var mapClientToCanvas = function mapClientToCanvas(evt, canvas, viewMatrix) {
var _canvas$getBoundingCl = canvas.getBoundingClientRect(),
top = _canvas$getBoundingCl.top,
left = _canvas$getBoundingCl.left;
var _viewMatrix = _slicedToArray(viewMatrix, 6),
a = _viewMatrix[0],
b = _viewMatrix[1],
c = _viewMatrix[2],
d = _viewMatrix[3],
e = _viewMatrix[4],
f = _viewMatrix[5];
var x = evt.clientX - left;
var y = evt.clientY - top;
var inverse = matrix_invert([[a, c, e], [b, d, f], [0, 0, 1]]);
return [inverse[0][0] * x + inverse[0][1] * y + inverse[0][2], inverse[1][0] * x + inverse[1][1] * y + inverse[1][2]];
};
exports.mapClientToCanvas = mapClientToCanvas;
var matrix_multiply = function matrix_multiply(_ref, _ref2) {
var _ref3 = _slicedToArray(_ref, 6),
a1 = _ref3[0],
b1 = _ref3[1],
c1 = _ref3[2],
d1 = _ref3[3],
e1 = _ref3[4],
f1 = _ref3[5];
var _ref4 = _slicedToArray(_ref2, 6),
a2 = _ref4[0],
b2 = _ref4[1],
c2 = _ref4[2],
d2 = _ref4[3],
e2 = _ref4[4],
f2 = _ref4[5];
return [a1 * a2 + c1 * b2, d1 * b2 + b1 * a2, a1 * c2 + c1 * d2, b1 * c2 + d1 * d2, a1 * e2 + c1 * f2 + e1, b1 * e2 + d1 * f2 + f1];
};
exports.matrix_multiply = matrix_multiply;
var extract_scale_from_matrix = function extract_scale_from_matrix(viewMatrix) {
return viewMatrix[0];
};
exports.extract_scale_from_matrix = extract_scale_from_matrix;
var detectMobileDevice = function detectMobileDevice() {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
};
exports.detectMobileDevice = detectMobileDevice;
var isMobileDevice = detectMobileDevice();
exports.isMobileDevice = isMobileDevice;