First and foremost, let me give credit where credit is due. When I ran into the problem of the mouse X and Y not being where I thought they should be in the Origami Phone patch, I came across this Macoscope blog post by Dawid Woldu which explains the cause of the issue (much better than I could) and a solution for the problem in iPhone portrait mode. This article and my mouse position patch are based on his work, and I highly recommend reading it!
Since he wrote that article, Origami was updated to version 1.2, which added not only other devices, but landscape orientation. Since the UI I am mocking up is landscape only, I needed a solution for that, and while I was at it, I figured I might as well take a stab at handling the new devices. The result is a Composition that will give you the correct mouse X and Y for all the Origami
Phone devices in landscape and portrait. Mostly1. It also renders the coordinates on the device screen, and has a happy little square
Hit Area that should follow in the center of the cursor as you move it around:
Here’s the file so you can follow along with the rest of the article, or if you just want to grab out the bits you need and get on with your day: MouseAnger.qtz.zip (889k) It’s got a bunch of Notes in there that explain a lot of what is going on as well.
How it works
In a nutshell, we pass in the window aspect ratio and device screen width and height (we don’t have access to
Pixels Wide and
Pixels High so we have bring them in again) to the
Render In Image patch:
These are published inputs of my
Where Da Mouse At? macro patch that does the conversion, which lives inside the
Render In Image:
Where Da Mouse At? Macro, we use the device height and device width to determine a couple things; the aspect ratio of the device, and its orientation. To get the aspect ratio of the screen, we divide the smaller side into the larger. Determining if we are in Portrait orientation is done by dividing height by width and checking to see if that number is greater than one in a
Once we know the orientation of the device, we correct the X position in one of two ways: if we are in portrait mode, we adjust based on the aspect ratio of the window, the device aspect ratio, and a fixed number that represents the size of the simulated device relative to the window (which I badly named origamiConstant):
mouseXPosition * (phoneAspectRatio / origamiConstant) * windowAspectRatio
If we are in landscape mode, we can just divide the mouse position by the
origamiConstant. These values are piped into a
Multiplexer which selects the value to output based on our
Is Portrait conditional:
Adjusting the Y position is similar to adjusting the X, but backwards! In portrait, we do a straight division by the
origamiConstant, but in landscape we have to account for the window and device aspect ratios:
mouseYPosition * (phoneAspectRatio / origamiConstant) / windowAspectRatio
Again, these two values are sent to a multiplexer that outputs the correct one based on our calculated device orientation:
There’s one glaring omission, and that’s the value of
origamiConstant. Where did that come from? Well, from another Macro patch I made that takes in the maximum value of the device screen size, and outputs the appropriate magic number based on that:
How does this work? Nothing fancy, I’m afraid. I use the screen size to tell what device you are using, and I spit out the right value based on that. How do I know the right value? Because I made my Quartz Composer window exactly 1000px wide, took screen shots of all the devices, then measured how many pixels across the screen was. How lazy is that? Very. But it works. Mostly2.
Here are the fudge factors I got if you would like to use them for some other reason:
- iPhone: 0.61
- Android: 0.62
- Windows Mobile: 0.59
- iPad: 0.736
Here’s the file link again just in case you missed it: MouseAnger.qtz.zip (889k)
1: The coordinates will start to not be accurate if the Viewer window itself is “more portrait” than a portrait device, or “more landscape” than a landscape device. This is because the ratio of the screen to the window stops being constant at that point.
Since I saw in a GitHub issue that Facebook was looking into this, I most likely will not go through the effort to calculate everything the “right” way, since they will probably do it much better than I. Until then, this works for the most part.
2: See note 1
back to top