how's it going?
Recently, with the help given from this site, I've learned how to draw a rectangle on an HTML5 canvas at the click of the button... that's not the problem:) The is problem this... unfortunately, every time I click on the canvas to make a new rectangle, the old rectangle disappears (or is instantly erased). It also didn't work at all when I tried to use it on my iPod... why:(?
Here's my code:
JAVASCRIPT:
// "Rectangle" Button
function rect()
{
var canvas = document.getElementById('canvasSignature'),
ctx = canvas.getContext('2d'),
rect = {},
drag = false;
function init() {
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() {
drag = false;
}
function mouseMove(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY ;
ctx.clearRect(0,0,canvas.width,canvas.height);
draw();
}
}
function draw() {
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
}
init();
}
HTML5:
<div id="canvasDiv">
<canvas id="canvasSignature" width="580px" height="788px" style="border:2px solid #000; background: #FFF;"></canvas>
</div>
<div id="rect">
<p><button onclick="rect();">Rectangle</button></p>
</div>
Any help at all would be greatly appreciated:)
You have a statement to clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
Related
I am using this simple script to enable users to enter their signatures. Unfortunately, this does not work on mobile devices.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var container = document.getElementById('container');
var container_style = getComputedStyle(container);
canvas.width = 400;
canvas.height = 300;
var mouse = {x: 0, y: 0};
canvas.addEventListener('mousemove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = "black";
function getSize(size){ctx.lineWidth = size;}
canvas.addEventListener('mousedown', function(e) {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
#canvas {
border: 1px solid rgba(0,0,0,.5);
}
<div id="container">
<canvas id="canvas"></canvas>
</div>
Is there an easy way to add touch support to this script?
Make these changes to your code:
Use pointer events (instead of mouse events): pointerdown, pointerup, and pointermove. Pointer events work for both mouse and touch interactions.
Add touch-action: none to your canvas CSS. This prevents the dragging of your finger from triggering the device's panning action (which stops your drawing).
Set your "mouse" coordinates upon pointerdown. This will stop previous lines from being connected to new ones.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var container = document.getElementById('container');
canvas.width = 400;
canvas.height = 300;
var mouse = {x: 0, y: 0};
canvas.addEventListener('pointermove', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('pointerdown', function(e) {
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('pointermove', onPaint, false);
}, false);
canvas.addEventListener('pointerup', function() {
canvas.removeEventListener('pointermove', onPaint, false);
}, false);
var onPaint = function() {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
#canvas {
border: 1px solid rgba(0,0,0,.5);
touch-action: none;
}
<div id="container">
<canvas id="canvas"></canvas>
</div>
I have code which draws a line as I move my mouse while clicking the mouse (mousedown event and mousemove event).
I also want a straight line to be drawn from the beginning of the point (where I first clicked the point, mousedown event) to the end (where I lift the mouse event, mouseup event).
(function() {
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {
x: 0,
y: 0
};
var last_mouse = {
x: 0,
y: 0
};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.closePath();
ctx.stroke();
};
}());
#sketch{
width: 100%;
height: 200px;
background-color: #CCCCCC;
}
<div id="sketch">
<canvas id="paint">
</canvas>
</div>
You want to store the coordinates of the mouseDown event and then use them to draw a single line to the coordinates of the mouseUp event. I modified your code to show a way that can be done:
(function() {
var canvas = document.querySelector('#paint');
var ctx = canvas.getContext('2d');
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var mouse = {
x: 0,
y: 0
};
var last_mouse = {
x: 0,
y: 0
};
/* Mouse Capturing Work */
canvas.addEventListener('mousemove', function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
}, false);
/* Drawing on Paint App */
ctx.lineWidth = 5;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', function(e) {
initialPoint = {x:mouse.x, y:mouse.y}
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', function() {
drawStraightLine()
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function() {
ctx.beginPath();
ctx.moveTo(last_mouse.x, last_mouse.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.strokeStyle = "#000000";
ctx.closePath();
ctx.stroke();
};
let initialPoint
const drawStraightLine = function() {
ctx.beginPath();
ctx.moveTo(initialPoint.x, initialPoint.y);
ctx.lineTo(mouse.x, mouse.y);
ctx.strokeStyle = "#FF000077";
ctx.stroke();
}
}());
#sketch{
width: 100%;
height: 180px;
background-color: #DDDDDD;
}
<div id="sketch">
<canvas id="paint" />
</div>
initialPoint is the mouse position when the button is pressed and drawStarightLine() is the method executed when said button is released. Also added different colors to the lines to make it obvious.
Just add another position object eg
const mouseDownAt = {x: 0, y: 0};
Then when the mouse down event happens record that position
canvas.addEventListener('mousedown', function(e) {
mouseDownAt.x = e.pageX - this.offsetLeft;
mouseDownAt.y = e.pageY - this.offsetTop;
canvas.addEventListener('mousemove', onPaint, false);
}, false);
On the mouse up event draw the closing line
canvas.addEventListener('mouseup', function() {
lastMouse.x = mouse.x;
lastMouse.y = mouse.y;
mouse.x = e.pageX - this.offsetLeft;
mouse.y = e.pageY - this.offsetTop;
// if mouse has moved?? draw the last little bit
if (mouse.x !== last_mouse.x || mouse.y !== last_mouse.y) {
onPaint();
}
// set the end position
lastMouse.x = mouse.x;
lastMouse.y = mouse.y;
// use the mouse down at pos as the new position
mouse.x = mouseDownAt.x;
mouse.y = mouseDownAt.y;
// draw the line
onPaint();
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
BTW I am not sure if you know that using closePath as you do will render the path segment twice and will reduce the quality of the line (too strong alphas on the anti aliasing) . closePath is like lineTo (draws a line segment) and not related to ctx.beginPath
function onPaint () {
ctx.beginPath();
ctx.lineTo(lastMouse.x, lastMouse.y); // after beginPath lineTo is the same
// moveTo
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
};
I'm trying to blur a part of the photo. My code is as follows:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var imageObj = null;
function init() {
imageObj = new Image();
imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() { drag = false; }
function mouseMove(e) {
if (drag) {
ctx.clearRect(0, 0, 500, 500);
ctx.drawImage(imageObj, 0, 0);
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'blue';
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
ctx.filter = 'blur(5px)';
}
}
//
init();
<canvas id="canvas" width="500" height="500"></canvas>
I draw a rectangle but I want to apply the blur filter only on that rectangle not to the whole image as it is now. Any idea how to do that?
Here is the fiddle
It is possible by using HTML5 Canvas
I have made a fiddle to blur the part 350 from image.
Fiddle Link: https://jsfiddle.net/k6aaqdx6/3/
Edit:
updated according to your fiddle: https://jsfiddle.net/tbjLk6eu/2
Code that I added:
imgData=ctx.getImageData(rect.startX, rect.startY, rect.w, rect.h);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.filter = 'none';
ctx.drawImage(imageObj, 0, 0);
ctx.putImageData(imgData,rw, rh);
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
working jsfiddle: https://jsfiddle.net/zoh5o9p5/
If you use a base64 image and do some changes it will work as you expected
made some changes in mouseMove function.
function mouseMove(e) {
if (drag) {
ctx.filter = 'blur(5px)';
ctx.drawImage(imageObj, 0, 0);
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'blue';
if(rect.w>0 && rect.h>0)
{
imgDrow=ctx.getImageData(rect.startX, rect.startY, rect.w, rect.h);
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.filter = 'none';
ctx.drawImage(imageObj, 0, 0);
w=rect.w<0?rect.startX+rect.w:rect.startX;
h=rect.h<0?rect.startY+rect.h:rect.startY;
if(imgDrow)
{
ctx.putImageData(imgDrow,w, h);
}
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
working jsfiddle: https://jsfiddle.net/zoh5o9p5/
we can use fabric.js library. Here you can draw a rectangle and move it and resize it. The original fiddle was having some console error and scaling was not working. I have resolved them all in the bellow jsfiddle.
Here we first copy the original image and create a copy canvas and make the full image blur. Then on move or scaling of the rectangle just showing actual crop to show the proper blur section.
function blurSelection(left=0, top=0, img=null) {
if (img) {
img.cropX = left;
img.cropY = top;
fabricCanvas.renderAll();
} else {
const image = fabric.Image.fromURL(blurredCanvas.toDataURL(), function (img) {
img.cropX = left;
img.cropY = top;
img.width = 200; // Default
img.height = 100; // Default
img.objectCaching = false;
fabricCanvas.add(img);
img.bringToFront();
img.on('moving', function (options) {
const newLeft = options.target.left;
const newTop = options.target.top;
blurSelection(newLeft, newTop, img=options.target);
});
img.on('scaling', function (options) {
const newLeft = options.target.left;
const newTop = options.target.top;
const newWidth = options.target.width * options.target.scaleX;
const newHeight = options.target.height * options.target.scaleY;
//console.log("scaleX",options.target.scaleX,'scaleY',options.target.scaleX,"newWidth",newWidth,"newHeight",newHeight)
options.target.scaleX=1;
options.target.scaleY=1;
options.target.width=newWidth;
options.target.height=newHeight;
})
});
}
}
function copyCanvas() {
const objects = fabricCanvas.getObjects();
const copiedCanvas = fabricCanvas.toCanvasElement();
const blurredImage = new fabric.Image(copiedCanvas);
const filter = new fabric.Image.filters.Blur({
blur: 0.8
});
blurredImage.filters.push(filter);
blurredImage.applyFilters();
blurredCanvas = new fabric.Canvas(copiedCanvas);
window.blurredCanvas = blurredCanvas;
blurredCanvas.add(blurredImage);
blurredCanvas.renderAll();
// Just for the inspection of the blurred image
document.getElementById('asd').src = copiedCanvas.toDataURL();
}
https://jsfiddle.net/debchy/ajbpefk4/7/
I am trying to get a signatur pad to work.
I managed to make it work with the mouse no issue with a piece of code I found here: http://demos.ijasoneverett.com/html5-sigpad.php
However it does not seem to work on mobile devices, I do not understand why since I have added the event listeners
canvas.addEventListener("touchstart", mouseDown, false);
canvas.addEventListener("touchmove", mouseXY, true);
canvas.addEventListener("touchend", mouseUp, false);
Here is my all jQuery:
$(document).ready(function () {
//User Variables
var canvas = document.getElementById('canvas'); //canvas element
var context = canvas.getContext("2d"); //context element
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
document.body.addEventListener("mouseup", mouseUp, false);
//For mobile
canvas.addEventListener("touchstart", mouseDown, false);
canvas.addEventListener("touchmove", mouseXY, true);
canvas.addEventListener("touchend", mouseUp, false);
document.body.addEventListener("touchcancel", mouseUp, false);
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height); // Clears the canvas
context.strokeStyle = "#000000"; //set the "ink" color
context.lineJoin = "miter"; //line join
context.lineWidth = 2; //"ink" width
for (var i = 0; i < clickX.length; i++) {
context.beginPath(); //create a path
if (clickDrag[i] && i) {
context.moveTo(clickX[i - 1], clickY[i - 1]); //move to
} else {
context.moveTo(clickX[i] - 1, clickY[i]); //move to
}
context.lineTo(clickX[i], clickY[i]); //draw a line
context.stroke(); //filled with "ink"
context.closePath(); //close path
}
}
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function mouseXY(e) {
if (paint) {
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop - 40, true);
draw();
}
}
function mouseUp() {
paint = false;
}
function mouseDown(e)
{
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop - 40);
draw();
}
//Clear the Zig
document.getElementById("clearSig").onclick = function () {
clickX = new Array();
clickY = new Array();
clickDrag = new Array();
context.clearRect(0, 0, canvas.width, canvas.height);
$("#imgData").html('');
};
});
To get correct value of pageX and pageY you have to use e.touches(e.changedTouches) for mobile devices. For example:
function mouseXY (e) {
var touches = e.touches || [];
var touch = touches[0] || {};
if (paint) {
addClick(touch.pageX - this.offsetLeft, touch.pageY - this.offsetTop - 40, true);
draw();
}
}
See more about it on https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
I am trying to draw a rectangle on an image using the mouse and dragging events on HTML5.
My code is shown below. When I draw the rectangle below, the actual image on the canvas disappears. Could you tell me what I am doing wrong? My intended goal is to have the rectangle on top of the image. I have attached a picture of what I actually want to see as the end result.
What am I doing wrong ?
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="400"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 69, 50);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
// ctx.globalAlpha = 0.5;
rect = {},
drag = false;
var rectStartXArray = new Array() ;
var rectStartYArray = new Array() ;
var rectWArray = new Array() ;
var rectHArray = new Array() ;
function init() {
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() {
rectStartXArray[rectStartXArray.length] = rect.startX;
rectStartYArray[rectStartYArray.length] = rect.startY;
rectWArray[rectWArray.length] = rect.w;
rectHArray[rectHArray.length] = rect.h;
drag = false;
}
function mouseMove(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
draw();
}
//drawOldShapes();
}
function draw() {
ctx.beginPath();
ctx.fillStyle="#FF0000";
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
ctx.stroke();
}
function drawOldShapes(){
for(var i=0;i<rectStartXArray.length;i++)
{
if(rectStartXArray[i]!= rect.startX && rectStartYArray[i] != rect.startY && rectWArray[i] != rect.w && rectHArray[i] != rect.h)
{
ctx.beginPath();
ctx.fillStyle="#FF0000";
ctx.fillRect(rectStartXArray[i], rectStartYArray[i], rectWArray[i], rectHArray[i]);
ctx.stroke();
}
}
}
init();
</script>
</body>
</html>
You are clearing the whole canvas inside draw() by calling ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);. Remove the line and it works. Fiddle - http://jsfiddle.net/da8wv75k/