mirror of
https://github.com/Doodle3D/doodle3d-client.git
synced 2024-06-29 06:01:21 +02:00
---------------------------------------------------------------------- Merge branch 'new_layouting_approach' into feature/printerdriver * new_layouting_approach: (22 commits) changed chmod adjustments to make preview be initialized and updated better (when resizing) updates css styles changes to how the draw and preview canvasses are positioned and initted many updates CSS and LESS files and generally a responsive scaling overhaul of the settings page new LESS simple js lib for managing the folded in/out state of the sidebars on the minimal interface arrow file used in the minimal doodle3d interface the resulting css files which LESS outputs removed this because it's being rolled into the styles.css by LESS moved logos to their own dir + removed a few redundant ones copy normalize.css to the LESS dir since it's a source file smallest size of the doodle3d logo started using LESS for stylesheeting commit of current state of this branch. It's a work-in-progress (comitting because I need to change to other branch) a lot of changes -> almost there but the drawing is not consistent yet across devices. Drawing on the draw canvas is going OK but the preview is not drawing well now. Giving up for now. changes (sry) intermediary progress commented out part of the css (not final solution) added todo for future ...
478 lines
13 KiB
JavaScript
478 lines
13 KiB
JavaScript
/* * * * * * * * * *
|
|
*
|
|
* VARS
|
|
*
|
|
* * * * * * * * * */
|
|
var preview;
|
|
var previewCtx;
|
|
|
|
var svgPathRegExp = /[LM]\d* \d*/ig;
|
|
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/;
|
|
|
|
var dragging = false;
|
|
|
|
var $canvas, canvas, ctx;
|
|
var canvasWidth, canvasHeight;
|
|
|
|
var drawCanvas;
|
|
var drawCanvasTopLeftCoords = [0, 0];
|
|
|
|
var doodleBounds = [-1, -1, -1, -1]; // left, top, right, bottom
|
|
// var doodleScaleVals = [[0, 0], [1.0, 1.0]]; // [ [x, y], [scaleX, scaleY] ]
|
|
var doodleTransform = [0, 0, 1.0, 1.0]; // [ x, y, scaleX, scaleY ]
|
|
|
|
var _points = [];
|
|
|
|
var prevCountingTime = 0;
|
|
var movementCounter = 0;
|
|
|
|
var drawVariableLineWeight = false; // set to true to have the momentum of the mouse/touch movement result in larger/smaller strokes
|
|
var lineweight = 2;
|
|
|
|
/* * * * * * * * * *
|
|
*
|
|
* INIT
|
|
*
|
|
* * * * * * * * * */
|
|
function initDoodleDrawing() {
|
|
console.log("f:initDoodleDrawing()");
|
|
|
|
$canvas = $("#mycanvas");
|
|
canvas = $canvas[0];
|
|
ctx = canvas.getContext('2d');
|
|
|
|
canvasWidth = canvas.width;
|
|
canvasHeight = canvas.height;
|
|
|
|
|
|
//*
|
|
//TODO make these jquery eventhandlers (works for all)
|
|
if (!canvas.addEventListener) {
|
|
canvas.attachEvent('onmousedown',onCanvasMouseDown);
|
|
canvas.attachEvent('onmousemove',onCanvasMouseMove);
|
|
canvas.attachEvent('onmouseup',onCanvasMouseUp);
|
|
canvas.attachEvent('ontouchstart',onCanvasTouchDown);
|
|
canvas.attachEvent('ontouchmove',onCanvasTouchMove);
|
|
canvas.attachEvent('ontouchend',onCanvasTouchEnd);
|
|
document.body.attachEvent('ontouchmove',prevent);
|
|
} else {
|
|
canvas.addEventListener('mousedown',onCanvasMouseDown,false);
|
|
canvas.addEventListener('mousemove',onCanvasMouseMove,false);
|
|
canvas.addEventListener('mouseup',onCanvasMouseUp,false);
|
|
canvas.addEventListener('touchstart',onCanvasTouchDown,false);
|
|
canvas.addEventListener('touchmove',onCanvasTouchMove,false);
|
|
canvas.addEventListener('touchend',onCanvasTouchEnd,false);
|
|
}
|
|
//*/
|
|
|
|
// drawCanvas = $(".drawareacontainer");
|
|
drawCanvas = $("#mycanvasContainer"); // $("#drawAreaContainer")
|
|
|
|
console.log("drawCanvasTopLeftCoords: " + drawCanvasTopLeftCoords);
|
|
// drawCanvasTopLeftCoords[0] = drawCanvas.css("left").match(/[0-9]/g).join("");
|
|
// drawCanvasTopLeftCoords[1] = drawCanvas.css("top").match(/[0-9]/g).join("");
|
|
drawCanvasTopLeftCoords[0] = drawCanvas.offset().left;
|
|
drawCanvasTopLeftCoords[1] = drawCanvas.offset().top;
|
|
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
|
|
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
|
|
|
|
console.log("f:initDoodleDrawing() >> canvasWidth: " + canvasWidth);
|
|
console.log("f:initDoodleDrawing() >> canvasHeight: " + canvasHeight);
|
|
|
|
}
|
|
|
|
/* * * * * * * * * *
|
|
*
|
|
* CANVAS DRAWING FUNCTION
|
|
*
|
|
* * * * * * * * * */
|
|
function draw(_x, _y, _width) {
|
|
// console.log("f:draw() >> _width: " + _width);
|
|
|
|
if (prevX == 0 && prevY ==0) {
|
|
prevX = _x;
|
|
prevY = _y;
|
|
}
|
|
|
|
ctx.beginPath();
|
|
ctx.moveTo(prevX, prevY);
|
|
ctx.lineTo(_x, _y);
|
|
|
|
if (_width != undefined) {
|
|
ctx.lineWidth = _width;
|
|
} else {
|
|
if (drawVariableLineWeight) {
|
|
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
|
|
if (dist < 10) {
|
|
lineweight += .25;
|
|
} else if (dist < 20) {
|
|
lineweight += .5;
|
|
} else if (dist < 30) {
|
|
lineweight += .75;
|
|
} else if (dist < 50) {
|
|
lineweight += 1;
|
|
} else if (dist < 80) {
|
|
lineweight += 1.5;
|
|
} else if (dist < 120) {
|
|
lineweight += 2.25;
|
|
} else if (dist < 170) {
|
|
lineweight += 3.5;
|
|
} else {
|
|
lineweight += 2;
|
|
}
|
|
lineweight = Math.min(lineweight, 30);
|
|
lineweight *= 0.90;
|
|
lineweight = Math.max(lineweight, 1.0);
|
|
} else {
|
|
lineweight = 2;
|
|
}
|
|
|
|
ctx.lineWidth = lineweight;
|
|
}
|
|
ctx.lineCap = 'round';
|
|
ctx.stroke();
|
|
|
|
prevX = _x;
|
|
prevY = _y;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * *
|
|
*
|
|
* SUPPORTING FUNCTIONS
|
|
*
|
|
* * * * * * * * * */
|
|
function clearDoodle() {
|
|
console.log("f:clearDoodle");
|
|
|
|
_points = [];
|
|
|
|
prevX = 0;
|
|
prevY = 0;
|
|
|
|
updatePrevX = -1;
|
|
updatePrevY = -1;
|
|
|
|
doodleBounds = [-1, -1, -1, -1]; // left, top, right, bottom
|
|
doodleTransform = [0, 0, 1.0, 1.0]; // [ x, y, scaleX, scaleY ]
|
|
|
|
dragging = false;
|
|
|
|
clearMainView();
|
|
resetPreview();
|
|
resetVerticalShapes();
|
|
}
|
|
|
|
function redrawDoodle() {
|
|
console.log("f:redrawDoodle()");
|
|
|
|
clearMainView();
|
|
|
|
prevX = 0;
|
|
prevY = 0;
|
|
|
|
for (var i = 0; i < _points.length; i++) {
|
|
// console.log(" drawing points " + _points[i]);
|
|
if (_points[i][2] == true) {
|
|
draw(_points[i][0], _points[i][1], 0.5);
|
|
} else {
|
|
draw(_points[i][0], _points[i][1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function adjustBounds(x, y) {
|
|
var newPointsOutsideOfCurrentBounds = false;
|
|
// console.log("f:adjustBounds("+x+","+y+")");
|
|
|
|
if (doodleBounds[0] == -1) {
|
|
// if doodleBounds[0] is -1 then it isn't initted yet, so x and y are both the min and max vals
|
|
|
|
doodleBounds[0] = x;
|
|
doodleBounds[1] = y;
|
|
doodleBounds[2] = x;
|
|
doodleBounds[3] = y;
|
|
return;
|
|
}
|
|
|
|
if (x < doodleBounds[0]) {
|
|
doodleBounds[0] = x;
|
|
newPointsOutsideOfCurrentBounds = true;
|
|
}
|
|
if (x > doodleBounds[2]) {
|
|
doodleBounds[2] = x;
|
|
newPointsOutsideOfCurrentBounds = true;
|
|
}
|
|
if (y < doodleBounds[1]) {
|
|
doodleBounds[1] = y;
|
|
newPointsOutsideOfCurrentBounds = true;
|
|
}
|
|
if (y > doodleBounds[3]) {
|
|
doodleBounds[3] = y;
|
|
newPointsOutsideOfCurrentBounds = true;
|
|
}
|
|
// doodleBounds[0] = Math.min(doodleBounds[0], x); // left
|
|
// doodleBounds[2] = Math.max(doodleBounds[2], x); // right
|
|
//
|
|
// doodleBounds[1] = Math.min(doodleBounds[1], y); // top
|
|
// doodleBounds[3] = Math.max(doodleBounds[3], y); // bottom
|
|
|
|
// draw the bounding rect (DEBUG)
|
|
/*
|
|
ctx.beginPath();
|
|
ctx.rect(doodleBounds[0],doodleBounds[1], doodleBounds[2] - doodleBounds[0], doodleBounds[3] - doodleBounds[1]);
|
|
ctx.lineWidth = .2;
|
|
ctx.strokeStyle = "#333"
|
|
ctx.stroke();
|
|
ctx.closePath();
|
|
//*/
|
|
|
|
// console.log(" new bounds: " + doodleBounds);
|
|
|
|
return newPointsOutsideOfCurrentBounds;
|
|
}
|
|
|
|
// does what exactly?
|
|
function adjustPreviewTransformation() {
|
|
// console.log("f:adjustPreviewTransformation()");
|
|
|
|
// doodleTransform[0] = doodleBounds[0] - (doodleBounds[2] - doodleBounds[0]) / 2;
|
|
// doodleTransform[1] = doodleBounds[1] - (doodleBounds[3] - doodleBounds[1]) / 2;
|
|
// doodleTransform[0] = doodleBounds[0] - ((doodleBounds[2] - doodleBounds[0]) / 2);
|
|
// doodleTransform[1] = doodleBounds[1] - ((doodleBounds[3] - doodleBounds[1]) / 2);
|
|
doodleTransform[0] = doodleBounds[0];
|
|
doodleTransform[1] = doodleBounds[1];
|
|
|
|
var sclX, sclY, finalScl;
|
|
if (_points.length < 2) {
|
|
// console.log(_points);
|
|
sclX = 1.0;
|
|
sclY = 1.0;
|
|
finalScl = Math.min(sclX, sclY);
|
|
} else {
|
|
sclX = canvasWidth / (doodleBounds[2] - doodleBounds[0]);
|
|
sclY = canvasHeight / (doodleBounds[3] - doodleBounds[1]);
|
|
|
|
// TODO this shouldn't be a matter if choosing the smallest but should probably involve maintaining aspect ratio??
|
|
finalScl = Math.min(sclX, sclY);
|
|
}
|
|
|
|
doodleTransform[2] = finalScl;
|
|
doodleTransform[3] = finalScl;
|
|
}
|
|
|
|
|
|
/* * * * * * * * * *
|
|
*
|
|
* MOUSE/TOUCH EVENTHANDLERS
|
|
*
|
|
* * * * * * * * * */
|
|
function onCanvasMouseDown(e) {
|
|
// console.log("onmousedown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
|
|
// console.log("onmousedown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
|
|
// console.log("onmousedown >> e: " + e);
|
|
// console.log(e);
|
|
// console.log("f:onCanvasMouseDown()");
|
|
dragging = true;
|
|
|
|
prevCountingTime = new Date().getTime();
|
|
movementCounter = 0
|
|
|
|
// _points.push([e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, true]);
|
|
// adjustBounds(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
|
|
// adjustPreviewTransformation();
|
|
// draw(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, 0.5);
|
|
|
|
var x, y;
|
|
if (e.offsetX != undefined) {
|
|
x = e.offsetX;
|
|
y = e.offsetY;
|
|
} else {
|
|
x = e.layerX;
|
|
y = e.layerY;
|
|
}
|
|
// console.log(" x: " + x + ", y: " + y);
|
|
|
|
_points.push([x, y, true]);
|
|
adjustBounds(x, y);
|
|
adjustPreviewTransformation();
|
|
draw(x, y, 0.5);
|
|
}
|
|
|
|
var prevPoint = {x:-1, y:-1};
|
|
function onCanvasMouseMove(e) {
|
|
// console.log("f:onCanvasMouseMove()");
|
|
if (!dragging) return;
|
|
// console.log("onmousemove");
|
|
|
|
var x, y;
|
|
if (e.offsetX != undefined) {
|
|
x = e.offsetX;
|
|
y = e.offsetY;
|
|
} else {
|
|
x = e.layerX;
|
|
y = e.layerY;
|
|
}
|
|
|
|
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
|
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
|
if (dist > 5) { // replace by setting: doodle3d.simplify.minDistance
|
|
_points.push([x, y, false]);
|
|
adjustBounds(x, y)
|
|
adjustPreviewTransformation();
|
|
draw(x, y);
|
|
prevPoint.x = x;
|
|
prevPoint.y = y;
|
|
}
|
|
} else {
|
|
_points.push([x, y, false]);
|
|
adjustBounds(x, y)
|
|
adjustPreviewTransformation();
|
|
draw(x, y);
|
|
prevPoint.x = x;
|
|
prevPoint.y = y;
|
|
}
|
|
|
|
// DEBUG
|
|
// $("#textdump").text("");
|
|
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
|
|
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
|
|
|
|
if (new Date().getTime() - prevRedrawTime > redrawInterval) {
|
|
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
|
|
prevRedrawTime = new Date().getTime();
|
|
if (_points.length < 50) {
|
|
redrawPreview();
|
|
} else {
|
|
updatePreview(x, y, true);
|
|
/*
|
|
if (_points.length - prevUpdateFullPreview > prevUpdateFullPreviewInterval) {
|
|
console.log("f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview");
|
|
redrawPreview();
|
|
prevUpdateFullPreview = _points.length;
|
|
} else {
|
|
updatePreview(x, y, true);
|
|
}
|
|
//*/
|
|
// redrawPreview();
|
|
}
|
|
}
|
|
}
|
|
prevUpdateFullPreview = 0; // 0 is not a timeframe but refers to the _points array
|
|
prevUpdateFullPreviewInterval = 25; // refers to number of points, not a timeframe
|
|
|
|
function onCanvasMouseUp(e) {
|
|
// console.log("f:onCanvasMouseUp()");
|
|
// console.log("onmouseup");
|
|
dragging = false;
|
|
console.log("doodleBounds: " + doodleBounds);
|
|
console.log("doodleTransform: " + doodleTransform);
|
|
// ctx.stroke();
|
|
|
|
console.log("_points.length :" + _points.length);
|
|
// console.log(_points);
|
|
|
|
// DEBUG
|
|
// $("#textdump").text("");
|
|
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
|
|
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
|
|
|
|
// redrawPreview();
|
|
renderToImageDataPreview();
|
|
}
|
|
|
|
function onCanvasTouchDown(e) {
|
|
e.preventDefault();
|
|
console.log("f:onCanvasTouchDown >> e: " , e);
|
|
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
|
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
|
// var x = e.touches[0].pageX - drawCanvasTopLeftCoords[0];
|
|
// var y = e.touches[0].pageY - drawCanvasTopLeftCoords[1];
|
|
var x = e.touches[0].layerX;
|
|
var y = e.touches[0].layerY;
|
|
|
|
_points.push([x, y, true]);
|
|
adjustBounds(x, y);
|
|
adjustPreviewTransformation();
|
|
draw(x, y, .5);
|
|
|
|
movementCounter = 0;
|
|
|
|
prevRedrawTime = new Date().getTime();
|
|
}
|
|
|
|
function onCanvasTouchMove(e) {
|
|
e.preventDefault();
|
|
console.log("f:onCanvasTouchMove >> e: " , e);
|
|
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
|
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
|
var x = e.touches[0].pageX - drawCanvasTopLeftCoords[0];
|
|
var y = e.touches[0].pageY - drawCanvasTopLeftCoords[1];
|
|
// var x = e.touches[0].layerX;
|
|
// var y = e.touches[0].layerY;
|
|
|
|
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
|
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
|
if (dist > 5) {
|
|
_points.push([x, y, false]);
|
|
adjustBounds(x, y)
|
|
adjustPreviewTransformation();
|
|
draw(x, y);
|
|
prevPoint.x = x;
|
|
prevPoint.y = y;
|
|
}
|
|
} else {
|
|
_points.push([x, y, false]);
|
|
adjustBounds(x, y)
|
|
adjustPreviewTransformation();
|
|
draw(x, y);
|
|
prevPoint.x = x;
|
|
prevPoint.y = y;
|
|
}
|
|
|
|
// update counter -> this was for getting a handle on how often the Canvas fires a move-event
|
|
/*
|
|
movementCounter++;
|
|
if (new Date().getTime() - prevCountingTime > 1000) {
|
|
// console.log("number of moves in 1sec: " + movementCounter)
|
|
prevCountingTime= new Date().getTime();
|
|
$("#numtimes").text(movementCounter + " times");
|
|
movementCounter = 0;
|
|
}
|
|
//*/
|
|
|
|
if (new Date().getTime() - prevRedrawTime > redrawInterval) {
|
|
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
|
|
if (_points.length < 50) {
|
|
redrawPreview();
|
|
} else {
|
|
updatePreview(x, y, true);
|
|
/*
|
|
if (_points.length - prevUpdateFullPreview > prevUpdateFullPreviewInterval) {
|
|
console.log("f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview");
|
|
redrawPreview();
|
|
prevUpdateFullPreview = _points.length;
|
|
} else {
|
|
updatePreview(x, y, true);
|
|
}
|
|
//*/
|
|
}
|
|
prevRedrawTime = new Date().getTime();
|
|
}
|
|
}
|
|
|
|
function onCanvasTouchEnd(e) {
|
|
console.log("f:onCanvasTouchEnd()");
|
|
console.log("doodleBounds: " + doodleBounds);
|
|
console.log("doodleTransform: " + doodleTransform);
|
|
// ctx.stroke();
|
|
|
|
console.log("_points.length :" + _points.length);
|
|
|
|
// redrawPreview();
|
|
renderToImageDataPreview();
|
|
}
|
|
|
|
function prevent(e) {
|
|
e.preventDefault();
|
|
} |