Heads up: Accel orientation may not match phone (bug?)


This is in WebAR, using an iPhone. If a user turns their phone on its side, we potentially need to reposition and scale elements to fit them to the new shape of our canvas. So it makes sense that we’d use an Accelerator node’s events to trigger a state shift, and possibly use any aspect ratio we’ve found out to tidy up positioning.

But Zap seems to trigger an orientation change before the phone has decided to reorient things. See video for what I mean: as I turn the phone slowly, Zap decides the phone is far enough over to go into “landscape” mode way before the phone has - https://youtu.be/go6JJwG0s38. So there’s no point repositioning stuff when those orientation events get fired off as the browser hasn’t yet decided to reconfigure itself.

I’ve worked round this for now by setting up handlers for the accelerometer that just note what orientation is being reported (portrait / landscape / land_inverted etc) but don’t actually trigger the state. Then you can use a Z.screen.on(“resize”… to actually trigger the state change:

var curr_orient = 0;
var curr_height = 100;
var curr_width = 100;
var aspect_ratio = 1.0;

parent.on("landscape", () => {
	// Runs when landscape occurs on the parent node
    // check aspect ratio
    curr_orient = 0;    

parent.on("portrait", () => {
	// Runs when portrait occurs on the parent node
	curr_orient = 1;    

parent.on("landscapeinverted", () => {
	// Runs when landscapeinverted occurs on the parent node
	curr_orient = 2;    

parent.on("portraitinverted", () => {
	// Runs when portraitinverted occurs on the parent node
	curr_orient = 3;    

    curr_height = height;
    curr_width = width;
    aspect_ratio = height/width;

function do_resize() {
    switch(curr_orient) {
        case 0: symbol.controllers.orientation.elements.landscape.activate();
        case 1: symbol.controllers.orientation.elements.portrait.activate();
        case 2: symbol.controllers.orientation.elements.lanscape_inv.activate();
        case 3: symbol.controllers.orientation.elements.portrait_inv.activate();

This seems like a long way round, but it seems like the safest approach for now (particularly if you want to use a device’s aspect ratio to position things nicely).


Unfortunately this is not an issue with Zappar, but with the browser. Zappar uses the accelerometer readings provided by the browser. The orientation change event is triggered by the browser and Zappar listens to it. I know because this issue happened on a non-zappar project before.

Inconsistencies like this will always be present because browsers implement the web apis differently under the hood. Specially if we’re talking about Safari.


Interesting. I’ve just noticed that portrait lock on an iPhone doesn’t stop Zap from triggering orientation changes – it’s arguable that if the user has locked orientation then Zap shouldn’t fire orientation change events. Still, with the combination of the orientation events plus the on(“resize”) event, you can infer the user’s preference. If no resize occurred (ie the browser chrome hasn’t shifted), you may not want to shift your UI round, depending on the context of your particular project.

I’ve just been playing around a bit more: it’s interesting that the height and width returned by on(“resize”…) don’t follow the orientation either: the height reported (on my phone at least) is always the larger of the two dimensions. Useful to know.

Heh - it’s the perennial problem: the docs for Zap Studio are pretty good, but there’s a wealth of nitty gritty stuff that you only find out by trawling the forums or testing yourself. Sorta wish there was a wiki we could add all this stuff to (not least because I forget more than I remember :wink: )


One last quick note - if you do use the code above to reposition UI elements, note that the Zappar app never resizes, even if you turn your device over, so that’ll need to be handled with the normal Accel events.

:upside_down_face: ƃƃƃƃɹɹɹɐ uoıʇɐʇuǝıɹo ǝןpuɐɥ oʇ pɹɐɥ os ʇı sı ʎɥʍ