I have a drawing interface which the drawings need to be saved at 1280x720px. However, I want the canvas to be able to be scalable in relation to that aspect ratio. A problem is that when I draw, the start of the path is not on the cursor.
I've looked everywhere and cannot find a solution. Here is the javascript:
var clearButton = document.getElementById('doodle-bin');
var canvascontainer = document.getElementById('doodle-canvas-container');
var canvas = document.getElementById('doodle-canvas');
var context = canvas.getContext('2d');
var radius = (document.getElementById('doodle-canvas-container').clientWidth + document.getElementById('doodle-canvas-container').clientHeight)/150;
var dragging = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
canvas.width = 1280;
canvas.height = 720;
canvas.style.width = '100%';
canvas.style.height = '100%';
/* CLEAR CANVAS */
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
clearButton.addEventListener('click', clearCanvas);
var putPoint = function (e) {
if (dragging) {
context.lineTo(e.offsetX, e.offsetY);
context.lineWidth = radius * 2;
context.stroke();
context.beginPath();
context.arc(e.offsetX, e.offsetY, radius, 0, Math.PI * 2);
context.fill();
context.beginPath();
context.moveTo(e.offsetX, e.offsetY);
}
};
var engage = function (e) {
dragging = true;
putPoint(e);
};
var disengage = function () {
dragging = false;
context.beginPath();
};
canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);
document.addEventListener('mouseup', disengage);
canvas.addEventListener('contextmenu', disengage);
Use the following function to get the proper mouse position even if the canvas is re-scaled. This will resolve the path start issue.
function getMouesPosition(e) {
var mouseX = e.offsetX * canvas.width / canvas.clientWidth | 0;
var mouseY = e.offsetY * canvas.height / canvas.clientHeight | 0;
return {x: mouseX, y: mouseY};
}
var clearButton = document.getElementById('doodle-bin');
var canvascontainer = document.getElementById('doodle-canvas-container');
var canvas = document.getElementById('doodle-canvas');
var context = canvas.getContext('2d');
var radius = (document.getElementById('doodle-canvas-container').clientWidth + document.getElementById('doodle-canvas-container').clientHeight) / 150;
var dragging = false;
context.mozImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
canvas.width = 1280;
canvas.height = 720;
canvas.style.width = '100%';
canvas.style.height = '100%';
/* CLEAR CANVAS */
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
clearButton.addEventListener('click', clearCanvas);
function getMouesPosition(e) {
var mouseX = e.offsetX * canvas.width / canvas.clientWidth | 0;
var mouseY = e.offsetY * canvas.height / canvas.clientHeight | 0;
return {x: mouseX, y: mouseY};
}
var putPoint = function (e) {
if (dragging) {
context.lineTo(getMouesPosition(e).x, getMouesPosition(e).y);
context.lineWidth = radius * 2;
context.stroke();
context.beginPath();
context.arc(getMouesPosition(e).x, getMouesPosition(e).y, radius, 0, Math.PI * 2);
context.fill();
context.beginPath();
context.moveTo(getMouesPosition(e).x, getMouesPosition(e).y);
}
};
var engage = function (e) {
dragging = true;
putPoint(e);
};
var disengage = function () {
dragging = false;
context.beginPath();
};
canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);
document.addEventListener('mouseup', disengage);
canvas.addEventListener('contextmenu', disengage);
body{margin:0;overflow:hidden}canvas{border:1px solid #ccc}
<button id="doodle-bin">Clear</button>
<div id="doodle-canvas-container">
<canvas id="doodle-canvas"></canvas>
</div>
Related
const canvas = document.getElementById("canvas");
canvas.width = window.innerWidth = 750;
canvas.height = 600;
var context = canvas.getContext("2d");
context.fillStyle = "white";
context.fillReact(0, 0, canvas.width, canvas.height);
let draw_color = "black";
let draw_width = "2";
let is_drawing = false;
canvas.addEventListener("touchstart", start, false);
canvas.addEventListener("touchmove", draw, false);
canvas.addEventListener("mousedown", start, false);
canvas.addEventListener("mousemove", draw, false);
function start(event) {
is_drawing = true;
context.beginPath();
context.moveTo(event.clientX = canvas.offsetLeft, event.clientY = canvas.offsetTop);
event.preventDefault();
}
function draw(event) {
if (is_drawing) {
context.beginPath();
context.moveTo(event.clientX = canvas.offsetLeft, event.clientY = canvas.offsetTop);
context.strokeStyle = draw_color;
context.lineWidth = draw_width;
context.lineCap = "round";
context.lineJoin = "round";
context.stroke();
}
}
I did everything right yet it is showing context.fillReact is not a function, it should have draw a line on moving the cursor but it is not doing anything just showing the error.
As far as I know, canvas element's context object does not have any fillReact method in it. Maybe you mean fillRect?
I have tried a few solutions on SO but they didn't work for my setup. For some reason the mouse position is off on my canvas. I have pasted my HTML and JS below for reference.
The mouse works fine when the canvas size matches the window size, but I need it to work well when it is smaller or bigger too. How can I do this?
HTML
<canvas id="canvas"></canvas>
JS
window.addEventListener('load', () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
// canvas.height = window.innerHeight;
// canvas.width = window.innerWidth;
canvas.height = 540;
canvas.width = 960;
// canvas.height = canvas.offsetHeight;
// canvas.width = canvas.offsetWidth;
let painting = false;
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
function windowSize() {
// canvas.height = window.innerHeight;
// canvas.width = window.innerWidth;
// canvas.height = 540;
// canvas.width = 960;
// canvas.height = canvas.offsetHeight;
// canvas.width = canvas.offsetWidth;
}
function startPosition(e) {
painting = true;
draw(e);
}
function finishedPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if(!painting) return;
ctx.lineWidth = lineSize;
ctx.lineCap = "round";
ctx.strokeStyle = color;
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
var lineSize = 5;
var color = "Black";
// Event Listeners
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', finishedPosition);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('touchstart', startPosition);
canvas.addEventListener('touchend', finishedPosition);
canvas.addEventListener('touchmove', draw);
// window.addEventListener('resize', windowSize);
});
The accepted solution here solved my problem. I hope this helps someone else in the future, as it did not appear high in search results.
Real mouse position in canvas
I have a canvas code to draw a signature. The code works perfectly fine with chrome and Firefox but does not draw at all on IE 11.
My canvas is:
<canvas id="signitureCanvas" style="border: 3px solid #000; cursor:crosshair; background-color:white;"></canvas>
My code is as below:
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
var canvasWidth = 200;
var canvasLength = 120;
canvas.width = canvasWidth;
canvas.height = canvasLength;
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
var tooltype = 'draw';
//Mousedown
$(canvas).on('mousedown', function (e) {
last_mousex = mousex = parseInt(e.clientX - canvasx);
last_mousey = mousey = parseInt(e.clientY - canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function (e) {
mousedown = false;
});
//Mousemove
$(canvas).on('mousemove', function (e) {
mousex = parseInt(e.clientX - canvasx);
mousey = parseInt(e.clientY - canvasy);
if (mousedown) {
ctx.beginPath();
if (tooltype == 'draw') {
ctx.globalCompositeOperation = 'source-over';
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
} else {
ctx.globalCompositeOperation = 'destination-out';
ctx.lineWidth = 10;
}
ctx.moveTo(last_mousex, last_mousey);
ctx.lineTo(mousex, mousey);
ctx.lineJoin = ctx.lineCap = 'round';
ctx.stroke();
}
last_mousex = mousex;
last_mousey = mousey;
});
function ClearCanvas() {
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
Is IE 11 in particular having problems?
Edit:
I figured out the problem is with my Iframe:
When height and width are set to 300 everything works fine:
<embed id="fred" type="application/pdf" style="border:1px solid #666CCC" title="PDF in an i-Frame" src="#Model.FilePath" frameborder="1" scrolling="yes" height="300" width="300" />
When I set it to 1000, it won't work:
<embed id="fred" type="application/pdf" style="border:1px solid #666CCC" title="PDF in an i-Frame" src="#Model.FilePath" frameborder="1" scrolling="yes" height="1000" width="1000" />
I believe it's something with the offset but I can't figure how to fix it.
any help?
For further knowledge to whom might ask:
I have found this piece of code that works on all browsers, layerX and layerY are different for firefox browsers:
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
var canvasWidth = 200;
var canvasLength = 120;
canvas.width = canvasWidth;
canvas.height = canvasLength;
var x = 0;
var y = 0;
function tool_pencil() {
var tool = this;
this.started = false;
// This is called when you start holding down the mouse button
// This starts the pencil drawing
this.mousedown = function (ev) {
ctx.beginPath();
ctx.strokeStyle = 'black';
ctx.lineWidth = 3;
ctx.lineJoin = ctx.lineCap = 'round';
ctx.moveTo(x, y);
tool.started = true;
};
// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button)
this.mousemove = function (ev) {
if (tool.started) {
ctx.lineTo(x, y);
ctx.stroke();
}
};
// This is called when you release the mouse button
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
}
};
}
// The general-purpose event handler. This function just determines
// the mouse position relative to the <canvas> element
function ev_canvas(ev) {
// Firefox
if (ev.offsetX || ev.offsetX == 0) {
x = ev.offsetX;
y = ev.offsetY;
// Opera
} else if (ev.layerX || ev.layerX == 0) {
x = ev.layerX;
y = ev.layerX;
}
// Call the event handler of the tool
var func = tool[ev.type];
if (func) {
func(ev);
}
}
function ClearCanvas() {
var canvas = document.getElementById('signitureCanvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
I am trying to clear the canvas for redrawing, it gets clear and when we try to redraw, the previous thing comes back.
Here is my code:
var drawingApp = (function () {
//declaring Variables
var canvas,
canvasDiv,
context,
canvasWidth = 200,
canvasHeight = 200,
clickX = [],
clickY = [],
clickDrag = [],
paint = false;
//Initalisation Function
function init() {
canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', canvasHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
if (typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
context = canvas.getContext("2d");
loadEvents(); //Load events
}
function loadEvents() {
//Mouse down Event
$('#canvas').mousedown(function (e) {
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
//Mouse Move Event
$('#canvas').mousemove(function (e) {
if (paint) {
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
//Mouse Up Event
$('#canvas').mouseup(function (e) {
paint = false;
});
//Mouse Leave Event
$('#canvas').mouseleave(function (e) {
paint = false;
});
}
//Add Click Function
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
//Redraw Function
function redraw() {
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for (var i = 0; i < clickX.length; i++) {
context.beginPath();
if (clickDrag[i] && i) {
context.moveTo(clickX[i - 1], clickY[i - 1]);
} else {
context.moveTo(clickX[i] - 1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
// Clears the canvas.
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
return {
init: init,
erase: clearCanvas
};
})();
$(function () {
drawingApp.init();
});
Here is my fiddle
Please see where m getting wrong
When you clear your canvas using the erase function, you fail to clear the clickX, clickY and clickDrag variables. So the next time it draws it still draws the old data.
Updated JSFiddle - http://jsfiddle.net/P8acZ/6/
The code that changed
function clearCanvas() {
clickDrag = [];
clickX = [];
clickY = [];
context.clearRect(0, 0, canvas.width, canvas.height);
}
I tried to provide an eraser as if it was a brush, to erase distinctively. I have a black rect and a picture as canvas background. How can I erase parts of the rect?
"Erasing" in html5 canvas, did not work
my fiddle: http://jsfiddle.net/FgNQk/10/
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var width = window.innerWidth;
var height = window.innerHeight;
canvas.height = height;
canvas.width = width;
ctx.fillRect(100,100,100,100);
canvas.addEventListener('mousedown', function(e) {
this.down = true;
this.X = e.pageX ;
this.Y = e.pageY ;
this.color = rgb();
}, 0);
canvas.addEventListener('mouseup', function() {
this.down = false;
}, 0);
canvas.addEventListener('mousemove', function(e) {
if(this.down) {
with(ctx) {
beginPath();
moveTo(this.X, this.Y);
lineTo(e.pageX , e.pageY );
strokeStyle = "rgba(255,255,255,0.0)";
ctx.lineWidth=1;
stroke();
}
this.X = e.pageX ;
this.Y = e.pageY ;
}
}, 0);
The solution in the link actually works. Try:
with(ctx) {
beginPath();
moveTo(this.X, this.Y);
lineTo(e.pageX , e.pageY );
globalCompositeOperation = "destination-out";
strokeStyle = "rgba(0,0,0,1)";
ctx.lineWidth=1;
stroke();
}