I am trying to copy the output of a canvas running webglearth (http://www.webglearth.org/) to a standard 2d canvas. I followed the answer to this question, but I can only see the background colour of the canvas.
My code is:
<html>
<body>
<div id="earthDiv" style="background-color:rgba(255,0,255,0.5); width:500px; height: 500px;"></div>
<canvas id="canvas" style="background-color:rgba(0,255,0,0.5); width:500px; height: 500px;"></canvas>
<script src="http://www.webglearth.com/v2/api.js"></script>
<script type="text/javascript">
window.onload = function () {
var earth = new WE.map("earthDiv");
var earthCanvas = earth.canvas;
var earthContext = earthCanvas.getContext("webgl", {
preserveDrawingBuffer: true,
});
WE.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {}).addTo(earth);
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
setInterval(function () {
context.drawImage(earthContext.canvas, 0, 0);
}, 1000);
};
</script>
</body>
</html>
Turns out this is an issue:
https://github.com/webglearth/webglearth2/issues/104 , where the context for the canvas needs "preserveDrawingBuffer: true" when it is got for the first time.
It can be worked around by changing
Cesium.Scene({
canvas: this.canvas,
contextOptions: { webgl: { alpha: !0 !== c.sky } }
});
in http://www.webglearth.com/v2/api.js
to
Cesium.Scene({
canvas: this.canvas,
contextOptions: { webgl: { alpha: !0 !== c.sky, preserveDrawingBuffer: true } }
});
(and then saving it and using it as a local file).
It can be worked around by getting a png image using
earth.getScreenshot(function(dataUrl) {...}))
(see
https://github.com/webglearth/webglearth2/issues/60 )
However the png approach does not perform amazingly.
Related
I am trying to draw a textbox on canvas that contains an image and some drawing over it. now I am trying to draw a textbox over it.
When I am trying to initialize canvas object using fabricJS it's making canvas empty first. like..
var canvas = new fabric.Canvas('mycanvas')
after this code, it makes canvas empty. but if I initialize this code in the very beginning just after canvas initialized and then I try to add a textbox to that canvas object like...
var text = new fabric.Textbox('A Computer Science Portal',
{
width: 450,
height: 10,
top: 100,
left: 100,
});
this.canvas.add(text);
Then the textbox is not visible. I think it went in the background of the image.
I have already written lots of code for drawing over the canvas not want to draw textbox on the canvas after with all existing drawing and image that is developed in javascript only.
On Fabric you have bringToFront use that to keep the text on top.
Here is the official documentation:
http://fabricjs.com/docs/fabric.Canvas.html#bringToFront
Sample code:
var image;
var canvas = new fabric.Canvas('canvas');
var url = "http://swagger-net-test.azurewebsites.net/api/SvgImage?"
var text = new fabric.Textbox('TEST', { width: 90, height: 10, top: 30, left: 50 });
this.canvas.add(text);
function loadSVG(url) {
fabric.loadSVGFromURL(url, function(objects, options) {
if (image) canvas.remove(image);
image = fabric.util.groupSVGElements(objects, options);
image.name = 'sticker';
canvas.add(image);
image.scaleToHeight(100);
image.center();
image.setCoords();
canvas.renderAll();
canvas.bringToFront(text)
});
}
loadSVG(url + "color=red")
setTimeout(function() {
loadSVG(url + "color=blue")
}, 3000);
<canvas id="canvas" width="200" height="200"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.4/fabric.min.js"></script>
I got this sample of code which i was working on it, i got a trouble with because my image angular doesn't appear on the web browser, i can't understand what's my mistake, thanks in advance for your help.
<html>
<script>
var canvas,context;
function init(){
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
monImg = new Image();
monImg.src="img/angular.png";
context.drawImage(monImg,300,300);
}
window.onload=init();
</script>
<body>
<canvas id="canvas" width="1920" height="1080"></canvas>
</body>
See this question.
You have to wait for the image to load before you do anything with it. The easiest way is:
monImg = new Image();
monImg.onLoad = function() {
context.drawImage(monImg, 300, 300);
}
monImg.src = "img/angular.png";
You need to add a handler for the Image onload where you call drawImage() such as:
<html>
<body>
<canvas id="canvas" width="1920" height="1080"></canvas>
</body>
<script>
var canvas,context;
function init(){
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
monImg = new Image();
monImg.src="img/angular.png";
monImg.onload = function() {
context.drawImage(monImg,300,300);
}
}
window.onload=init();
</script>
</html>
I am learning html canvas and below is my html code.
<!DOCTYPE html>
<html>
<head>
<script language="javascript">
function moveImage(x) {
var context = document.getElementById('myCanvas').getContext("2d");
var img = new Image();
img.onload = function () {
context.drawImage(img, x, 259);
}
img.src = "flower.jpg";
}
function startDrawing() {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(50, 300);
context.lineTo(950, 300);
context.stroke();
var x=50;
setInterval(function() {
x = x+20;
moveImage(x);
}, 1000);
}
</script>
</head>
<body onload="startDrawing()">
<canvas id="myCanvas" width="1000" height="1000">
</body>
</html>
Please find the below output from this code:
How can I remove the traces of 'older frames' (of the flower), as you could see lots of flowers while it is moving from left to right in the screen shot ? Please help the code changes required.
Thanks.
The problem is you aren't clearing the canvas before drawing on it again. You can clear it using clearRect.
setInterval(function() {
// Clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
x += 20;
moveImage(x);
}, 1000);
Keep in mind that this will clear the entire canvas. If you're rendering anything else, you'll want to redraw it after the clear.
You need to re-render the frame. Here's some code from an incomplete game I wrote:
var main = function () {
var now = Date.now(),
delta = now - then;
update(delta / 1000);
render();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
GitHub repo code
My render function contains the context.drawImg() work (getting properly re-rendered), and that's similar to your moveImage function.
Edit: A little explanation. The image traces are previous renderings of the your image at each updated position. Without the frame itself being reset, each move of the image is preserved on the screen, giving the appearance of a trail of images.
I have a canvas, which handle images drawn on it with the CamanJS plugin and it works perfectly. But if I manipulate the canvas manually (without the aid of plugin) the image loses its effect. For example, if I add a filter (Vintage, for example) to the image, works perfectly, but if I turn the canvas, using translate and scale the canvas is reversed but the image loses its effect. It seems that with each change in the image through the plugin, it saves its current state, and therefore, the effect is lost after a change without using it. How to do this while preserving the effects of the image?
To add to the effect, use the same examples of the plugin site, since the code to reverse the canvas is (scripts.js):
$(document).ready(function() {
$("html, body").on("click", "#vintage", function() {
Caman("#filtrar", function() {
this.vintage().render();
});
});
$("html, body").on("click", "#inverter_foto", function() {
var c = $("#filtrar")[0];
var ctx = c.getContext("2d");
ctx.translate(filtro_width, 0);
ctx.scale(-1, 1);
ctx.drawImage(filtro, 0, 0);
});
});
The filtro_width variables and filtro correspond to the image drawn on the canvas.
on HTML:
<canvas id="filtrar" width="640" height="255"></canvas>
<button id="vintage">Vintage Effect</button>
<button id="inverter_foto">Reverse</button>
<script type="text/javascript" src="/js/jquery-2.1.3.min.js"></script>
</script>
<script type="text/javascript" src="/js/caman.full.min.js"></script>
<script type="text/javascript" src="/js/scripts.js"></script>
Example:
If you do manipulate the canvas outside of the Caman library, you need to use the reloadCanvasData method to reinitialize the imageData stored in the Caman object, otherwise, it only uses the first one + what it updated itself.
vintage.onclick = function() {
Caman("#filtrar", function() {
this.vintage().render();
});
};
inverter_foto.onclick = function() {
var c = $("#filtrar")[0];
var clone = c.cloneNode(true);
var ctx = clone.getContext("2d");
ctx.translate(c.width, 0);
ctx.scale(-1, 1);
ctx.drawImage(c, 0, 0);
var oCtx = c.getContext('2d');
oCtx.clearRect(0, 0, c.width, c.height);
oCtx.drawImage(clone, 0, 0);
if(check.checked){
Caman("#filtrar", function() {
this.reloadCanvasData();
});
}
};
var filtro = new Image();
filtro.crossOrigin = 'Anonymous';
var filtro_width = filtrar.width / 2;
filtro.onload = function() {
filtrar.getContext('2d').drawImage(this, 0, 0, filtrar.width, filtrar.height);
};
filtro.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/camanjs/4.1.2/caman.full.js"></script>
<p>First revert the image then apply the effect</p>
<button id="inverter_foto">Reverse</button>
<button id="vintage">Vintage Effect</button>
reloadCanvasData<input id="check" type="checkbox" checked/>
<canvas id="filtrar" width="640" height="255"></canvas>
I am drawing image which is loaded using loader method in two different places. But it only displays the second one. (I am following this http://www.html5canvastutorials.com/tutorials/html5-canvas-image-loader/)
If I add an alert() it works in Fx but not in Chrome. I want it to work everywhere without alert()
If I try drawing Image without using preloaded image I am getting the desired result. But I am thinking it is extra load (http://www.html5canvastutorials.com/tutorials/html5-canvas-images/)
ImageOnload("O",120,120); //This image not displaying
alert("If i add alert it works only in Fx but not in Chrome")
ImageOnload("O",120,20);//only this is displaying ???
<html>
<head>
</head>
<script type="text/javascript" >
var ctx;
var ImageVariable={};
window.onload= function()
{
var canvas = document.getElementById("gameLoop");
ctx = canvas.getContext("2d");
ImageBuilder(ImageSourceDB);
ImageOnload("O",120,120); //This image is not displaying
//alert("If i add alert it works only in FFox but not in chrome")
ImageOnload("O",120,20);
}
var ImageSourceDB=
{
X:"./Images/X.gif",
O:"./Images/O.gif"
}
function ImageBuilder(ImageSrcDB)
{
for (iSrc in ImageSrcDB)
{
ImageVariable[iSrc]= new Image();
ImageVariable[iSrc].src = ImageSrcDB[iSrc];
}
}
function ImageOnload(ImageSrc,x,y)
{
ImageVariable[ImageSrc].onload= function ()
{
ctx.drawImage(ImageVariable[ImageSrc],x,y);
};
ImageVariable[ImageSrc].src = ImageSourceDB[ImageSrc];
}
</script>
<body>
<canvas class ="pattern" id="gameLoop" height="300" width="300" />
</body>
</html>
List item
ImageOnload("O",120,120); //This image not displaying
ImageOnload("O",120,20);//only this is displaying ???
You forgot to change the id of the object:
ImageOnload("O",120,120);
ImageOnload("X",120,20); // Use "X", not "O"!!!
If you still want to show "O" twice, then you should draw it twice, but with only one onload function. See example below:
<script type="text/javascript" >
var ctx;
var ImageVariable={};
var ImageSourceDB = {
X:"./Images/X.gif",
O:"./Images/O.gif"
}
window.onload = function() {
var canvas = document.getElementById("gameLoop");
ctx = canvas.getContext("2d");
ImageBuilder(ImageSourceDB);
ImageVariable["O"].onload = function() {
// this will be executed when the image "O" is loaded
// this is a pointer to ImageVariable["O"]
ctx.drawImage(this, 120, 120);
ctx.drawImage(this, 120, 20);
}
ImageVariable["X"].onload = function() {
// this will be executed when the image "X" is loaded
ctx.drawImage(this, 30, 30);
}
}
function ImageBuilder(ImageSrcDB) {
for (iSrc in ImageSrcDB) {
ImageVariable[iSrc]= new Image();
ImageVariable[iSrc].src = ImageSrcDB[iSrc];
}
}
</script>