blog.pretopia.net

Thijs van As (@tvanas)

SketchIt - A mobile HTML5 doodling app

April 21st, 2011

Some time ago, while using the Adobe Ideas drawing/sketching app on my iPad, an idea sprung to mind to create a mobile web-based (HTML5) sketching app. The advantage of having a web-based app is mainly that is platform-independent. That, and the fact that I had a straightforward implementation in mind, made me decide to create one: SketchIt.

Just another little fun project after creating some HTML5 games.

Functional Design

The core functionality of SketchIt had to be really straight-forward: allow the user to create some sketches, and save them as an image to his device. I defined the following core features of the app:

  • Doodle using touch or mouse gestures (depending on the device)
  • Pick a color to doodle with
  • Choose the line-width of the pencil
  • Save the sketch as an image

Starting with these features, SketchIt provides just enough functionality to be useful for people. And I wanted to keep the interface really minimalistic. There were some constraints that I laid down for myself:

  • The app should work on as many devices as possible
  • The application should exclusively run on the client (in the browser), no server-side activity other than downloading the application are allowed (so that the application can be ran offline)
  • The codebase should be clean

Implementation

As I wanted SketchIt to be web-based and running on the client in the browser, choosing JavaScript + HTML5 for the implementation was the obvious thing to do. These technologies are supported by all major web 

browsers, both on desktop computers as well as mobile devices. Not all browsers have the same grade of support, but that will fade over time (that’s an infrastructural issue).

I broke down the application logic of SketchIt into 2 modules:

  1. A drawing surface that allows a user to doodle on, and save its creation (Sketchpad.js)
  2. A color picker that allows the user to pick a color that he wants to use (ColorPicker.js)

Those 2 modules, wrapped inside a jQuery Mobile interface would become the initial version of the application. There are some other nice mobile UI frameworks, but I really like the simplicity and quality of jQuery Mobile.

Both Sketchpad.js and ColorPicker.js are open source modules, and can be retrieved from Google Code. The source code is annotated with JSDoc.

Sketchpad.js

Sketchpad.js is the module that implements the sketching surface. It is mostly fluff around the HTML5 Canvas API. With this module you can instantiate one or more sketching surfaces with a given width and height. Instance methods are provided to set the sketching color, line width, and to export the sketch to an image.

To export an image, the toDataURL method of the Canvas object is used. This returns a Base64 image representation of the Canvas, in a given (and supported) file format. Unfortunately, this method is not yet implemented in Android (<= 2.3), so saving a sketch as an image is not yet supported on Android devices. I read somewhere that Android Honeycomb (3.0) for tablets already implements the toDataURL method on the Canvas.

Example of Sketchpad.js usage (jsfiddle.net)

ColorPicker.js

ColorPicker.js instantiates a color picker, defined by a number of optional parameters: width, height, lightness and callback functions for choosing a color or mouse-over’ing a color.

Example of ColorPicker.js usage (jsfiddle.net)

Extra features

This basic implementation of SketchIt leaves room for many features on different areas:

  • A local library of saved sketches (and resume editing)
  • Post sketches to social networks
  • Share/collaborate on sketches with friends
  • Different pencil types

Anyway, at least for now these are beyond the scope of this little project. You can try SketchIt on http://m.pretopia.net/sketchit

Classes with private properties in JavaScript

April 6th, 2011

JavaScript, a prototyped language, offers multiple ways to ‘emulate’ a classical class model. The best way to add methods to a constructor (class) function, is by extending its prototype object. However, all these properties are public, and can thus be accessed by anybody who has access to the object. It is somewhat less obvious to create a class that has private properties (methods or variables that are only accessible from within the class). I created a boilerplate class for the situations when I need this: 

MyClass = function() {
    // 'that' is used to access 'this' of MyClass from within private
    // methods, because 'this' is then bound to the global object
    var that = this;

    // private variables
    var privateVariable = 'I am private';

    // public variables
    this.publicVariable = 'I am public';


    // private methods
    var privateMethod = function() {
        console.log('Private method entered');
        console.log(privateVariable);
        console.log(that.publicVariable); // note the use of 'that'
    };

    // public methods
    this.publicMethod = function() {
        console.log('Public method entered');
        console.log(privateVariable);
        console.log(this.publicVariable); // note the use of 'this'

        privateMethod();
    };
};

When you create an instance of MyClass, only publicVariable and publicMethod will be public properties. This can be confirmed by looping over all properties of an instance:

MyInstance = new MyClass();

var property;
// iterate over all public properties (variables and methods)
for (property in MyInstance) {
    // print the property's name + type
    console.log(property + ' : ' + typeof MyInstance[property]);
}

/* console output:   
    publicVariable : string
    publicMethod : function
 */

Note that from within a private method, public properties are accessed through that. This is because of an unfortunate choice in the design of JavaScript which states that within all functions called directly, this is bound to the global object. This doesn’t happen when a function is called as a method (a property from another object), constructor (a class), or using the standard apply method of a function.

A disadvantage of above boilerplate code is that for each newly created instance of the class, the public and private properties are copied into memory for the new instance. This doesn’t happen when using prototypal inheritance - but then we are not able to make private properties easily.

There is a workaround for this, by having the constructor function (MyClass) return an object containing all the public properties. Private properties are accessible through the created closures. This also allows more advanced mechanisms such as super methods. To read more about inheritance in JavaScript, I suggest reading Chapter 5 of JavaScript: The Good Parts by Douglas Crockford.

f1rst p0st

March 23rd, 2011

String.prototype.toString = function() {
    return 'Welcome ' + this;
};

console.log('to my blog!'.toString());