Record and Playback Drawing in HTML5 Canvas – Part II

A reader of my blog post De/Serializing Recordings in Recordable HTML5 Canvas had asked me how to change stroke color and size when recording. I told him that this could be done by adding actions, like setColor and setStrokeSize. For more information about how the recordable canvas was implemented, see my blog post Record and Playback Drawing in HTML5 Canvas . I have updated the example with following new features –

  • Setting stroke color and size – both for drawing and recording
  • Pausing and resuming recording. You may want to pause recording if, for example, you do not want to record time delay when you select stroke color/size. Duration of time that the recording is paused is skipped when playing back the recording.

Here is the demo of how the new features work. Select a color by clicking on any color box on the right side of the canvas. Default selection is black. Currently selected color is displayed in a little bigger box with rounded corner. To select stroke size, I have added a few predefined circles of different sizes on the right side. Currently selected stroke size is displayed in black.

Colors :


Stoke Size :


After you select color and stroke size, draw a few stroke on the canvas. You can change color and stroke size any time during recording. Click pause before you change stroke color/size so that time delay is not added to the recording. Don’t forget to click resume button after you are done selecting stroke color/size.

As in my post De/Serializing Recordings in Recordable HTML5 Canvas, I am making a test serialized recording data available below. To see how deserialization with new features work, copy the data,  click Deserialize button, paste the data in the text box and click Submit. The pre-recorded strokes with different colors and sizes will be played back in the Canvas.

Implementation of SetColor and SetStrokesize

I have added two JS (action) objects at the end of file RecordableDrawing.js

SetColor = function (colorValue)
{
	var self = this;
	this.color = colorValue;

	Action.call(this,_SET_COLOR_ACTION);
}
SetColor.prototype = new Action();

SetStokeSize = function (sizeArg)
{
	var self = this;
	this.size = sizeArg;

	Action.call(this,_SET_STOKE_SIZE);
}
SetStokeSize.prototype = new Action();

Added two methods setColor and setStrokeSize to RecordableDrawing object –

RecordableDrawing = function (canvasId) {
	...
       this.setColor = function (color)
	{
		self.drawingColor = color;
		var colorAction = new SetColor(color);
		self.actions.push(colorAction);
		if (self.currentRecording != null)
			self.currentRecording.addAction(colorAction);
	}

	this.setStokeSize = function (sizeArg)
	{
		self.currentLineWidth = sizeArg;
		var sizeAction = new SetStokeSize(sizeArg);
		self.actions.push(sizeAction);
		if (self.currentRecording != null)
			self.currentRecording.addAction(sizeAction);
	}
        ...
}

Above methods create action objects with color/stroke size data and add them to action set or to the current recording.

Modified drawAction method in RecordableDrawing object. Earlier there was only one Action – Point. So the function just used to handle action based on type of the Point action (move or line). But now we will have to check actionType (Point/SetColor/SetStrokeSize).

_POINT_ACTION = 1;
_SET_COLOR_ACTION = 2;
_SET_STOKE_SIZE = 3;
RecordableDrawing = function (canvasId)
{
...
	this.drawAction = function (actionArg, addToArray)
	{
		switch (actionArg.actionType)
		{
			case _POINT_ACTION :
				drawPoint(actionArg);
				break;
			case _SET_COLOR_ACTION :
				self.drawingColor = actionArg.color;
				break;
			case _SET_STOKE_SIZE:
				self.currentLineWidth = actionArg.size;
			default:
				break;
		}

		if (addToArray)
			self.actions.push(actionArg);
	}
...
}

Old content of drawAction is now moved to drawPoint function.

Added serializeAction and deserializeAction functions in drawingSerializer.js

function serializeAction (action)
{
	switch (action.actionType)
	{
		case 1: //Point Action
			return serializePoint (action);
		case 2: //SeColor Action
			return {actionType : 2,
					color : action.color};
		case 3: //Set Stroke Size
			return {actionType : 3,
					size : action.size};
	}

	return null;
}

function deserializeAction (actionWrp)
{
	switch (actionWrp.actionType)
	{
		case 1: //Point action
			return deserializePoint(actionWrp);
		case 2: //SetColor action
			return new SetColor(actionWrp.color);
		case 3: //Set Stroke Size
			return new SetStokeSize(actionWrp.size);
	}

	return null;
}

Adding support for pause and resume of recording

I now keep track of total pause time during recording. And before adding action set in the linked list (see Record and Playback Drawing in HTML5 Canvas to understand how recording is stored ), time interval for the action set is set to (current time) – (time when recording started) – (total time paused). This is how onInterval function of Recording object (in RecordableDrawing.js) looks now –

	this.onInterval = function()
	{
		if (self.buffer.length > 0)
		{
			var timeSlot = (new Date()).getTime() - self.recStartTime - totalPauseTime;

			if (self.currActionSet == null)
			{
				self.currActionSet = new ActionsSet(timeSlot, self.buffer);
				self.actionsSet = self.currActionSet;
			}
			else
			{
				var tmpActionSet = self.currActionSet;
				self.currActionSet = new ActionsSet(timeSlot, self.buffer);
				tmpActionSet.next = self.currActionSet;
			}

			self.buffer = new Array();
		}
		self.currTime += self.timeInterval;
	}

Added two methods, pause and resumeRecording, to the Recording object (in RecordableDrawing.js)

Recording = function (drawingArg)
{
	...
	var totalPauseTime = 0;
	var pauseStartTime = 0;

	this.pause = function()
	{
		pauseStartTime = (new Date()).getTime();
		window.clearInterval(self.intervalId);
	}

	this.resumeRecording = function() {
		totalPauseTime += (new Date()).getTime() - pauseStartTime;
		pauseStartTime = 0;
		self.intervalId = window.setInterval(self.onInterval, self.timeInterval);
	}
	...
}

Notice calls to clearInterval in pause method and (re) setInterval in resumeRecording method.

Finally, added pauseRecording and resumeRecording methods to RecordableDrawing object. These functions call corresponding methods of current recording object.

RecordableDrawing = function (canvasId)
{
	...
	this.pauseRecording = function()
	{
		if (self.currentRecording != null)
			self.currentRecording.pause();
	}

	this.resumeRecording = function()
	{
		if (self.currentRecording != null)
			self.currentRecording.resumeRecording();
	}
	...
}

-Ram Kulkarni

14 Replies to “Record and Playback Drawing in HTML5 Canvas – Part II”

  1. Halo Ram, I want to make the background color become transparent, but the replay and clear function is not working, can you give me some suggestion on that? thanks!

  2. hello ram, i don’t know why but your resume button didn’t work properly on me, when i resume a paused record, it always have a delay before the line continues, it looks like it starting from the beginning of the record…
    can you solve it? i’m sorry for asking to much…..

  3. Dear Ram,

    Good day.. Very nice to work Record and Playback Drawing with your drawing surface. Is it suitable for any other drawing surface. for example when we are using wpaint(http://wpaint.websanova.com/). Hope you will reply.

    Very Thank you.

    Regards,
    Parivallal J.

  4. Wpaint is VERY bad written work. The author is crazy!!! I could write the same functionality minimum 100 time shorter. I would not recommend it to use.

Leave a Reply to Costas Cancel reply