2

If we want to draw something on canvas we need to get 2D context of it. I have a canvas element in index.html of project:

 <body>
    <canvas id="canv" width="200" height="200"></canvas>
 </body>

So now I need to get access for that element, ok, let's write code:

var cans:CanvasElement = Browser.document.getElementById("canv");

and in compile phase I get error:

src/Main.hx:32: characters 2-78 : js.html.Element should be js.html.CanvasElement

But if we use unsafe casting, already will be fine:

var cans:CanvasElement = cast Browser.document.getElementById("canv");

And everything works fine, I get access and can get 2D context or make some settings like:

cans.width = cans.height = 800;
cans.style.backgroundColor = 'rgba(158, 167, 184, 0.4)';

Yes, I know, "if it works - don't fix", and I roughly understand that everything is normal, in principle I get what I need, when get cast, but can anybody explain this process for me? What does that mean - js.html.Element should be js.html.CanvasElement? I'm only started Haxe learning (and programming in particular), I'm glad, that I can do workable things, but I want to know, why it works when it works and why not when it doesn't.

Gama11
  • 31,714
  • 9
  • 78
  • 100
Green Joffer
  • 580
  • 1
  • 4
  • 16

2 Answers2

5

js.html.Element should be js.html.CanvasElement

This just means that the compiler expected the type CanvasElement (because that's what the type hint for the cans variable tells it), but encountered something else (Element in this case). You're trying assign the value returned by getElementById() to cans, but getElementById() returns an Element.

Since Element is less specific than CanvasElement (CanvasElement extends Element), you can't just assign an Element to a CanvasElement - who's to say it's not a DivElement, or any of the other options? This can only be decided when the code is executed / the compiler can't know this, hence the error (runtime vs compile time).

This works fine in this case because you know that the element with the ID "canv" is in fact a CanvasElement, so you can silence the compiler by telling it that you know what you're doing with a cast. It will go wrong when the returned value actually has another type.

Gama11
  • 31,714
  • 9
  • 78
  • 100
-1

Gama11 answer is really good. Sometimes easier just to create the canvas in code, like this simple snake. https://try.haxe.org/#D0324 Secondly sometimes you can use another variable and let the abstractions stuff auto cast it for you, but I think you might end up still using a cast in your code.

var canvas = document.createCanvasElement(); 
var dom = canvas; 
var style = dom.style; 
// HTMLDocument is needed here so dom is infered to
// HTMLDocument type and the canvas is auto cast, 
// via the use of the secondary variable.

The problem here is not really Haxe, the problem is the way HTML5 has evolved or retrospecively re-designed, Haxe is just trying to wrap something that is sort of Dynamic and inconsistant with some attempt at providing proper compiler checking and consistancy, often when types come into Haxe like loading data, you have to cast them for Haxe, but you only have one risky point, from then on the compiler can help you. You can in some cases be more explicit with your cast:

var style = cast( canvas, HTMLDocument ).style;

telling Haxe how you are expecting it to be cast. For some targets that are less dynamic Haxe can do a better job with the type systems, but the fact that js is so slack means despite the odd complication the use of Haxe is even more powerful for js coding. Stick with Haxe it's good for your general code understanding of many languages.

Justinfront
  • 472
  • 2
  • 10
  • 1
    Actually, it's considered bad practice to use a safe cast here. Safe casts carry a runtime overhead, and for that overhead they guarantee an exception to be thrown in case the cast fails - meaning that if you're not wrapping it in a try-catch, you're just wasting performance / should be using an unsafe cast. See the [last section](https://haxe.org/manual/expression-cast-safe.html) of the Haxe Manual page. – Gama11 Aug 23 '17 at 21:44
  • Oh ok, that's useful to know :), sorry about that. – Justinfront Aug 24 '17 at 08:50
  • No problem. I find it's one of the most common misconceptions about Haxe syntax. – Gama11 Aug 24 '17 at 09:35