Monday, October 3, 2016

Debugging Touch Events on the Desktop

It can be a pain in the behind to debug touch events when developing your web application on the desktop. But I found this great setting in Chrome that makes it a whole lot easier. Just put this into the browser:

chrome://flags/#touch-events

If you set the value to "enabled" it will then emulate touch events whenever you are emulating a touch device. How do you emulate a touch device, you ask?

To emulate a touch device open up developer tool (F12) and click on the "Toggle Device Toolbar" button. At the time of this writing it's in the upper left corner of the window (it seems to move around with each new release so you may have to hunt for it).


When you turn this feature on it shows how the web page would look on that device, allows you to rotate the device, and allows you to choose from multiple devices including iPhone and Nexus or even define your own device.



When you have both of these features enabled you will start getting touch events instead of mouse events. To switch back to mouse events just turn device emulation off. You can leave the touch-events flag on, it won't hurt anything.

Code hard!

Thursday, August 25, 2016

HTML5 Canvas DrawImage Artifacts

I'm working on an HTML5 canvas game that requires smooth scrolling of images across the screen. The coordinates of the images are real numbers, not integers. The canvas can handle real number coordinates just fine and antialiases everything to make it look smooth. The problem is that it also sometimes produces some weird artifacts to be drawn.

What do I mean by artifacts? Artifacts are pixels that are drawn that you don't expect. In my case, for example, I have an image that has a significant amount of transparent pixels. When it's drawn at particular locations thin gray lines get drawn in some of the space where it should be transparent. It's not a lot, but it's noticeable.

So what can you do about it? There are a couple things, but they have their disadvantages. For one thing you can convert all of your coordinates to integers. One way to do this is with a little JavaScript trick; binary "or" the value with 0.

var x = 1.67;
x = x | 0; // x is now 1

That eliminates the artifacts because the images are drawn on whole pixel boundaries, so there's no need for the canvas to smooth out the image. The problem is that it makes your animations really choppy, especially if you have a lot of images scrolling next to each other.

Another thing I tried was to use Math.round() instead of just lopping off the fraction. I figured that would reduce the amount of choppiness. Unfortunately it didn't make much of a difference.

var x = 1.67;
x = Math.round(x); // x is now 2

But wait, there's one more. The canvas context has an imageSmoothingEnabled property you can set to true or false. By default it's true. I found that when you set it to false it's basically the same as using Math.round() above. It forces your images to be drawn on whole pixel boundaries. Which also produces choppiness.

context.imageSmoothingEnabled = false;
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;

So now we're right back where we started. In the end I decided not to use any of these methods and just stick with the occasional artifact being drawn. It looks crappy, but it only seems to happen at certain screen locations. In my case having smooth animations was far more important than the occasional artifact.

I think in most cases the choppiness wouldn't be such an issue and one of these techniques would work. It's up to you to determine what looks best. I would go with using imageSmoothingEnabled property because then you don't have to add any extra code to convert to an integer. Let the system do the work for you.

Code hard!

Saturday, May 7, 2016

Testing TypeScript Modules with Jasmine

In my previous post I talked about using TypeScript/ES6 modules. I have been thinking about making the transition from namespaces to modules, but there were a few things I needed to work out first. First of all how to load them (native ES6 support isn't widely available at the time of this writing). In the previous post I talked about using a library called Require1k (http://requirejs.org/) as the module loader. As the name suggests it is only 1kb in size yet provides the basics you need for CommonJS module loading. So far it does everything I need.

The next thing I needed to work out was how to package up my application when it was ready for release. In that post I also talked about using WebPack in Node.js to combine and minify the application modules.

The final thing I needed to work out was how to get my Jasmine (http://jasmine.github.io/) unit tests to run against modules. This was giving me a lot of trouble; it's not as easy as you might think. Jasmine was built in such a way that it expects all of your files to be loaded using script tags, then it runs when the page onload event fires. Unfortunately when using a module loader things don't happen that way. The module loader doesn't load your modules until after the page is loaded.

So for the remainder of this post I'll show how I got my Jasmine tests to run using the Require1k module loader. Although I'm using a specific module loader there shouldn't be any problem using the same principles for any other CommonJS module loader library as they most all work the same way.

Creating the Unit Tests


The first thing we need to do is create unit tests. I won't go into how to write Jasmine tests. There are plenty of good examples on their web site. The only difference is that you will need to use import statements to reference the modules you want to test.

For example, say you want to test module1.ts. Then your unit tests might look something like this.

/// <reference path="../scripts/typings/jasmine/jasmine.d.ts" />
import * as Module1 from "./module1";
describe("When testing module1", () =>
{
    it("should be true when something happens", () =>
        expect(Module1.something()).toBeTruthy());
});

First we have a reference to the Jasmine type definition file (because as TS programmers we like to have better tooling and autocompletion). Then we import everything from module1. Then we define the Jasmine specs for the unit tests. It's that simple ;-).

One important thing to point out here: your unit tests are modules too. Once you decide to use modules everything needs to be a module. Our unit tests need to load the modules they test, therefore they have to be modules for the module loader to pick up the imports and load them.

The Bootstrap File


Now we need a bootstrap file. This is the main file that gets things going. We will call this file unit-tests.ts.

declare function require(s: string): void;
 
require("./module1.spec");
require("./module2.spec");
 
jasmine.getEnv().execute();

The first thing we did was to declare the require function. This is the function defined by the Require1k library (or any other library for loading CommonJS modules) to load a module file. Without this we would get errors from the compiler because it doesn't know what "require" is.

Next we use require to load all of the unit test modules. In this case we have unit tests for two different modules.

I like to name my unit test files with the name of the module it's testing and a ".spec.ts" extension. This way you know exactly which module it's for and you know it's a Jasmine test file (Note: unit tests are known as specs in Jasmine).

The last line is necessary to tell Jasmine to start running the tests. As I stated above, Jasmine will look for any unit tests and run them on page load. But since this is all happening after page load we have to explicitly tell it to run again.

You might be asking yourself: why not use import statements to load all of the unit test files? That's a valid question. The unit tests are modules, I said so previously. The answer is: because nothing is being exported from the unit test modules. All they do is define Jasmine specs. Therefore if you tried to import them the TypeScript compiler would see there's nothing being exported and just skip it. Then your unit tests wouldn't load and you would be wondering what's going on (not that I'm speaking from experience or anything like that).

The Host File


The final thing we need to do is set up the host HTML file to run the unit tests. It will have all of the files for jasmine, of course. Then it will need the script tag for Require1k.

<link href="../Content/jasmine/jasmine.css" rel="stylesheet" />
<script src="../Scripts/jasmine/jasmine.js"></script>
<script src="../Scripts/jasmine/jasmine-html.js"></script>
<script src="../Scripts/jasmine/boot.js"></script>
 
<script src="require1k.js" data-main="./unit-tests"></script>

The "data-main" attribute tells Require1k what the main or start file is. In this case unit-tests.js which we created above. This will define the starting point of the module loader. From there it will load the unit test modules which will in turn load the modules they are testing.

Conclusion


The trick to testing external modules with Jasmine is to have a single bootstrap file that loads all of the unit test files and to tell the module loader where to find it. Then the key to making it work is to tell Jasmine to run again after all of the tests and modules have been loaded.

Switching from internal namespaces to external modules in TypeScript requires a whole new way of looking at things and some new ways of doing things that you're not used to. You just have to learn a few new tricks to get it to work across the board from your source code to your unit tests.

I think in the end using modules is the way of the future for TypeScript, and JavaScript. Once ES6 is fully supported by all browsers and able to provide native module loading things will be a lot easier and modular JS will become more popular.

<jmg/>