I want to manipulate a canvas but I'm not able to call getContext on the canvas element which I get from Webdriver:
browser.findElement(webdriver.By.id('my-canvas')).then(function (canvas) {
var ctx = canvas.getContext('2d');
...
});
I've also tried canvas[0] but that doesn't work too, getContext is undefined. How can I reach this native canvas function ?
UPDATE: I've tried executeScript which works, but is extremely slow
Related
Chrome keep printing this warning: "Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true.". I checked the code, where the warning triggers, and you can see I set the willReadFrequently attribute to true. What could be the problem? There was this warning in other places, but there the willReadFrequently attribute solved it.
The problem in Chrome 104-108 exists for sure. Btw, I am in a WebWorker. Could this be a chrome bug?
const offdesireCtx = offDesire.getContext("2d", { willReadFrequently: true });
if (!offdesireCtx) {
throw new Error("Desired OffscrenCanvas ctx undefined");
}
const offGetCtx = offGet.getContext("2d", { willReadFrequently: true });
if (!offGetCtx) {
throw new Error("Get OffscrenCanvas ctx undefined");
}
var imgd = offdesireCtx.getImageData(0, 0, tileSize, tileSize), pix = imgd.data; //Warning triggers
var imgdGet = offGetCtx.getImageData(0, 0, tileSize, tileSize), pixGet = imgdGet.data; //Warning triggers
As MDN says about willReadFrequently:
This will force the use of a software (instead of hardware accelerated) 2D canvas and can save memory when calling getImageData() frequently.
This means the canvas must be created, drawn to, and read from entirely on the CPU. Calling getContext provides a handle to the canvas buffer on the GPU by default, and if that call ever occurs with this canvas earlier on, that data is already on the GPU and it would have to be copied back to the CPU, defeating the goal of the performance warning.
I found in my case, I was creating the canvas and writing to it in one function, then returning the canvas. Later in my code, the result of that function call took the same canvas and created another context. It applied the
{ willReadFrequently: true } options argument to that call, but that was the second time getContext was called for this canvas. That means the texture buffer was already living on the GPU by this point and the second getContext call was ignoring the willReadFrequently suggestion as the data was already on the GPU.
So you need to trace back to where your canvas is first created, and then where its first getContext is called and drawn to. Subsequent canvas.getContext("2d", { willReadFrequently: true }) calls are too late to matter (and are likely even fine to omit the option). Think about when the texture buffer is being created and trace through your data flow to make sure it all lives on the CPU since its inception.
I'm trying to use offscreen canvas for rendering in webworker, which works perfectly fine in Chrome, but it seems that 2D context is not yet available in Firefox. How do I know that in advance? By the time I get to creating the context, it is already too late and the original canvas is no longer functional for drawing.
Basically what I'm doing
const offscreen = canvas.transferControlToOffscreen();
worker.postMessage({canvas: offscreen});
...
// in worker
canvas.getContext("2d") // exception!
// but there's no fallback now, because we already called transferControlToOffscreen
Edit: somehow it didn't occur to me to create another canvas and make it offscreen before "experimenting" with the main ones. That works, but seems like a hack.
The context returned by OffscreenCanvas.getContext('2d') is an OffscreenCanvasRenderingContext2D instance.
Browsers that will support this call, will have this interface available, so all you need is:
const supports = typeof OffscreenCanvasRenderingContext2D === "function";
console.log(`Your browser ${supports ? "supports" : "doesn't support" } the 2d context of the OffscreenCanvas`);
You have to concatenate both getContext and getContext('2d'):
function isCanvasSupported(){
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
}
I'm not sure what I'm doing wrong in this problem. I'm using OpenProcessing and trying to put a canvas element within a container but I'm running into an Uncaught TypeError, Cannot read property "id"
I'm copying the same code from https://github.com/processing/p5.js/wiki/Positioning-your-canvas
function setup() {
var cnv = createCanvas(100, 100);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
background(255, 0, 200);
}
This is my code...
function setup() {
var cnv = createCanvas(500, 100);
cnv.id("hello");
cnv.position(0,0);
}
function draw() {
}
Here is a link to my sketch...
https://www.openprocessing.org/sketch/407956
It has something to do with OpenProcessing because your code works absolutely fine on p5 editor (and locally).
The createCanvas method returns an object so calling the id function on it should not return "Cannot read property 'id' of undefined" as it did on OpenProcessing so createCanvas possibly isn't returning anything, and it should return an object according to p5 documentation..
You can try positioning the canvas using css as described in p5 wiki by adding a stylesheet that uses flexible box layout or try not using OpenProcessing if possible.
The createCanvas() function is not returning anything. This doesn't jive with what's in the P5.js reference, so I understand your confusion.
My guess is that OpenProcessing uses a slightly modified version of P5.js, because it doesn't really require any positioning. The canvas is always centered in the screen.
If you're going to continue using OpenProcessing, then I'd stop worrying about positioning the canvas yourself. Or I'd search for existing sketches that reposition the canvas and see how they do it.
Even if the createCanvas() function returns soemthing, I'm not sure what the id() function is supposed to do in this case. Nothing in the link you posted uses that function. Nonetheless, it seems to work fine if I run it locally.
Ok so I'm creating a game with JavaScript Canvas Elements and such. I've been able to load in TONS of Images, but on a select few, JavaScript replies with Errors such as
Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': No function was found that matched the signature provided.
Which makes NO SENSE at all, because the same code works in other places!?!
Here is an example I have in my code:
board.drawImage(document.getElementById("player_explode"), this.x, this.y);
Inside of an objects method, Player.die(), respectively.
Does anyone know why this behaviour is coming about? I'm getting very frustrated about it...
Here is a JSFiddle to demonstrate, alonside all the code.
Player.die() is located on line[242].
The problem was the way that I was loading my Images, I should've been doing:
var image = new Image();
image.src = "imagesource.jpg";
But instead I was get the elements by id from the document page.
Resources:
Explanation on loading images
Explanation on how html loads images
you should wait all elements load,so do like this:
window.onload=function(){
board.drawImage(document.getElementById("player_explode"), this.x, this.y);
}
For people in 2021 learning React, you have to call the context.drawImage() in the img.onload or nothing will be shown on the canvas! Here is a real world working example:
useEffect(() => {
canvasRef.current.width = mapXYWH.w * UNIT
canvasRef.current.height = mapXYWH.h * UNIT
const context = canvasRef.current.getContext("2d")
map.map(o => {
const img = new Image(o.width*UNIT,o.height*UNIT)
img.src = o.normal
img.onload = () =>
context.drawImage(img, (o.x-mapXYWH.x)*UNIT, (o.y-mapXYWH.y)*UNIT)
})
}, [map, mapXYWH])
See also: React -- Canvas Won't Draw Image
In my Greasemonkey script, when I obtain a handle on an HTMLImageElement I want to use with an HTML Canvas, I get the following error in Firefox's Error Console (I assume it's because it's enclosed in an XPCNativeWrapper):
Error: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE)
[nsIDOMCanvasRenderingContext2D.drawImage]
Putting GM_log() statements throughout my code, I have traced the image object I'm trying to use from it's initial assignment through until I try to use it with an HTML Canvas.
It's always wrapped in an XPCNativeWrapper:
[object XPCNativeWrapper [object HTMLImageElement]]
I've unwrapped the HTMLImageElement by obtaining reference to it with image.wrappedJSObject.
My canvas code:
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0);
Any ideas why Firefox is throwing the above component failure code?
I should have looked more thoroughly on Google.
image.wrappedJSObject;
Works.
var canvas = document.createElement("canvas").wrappedJSObject,
ctx = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0);
this is what i did. hope it helps
I just had the same problem. The error went away when I used an absolute/complete URL for the image. Also, as someone else had noted, make sure the image is loaded first of all, or just create a new Image() in javascript first of all.
Working example for firefox 3.6.16 (I had similar problem):
http://userscripts.org/scripts/review/106800