Flip image and the line drawed in HTML5 canvas - javascript

I am using canvas loading an image. draw some lines on the image. Then I want to click a "flip" button to flip the image and the lines I just draw. The code is here on jsfiddle.
My current problem is:
The lines I draw won't get flipped but the image is flipped after I
click the "flip" button.
The lines wont' show up immediately after I
click the "flip" button. The lines will show when I start to draw
again.
Any help will be appreciated.
Thanks,
var context;
var canvas;
var imageObj = new Image();
var flipH = true;
var flipV = true;
var scaleH = 1,
scaleV = 1;
var posX = 0,
posY = 0;
var isDrawingFreeDraw;
canvas = document.getElementById('myCanvas');
context = canvas.getContext('2d');
context.strokeStyle = "#FFFF00";
//context.save();
canvas.addEventListener('mousedown', MouseDown, true);
canvas.addEventListener('mouseup', MouseUp, true);
canvas.addEventListener('mousemove', MouseMove, true);
imageObj.src = 'http://upload.wikimedia.org/wikipedia/commons/1/1a/Image_upload_test.jpg';
imageObj.onload = function () {
context.drawImage(imageObj, posX, posY, canvas.height * imageObj.width / imageObj.height, canvas.height);
};
console.log(context);
$(document).on('click', '#FlipH', function () {
console.log("Flip Me");
// context.restore();
context.save();
//canvas.width = 100;
scaleH = flipH ? -1 : 1;
context.scale(scaleH, scaleV);
posX = flipH ? (canvas.height * imageObj.width / imageObj.height) * -1 : 0;
context.drawImage(imageObj, posX, posY, canvas.height * imageObj.width / imageObj.height, canvas.height);
flipH = !flipH;
context.scale(1, 1);
//console.log(context);
context.restore();
});
function MouseUp(e) {
isDrawingFreeDraw = false;
context.save();
}
function MouseDown(e) {
context.save();
isDrawingFreeDraw = true;
console.log(e);
context.moveTo(e.pageX, e.pageY);
context.restore();
}
function MouseMove(e) {
if (isDrawingFreeDraw) {
context.save();
context.lineTo(e.pageX, e.pageY);
context.stroke();
context.restore();
}
}

To flip both the image and your drawings, you can use the canvas itself as a source for drawImage.
// draw the canvas to itself
ctx.drawImage(canvas,0,0);
A Demo: http://jsfiddle.net/m1erickson/Y9SLQ/
Example code:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var img=new Image();
img.onload=start;
img.src="http://upload.wikimedia.org/wikipedia/commons/1/1a/Image_upload_test.jpg";
function start(){
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(50,300);
ctx.lineTo(250,300);
ctx.lineWidth=8;
ctx.stroke();
}
$("#flipbutton").click(function(){
ctx.save();
ctx.translate(canvas.width,0);
ctx.scale(-1,1);
ctx.drawImage(canvas,0,0);
ctx.restore();
});

Related

How to upload image to canvas and draw squares on it and get the squares' coordinates

I'm trying to upload an image to canvas and draw squares on it and get the squares' coordinates to send it to the backend for keys identification.
But something not right, I can't draw squares on my images.
This is my javascript which I use:
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 =
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 = 'red';
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
}
//
init();
</script>
<script type="text/javascript">
document.getElementById('imageLoader').onchange = function(e) {
var img = new Image();
img.onload = draw;
img.onerror = failed;
img.src = URL.createObjectURL(this.files[0]);
};
function draw() {
var canvas = document.getElementById('canvas');
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0,0);
}
function failed() {
console.error("The provided file couldn't be loaded as an Image media");
}
and HTML:
<canvas id="canvas" ></canvas>
<input type="file" id="imageLoader" name="imageLoader"/>
You just need to assign the image to imageObj.
function draw() {
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0,0);
imageObj = this; //here
}
JSFiddle here

Blur part of the image with Javascript/Jquery

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/

How to have two layers of Canvas one over another

I am making a canvas, where there is a large image and behind it there is another image. then by using mouse coordinate I made a circle around the cursor. This circle will work as a hole to reveal the hidden image under the background. I made it kinda but I cannot set the front image.
Have a look at my code please: JSFiddle
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
//var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
context.fillStyle = 'black';
context.fill();
Can someone tell me please how to have an image as big as the canvas to cover it?
Thanks
It looks like you are on the right track. The easiest way to have an image where the circle is not in your setup, would be to set a background image on the canvas element, and use background-size: cover to make it fill the canvas area.
Working Example (see CSS in second block):
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageObj, 'no-repeat');
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>
To get the foreground image to fill the canvas, and take care of the edge, you need to resize the image in another canvas.
Working Example:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 0;
var y = 0;
var width = 578;
var height = 400;
var imageObj = new Image();
//Create another canvas to darw a resized image to.
var imageResized = document.createElement('canvas');
imageResized.width = width;
imageResized.height = height;
//Wait for the original image to low to draw the resize.
imageObj.onload = function() {
//Find hoe mauch to scale the image up to cover.
var scaleX = width / imageObj.width;
var scaleY = height / imageObj.height;
var scaleMax = Math.max(scaleX, scaleY);
var ctx = imageResized.getContext('2d');
ctx.scale(scaleMax, scaleMax);
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
function writeMessage(canvas, message, x, y) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
var pattern = context.createPattern(imageResized, 'no-repeat');//Use imageResized, not imageObj.
context.fillStyle = pattern;
context.fill();
context.font = '28pt Calibri';
context.fillStyle = 'black';
//context.fillText(message, x, y);
context.beginPath();
context.arc(x, y, 50, 0, 2 * Math.PI);
context.stroke();
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
writeMessage(canvas, message, mousePos.x, mousePos.y);
}, false);
canvas, img {
display:block;
margin:1em auto;
border:1px solid black;
}
canvas {
background:url('http://img2.wikia.nocookie.net/__cb20090917002539/starwars/images/7/70/Vader_yelloweyes.jpg');
background-size: cover;
}
<canvas id="myCanvas" width="578" height="400"></canvas>
<p></p>

HTML5 Canvas why fillText() method clears everything after clearRect()

When i call writeTextToCanvas method before clearCanvas method, it works perfectly,
if i call clearCanvas method first than writeTextToCanvas, it doesn't works, drawing functions etc. all works after clearCanvas but fillText doesn't work and also clears all canvas when i call fillText
when i set context.globalAlpha = 0.5 before fillText, i can barely see text on the canvas but anything in canvas erased somehow
var canvas;
var context;
var selectedRole = DRAW_TOOLS.PENCIL;
function initDrawingCanvas(index) {
var question = document.getElementsByClassName('question').item(index);
canvas = question.getElementsByClassName('questionDrawingCanvas').item(0);
context = canvas.getContext("2d");
canvasWidth = canvas.width;
canvasHeight = canvas.height;
compositeOperation = context.globalCompositeOperation;
canvas.addEventListener("touchmove", onCanvasTouchMove, false);
canvas.addEventListener("touchstart", onCanvasTouchStart, false);
canvas.addEventListener("touchstop", onCanvasTouchStop, false);
}
var startX = 0;
var startY = 0;
var endX = 0;
var endY = 0;
var compositeOperation;
function onCanvasTouchMove(event){
endX = event.changedTouches[0].clientX - $(canvas).offset().left;
endY = event.changedTouches[0].clientY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.PENCIL){
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(endX, endY);
context.strokeStyle = $('.colorPicker').css('background-color');
context.lineWidth = parseInt($('#pencilSize').attr("data-size"));
context.stroke();
}else if(selectedRole == DRAW_TOOLS.ERASER){
context.save();
context.globalCompositeOperation = "destination-out";
context.arc(endX,endY,25,0,Math.PI*2,false);
context.fill();
context.restore();
}
startX = endX;
startY = endY;
}
function onCanvasTouchStart(event){
$("#colorPicker").css("display", "none");
$("#pencilSize").css("display", "none");
$("#textColorPicker").css("display", "none");
$("#canvas_textSize").css("display", "none");
startX = event.changedTouches[0].pageX - $(canvas).offset().left;
startY = event.changedTouches[0].pageY - $(canvas).offset().top;
if(selectedRole == DRAW_TOOLS.TEXT){
showConfirmDialog('<textarea id="canvasTextArea" class="canvasTextArea"></textarea>', RESOURCES.CANVAS_TEXT_TITLE, {positiveButton: RESOURCES.OKAY, negativeButton: RESOURCES.CANCEL}, function(){
var text = $("#canvasTextArea").val();
if(isNullOrUndefined(text)) return;
writeTextToCanvas(text);
hideDialog();
}, function(){
hideDialog();
});
$("#canvasTextArea").focus();
$("#canvasTextArea").css("font-size", $('#textSizePicker').attr("data-size") + "px");
$("#canvasTextArea").css("color", $('.textColorPicker').css("background-color"));
}
}
function onCanvasTouchStop(event){
console.log(event);
}
function clearCanvas(){
context.clearRect(0, 0, canvas.width, canvas.height);
}
function getCanvasContent(){
return canvas.toDataURL();
}
function writeTextToCanvas(text) {
context.globalCompositeOperation = "source-over";
context.textBaseline = "top";
context.font = $('#textSizePicker').attr("data-size") + 'px sans-serif';
context.fillStyle = $('.textColorPicker').css("background-color");
context.fillText(text, startX, startY);
}
What should i use to clear canvas or clear some parts like eraser then i can fillText normally?
Your call to clearRect() is stopping the entire script because it throws an error (check the console). You're not passing in a rectangle to the call.
It needs to be called like:
context.clearRect(0, 0, canvas.width, canvas.height);
Here's a working example: http://jsfiddle.net/pe19L15m

Html5 Canvas rotate single element

I know that there are many similiar questions already asked on stackoverflow, but still, I can not figure out how to do it. I want to rotate only ball texture. draw is called with timer:
var canvas;
var ctx;
var width;
var height;
var ready;
var textures;
var loadIndex;
var loadCount;
var keyCodes;
var mouseLoc;
var playerX;
var playerY;
var playerVelocity;
function init() {
canvas = document.getElementById('game');
ctx = canvas.getContext("2d");
width = canvas.width;
height = canvas.height;
textures = [];
loadingCount = 0;
keyCodes = [];
mouseLoc = {};
playerX = 0;
playerY = 0;
playerVelocity = 6;
textures['Background'] = loadTexture('./textures/Background.png');
textures['Ball'] = loadTexture('./textures/Ball.png');
setInterval(function(){
if(loadingCount == 0) {
update();
draw();
}
}, 50);
}
function update(){
if(keyCodes[37])
playerX -= playerVelocity;
if(keyCodes[38])
playerY -= playerVelocity;
if(keyCodes[39])
playerX += playerVelocity;
if(keyCodes[40])
playerY += playerVelocity;
}
function draw() {
//ctx.clearRect(0, 0, width, height);
//ctx.beginPath();
drawBackground();
drawPlayer();
//ctx.closePath();
//ctx.fill();
}
function drawBackground(){
ctx.drawImage(textures['Background'], 0, 0, width, height);
}
function drawPlayer(){
ctx.save();
ctx.rotate(0.17);
ctx.drawImage(textures['Ball'], playerX, playerY, 100, 100);
ctx.restore();
}
function loadTexture(src){
var image = new Image();
image.src = src;
loadingCount++;
image.onload = function(){
loadingCount--;
};
return image;
}
document.onkeydown = function(evt){
keyCodes[evt.keyCode] = true;
evt.returnValue = false;
}
document.onkeyup = function(evt){
keyCodes[evt.keyCode] = false;
}
document.onmousemove = function(evt){
mouseLoc.x = evt.layerX;
mouseLoc.y = evt.layerY;
}
document.onmousedown = function(evt){
mouseLoc.down = true;
}
document.onmouseup = function(evt){
mouseLoc.down = false;
}
init();
Assuming that you want to give the illusion of the ball continuing to rotate, you should increase the rotation angle for each frame drawn.
As written, your code will give the ball a fixed rotation of 0.17 radians on each frame.
var frame = 0;
function drawPlayer() {
ctx.save();
ctx.rotate(0.17 * frame);
...
ctx.restore();
}
function draw() {
++frame;
drawPlayer();
...
}
You just need to save and restore the state of the canvas('s state-machine)
function drawPlayer(){
ctx.save();
ctx.rotate(0.17);
ctx.drawImage(textures['Ball'], playerX, playerY, 100, 100);
ctx.restore();
}
You want to use delta time for calculating the distance of your rotation. That is, the time that has passed since the last frame. That will make your rotation smoother should your browser hiccup and lose a frame here or there.
So store the time of each frame so you can make the comparison between frames and set your rotation speed as radians per second.

Categories

Resources