I want to stitch several images together into a one image.
Below are my images.
1st image :
2nd image :
3rd image :
4th image :
I want to stitch above all images into one like below
Final image :
I tried below code
let imgEle1 = document.querySelectorAll(".image")[0];
let imgEle2 = document.querySelectorAll(".image")[1];
let imgEle3 = document.querySelectorAll(".image")[2];
let imgEle4 = document.querySelectorAll(".image")[3];
let resEle = document.querySelector(".result");
var context = resEle.getContext("2d");
let BtnEle = document.querySelector(".Btn");
BtnEle.addEventListener("click", () => {
resEle.width = imgEle1.width;
resEle.height = imgEle1.height;
context.globalAlpha = 1.0;
context.drawImage(imgEle1, 0, 0);
context.globalAlpha = 0.5;
context.drawImage(imgEle2, 0, 0);
context.globalAlpha = 0.5;
context.drawImage(imgEle3, 0, 0);
context.globalAlpha = 0.5;
context.drawImage(imgEle4, 0, 0);
});
but getting output as below
Expanding on my comment, your calls to drawImage are all in the same location...
For the effect you show, the solution is to add a bit of offset to the locations.
Here is some sample code:
var image = `<svg xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40"/></svg>`;
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
context.globalAlpha = 0.5;
var img = new Image();
img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(image);
img.onload = function() {
// draw images with offset
context.translate(40, 40)
context.drawImage(img, -20, 0);
context.drawImage(img, 20, 0);
context.drawImage(img, 0, -20);
context.drawImage(img, 0, 20);
// draw images with NO offset
context.translate(140, 0)
context.drawImage(img, 0, 0);
context.drawImage(img, 0, 0);
context.drawImage(img, 0, 0);
context.drawImage(img, 0, 0);
}
<canvas id=canvas width=600 height=160></canvas>
I'm using just one hardcoded SVG image to show what is possible, but you can certainly add other images latter like you have in your sample code.
Related
I am experiencing an issue with converting a canvas to PNG.
Although the canvas looks exactly as I want it and the conversion from canvas to data URL PNG seems right, the image is blank.
I also tried converting a div to PNG but it did not work for me because I wanted a greyscale filter to be applied. Anyone have any ideas?
JavaScript
var imgis = new Image();
var bubble = new Image();
var canvasWidth;
var canvasHeight;
var ctx = canvas.getContext('2d');
bubble.onload = function() {
var imgis = new Image();
var bubble = new Image();
var ctx = canvas.getContext('2d');
bubble.onload = function() {
// set the canvas' size
canvas.width = this.width;
canvas.height = this.height;
// first fill a rect
ctx.fillStyle = 'rgba(255, 255, 255, 0)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// set the gCO
ctx.globalCompositeOperation = 'luminosity';
// if the browser doesn't support Blend Modes
console.log(ctx.globalCompositeOperation)
if (ctx.globalCompositeOperation !== 'luminosity')
fallback(this);
else {
// draw the image
ctx.drawImage(this, 0, 0);
ctx.drawImage(imgis, 30, 60);
// reset the gCO
ctx.globalCompositeOperation = 'source-over';
}
}
imgis.crossOrigin = "anonymous";
bubble.crossOrigin = "anonymous";
imgis.src = "image1 src";
bubble.src = "image2 src";
function fallback(img) {
// first remove our black rectangle
ctx.clearRect(0, 0, canvas.width, canvas.height);
//draw the image
ctx.drawImage(img, 0, 0);
ctx.drawImage(imgis, 30, 60);
// get the image data
var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var d = imgData.data;
// loop through all pixels
// each pixel is decomposed in its 4 rgba values
for (var i = 0; i < d.length; i += 4) {
// get the medium of the 3 first values
var med = (d[i] + d[i + 1] + d[i + 2]) / 3;
// set it to each value
d[i] = d[i + 1] = d[i + 2] = med;
}
// redraw the new computed image
ctx.putImageData(imgData, 0, 0);
}
canvas = document.getElementById('canvas');
var image = Canvas2Image.convertToPNG(canvas);
console.log(image.src);
// document.getElementById('theDemo').src = image.src;
var image_data = $(image).attr('src');
console.log(image_data);
$("#theDemo").attr('src', image_data);
HTML
<canvas id='canvas' > </canvas>
<img src="" id="theDemo" />
I assume you're using canvas2image. You should replace var image = Canvas2Image.convertToPNG(canvas); with Canvas2Image.convertToPNG(canvas, width, height). Hopefully that helps!
EDIT Since the issue is with the actual canvas to base64 conversion, you can try to use the .toDataURL() method instead of using that library. My comment explains how to test this in your specific code.
var testPhoto = new Image();
testPhoto.src = "http://plan9.bell-labs.com/plan9/img/9logo.jpg"
testPhoto.className = "pulse";
and then:
topSlice.drawImage(testPhoto, 100, 200, 40, 40);
It appears the pulsating effect doesn't work after drawing the image, how should I fix this? I'm following this tutorial for the pulsating effect.
You can use Window.requestAnimationFrame instead and work with blend modes / alpha blending:
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
image = new Image();
image.src = "http://plan9.bell-labs.com/plan9/img/9logo.jpg";
function update(timestamp) {
context.clearRect(0, 0, canvas.width, canvas.height);
context.globalAlpha = Math.sin(timestamp/100) * 0.5 + 0.5;
context.drawImage(image, 0, 0);
window.requestAnimationFrame(update);
}
window.requestAnimationFrame(update);
<canvas id="canvas"></canvas>
I am trying to make a variant of the boomshine game in javascript and everything works when I draw a circular shape with the arc function. However when i try to replace the arc function with the drawImage function to use a coin image instead of a circular shape I start having problems when I clear the canvas to delete the previous drawn circular shapes. If I don't clear the canvas before rendering the images, the images are drawn on the canvas except the old images are still on the canvas. But when i do clear the canvas before rendering the images again, nothing is drawn on the canvas.
I have included screenshots, the links are below.
This is how I clear the canvas:
var ctx = game.context;
ctx.fillStyle = "darkgray";
ctx.fillRect(0, 0, game.canvas.width, game.canvas.height);
This is how i draw the image:
function drawImageBall(x,y,radius,startAngle,color)
{
var img = document.createElement('img');
img.src = 'img/coin-icon.png';
var tmpCtx= game.context;
var ax = x-radius;
var ay = y-radius;
img.onload = function() {
tmpCtx.save();
tmpCtx.beginPath();
tmpCtx.arc(x, y, radius, 0, Math.PI * 2, true);
tmpCtx.closePath();
tmpCtx.clip();
tmpCtx.drawImage(img, ax, ay, img.width, img.height);
tmpCtx.beginPath();
tmpCtx.arc(0, 0, radius, 0, Math.PI * 2, true);
tmpCtx.clip();
tmpCtx.closePath();
tmpCtx.restore();
};
}
Clearing canvas (screenshot)
Without clearing canvas (screenshot)
Keep in mind that downloading the img will take some time.
During that downloading time, Javascript does not stop(!). Instead JS will continue executing any following code. This is causing your unexpected problems.
So download the img just once at the start of your app. That way your drawImage will be done in the order that you expect because there will be no delay while your image is downloading.
Using your code, I maked some changes, I removed the tmpTcx.clip(), look the fidlle. Tip: For performace questions you don't need load the image every time that you want write the canvas.
Poor Example: https://jsfiddle.net/wf4z0d2h/1/
function clearCanvas(){
var ctx = game.context;
ctx.fillStyle = "darkgray";
ctx.fillRect(0, 0, game.canvas.width, game.canvas.height);
}
function drawImageBall(x,y,radius,startAngle,color)
{
if(x == undefined){x = 100;}
if(y == undefined){y = 100;}
if(radius == undefined){radius = 40;}
//var img = document.createElement('img');
//img.src = 'img/coin-icon.png';
//img.src = "http://ps2.lansa.com/images/icons/normal/256/coin_256.png";
var tmpCtx= game.context;
var ax = x-radius;
var ay = y-radius;
//img.onload = function() {
tmpCtx.save();
tmpCtx.beginPath();
tmpCtx.arc(x, y, radius, 0, Math.PI * 2, true);
tmpCtx.stroke(); // Draw it
tmpCtx.closePath();
//tmpCtx.clip();
tmpCtx.drawImage(img, ax, ay, img.width, img.height);
//tmpCtx.beginPath();
//tmpCtx.arc(0, 0, radius, 0, Math.PI * 2, true);
////tmpCtx.clip();
//tmpCtx.stroke(); // Draw it
//tmpCtx.closePath();
//tmpCtx.restore();
//};
}
var img = document.createElement('img');
//img.src = 'img/coin-icon.png';
img.src = "http://ps2.lansa.com/images/icons/normal/256/coin_256.png";
//drawImageBall();
img.onload = function(){
x = 0;
y = 0;
setInterval(function(){
x = x+10;
y = y+10;
clearCanvas();
drawImageBall(x,y);
},300);
}
I am currently testing using the <canvas> element to draw all of the backgrounds (I will add effects later to these images later and is the reason I'm not using CSS to load the images). That said, I'm currently having difficulty loading a image on to the canvas. Here is the code:
<html>
<head>
<title>Canvas image testing</title>
<script type="text/javascript">
function Test1() {
var ctx = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
//Loading of the home test image - img1
var img1 = new Image();
img1.src = 'img/Home.jpg';
//drawing of the test image - img1
img1.onload = function () {
//draw background image
ctx.drawimage(img1, 0, 0);
//draw a box over the top
ctx.fillStyle = "rgba(200, 0, 0, 0.5)";
ctx.fillRect(0, 0, 500, 500);
};
}
}
</script>
<style type="text/css">
canvas { border: 2px solid black; width: 100%; height: 98%; }
</style>
</head>
<body onload="Test1();">
<canvas id="canvas" width="1280" height="720"></canvas>
</body>
</html>
I think that I'm not loading the image correctly, but I'm not sure.
There are a few things:
drawimage should be drawImage - note the capital i.
Your getElementById is looking for an element with ID of canvas, but it should be test1. canvas is the tag, not the ID.
Replace the canvas variable (e.g. in your canvas.getContext lines) with ctx, since that's the variable you've used to select your canvas element.
Bind your onload handler before you set the src of the image.
So your function should end up like this:
function Test1() {
var ctx = document.getElementById('test1');
if (ctx.getContext) {
ctx = ctx.getContext('2d');
//Loading of the home test image - img1
var img1 = new Image();
//drawing of the test image - img1
img1.onload = function () {
//draw background image
ctx.drawImage(img1, 0, 0);
//draw a box over the top
ctx.fillStyle = "rgba(200, 0, 0, 0.5)";
ctx.fillRect(0, 0, 500, 500);
};
img1.src = 'img/Home.jpg';
}
}
Using newer JavaScript features:
let img = await loadImage("./my/image/path.jpg");
ctx.drawImage(img, 0, 0);
and the loadImage function looks like this:
function loadImage(url) {
return new Promise(r => { let i = new Image(); i.onload = (() => r(i)); i.src = url; });
}
move the onload event listener to before you set the src for the image.
var img1 = new Image();
//drawing of the test image - img1
img1.onload = function () {
//draw background image
ctx.drawImage(img1, 0, 0);
//draw a box over the top
ctx.fillStyle = "rgba(200, 0, 0, 0.5)";
ctx.fillRect(0, 0, 500, 500);
};
img1.src = 'img/Home.jpg';
Assign your local file resource (url) to image source and draw image using context from canvas you want to load. That's it. See code bellow.
var loadImage = function (url, ctx) {
var img = new Image();
img.src = url
img.onload = function () {
ctx.drawImage(img, 0, 0);
}
}
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var img1 = new Image();
//drawing of the test image - img1
img1.onload = function () {
//draw background image
ctx.drawImage(img1, 0, 0);
//draw a box over the top
ctx.fillStyle = "rgba(200, 0, 0, 0.5)";
ctx.fillRect(0, 0, 500, 500);
};
img1.src = 'img/Home.jpg';
<canvas id="canvas"></canvas>
I wrote a function that draws out a slice of a pizza based on how big you specify it to be (in degrees)
function drawProgress(degs){
var canvas = document.getElementById('progress');
var context = canvas.getContext('2d');
context.globalAlpha=1;
var img = new Image();
img.onload = function(){
context.beginPath();
context.arc(canvas.width/2,canvas.height/2, canvas.height/2, 0, degs * (-Math.PI/180), true);
context.lineTo(canvas.width/2, canvas.height/2);
context.clip();
context.drawImage(img, 0, 0, canvas.width,canvas.width);
}
img.src = 'pizza.png';
}
When I try to call this function every 250ms, the progress is not updated after the first draw.
function runsEvery250ms(percent){
drawProgress(3.6 * percent);
}
What changes do I need to make to the code to get the canvas to redraw each time drawProgress(degs) is called? Is it possible to perform redraws without causing the pizza to flicker?
Use context.clearRect(0, 0, canvas.width, canvas.height); and cache your image, don't reload each time you refresh
UPDATE: No idea if this will work, untested and been a while since I used canvas but try it
var canvas = document.getElementById('progress');
var context = canvas.getContext('2d');
var img = new Image();
var imgLoaded = false;
img.src = 'pizza.png';
img.onload = function(){
imgLoaded = true;
}
function drawProgress(degs){
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
context.globalAlpha=1;
context.beginPath();
context.arc(canvas.width/2,canvas.height/2, canvas.height/2, 0, degs * (-Math.PI/180), true);
context.lineTo(canvas.width/2, canvas.height/2);
context.clip();
if (imgLoaded) context.drawImage(img, 0, 0, canvas.width,canvas.width);
context.restore();
}