/InkMLjs

Primary LanguageJavaScriptApache License 2.0Apache-2.0

InkMLjs

Project Description

The InkMLjs JavaScript library allows InkML digital ink to be referenced within web pages and rendered directly into HTML5 <canvas> tags. Ink Markup Language (InkML) is a W3C standard for encoding digital ink (http://www.w3.org/tr/inkml).  The Ink Markup Language serves as the data format for representing ink entered with an electronic pen or stylus.   Products such as Microsoft Office 2010 allow users to draw ink directly into Office documents, and the ink is persisted within the documents as InkML.   The InkMLjs library allows a web page to render InkML generated by Microsoft Office or any other InkML compliant application. Below are examples of the same InkML rendered within PowerPoint 2010 and within a web page using the InkMLjs library.

InkML rendered in PowerPoint 2010

InkML rendered in PowerPoint 2010

InkML rendered by InkMLjs Library

InkML rendered by InkMLjs Library

Usage

To use InkMLjs on an HTML page, the page must reference both the JQuery 1.5 library and a copy of the InkMLjs library.   For example:

<head>
  <script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.5.min.js"></script>
  <script type="text/javascript" src="inkml.js"></script>
  ...
</head>

Then, create an HTML5 <canvas> element where you would like Ink to be rendered on the page.   The <canvas> element must have a data-inkml-src attribute which references the inkml file you wish to be rendered.   For example:

<canvas id="Canvas1" width="600" height="300" data-inkml-src="ink1.inkml">
</canvas>

Optionally, you may also specify the data-inkml-ignorepressure attribute.   If the value of this attribute is true, then and Force channels present in the InkML will be ignored. Without pressure enabled, each continuous stroke within the InkML will be rendered with a single stroke thickness, but it will be drawn using antialiasing.   With pressure enabled, strokes will be rendered with variable widths depending on the pressure applied by the stylus when the ink was original captured, but since SVG and HTML5 Canvases don’t natively support variable width strokes, the variability is approximated by rendering each segment of the stroke separately. This technique makes it possible to approximate variable width strokes, but it destroys antialiasing. Below is an example of a canvas using the data-inkml-ignorepressure attribute:

<canvas id="Canvas1" width="600" height="300" data-inkml-src="ink1.xml" data-inkml-ignorepressure="true">
</canvas>
data-inkml-ignorepressure="true" data-inkml-ignorepressure="false" (default)
ignorepressure true ignorepressure false

The InkMLjs library can also be driven using your own JavaScript code.   Below is an example of JavaScript code loading an inkml file into an Ink() object:

$(this).ready(function () {
       $.get("ink1.xml", {}, function (xml, textStatus, jqXHR) {
              var ink = new Ink(xml);
              ...

Once you have an Ink() object, you can resave the object back to InkML XML;

              var inkml = ink.toInkML();

Or you can render the Ink() into a canvas:

              ink.draw(canvas, ignorePressure);

Or you can walk the InkML DOM by manipulating its fields such as .contexts, .brushes, etc.

Not Yet Implemented Features

  • InkML <traceGroup> elements are read, but are not round-tripped via the toInkML() method.
  • The traceRef attribute is not yet implemented.
  • Not all brush properties are supported, most notably alpha and brush tip shapes.
  • Traces that contain a single point (like a dotted ‘i’ or ‘j’) are not currently supported.
  • Named channel types are not currently supported. X and Y are of course supported, but if a third channel is present it assume to always be Force. Any additional channels are ignored.
  • An Ink Capture Mode is partially implemented, but it is not complete.
  • The inkSourceRef attribute is not supported.
  • Channel properties for X and Y are assumed to be present (defaults are not provided if they are absent from the InkML)
  • First and second order derivative channel values are supported, but the algorithm needs to be refactored to be a single pass.
  • First and second order derivate channel values are round-tripped as absolute values via the toInkML() method.
  • InkML <mapping>'s are not implemented