I have a multilayer canvas that I want to save locally with a button(it will eventually have to be saved on aws but for now I am trying to figure out how to do it locally). I want one png file of the entire canvas and not just one layer. How would I do this, I've tried a few tutorials but they didn't seem to work. I have just started using javascript and angularjs so bear with me
AngularJS/HTML
<div style="position: relative; border: 1px solid black;">
<canvas id="layer1" width="200" height="200" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="200" height="200" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
<p><button onclick="body()">Body</button></p>
<p><button onclick="hairstyle1()">Hair style 1</button></p>
<p><button onclick="hairstyle2()">Hair style 2</button></p>
Javascript
function body() {
var canvas = document.getElementById('layer1');
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
};
imageObj.src = 'body.png';
}
function hairstyle1() {
var canvas = document.getElementById('layer2');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 50, 7, imageObj.width, imageObj.height);
};
imageObj.src = 'hair1.png';
}
function hairstyle2() {
var canvas = document.getElementById('layer2');
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 50, 7, imageObj.width, imageObj.height);
};
imageObj.src = 'hair2.png';
}
If the canvas's are the same size, you can use drawImage to draw each one on another canvas.
var newCanvas = document.createElement('canvas');
newCanvas.width = 200;
newCanvas.height = 200;
var newCtx = newCanvas.getContext('2d');
newCtx.drawImage(document.getElementById("layer1"), 0, 0);
newCtx.drawImage(document.getElementById("layer2"), 0, 0);
// convert to url
console.log(newCanvas.toDataURL());
Esentially, canvas's can be treated as image objects as well.
Related
I need to draw an image with transparent background on canvas. I have a code that should do that:
var can = document.getElementById('canvasId');
var ctx = can.getContext('2d');
ctx.fillRect(50,50,500,500); // something in the background
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "https://i.stack.imgur.com/7JXBD.png"; //transparent png
<canvas id="canvasId"></canvas>
But the background is not transparent:
Your code works perfectly - you just need an image with a transparent background - like this question mark:
var can = document.getElementById('canvasId');
var ctx = can.getContext('2d');
ctx.fillRect(50,50,500,500); // something in the background
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "https://i.stack.imgur.com/RPEQQ.png"; //transparent png
<canvas id="canvasId"></canvas>
And to prove it's not just got a white background image, I set the background image of the body to red:
var can = document.getElementById('canvasId');
var ctx = can.getContext('2d');
ctx.fillRect(50,50,500,500); // something in the background
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
img.src = "https://i.stack.imgur.com/RPEQQ.png"; //transparent png
body {
background-color: red;
}
<canvas id="canvasId"></canvas>
The image that you are trying to display isn't transparent, it simply just has a transparent checkered background.
A link to an image which does have a transparent background can be found here
Using this link fixes your issue:
var can = document.getElementById('canvasId');
var ctx = can.getContext('2d');
ctx.fillRect(50, 50, 500, 500); // something in the background
var img = new Image();
img.src = "https://cdn.sstatic.net/Sites/stackoverflow/img/apple-touch-icon#2.png?v=73d79a89bded"; //transparent png
img.onload = function() {
ctx.drawImage(img, 0, 0);
}
canvas {
border: 1px solid black;
}
<canvas id="canvasId" height="300" width="500"></canvas>
So I am trying to build a Meme-Creator. You already can upload the pics as the background-img from the canvas. Now I am trying to do the Meme font but it isnt really working. However it is creating a big gap in the picture. Thanks for your help and attention! :D
var canvas = document.getElementById("meme-canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
function readImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function(e) {
var img = new Image();
img.addEventListener("load", function() {
ctx.clearRect(0, 0, width, height);
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
});
img.src = e.target.result;
};
FR.readAsDataURL(this.files[0]);
}
}
function Text() {
ctx.clearRect(0, 0, width, height);
var textT = document.getElementById("top-text").value;
var textB = document.getElementById("bottom-text").value;
ctx.font = "60px Impact";
ctx.lineWidth = 3;
ctx.strokeText(textT, 10, 65);
ctx.strokeText(textB, 10, 400);
}
document.getElementById("image-input").addEventListener("change", readImage, false);
<input type="file" id="image-input" accept="image/*">
<input type="text" id="top-text" oninput="Text()">
<input type="text" id="bottom-text" oninput="Text()">
<canvas style="position: absolute; width: 400px; top: 100px; left: 10px;" id="meme-canvas"></canvas>
I've made a few changes to your script. because you need to draw the image several times I've written a function that draws the image. The canvas is cleared every time one of the 2 text input changes it's value, and every time you have to redraw everything.
Also textT and textB can be declared only once. You don't need to declare them in the Text function.
I need to use the font size (60) more than once, so I've made a variable fontSize = 60
Since you don't know the size of your canvas ( depends on the size of the uploaded image ) you need to calculate the position for the bottom text textB = height - fontSize/2 where height is the height of the canvas: height = canvas.height = img.height;
I hope it's useful.
var canvas = document.getElementById("meme-canvas");
var ctx = canvas.getContext("2d");
var width = (canvas.width = 400);
var height = (canvas.height = 400);
var fontSize = 60;
var img = new Image();
var textT = document.getElementById("top-text");
var textB = document.getElementById("bottom-text");
function readImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function(e) {
img.addEventListener("load", function() {
width = canvas.width = img.width;
height = canvas.height = img.height;
drawImage();
});
img.src = e.target.result;
};
FR.readAsDataURL(this.files[0]);
}
}
function drawImage() {
ctx.drawImage(img, 0, 0);
}
function Text() {
ctx.font = fontSize + "px Impact";
ctx.textAlign = "center";
ctx.lineWidth = 3;
ctx.clearRect(0, 0, width, height);
drawImage();
ctx.strokeText(textT.value, width / 2, 65);
ctx.strokeText(textB.value, width / 2, height - fontSize/2);
}
document
.getElementById("image-input")
.addEventListener("change", readImage, false);
textT.addEventListener("input", Text);
textB.addEventListener("input", Text);
canvas{position: absolute; left: 10px; top:60px;border:1px solid #d9d9d9;}
<input type="file" id="image-input" accept="image/*">
<input type="text" id="top-text" />
<input type="text" id="bottom-text" />
<canvas style="" id="meme-canvas"></canvas>
A few of the issues I encountered:
If you change the size of the canvas you should not use the variables, because those wont be correct, or you will need to keep track of them
If you do clearRect you have to be aware what are you clearing and re-draw it.
The font did not look too clear so I added a white shadow for better contrast
The bottom text needed to be relative to the canvas height
Here is the code:
var canvas = document.getElementById("meme-canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
function readImage() {
if (this.files && this.files[0]) {
var FR = new FileReader();
FR.onload = function(e) {
img.addEventListener("load", function() {
canvas.width = img.width;
canvas.height = img.height;
draw();
});
img.src = e.target.result;
};
FR.readAsDataURL(this.files[0]);
}
}
function draw() {
var textT = document.getElementById("top-text").value;
var textB = document.getElementById("bottom-text").value;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = "60px Impact";
ctx.shadowColor = "white"
ctx.shadowOffsetX = ctx.shadowOffsetY = 2
ctx.lineWidth = 3;
if (img) ctx.drawImage(img, 0, 0);
ctx.strokeText(textT, 10, 45);
ctx.strokeText(textB, 10, canvas.height -10);
}
document.getElementById("image-input")
.addEventListener("change", readImage, false);
<input type="file" id="image-input" accept="image/*"><br>
<input type="text" id="top-text" placeholder="Top text" oninput="draw()"><br>
<input type="text" id="bottom-text" placeholder="Bottom text" oninput="draw()"><br>
<canvas id="meme-canvas"></canvas>
I have a problem. I am creating simple game in Canvas using JavaScript. Image doesn't display after call clearRect(), does anyone know, how to solve it?
var left1 = 0;
var context1 = document.getElementById('canvas1').getContext('2d');
render1();
function render1() {
var image = new Image();
image.onload = function () {
context1.drawImage(image, left1, 0, 200, 200);
};
image.src = 'http://www.pngall.com/wp-content/uploads/2016/06/Earth-Free-Download-PNG.png';
left1++;
requestAnimationFrame(render1);
}
var left2 = 0;
var context2 = document.getElementById('canvas2').getContext('2d');
render2();
function render2() {
context2.clearRect(0, 0, 500, 250);
var image = new Image();
image.onload = function () {
context2.drawImage(image, left2, 0, 200, 200);
};
image.src = 'http://www.pngall.com/wp-content/uploads/2016/06/Earth-Free-Download-PNG.png';
left2++;
requestAnimationFrame(render2);
}
canvas {
display: block;
}
It works, but old images are not deleted:
<canvas id="canvas1" height="250" width="500"></canvas>
It doesn't work, because of clearRect():
<canvas id="canvas2" height="250" width="500"></canvas>
if you try to animate your image , its not necessary to make two canvas instead use a timer , i hope this will help
`
var left1 = 0;
var context1 = document.getElementById('canvas1').getContext('2d');
var canvas1 = document.getElementById('canvas1');
window.onload = init;
function init() {
setInterval(drawc, 1000 / 60);
};
function drawc() {
if (left1 > canvas1.width) {
left1 = 0;
}
render1();
}
function render1() {
with(context1) {
clearRect(0, 0, canvas1.width, canvas1.height);
var image = new Image();
image.src = 'http://www.pngall.com/wp-content/uploads/2016/06/Earth-Free-Download-PNG.png';
beginPath();
drawImage(image, left1, 0, 200, 200);
closePath();
fill();
left1++;
// requestAnimationFrame(render1);
}
};
I've a <canvas> with an image already loaded and all the graphics coordinates needed for a crop (x, y, w, h) in an array.
What I'm trying to do is to crop the canvas directly, without a temporary other canvas to copy to/from (as suggested in other SO answers).
My idea is to:
1) Draw the selected area on the top-left corner of the canvas
2) Shrink the canvas size to the area
$('#edit').on("click", function() {
var img = $('#canvas');
var c = img[0];
var ctx = c.getContext("2d");
//var imageData = ctx.getImageData(0, 0, 100, 100);
ctx.drawImage(c, 0, 0, 100, 100, 0, 0, 100, 100);
c.width = 100;
c.height = 100;
});
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 350, 350);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="350" height="350"></canvas>
<input id="edit" type="button" value="Edit" />
Seems easy to me, but I'm missing something: when I execute, I get nothing https://jsfiddle.net/qg0znpu7/
What's wrong with my code? how can I fix it to obtain an in-place canvas crop?
Changing the width or height of a canvas will clear it. For that reason you will have to copy the data first.
You can use putImageData() for that:
$('#edit').on("click", function() {
var c = $('#canvas')[0];
var ctx = c.getContext("2d");
var imageData = ctx.getImageData(0, 0, 100, 100);
c.width = 100;
c.height = 100;
ctx.putImageData(imageData, 0, 0);
});
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 350, 350);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="350" height="350"></canvas>
<input id="edit" type="button" value="Edit" />
I have 2 images on canvas and i want to make imageObg to animate. Actually i want it to make a linear move to the right.I found a way to animate an object like a rectangle but i cant animate an image object that i use from another source.
Is there anyway that can i manage to do i? Does anyone knows?
window.onload = function() {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
var imageObj2 = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 69, 130);
};
imageObj2.onload = function() {
context.drawImage(imageObj2, 0, 0);
};
imageObj.src = 'http://imageshack.com/a/img745/822/pXDK5F.png'
imageObj2.src = 'http://i.dailymail.co.uk/i/pix/2014/09/04/1409790551890_wps_28_Astronaut_Reid_Wiseman_po.jpg'
};
body {
background-color: black
}
<div id='d1' style="position:absolute; top:80px; left:150px; z-index:1">
<canvas id='myCanvas' width='962' height='500' style="border:10px solid #ffffff;">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
Just two things.
Set a periodically render routine using setInterval.
Set a move (or physics) routine, call it after each render.
window.onload = function() {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
var imageObj2 = new Image();
imageObj.src = 'http://imageshack.com/a/img745/822/pXDK5F.png'
imageObj2.src = 'http://i.dailymail.co.uk/i/pix/2014/09/04/1409790551890_wps_28_Astronaut_Reid_Wiseman_po.jpg'
window.setInterval(renderFrame, 50);
var ship = {
x: 69,
y: 130
};
function renderFrame() {
moveShip();
context.clearRect(0, 0, canvas.width, canvas.height);
if (imageObj.complete) {
context.drawImage(imageObj2, 0, 0);
}
if (imageObj.complete) {
context.drawImage(imageObj, ship.x, ship.y);
}
}
function moveShip() {
ship.x += 20;
if (ship.x > canvas.width) {
ship.x = 0 - imageObj.width;
ship.y = Math.random() * 250 + 50;
}
}
};
body {
background-color: black
}
<div id='d1' style="position:absolute; top:80px; left:150px; z-index:1">
<canvas id='myCanvas' width='962' height='500' style="border:10px solid #ffffff;">
Your browser does not support HTML5 Canvas.
</canvas>
</div>
Just increase the x position of the image with a setInterval command.
var img = document.createElement("IMG");
var img.src = [Image Source];
var x = 0;
window.setInterval(function() {
x ++;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(img, x, 0);
}, 50);
Hope this helps.
Edit:
Here is a JSFiddle Example.