I have a similar slideshow displayed a few times here! It works fine but I don't get the right mapping on an a-sky. I am not a coder but I guess drawImage is just made for rectangular objects instead of spherical? Is there an alternative to drawImage which works for spherical?
Here are my codes:
AFRAME.registerComponent('draw-canvas', {
schema: {
type: 'selector'
},
init: function() {
var canvas = this.canvas = this.data;
var ctx = this.ctx = canvas.getContext('2d');
var i = 0; // Start Point
var images = []; // Images Array
var time = 3000; // Time Between Switch
// Image List
images[0] = "Tulips.jpg";
images[1] = "Tulips2.jpg";
images[2] = "Tulips3.jpg";
// Change Image
function changeImg() {
document.getElementById('pic01').src = images[i];
ctx.drawImage(document.getElementById('pic01'), 0, 0, 300, 300);
// Check If Index Is Under Max
if (i < images.length - 1) {
// Add 1 to Index
i++;
} else {
// Reset Back To O
i = 0;
}
// Run function every x seconds
setTimeout(function() {
changeImg()
}, time);
}
// Run function when page loads
window.onload = changeImg;
console.log("Hello World!");
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas Texture</title>
<meta name="description" content="Canvas Texture - A-Frame">
<script src="./components/aframe-v0.6.0.js"></script>
<script src="./components/slideshow.js"></script>
</head>
<body>
<a-scene>
<a-assets>
<img id="pic01" src="Tulips.jpg">
<img id="pic02" src="Tulips2.jpg">
<img id="pic03" src="Tulips3.jpg">
<canvas id="slide" name="slide" crossOrigin="anonymous"> </canvas>
</a-assets>
<a-sky material="shader: flat; src: #slide" draw-canvas="#slide">
<a-sky/>
</a-scene>
</body>
</html>
And if anybody knows how to nicely fade over the pictures, please feel free to share! I bet a lot of people would be happy about a nice A-Frame Slideshow.
I've got a solution, but I've altered quite a lot of Your stuff.
I've got rid of the canvas, You already have three image assets, no need to rewrite, or buffer them on each other.
Just store the asset id's and use setAttribute("material", "src", picID)
Furthermore I've added the a-animation component, so Your slideshow will have a nice smooth transition. You need to set the animation duration to the slideshow's time / 2, for it goes back and forth.
This said, check out my fiddle.
As for the drawImage part of the question, drawImage draws (writes) an image onto a canvas element. The mapping is fine, since You only need to make sure You have a spherical photo, otherwise it will get stretched all over the model.
i have a canvas dynamically written with no id assigned to it. How can i overlay image on the first canvas (out of multiple canvas) via JS ?
<canvas width="240" height="297">
<canvas id = "image_to_Overlay" width = "800" height = "500"></canvas>
In order to get the 1st canvas of the DOM using plain javascript you can use the good old function document.getElementsByTagName(). Then do what you want with it.
Probably it would be safer matching even on other attributes - such as class name - just to avoid getting the wrong canvas (jquery selectors would work great).
BTW the following should work
<html>
<head>
<script>
var image = new Image();
image.onload = function (){//react on image download completed
//you can get the 1st canvas of the DOM accessing the array of canvas
var canvas = document.getElementsByTagName("canvas")[0];
//then draw on it as needed
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
};
//load image
image.src = "http://i.imgur.com/ITWfejd.png";
</script>
</head>
<body>
<canvas width="240" height="297"></canvas>
<canvas id = "image_to_Overlay" width = "800" height = "500"></canvas>
</body>
</html>
I have two canvases on my HTML page and what i actually want to do is pasting all stuff inside first canvas in bottom right corner of second canvas.
This is the code I was trying:
<canvas id="first"></canvas>
<canvas id="second"></canvas>
<script>
var first = document.getElementById('first').getContext('2d');
var sec = document.getElementById('second').getContext('2d');
//--code for drawing in first canvas--
var img = new Image();
img.src="imgName.jpg";
img.onload = function() {
sec.drawImage(img,0,0,sec.canvas.width,sec.canvas.height);
//Actually i want first canvas to overlap image on second canvas
var paste = new Image();
paste.src = first.canvas;
paste.onload = function() {
sec.drawImage(paste,100,100,400,600);
};
};
</script>
Problem is: second canvas shows image but doesn't shows first canvas in its bottom right corner.
Please worthy guys, i need the answer. Its very Important. Thanks in advnce to all helpers..
The way you are drawing the first canvas on the second one is not correct. You can directly draw a canvas on another canvas using drawImage() method.
var first = document.getElementById('first').getContext('2d');
var sec = document.getElementById('second').getContext('2d');
// draw on first canvas
first.fillStyle = '#07C';
first.fillRect(0, 0, first.canvas.width, first.canvas.height);
// draw image on second canvas
var img = new Image();
img.src = "http://lorempixel.com/300/300";
img.onload = function() {
sec.drawImage(img, 0, 0, sec.canvas.width, sec.canvas.height);
sec.drawImage(first.canvas, 100, 100, 100, 100); // draw first canvas on a portion of second canvas
};
body {display: flex}
<canvas id="first" width="200" height="200"></canvas>
<canvas id="second" width="200" height="200"></canvas>
Currently there are are two images I would like to rotate on the canvas, I tried save and restore but didn't work
function SetCanvas()
{
var canvas = document.getElementById('pic1');
if(canvas.getContext)
{
var ctx = canvas.getContext('2d');
// ctx.save();
ctx.rotate(0.5);
var image = new Image();
image.src ='ME.JPG';
image.onload = function(){
ctx.drawImage(image, 90,0,200,100);
};
}
//ctx.restore();
var canvas2 = document.getElementById("pic2");
var image2 = new Image();
image2.src = 'ME2.JPG';
if(canvas2.getContext)
{
image2.onload = function(){
ctx2=canvas2.getContext('2d');
ctx2.drawImage(image2, 0,0,200,100);
};
}
}
<ul id="picsCanvas" style="overflow:hidden;white-space:nowrap; list-style-type:none;">
<li style=" display:inline; float:left" id="first">
<canvas ID="pic1" width="300" height="360" ></canvas>
</li>
<li id="second" style="margin-top:0px; display:inline; float:left; position:absolute ">
<canvas id="pic2" width="300" height="360" style="position:absolute" ></canvas>
</li>
</ul>
Please note that the code might not be correct as it is something I did a while ago, I just want to get an idea of how to do it and if it is possible... thanks for your help.
The images are loading asynchronously. This means that that entire function (minus the onload handlers for the images happens first. Then when the images are loaded, their handlers are called. This happens in a second pass. By the time this happens, you already rotated and restored the canvas, effectively wiping the rotation out.
The simple fix is to rotate and restore the canvas inside each of the image onload handlers.
These two links give a pretty good explanation and example of how to rotate with HTML5 canvas
https://developer.mozilla.org/en/Drawing_Graphics_with_Canvas
https://developer.mozilla.org/en/Canvas_tutorial/Basic_animations
You set the different angles when you rotate (see code example below).
The general gist of it is:
1) save the context
2) transform to, usually, the center of the image
3) rotate
4) transform back
5) draw image
6) restore
In your case, with two images, you need to transform the origin to the second image before you make the second rotation call. Below is a simplified example rotating one image. Get that sorted and then make the second transform/rotate.
Example:
var canvas = document.getElementById("yourCanvas");
var ctx = canvas.getContext("2d");
var angle = 0;
window.setInterval(function(){
angle = angle+1;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
ctx.fillStyle = "#FF0000";
// first image
ctx.translate(150,200);
ctx.rotate( angle*Math.PI/180 ); // rotate 90 degrees
ctx.translate(-150,-200);
ctx.fillStyle = "black";
ctx.fillRect(100, 150, 100, 100);
ctx.fill();
ctx.restore();
}, 5);
there's an example, which loads 2 images:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img1 = new Image();
img.src = "/path/to/image/img1.png";
img.onload = function() {
ctx.drawImage(img, 0, 0);
};
var img2 = new Image();
img2.src = "/path/to/image/img2.png";
img2.onload = function() {
ctx.drawImage(img2, 100, 100);
};
I need to remove(replace) img2 from canvas. What is the best way to do it?
I think maybe you misunderstand what a Canvas is.
A canvas is essentially a 2 dimensional grid of pixels along an 'X' axis and a 'Y' axis. You use the API to draw pixels onto that canvas, so when you draw an image you're basically drawing the pixels that make up that image onto your canvas. The reason there is NO method that lets you just remove an image, is because the Canvas doesn't know there's an image there in the first place, it just see pixels.
This is unlike the HTML DOM (Document Object Model) where everything is a HTML element, or an actual 'thing' you can interact with, hook-up script events to etc. this isn't the case with stuff you draw onto a Canvas. When draw a 'thing' onto a Canvas, that thing doesn't become something you can target or hook into, it's just pixels. To get a 'thing' you need to represent your 'thing' in some way such as a JavaScript object, and maintain a collection of these JS objects somewhere. This how how Canvas games work. This lack of a DOM-like structure for Canvas makes rendering very fast, but can be a pain for implementing UI elements that you can easily hook into and interact with, remove etc. For that you might want to try SVG.
To answer your question, simply paint a rectangle onto your Canvas that covers up your image by using the same X/Y coords and dimensions you used for your original image, or try Pointy's solution. 'Cover-up' is probably the wrong terminology, since you're actually replacing the pixels (there are no layers in Canvas).
It's not clear what you want the canvas to show when the image is gone. If you want it to be transparent, you could get the image data and fill it with transparent pixels:
var img = ctx.createImageData(w, h);
for (var i = img.data.length; --i >= 0; )
img.data[i] = 0;
ctx.putImageData(img, 100, 100);
where "w" and "h" would be the width and height of your original image.
edit — if you just want another image there, why not just put one there? It will overwrite whatever pixels are there on the canvas.
You can use clearRect() function to clear the image area.Rather then clearing whole context you can clear only the image area using this:
ctx.clearRect(xcoordinate_of_img1,ycoordinate_of_img1,xcoordinate_of_img1 + img1.width ,ycoord_of_img1 +img1.height );
If what "Sunday Ironfoot" said is right, then the best way to remove an image is by drawing the images once again from scratch. For this, you need to have an array of images and draw only the ones you use. For example,
function EmptyClass{};
var img=new Array();
img[0]=new EmptyClass;
img[0].i=new Image();
img[0].src="yourfile1.jpg";
img[0].enabled=true;
img[1]=new EmptyClass;
img[1].i=new Image();
img[1].src="yourfile2.jpg";
img[1].enabled=false;// <-------- not enabled, should not be drawn equivalent to removing
img[2]=new EmptyClass;
img[2].i=new Image();
img[2].src="yourfile3.jpg";
img[2].enabled=true;
for(var i=0;i<3;i++){
if(img[i].enabled)ctx.drawImage(img[i], 100, 100);
}
P.S. I am creating an engine for javascript canvas. Will post it within a week
Peace
You can erase an image by drawing the same image again, using a different globalCompositeOperation
ctx.globalCompositeOperation ="xor"
ctx.drawImage(img2, 100, 100);
See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation
Unlike drawing things yourself, if you 'replace' THE image on a canvas, the old one is still there.
Canvas c2;
...
if (null != Image2) {
var ctx = c2.getContext("2d");
ctx.clearRect(0, 0, c2.width, c2.height);
}
Can you overlay canvas objects (I guess I should try before asking, you can -1 one me for being lazy). I guess I'd be interested in have one canvas element as a background, and then another for a layer objects that pop in and out of view. Might be a little more efficient then having to redraw every image if one gets deleted or moved. I'll play around and see what I can find.
There is ``ctx.clearRect(x, y, w, h)'' but this is not a good way to remove the shape, because it will remove any full or partial shapes in the same area of the removed shape. This shouldn't happen, and may remove one or more shapes, I've found it's best to save all your shapes in a list that usually comes from the database using backend language or ajax request, and add for it's shape object an identifier, when you need to remove a shape just remove that shape from the list using the id or the index, then Redraw the canvas with this new array of shapes without a deleted shape, the next time the page loads, this shape will not be added to this list, because it should be deleted from database.
const projectStamps = [{image_id: 'scream', x: 100, y: 100, id: 1}, {image_id: 'scream', x: 100, y: 100, id: 2}, {image_id: 'scream', x: 50, y: 0, id: 3}, {image_id: 'scream', x: 150, y: 0, id: 4}];
let currentShapes = [];
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");
function validStampObj(stamp){
if (typeof(stamp.x) !== 'number' || typeof(stamp.y) !== 'number' || typeof(stamp.image_id) === 'undefined' || !document.getElementById(stamp.image_id)){
return false;
} else {
return true;
}
}
function addStamp(stamp){
if (!validStampObj(stamp)){
console.log("can not add stamp, invalid object");
return false;
}
const image = document.getElementById(stamp.image_id);
stamp['w'] = image.getBoundingClientRect().width;
stamp['h'] = image.getBoundingClientRect().height;
ctx.drawImage(image, stamp.x, stamp.y, stamp.w, stamp.h);
currentShapes.push(stamp);
return stamp;
}
let id = 1;
window.onload = function() {
drawProject();
};
function clearCanvas(){
currentShapes = [];
ctx.clearRect(0, 0, canvas.width, canvas.height);
return true;
}
const projectImage = document.getElementById("project_image");
function drawProject(){
if (!projectImage){console.log('missing project image element');return false;}
clearCanvas();
ctx.drawImage(projectImage,0,0);
projectStamps.forEach( (stamp)=>{
addStamp(stamp);
});
}
function removeStamp(targetId){
let targetI = false;
for (let i=0; i<projectStamps.length; i++){
if (projectStamps[i].id == targetId){
targetI = i;
break;
}
}
if (targetI !== false){
/* remove the stamp from drawing stamps list and redraw the data */
projectStamps.splice(targetI,1);
drawProject();
}
}
setTimeout( ()=>{
removeStamp(3);
console.log("removed icon with id 3");
}, 2500 );
<p>Image to use:</p>
<img id="scream" width="35" height="35"
src="https://i.ibb.co/wYyc259/iconimage.png" alt="The Scream">
<img id="project_image" width="450" height="300"
src="https://i.ibb.co/sK5HtQy/bulding-image.png" style="position:absolute;left:-15455px;">
<p>Canvas:</p>
<button onclick="drawProject()">Redraw things</button>
<canvas id="myCanvas" width="450" height="300"
style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
notes if you used clearRect in this example it will remove the part of main image of the canvas not just the icon with id 3 like this code does hope it helps.