MISCELLANEOUS TECHNICAL ARTICLES BY Dr A R COLLINS

Cango User Guide

Cango canvas graphics library

This is the user guide and reference manual for the Cango canvas graphics library. For an introduction to Cango capabilities see Canvas Graphics page. The latest Cango release is Version 27. The source code is open source and may be downloaded at Cango-27v00.js and a minified version at Cango-27v00-min.js.

New in version Version 27:

  • Version27 has further simplified drag-n-drop handling to remove the 'grabTransformRestore' method and the eventData object has the 'dragRot' property function replaced by the new 'dragOfsAngle' property which returns the rotation increment since the last time the target object was rendered.

  • The 'transformRestore' methods have been refactored to eliminate the rapid growth in the number of transforms applied to position the target object. The set applied is now the minimal, regardless of the number of events that have occurred since the 'grab' event.

New in version Version 26:

  • Version26 introduces support for Cango Extension Objects. These are more specialized objects than the core Path, Shape, Img, Text and ClipMask objects. They are built as a subclass of the Group object and have their own purpose specific properties and methods. Some of the Extension Objects available are VectorText, Arrow, Axes etc.

  • The children of a Group are assured to be rendered in the order of insertion. If a child object is only available asynchronously, such as an Image that is still loading, the render method waits until all children of the Group are loaded before proceeding to render them.
  • Drag-n-drop handling has been refactored. The enableDrag method arguments order have been changed so the drag callback is first and the grab and drop callbacks are now optional. The callback functions are now passed an EventData object containing various properties useful in event handler code. The event callbacks are called in the scope of the Cango context that rendered the target object. Object and Groups have two new method transformRestore which are useful for redrawing objects as they were when last rendered.
  • The old 'setProperty' method has been split into 'setStyleProperty' and 'addTransformProperty' methods. Properties set by the 'setStyleProperty' method replace the previous or default value. Transforms added by the 'addTransformProperty' accumulate and are all applied in the order of insertion. Path, Shape, Img, Text all have both methods, Groups have only the 'addTransformProperty' which is just a wrapper function that calls the 'addTransformProperty' method of all the Group descendants recursively.

Several modules are available to extend the capabilities of the Cango core module.

PathSVGUtils provides the PathSVG object that can create Path and Shape descriptors for many forms of data and has methods to manipulate these path descriptors such as rotate, scale, join etc. These are detailed in the PathSVG User Guide.

CangoAnimation provides additional Cango methods to enable creation and control of canvas animations. These are detailed in the Cango Animation User Guide.

CangoZoomPan provides the 'initZoomPan' utility to create controls to zoom and pan the canvas content drawn with Cango. This function is detailed below in the Zoom and Pan section.

CangoAxes provides 'Axes', 'BoxAxes', 'Xaxis', and 'Yaxis' extension objects to assist in drawing and labeling axes when plotting graphs with Cango. Details are in CangoAxes User Guide.

CangoTextUtils provides 'MathText', 'HTMLText', 'TextOnPath', 'VectorText', 'ExpNotationText' and 'SciNotationText' extension objects to draw specialized forms of text. Details are in CangoTextUtils User Guide.

CangoArrows provides the 'Arrow' and 'ArrowArc' extension objects to assist in drawing arrows with Cango. Detils are in CangoArrows.

Cango drawing principles

Cango provides methods to simply construct basic objects and render them to a canvas. These are drawPath, drawShape, drawImg and drawText.

To handle redrawing of objects without the overhead of reconstructing them, as required in animation and zoom-n-pan drawing, Cango uses splits the task, providing five core objects: Path, Shape, Img, Text and ClipMask that are constructed independent of the context in which they are to be drawn. Once constructed with various style and transform options, they are can then be rendered and re-rendered with different Cango contexts even to different canvases. They can have various dynamic transforms applied to translate, rotate and scale them prior to rendering. They can be collected in Group objects which can be manipulated and rendered as a single entity.

Cango Extension Objects

Canvas drawings often need more specialized graphic objects than the core five: Path, Shape, Img, Text and ClipMask. Cango addresses this requirement with the Cango Extension Object, a sub-class of the Group object made up of the core five objects but having purpose specific properties and methods. Many useful Extension Objects have been gathered into the Cango extension modules mentioned above.

Getting Started with Cango

The Cango core module Cango-27v00-min.js should be downloaded and saved to a directory accessible to your application code, then add the following lines to the web page header or to the foot of the HTML code:

<script src="directory path/Cango-27v00-min.js"></script>

The application webpage must have a canvas element with a unique ID. Create an instance of Cango, the returned object will have all the methods to make drawing on a canvas easy.

...
const g = new Cango(canvasID);

g.drawShape("M 0,0 l 200,0 l -100,200 z", {fillColor:"red"});

Cango constructor

Syntax:

const cgo = new Cango(canvas);

Description:

To create an instance of the Cango graphics context requires an existing canvas element on the web page or an off-screen canvas (created in memory but not added to the DOM). Pass the canvas 'id' or a reference to the canvas object to the Cango constructor and the Cango graphics object is returned. A canvas can host multiple Cango instances and each instance can have its own coordinate system.

Parameters:

canvas: String or HTMLCanvasElement - The 'id' property of the HTML canvas or a reference to the canvas element on which the Cango library will draw.

Returns:

A new Cango object.

Cango coordinates systems

Right Handed or Left Handed coordinates

All Cango graphics drawing dimensions refer to a world coordinate system which can be either the standard Right Handed Cartesian (RHC) coordinates or SVG style, which is a left handed Cartesian coordinate system also used by native canvas graphics methods. The system to be used is set by a call to either setWorldCoordsRHC or setWorldCoordsSVG.

Figure 1. RHC coordinates.

The RHC coordinates X axis values increase to the RIGHT, Y axis values increase UP the canvas, and angles increase anticlockwise (CCW).

To set up a RHC world coordinate system call:

cgo.setWorldCoordsRHC(gbLowerLeftX, gbLowerLeftY, gbWidth, gbHeight);

Figure 2. SVG coordinates.

The SVG coordinates X axis values increase to the RIGHT, Y axis values increase DOWN the canvas, and angles increasing clockwise (CW).

To set up a SVG world coordinate system call:

cgo.setWorldCoordsSVG(gbLowerLeftX, gbLowerLeftY, gbWidth, gbHeight);

World coordinate scaling

To set the X and Y scaling of world coordinates Cango uses a reference rectangle called its gridbox. The size and position of the gridbox is controlled by the setGridbox method or the gridboxPadding method.

cgo.setGridbox(lowerLeftX, lowerLeftY, spanX, spanY);

or

cgo.gridboxPadding(left, bottom, right, top);

The gridbox dimensions are expressed as a percentage of the canvas width. By default the gridbox is set to the full canvas.

The setWorldCoordsRHC method defines the X, Y coordinates of the LOWER LEFT corner of the gridbox and the width and height of the gridbox in world coordinate units.

The setWorldCoordsSVG defines the X, Y coordinates of the UPPER LEFT corner of the gridbox, and the width and height of the gridbox in world coordinate units.

Fig. 3 shows how setWorldCoordsRHC uses the gridbox to define the coordinates and Fig 4 shows setWorldCoordsSVG. If isotropic scaling (square pixels) is required, omit last argument and the Y scale factor will be set equal to the X scale factor.

const cgo = new Cango(cvsID);
cgo.gridboxPadding(10, 10, 5, 5);
cgo.setWorldCoordsRHC(0, 0, 300, 5);
cgo.fillGridbox("lightgreen");
cgo.drawAxes();
  
Figure 3. Setting the world coordinates using the setWorldCoordsRHC with independent X and Y scaling.
const cgo = new Cango(cvsID);
cgo.gridboxPadding(10, 5, 5, 10);
cgo.setWorldCoordsSVG(0, 0, 300);
cgo.fillGridbox("lightpink");
cgo.drawAxes();
  
Figure 4. Setting the world coordinates using the setWorldCoordsSVG with square pixels (height parameter omitted).

Coordinate system methods

gridboxPadding

Syntax:

cgo.gridboxPadding([left[, bottom[, right[, top]]]]);

Description:

The gridbox corner provides the reference point for the world coordinate origin and the gridbox width and height provide the reference lengths for setting the world coordinate scaling in the X and Y directions. The gridboxPadding method controls the gridbox position and dimensions by setting the padding from each edge of the canvas.

If only 'left' is specified then this values sets the padding on all sides of the gridbox. If 'left' and 'bottom' are defined then the right and top padding are set to the same values. If only 'left', 'bottom' and 'right' are defined the top is set equal to the 'bottom'.

If no call is made to gridboxPadding or setGridbox then the default gridbox is the full canvas. Any call to change the gridbox resets the world coordinates to their default which is equivalent to calling setWorldCoordsSVG() i.e. the coordinate origin will be the upper left corner of the gridbox and the scaling is 1 to 1 with the canvas pixels.

If the gridbox has been previously set that grigbox is discarded and the most recent setting used.

Parameters:

left: Number - (optional) Width of the padding from left edge of the canvas to the left of the gridbox.

bottom: Number - (optional) Width of the padding from bottom edge of the canvas to the bottom of the gridbox.

right: Number - (optional) Width of the padding from right edge of the canvas to the right of the gridbox.

top: Number - (optional) Width of the padding from top edge of the canvas to the top of the gridbox.

All padding values should be positive numbers expressed as a percentage of canvas width.

Note

The Cango property 'cgo.heightPW' holds the height of the canvas measured in units of percent of the canvas width, this is often useful in setting the gridbox padding ('cgo.widthPW' is always 100). For example the largest centered square area in a wide canvas has gridbox padding set as follows:

gc.gridboxPadding((100-gc.heightPW)/2, 0);

In a tall canvas it would be:

gc.gridboxPadding(0, (gc.heightPW-100)/2);
setGridbox

Syntax:

cgo.setGridbox(lowerLeftX, lowerLeftY, spanX, spanY);

Description:

The gridbox corner provides the reference point for the world coordinate origin and the gridbox width and height provide the reference lengths for setting the world coordinate scaling in the X and Y directions. The setGridbox method controls the gridbox position and dimensions by setting the position of the lower left corner and setting the width and height of the gridbox.

If no call is made to setGridbox or gridboxPadding then the default gridbox is the full canvas. Any call to change gridbox resets the world coordinates to their default which is equivalent to calling setWorldCoordsSVG() i.e. the coordinate origin will be the upper left corner of the gridbox and the scaling is 1 to 1 with the canvas pixels.

Parameters:

lowerLeftX: Number - The X coordinate if the lower left of the gridbox measured in percent of the canvas width.

lowerLeftY: Number - The Y coordinate if the lower left of the gridbox measured in percent of the canvas width.

spanX: Number - Width of the gridbox as a percentage of canvas width.

spanY: Number - Height of the gridbox as a percentage of canvas width.

Note

The Cango property 'cgo.heightPW' is the height of the canvas measured in units of percentage of the canvas width, this is may be useful in setting the dimensions of the gridbox. For example the largest centered square area in a wide canvas has gridbox padding set as follows:

gc.setGridbox((100-gc.heightPW)/2, 0, gc.heightPW, gc.heightPW);

In a tall canvas it would be:

gc.setGridbox(0, (gc.heightPW-100)/2, gc.heightPW, gc.heightPW);
fillGridbox

Syntax:

cgo.fillGridbox(fillColor);

Description:

Fills the area of the current gridbox with the color fillColor.

Parameters:

fillColor: String or color gradient - The fill color may be solid color defined by in one of the CSS Color formats or a reference to a LinearGradient or RadialGradient object should be passed. If 'fillGridbox' is called with no fillColor parameter then the gridbox is filled with the current Cango default fillColor. If not set by the application, the Cango default fillColor is mid gray.

Note

Filling the gridbox with fillColor "transparent" will not clear the gridbox. It will just draw a Shape object over the gridbox filled with the color "transparent". Hence the existing contents will remain visible, ie. the call have no effect. To clear the gridbox use the clearShape method setting the Shape descriptor to match the gridbox dimensions.

setWorldCoordsRHC

Syntax:

cgo.setWorldCoordsRHC([gbLowerLeftX, gbLowerLeftY, gbWidth [, gbHeight]]);

Description:

Defines a Right Handed Cartesian coordinate grid for subsequent drawing operations with the cgo graphics context. RHC coordinates have the X axis values increase to the RIGHT, Y axis values increase UP the canvas and angles increase ANTI-CLOCKWISE. The world coordinate system sets translation and scaling factors to map world coordinate values to canvas drawing pixels. This is done by specifying the world coordinate values of the Cango context's gridbox origin, width and height in world coordinate units. The 'gbLowerLeftX, gbLowerLeftY' will be the world coordinate values of the lower left corner of the gridbox. Specifying the gridbox width in world coordinate units determines the X axis scale factor (cgo.xscl) and specifying the gridbox height in world coordinates Y axis units will determine the Y axis scale factor (cgo.yscl). If no value is passed for the 'gbHeight' then the magnitude of the Y axis scale factor will be set equal to the X axis scale factor resulting in square pixels.

Calling 'setWorldCoordsRHC' with no parameters results in the lower left corner of the gridbox being set to 0,0 in world coordinates and X and Y axes scaled in canvas pixels.

Note: The world coordinate system extends to the full size of the canvas regardless of the size of the gridbox.

Note: If no call has been made to either 'setWorldCoordsRHC' or 'setWorldCoordsSVG', then the world coordinate system will be SVG style equivalent to calling cgo.setWorldCoordsSVG().

Parameters:

gridOrgX: Number - World coordinate X value of the gridbox lower left corner.

gridOrgY: Number - World coordinate Y value of the gridbox lower left corner.

gridboxWidth: Number - The width of the gridbox measured in world coordinate X axis units.

gridboxHeight: Number - The height of the gridbox measured in world coordinate Y axis units. If 'gbHeight' is omitted then Y axis units are assumed equal to X axis units and so Y scaling is set to equal the X scaling, resulting in square pixels.

setWorldCoordsSVG

Syntax:

cgo.setWorldCoordsSVG([gbUpperLeftX, gbUpperLeftY, gbWidth [, gbHeight]]);

Description:

Defines an SVG (Left Handed Cartesian) coordinate grid for subsequent drawing operations with the cgo graphics context. SVG coordinates have the X axis increase to the RIGHT and Y axis increase DOWN the canvas and angles increase CLOCKWISE. This is the sign convention used when drawing with native canvas (CanvasRenderingContext2D) commands. The world coordinate system sets translation and scaling factors to map world coordinate values to canvas drawing pixels. This is done by specifying the gridbox upper left corner, width and height in world coordinate units. Specifying the gridbox width in world coordinate units determines the X axis scale factor (cgo.xscl) and specifying the gridbox height in world coordinates Y axis units will determine the Y axis scale factor (cgo.yscl). If no value is passed for the 'gbHeight' then the magnitude of the Y axis scale factor will be set equal to the X axis scale factor resulting in square pixels.

Calling 'setWorldCoordsSVG' with no parameters results in the upper left of the gridbox being set to 0,0 and X and Y axes scaled in canvas pixels.

Note: The world coordinate system extends to the full size of the canvas regardless of the size of the gridbox.

Note: If no call has been made to either 'setWorldCoordsRHC' or 'setWorldCoordsSVG', then the world coordinate system will be SVG style equivalent to calling cgo.setWorldCoordsSVG().

Parameters:

gridOrgX: Number - World coordinate X value of the gridbox upper left corner.

gridOrgY: Number - World coordinate Y value of the gridbox upper left corner.

gridboxWidth: Number - The width of the gridbox measured in world X axis units.

gridboxHeight: Number - The height of the gridbox measured in world Y axis units.

dupCtx

Syntax:

cgo.dupCtx(sourceCtx);

Description:

This method copies the graphics context properties from one Cango context 'sourceCtx' into the 'cgo' context. When drawing onto layers this method provides a simple way to copy the underlying Cango coordinate system so the new layer's world coordinates match. The 'dupCtx' method copies the source properties by value so that after the call changing either 'sourceCtx' or 'cgo' properties will have no effect on the other.

Parameters:

sourceCtx: Cango graphics context - The source Cango instance from which the properties are copied.

toPixelCoords

Syntax:

const posObj = cgo.toPixelCoords(xWC, yWC);

Description:

This method converts the x and y values expressed in world coordinates to corresponding x and y values expressed in raw canvas pixel coordinates.

Parameters:

xWC, yWC:Numbers - X and Y coordinates of a point measured in world coordinates.

Returns:

Object {x: , y: } - An object with its 'x' and 'y' properties representing the coordinates of the point measured in pixel coordinates.

Note:

Cango sets the canvas width and height attributes to match screen pixels when the Cango graphics context is created. So toPixelCoords always returns the canvas pixel coordinates which map 1 to 1 with screen pixels.

toWorldCoords

Syntax:

const posObj = cgo.toWorldCoords(xPX, yPX);

Description:

This method converts the pixel coordinates (xPX, yPX) of a point to an object with x and y properties that hold the world coordinates of the point. There can be more than one Cango graphics context on a canvas, the world coordinates of the point in the calling graphics context are returned.

Parameters:

xPX, yPX: Numbers - X and Y coordinates of a point measured in pixel coordinates.

Returns:

Object {x: , y: } - An object with whose 'x' and 'y' properties hold the coordinates the point expressed in the world coordinates of the 'cgo' coordinate system.

Note:

Cango property cgo.rawWidth and cgo.rawHeight hold the width and height of the canvas in pixels.

Layer methods

The functionality of a CanvasStack is built into Cango. Layers can be drawn upon and cleared independent of the background canvas or other layers, so animations or drag-n-drop handlers can erase their canvas and re-draw at each frame or pointer event without affecting the content on other layers.

All layers are referenced to the background canvas ie. the original HTML element. Any number of layers can be created by a Cango instance hosted on a background canvas. Layers cannot be created on off-screen canvases or other layers.

Note: Detection of click or drag-n-drop events on an object work regardless of the layer on which the object is drawn. When a mouse event occurs on a canvas stack, each object enabled for drag-and-drop on each layer is checked to see if the event coordinates are within its outline. The first object encountered that has drag-n-drop enabled on itself or its parent Group determines the event handler to be called. The layers are searched starting at the top (last layer added) and going down the stack to the background canvas.

createLayer

Syntax:

const idStr = cgo.createLayer();

Description:

Creates a transparent canvas overlaying the background canvas. The overlay canvas will be the same size as the background canvas and will be transparent. A unique 'id' string is generated and assigned to the new canvas, this 'id' string is the return value from the method.

Only Cango contexts that are created on the original background canvas can create layers, calling 'createLayer' as a method of a Cango instance on an overlay layer does nothing and returns an empty string.

To draw on the new layer, an instance of Cango should be created on the overlay by calling the Cango constructor passing the layer's id string. The properties of the background canvas can be readily copied to the new Cango context using the cgo.dupCtx method.

Parameters:

none

Returns:

String - The id attribute of the newly created canvas element.

deleteLayer

Syntax:

cgo.deleteLayer(ovlID);

Description:

Deletes an existing canvas layer specified by its 'id' string. The 'id' of a canvas layer is returned from the 'createLayer' method. The 'deleteLayer' method will remove the layer's canvas from the DOM. The canvas can be anywhere within the stack except the background canvas which cannot be deleted with this method.

Parameters:

ovlID: String - The 'id' attribute of the canvas element to be deleted.

deleteAllLayers

Syntax:

cgo.deleteAllLayers();

Description:

Deletes all existing canvas layers from the DOM leaving only the original background canvas.

Parameters:

none

Basic drawing methods

Cango provides four basic methods for simple, single use, drawing of objects onto the canvas. They are:
drawPath,  drawShape,  drawImg,  drawText.

In addition the clearShape method will draw a Shape but clear the canvas so that the underlying canvas color shows through. The clearCanvas method will clear all drawing from the whole canvas.

drawPath

Syntax:

cgo.drawPath(pathData [, options]);

Description:

This method creates a Path object defined by the 'pathData' descriptor and sets any of its properties as specified in the 'options' object then renders the Path onto the canvas.

Parameters:

pathData: String, Array, PathSVG or Path2D - A string or an array consisting of a series of command letters and their associated parameters in SVG path data format or a pre-defined PathSVG or Path2D object defining a path outline. See Path, Shape and ClipMask descriptors for more details.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

drawShape

Syntax:

cgo.drawShape(pathData [, options]);

Description:

This method creates a Shape object defined by the 'pathData' parameter and sets any of its properties as specified in the 'options' object then renders the Path onto the canvas. The outline path is closed and the Shape formed is filled with color.

Parameters:

pathData: String, Array, PathSVG or Path2D - A string or an array consisting of a series of command letters and their associated parameters in SVG path data format or a pre-defined PathSVG or Path2D object defining a path outline. See Path, Shape and ClipMask descriptors for more details.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

drawImg

Syntax:

cgo.drawImg(imgSpec [, options]);

Description:

This method renders an Image specified by 'imgSpec' onto the canvas. The imgSpec can be a URL String, a pre-loaded Image object or a Canvas element. The properties of the 'options' object (if present) can specify where the image is positioned and how it is formatted. When fully loaded the Img is rendered onto the canvas.

Parameters:

imgSpec: Image, URL String, canvas or ImageSegment - A pre-loaded Image object, or the URL of the image which is asynchronously loaded and then rendered to the canvas, or an HTML Canvas element or an ImageSegment object which itself may take any of the preceding descriptor but has in addition x and y offset values and width and height values of the cropped segment of the image to be displayed.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

drawText

Syntax:

cgo.drawText(str [, options]);

Description:

This method renders a Text object onto the canvas. The text is specified by the string 'str'. The 'options' object (if present) can specify where the Text is positioned and how it is formatted. The text is then rendered onto the canvas.

Parameters:

str: String - The text string to be written.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

clearShape

Syntax:

cgo.clearShape(pathData [, options]);

Description:

This method creates a Shape defined by the 'pathData' parameter and sets any of its formatting properties specified by the 'options' parameter and clears this area of the canvas back to its background color. The 'options' object (if present) can specify where the Shape is positioned and how it is scaled or rotated when rendered.

Parameters:

pathData: String, Array, PathSVG or Path2D - A string or an array consisting of a series of command letters and their associated parameters in SVG path data format or a pre-defined PathSVG or Path2D object defining a path outline. See Path, Shape and ClipMask descriptors for more details.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

clearCanvas

Syntax:

cgo.clearCanvas([fillColor]);

Description:

Clears the canvas, deleting all drawing, images and text. The canvas may be optionally filled with the color fillColor. If 'clearCanvas' is called 'fillColor' undefined, or null the canvas is cleared back to its background color which is set by the HTML canvas element style. All graphics drawing contexts are left intact. Listening for mousedown events on any draggable objects is canceled.

Parameters:

fillColor: String or color gradient - An optional fill color defined by a string in one of the CSS color formats or if a gradient color is to be used a reference to a LinearGradient or RadialGradient object should be passed, see Colors section for detailed syntax.

Rendering method

The render method takes a Group or a single object and renders it to the canvas. In the case of Group, the entire family of descendent objects is rendered. Group transforms propagate down the descendent tree structure and are applied to the descendants along with any transforms applied to the objects directly. render takes a second, optional 'clear' parameter which if true will cause the canvas to be cleared of all previous drawing prior to rendering the objects.

After all the descendent children of a Group have been rendered any ClipMasks that has been applied will be reset to the full canvas. ClipMasks can be clesred earlier than at completion of the render call by inserting a Clipmask object constructed with no path descriptor, only drawing of objects between the ClipMask and the 'clear' ClipMask will be clipped.

render

Syntax:

cgo.render(rootobj, clear);

Description:

Renders a single object or all the descendent objects of a Group onto the canvas. If the 'rootobj' is a Group any transforms that have been applied to it are applied to all its descendent children recursively prior to rendering all descendent objects.

Parameters:

rootobj: Object or Group - The object or Group o be rendered to the canvas.

clear: Boolean - (optional) If 'clear' evaluates to 'true', the canvas is cleared before rendering, if undefined or evaluating to 'false', the canvas is not cleared and the objects being rendered are added to any existing drawing.

Miscellaneous method

Cango provides the setPropertyDefault method to set the default style properties of the basic drawing objects Path, Shape, Img and Text.

setPropertyDefault

Syntax:

cgo.setPropertyDefault(propertyName, val);

Description:

Sets the default values for various properties. The property default to be set is specified by the string 'propertyName' this string is not case sensitive and may take the values set out in column 1 of the table below.

The new default value is passed as 'value'. The value is restricted to be within the range of values appropriate to the property. If the property is not one of the string values listed or the value is an incorrect type or is outside the allowed range of values then the call is ignored and the current default value remains unaltered.

Parameters:

propertyName: String - The name of the property whose default value is to be set. It must be one of the strings listed in column 1 of the table above. The string value is not case sensitive.

value - The new default value for the property. Its type should match the type listed in column 2 of the table above and the range of values must fall within the range listed in column 3.

NameTypeRangeDefault
fillColorCSS Color-"rgba(0, 0, 0, 1.0)"
strokeColorCSS Color-"rgba(128, 128, 128, 1.0)"
lineWidthNumber (pixels)-1
lineCapString"butt", "round", "square""butt"
lineJoinString"bevel", "round", "miter""miter"
fontFamilyStringCSS font family definitions"Consolas, Monaco,
'Andale Mono', monospace"
fontSizeNumber (pixels)>012
fontWeightString or Number"bold", "normal", 100, 200, ..900400

Cango public properties

The following table describes the various properties available for each Cango graphics context. They may be helpful in setting up lower leveling graphics applications.

PropertyTypeDescription
ctxCanvasRenderingContext2DThe raw canvas drawing context. This is available to access the more esoteric canvas capabilities.
xsclNumberThe X axis scaling factor. World coordinate X axis values are multiplied by cgo.xscl to convert to pixels.
ysclNumberThe Y axis scaling factor. World coordinate Y axis values are multiplied by cgo.yscl to convert to pixels. cgo.yscl will always be a negative value for RHC coordinate systems and positive for SVG coordinate systems.
heightPWNumberThe canvas height expressed as a percentage of the canvas width. cgo.heightPW is often useful in setting gridboxPadding.
widthPWNumberThe canvas width expressed as a percentage of the canvas width, so always equal to 100. (Provided for completeness with the more useful heightPW).
aRatioNumberAspect ratio of the canvas element, the canvas width divided by canvas height. If the canvas is 300px wide and 200px high, cgo.aRatio = 1.5.
rawWidthNumberThe canvas width in pixels.
rawHeightNumberThe canvas height in pixels.

Drawing Objects

When an object is to be rendered to the canvas more than once as for animation or drag-and-drop, it is more efficient to reuse the object applying dynamic transforms and modifying properties prior to each rendering. Cango provides five basic Drawing Object classes for this purpose: Path, Shape, Img, Text and ClipMask. These are all sub-classes of the generic Obj2D and inherit Obj2D's methods. Once instantiated these Obj2D may be rendered by different Cango instances on any layer.

Drawing Object constructors

Path

Syntax:

const obj = new Path(descriptor, [, options]);

Description:

Creates a path from a set of commands and coordinates in the 'descriptor'. The commands are specified using the SVG path data syntax.

Parameters:

descriptor: String, Array, PathSVG, Path2D - The path outline defined by a series of SVG "path" format commands ("M", "l", "C", "a", "A" etc) with their associated parameters and coordinates. See Path, Shape and ClipMask descriptors for details).

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

Shape

Syntax:

const obj = new Shape(descriptor, [, options]);

Description:

Creates a shape with its outline path defined by a set of commands and coordinates in the 'descriptor'. The commands are specified using the SVG path data syntax.

Parameters:

descriptor: String, Array, PathSVG, Path2D - The shape outline defined by a series of SVG "path" format commands ("M", "l", "C", "a", "A" etc) with their associated parameters and coordinates. See Path, Shape and ClipMask descriptors for details.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

Img

Syntax:

const obj = new Img(descriptor, [, options]);

Description:

Creates an Img object from a string specifying an image file URL, a pre-loaded HTML Image object or an HTML Canvas element. The loading of the image is asynchronous ans is started as soon as the object is created.

Note: Img objects are always rendered 'upright' in either RHC or SVG coordinate systems unless an inverting scale transform has been applied.

Parameters:

descriptor: URL, Image, Canvas, ImgSegment -

  • URL String
    const desc = "./Images/JaneAvril2.jpg";
  • HTML Image object
    const desc = new Image();
    desc.src = "./Images/JaneAvril2.jpg"
  • HTML canvas element
    const desc = document.getElementById(canvasIDstring);
  • ImageSegment
    const desc = new ImageSegment(imgDescriptor, cropX, cropY, cropWidth, cropHeight);

    Note: An ImageSegment is a light weight object whose properties store the image descriptor (in any of the other three formats described above), the X and Y offsets from the top left of the image and the width and height of the cropped segment to be rendered to the canvas. All dimensions are in pixels.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties and Optional Style Properties below).

Text

Syntax:

const obj = new Text(descriptor, [, options]);

Description:

Creates a Text object from a descriptor string.

Note: Text objects are always rendered 'upright' in either RHC or SVG coordinate systems unless an inverting scale transform has been applied.

Parameters:

descriptor: String -

const desc = "Hullo World";
ClipMask

Syntax:

const obj = new ClipMask(descriptor, [, options]);

Description:

The ClipMask object defines a closed shape on the canvas where drawing outside this shape is clipped. To apply a clip mask the ClipMask object must be a child of a Group, only children of the Group that are drawn after the ClipMask is rendered will be clipped. Child objects rendered after the ClipMask is render will be clipped. The canvas clipping path is automatically reset to the full canvas (ie. no clipping) after the render method has render all the all descendent children of the root Group.

The clipping path may be manually reset by adding a "clear" ClipMask, all objects added to the Group after a clear ClipMask will not be clipped. A clear ClipMask is created by calling the ClipMask constructor with no path descriptor parameter

Parameters:

descriptor: String, Array, PathSVG, Path2D - The ClipMask outline defined by a series of SVG "path" format commands ("M", "l", "C", "a", "A" etc) with their associated parameters and coordinates. See Path, Shape and ClipMask descriptors for details.

options: Object - The values for the various optional transform or style properties may be passed as key-value pairs in this object (see Optional Transform Properties below).

Example:

Fig 8 shows an example of using a ClipMask. A Group is created comprising a Img object (Jane Avril) and a circular ClipMask. The ClipMask circle is then rendered which sets up the clipping path and then the Img is rendered. Only the part of the image within the clipping path is drawn. The clipping path will be reset to the full canvas (ie. no clipping) after all the objects been rendered.

Figure 8. A ClipMask example.

function testClip(cvsID)
{
const clipper = new ClipMask(PathSVG.circle(80)),
jane = new Img("Images/JaneAvril2.jpg", {imgWidth:65, lorg:5});

const grp = new Group(clipper, jane);

const g = new Cango(cvsID);
g.setWorldCoordsRHC(-60, -60, 120);
g.render(grp);
}

Path, Shape and ClipMask descriptors

Path, Shape and ClipMask constructors have their path or shape outline described by a series of SVG "path" format commands ("M", "l", "C", "a", "A" etc) with their associated parameters and coordinates. These SVG data can be represented in any of several formats;

Note: If the Path, Shape or ClipMask object appears 'upright' when rendered in SVG (left handed cartesian) world coordinates they will appear upside down when rendered in RHC (right handed cartesian) world coordinates, and vice-versa. Of course they can always be inverted by a 'flip' transform property or scale transform eg. obj.scale(1,-1).

  • Array of SVG path data commands and coordinates
    const desc = ["M",8.24,-0.1, "l",1.2,0.2, 0,1.6, -1.2,0.2, "A",8.3,8.3, 0,0,1, 4.9,6.6"];
  • String of SVG path data commands and coordinates
    const desc = "M8.24,-0.1 l1.2,0.2 0,1.6 -1.2,0.2 A8.3,8.3 0 0 1 4.9,6.6";
  • Pre-defined outlines (from the PathSVGUtils module)

    The following static methods of the PathSVG object: circle, arc, ellipse, square, rectangle, triangle, cross, ex

    const desc1 = PathSVG.rectangle(30, 50);
    
    const desc2 = PathSVG.circle(15).translate(7.5, 0);
  • PathSVG object (from the PathSVGUtils module)
    const desc1 = new PathSVG("M8.24,-0.1 l1.2,0.2 0,1.6 -1.2,0.2 A8.3,8.3 0 0 1 4.9,6.6");
    
    const desc2 = new PathSVG(["M",8.24,-0.1, "l",1.2,0.2,0,1.6,-1.2,0.2, "A",8.3,8.3, 0,0,1, 4.9,6.6"]);
    
    const desc3 = new PathSVG("M 8.24,-0.1 l 1.2,0.2 0,1.6 -1.2,0.2 A 8.3,8.3 0 0 1 4.9,6.6");   
    
    const right = new PathSVG(["M",0, 10, "C", 5,12, 3,3, 0,0]);
    const left = right.scale(-1, 1).revWinding();
    const desc4 = right.joinPath(left);
  • Path2D object (from the Canvas Path2D API)
    const desc1 = new Path2D("M8.24-0.1 l1.2 0.2 0 1.6 -1.2 0.2 A8.3 8.3 0 0 1 4.9 6.6");
    
    const desc2 = new Path2D();
    desc2.moveTo(125, 35);
    desc2.arc(100, 35, 25, 0, 2 * Math.PI);

Drawing Object methods

setDescriptor

Syntax:

obj.setDescriptor(newDescriptor);

Description:

Provides a way to change an object's definition. Object definition is initially set by the descriptor passed to the constructor but the the descriptor may be changed after construction without impact on all the object properties by calling 'setDescriptor' passing the new object definition.

Parameters:

newDescriptor: Various - The descriptor should be of the type that is expected by the different types of Obj2D, Path, Shape and ClipMask require a String, Array, PathSVG or Path2D object, an Img requires a URL or Image object, Text requires a String.

Hard transform methods (not reset after render)

dup

Syntax:

const newObj = obj.dup();

Description:

dup creates a new object of the same type as 'obj' and copies all the properties and methods from the original into the new object. The properties are copies of the values not references to the original. This method is useful a useful shortcut when creating complex objects made from similar components.

Parameters:

none.

Returns:

newObj: A new object which is a duplicate of the original.

addTransformProperty

Syntax:

obj.addTransformProperty(propertyName, val);

Description:

Provides an alternate way to add a transform to an object's properties which are usually set by key-value pairs in the 'options' argument of the object's constructor. After construction and before rendering the 'addTransformProperty' method may be called to add an extra transform property to the object. The transform properties are cumulative so the new one added will be applied after those previously added have been applied. They become permanent properties of the object, applied every time the object is rendered.

Parameters:

propertyName: String - The property to have its value set, must be one of the set "x", "y", "rot", "scl", "flip". The string is not case sensitive and may take the values set out in column 1 of the Object Optional Transform properties table. If the property is not one of these strings the call is ignored.

val: various types - The new value for the property. The value must be of an appropriate type and fall within the useful range of values for the property, otherwise the call is ignored and the current value remains unaltered.

setStyleProperty

Syntax:

obj.setStyleProperty(propertyName, val);

Description:

Provides an alternate way to set an object's style properties which are usually set by key-value pairs in the 'options' argument of the object's constructor. After construction and before rendering the 'setStyleProperty' method may be called to set a style property value. The style property values set by this method over-ride any previously set value.

Parameters:

propertyName: String - The property to have its value set. The string is not case sensitive and may take the values set out in column 1 of the Object Optional Style properties table. If the property is not one of these strings the call is ignored.

val: various types - The new value for the property. The value must be of an appropriate type and fall within the useful range of values for the property, otherwise the call is ignored and the current value remains unaltered.

getStyleProperty

Syntax:

const val = obj.getStyleProperty(propertyName);

Description:

Returns the current values of one of the style property of 'obj'.

Parameters:

propertyName: String - The property to have its value returned. The string is not case sensitive and may take the values set out in column 1 of the Object Optional Style properties table. If the property is not one of these strings the call is ignored.

Soft transform methods (cleared after rendering)

translate

Syntax:

obj.translate(x, y);

Description:

Applies a translate matrix to obj's transform matrix which effectively moves the object by adding offsets of 'x' and 'y' to the drawing origin the of the object.

These transforms are applied in insertion order. They are not permanent, the net transform is applied when the object is rendered and then the transform matrix reset to the identity matrix.

Parameters:

x, y: Numbers - The distance in the X and Y directions respectively that the object will be moved relative to the world coordinate origin.

Returns:

obj: The original object which allows transform chaining.

rotate

Syntax:

obj.rotate(degs);

Description:

Applies a rotate matrix to obj's transform matrix which rotates the object by 'deg' degrees centered on the world coordinates drawing origin (0,0).

These transforms are applied in insertion order. They are not permanent, the net transform is applied when the object is rendered and then the transform matrix reset to the identity matrix.

Parameters:

degs: Number - The angle of rotation measured in degrees counter-clockwise for RHC coordinate grids and clockwise for SVG coordinate grids.

Returns:

obj: The original object which allows transform chaining.

scale

Syntax:

obj.scale(xScale[, yScale]);

Description:

Applies a scale matrix to obj's transform matrix which scales the X dimensions of the object by a factor 'xScale' and if yScale is defined, scales the Y dimensions by 'yScale'. If yScale is undefined then the Y dimensions are scaled by xScale ie. isotropic scaling. The object's dimensions enlarge or contract relative to the world coordinate origin (0,0).

These transforms are applied in insertion order. They are not permanent, the net transform is applied when the object is rendered and then the transform matrix reset to the identity matrix.

If obj.lineWidthWC is defined then the line width of a Path or the width of any border on other objects will be scaled by 'xScale'. If the lineWidthWC is undefined then the line width is set by the lineWidth property (in pixels) will remain unaffected by this scale method.

Parameters:

xScale: Number - A number by which the object's X dimensions are scaled, negative numbers will flip the object horizontally if the num.

yScale: Number - (optional) A number by which the object's Y dimensions are scaled, negative numbers will flip the object vertically.

Returns:

obj: The original object which allows transform chaining.

skew

Syntax:

obj.skew(degH, degV);

Description:

Applies a skew matrix to obj's transform matrix which distorts the shape of the Obj2D by offsetting the outline X coordinates progressively at an angle of 'degH', and progressively offsetting the Y coordinates at an angle of 'degV'.

These transforms are applied in insertion order. They are not permanent, the net transform is applied when the object is rendered and then the transform matrix reset to the identity matrix.

Parameters:

degH: Number - Skew angle of rotation measured in degrees counter-clockwise from the Y axis for RHC coordinate grids and clockwise for SVG coordinate grids.

degV: Number - Skew angle of rotation measured in degrees counter-clockwise from the X axis for RHC coordinate grids and clockwise for SVG coordinate grids.

Returns:

obj: The original object which allows transform chaining.

Pointer event methods

enableClick

Syntax:

obj.enableClick(callbackFn);

Description:

This method creates the event handler for click events which occur within the outline of the object. The eventHandler calls the user defined callback function. The callback function is called in the scope of the Cango context that rendered the target object. An EventData object is passed as the only argument to the callBack function.

The click handler is de-activated if the canvas is cleared by a call to cgo.clearCanvas, or by calling the obj.disableClick method.

Parameters:

callbackFn: Function - This function to be called when a 'click' event occurs within the outline of 'obj'. An EventData object containing the properties: target, pointerPos, dragPos, dragAngle etc.

Note

Event listening is activated when the object is rendered to the canvas. This is obvious if enableDrag is called before any drawing, but if an event handler is to be changed by 'disableClick' followed by a 'enableClick' when the object has already been drawn it may not be so obvious that it should be redrawn to initiate event listening for the new event handlers.

Example

As an example of the enableClick method, here is the code that changes the object color when clicked:

Simple enableClick example.

function clickBox(cvsID)
{
  const box = new Shape(PathSVG.rectangle(130,160), {
    fillColor:'cyan',
    border:true,
    strokeColor:"gray"});

  function clickObj(evt)
  {
    const oldColor = evt.target.getProperty("fillColor");
    const newCol = (oldColor === "pink")? "cyan":"pink";
    evt.target.setProperty("fillColor", newCol);
    g.render(evt.target, true);  // true = clear canvas
  }

  const g = new Cango(cvsID);
  g.setWorldCoordsRHC(-200, -200, 400);

  box.enableClick(clickObj);
  g.render(box);
}
disableClick

Syntax:

obj.disableClick();

Description:

Sets the obj.dragNdrop property to 'null' and removes the reference to obj from the array of Obj2D to be checked for a hit on click events.

Parameters:

none

enableDrag

Syntax:

obj.enableDrag(dragCallback [, grabCallback[, dropCallback]]);

Description:

This method creates the event handlers that run when mousemove, mousedown and mouseup events occur within the outline of the Path as drawn on the canvas. The event handlers call the user defined callback functions passed as arguments. 'grabCallback' is called on a mousedown events, 'dragCallback' and 'dropCallback' functions are called on subsequent mousemove and mouseup or mouseout events. The obj will have drag and drop capability enabled when it is rendered to the canvas.

The callback functions are is called in the scope of the Cango context that rendered the target object are passed an EventData object which has properties, target, pointerPos, dragPos and dragAngle. See EventData properties section for details.

The drag-n-drop is de-activated if the canvas is cleared by a call to cgo.clearCanvas, or by calling the obj.disableDrag method.

Parameters:

dragCallback: Function or null - This function to be called when a 'mousemove' event occurs after the mouse down event has occurred with the outline of 'obj'. An EventData object is the only parameter passed when the function is called.

grabCallback: (optional) Function or null - This function to be called when a 'mousedown' event occurs within the outline of 'obj'. An EventData object is the only parameter passed when the function is called.

dropCallback: (optional) Function or null - This function to be called when a mouseup or mouseout event occurs after the mouse down event. An EventData object is the only parameter passed when the function is called.

Note

Event listening is when the object is rendered to the canvas. This is obvious if enableDrag is called before any drawing, but if an event handler is to be changed by 'disableDrag' followed by a 'enableDrag' after the object has already been drawn it may not be so obvious that it should be redrawn to initiate event listening for the new event handlers.

Example 1

As an example of the drag-n-drop method, here is the code that simply drags an object with the cursor:

Figure 6. Simple drag and drop example.

function dragBox(cvsID)
{
  const boxOutline = ['M', 0, 0, 'l', 40, 0, 0, 100, -40, 0, 'z'];
  const box = new Shape(boxOutline, {
    fillColor:'orange',
    border:true,
    strokeColor:"brown"});

  function dragObj(evt)
  {
    evt.target.transformRestore();
    evt.target.translate(evt.dragOfs.x, evt.dragOfs.y);
    g.render(evt.target, true);    // true = clear canvas
  }

  const g = new Cango(cvsID);
  g.setWorldCoordsRHC(-100, -100, 400);

  box.enableDrag(dragObj);
  g.render(box);
}

Example 2

Here is an example of the drag-n-drop method, here is the code to rotate a knob and pointer Group:

Figure 7. Drag and drop rotation example.

function simpleKnob(cvsID)
{
  const ptrCmds = ['M', 1.2, 0, 'L', 2.5, 0];
  const ptr = new Path(ptrCmds, {lineWidth:8}), 
        base = new Shape(PathSVG.circle(5), {
          fillColor:'gold',
          border: true,
          strokeColor:'gray',
          lineWidth: 2,
          shadowOffsetX:0.1,
          shadowOffsetY:-0.2,
          shadowBlur:0.1,
          shadowColor:"#303030" }),
        knob = new Group(base, ptr);

  function knobDrag(evt)
  {
    knob.transformRestore();
    knob.rotate(evt.dragOfsAngle);
    gc.render(knob, true);
  }

  const gc = new Cango(cvsID);
  gc.setWorldCoordsRHC(-5, -5, 10);   // isotropic coords
  // enable Drag and Drop on the knob
  knob.enableDrag(knobDrag);
  gc.render(knob);
}
disableDrag

Syntax:

obj.disableDrag();

Description:

Sets the obj.dragNdrop property to 'null' and removes the reference to obj from the array of Obj2D to be checked for a hit on mousedown events.

Parameters:

none

transformRestore

Syntax:

obj.transformRestore();

Description:

When an object has been rendered to the canvas its array of accumulated transforms that were to be applied are cleared. Hence to redraw an object in the same position and orientation requires the transforms to be reapplied. To simplify the code to do this, the transformRestore is available to apply a minimal set of transforms that reposition the object as it was most recently rendered onto canvas.

This method is useful in drag and drop handlers where objects that are not being dragged can be simply redrawn and appear unchanged.

Parameters:

none

EventData object properties

Pointer event callback functions are passed an EventData object as an argument. The EventData object has as properties often required when by event handlers, such as 'target', 'pointerPos', and so on. The details of the EventData object properties are listed below:

PropertyTypeDescription
target Obj2DObj2D that received the grab event (mousedown). If the drag-n-drop was enabled by a Group.enableDrag or enableClick then the target will be the whole Group.
pointerPos ObjectObject with 'x' and 'y' properties holding the 'as rendered' coordinates of the pointer (measured in world coordinates).
dragPos ObjectObject with 'x' and 'y' properties that are the distances in the X and Y directions that the pointer has moved relative since the 'grab' event occurred (measured in world coordinates).
dragOfs ObjectObject with 'x' and 'y' properties that are the distances in the X and Y directions that the pointer has moved relative since the last 'move' event occurred (measured in world coordinates).
dragAngle NumberThe angle of rotation that the movement of the pointer since the grab event would generate rotating the target object around its drawing origin.
dragOfsAngle NumberThe angle of rotation that the movement of the pointer since the last pointer 'move' event would generate rotating the target object around its drawing origin.
cancelDrag FunctionA function that effectively generates a software 'mouseup' event. The mousemove, mouseup, mouse out event listeners are cancelled and the user defined 'drop' callback function (if any) is called with the most recent EventData object passed as its only argument.

Object Optional properties

Object Optional Transform properties

The following table sets out all the supported object transform properties that may be set as key-value pairs passed to the constructor or set individually after construction using the 'addTransformProperty' method. Transforms added to an object as a constructor option or by the 'addTransformProperty' accumulate and are all applied in the order of insertion. They are permanent properties of the object, applied every time the object is rendered.

PropertyTypeDescriptionPathShapeImgTextClipMask
x Number
(World Coords)
The offset along the X axis by which the object is moved relative to its drawing origin which remains at (0, 0).
This is a permanent offset not reset after rendering.
y Number
(World Coords)
The offset along the Y axis by which the object is moved relative to its drawing origin which remains at (0, 0).
This is a permanent offset not reset after rendering.
rotNumber
(deg)
The angle by which the object its drawing origin which remains at (0, 0).
This is a permanent rotation not reset after rendering.
sclNumber
(non zero)
The scaling factor by which the objects dimensions are scaled, the expansion or contraction is centered on the object's drawing origin (0, 0).
This is a permanent change in size not reset after rendering.
flipString
("H" or "V")
Flips the object horizontally or vertically. The sign of all X or Y coordinates will be flipped when ever the object is rendered.
This is a permanent change not reset after rendering.

Object Optional Style properties

The following table sets out all the supported object style properties that may be set as key-value pairs passed to the constructor or set individually after construction using the 'setStyleProperty' method. Properties set by the 'setStyleProperty' method replace any the previous value passed to the constructor as an option or the default value if none had been previously set.

PropertyTypeRange / DescriptionPathShapeImgTextClipMask
strokeColorCSS Colorsee Colors
fillColorCSS Colorsee Colors
fillRuleString"nonzero" or "evenodd". Species how Shapes within Shapes will be filled.
lineWidthWCNumber
(World Coords)
A number >0 specifying the width of the line used to stroke Paths and draw borders around Shapes.
lineWidthNumber (pixels)A number >0 specifying the width of the line used to stroke Paths and draw borders around Shapes.
lineCapString'butt', 'round', 'square'. Specifies the style of end of at Path segment line.
lineJoinString'bevel', 'round', 'miter'. Specifies the style of junction at Path segment joins and Shape border corners.
isoBoolean
or
String
true, 'iso' or 'isotropic' will preserve the aspect ratio of a Path in non-isotropic coordinates.
false will allow independent X and Y scaling.
Path default iso value is false
ClipMask, Shape and Img default is true
dashedArray[mark, space ...] the repeating mark-space pixel lengths
dashOffsetNumber (pixels)The length of initial space before the first dash
borderBooleantrue or falsy
shadowOffsetXNumber
(World Coords)
The distance by which the shadow of the object is displaced along the X axis
shadowOffsetYNumber
(World Coords)
The distance by which the shadow of the object is displaced along the Y axis
shadowBlurNumber
(World Coords)
The radius of blurring of the edge of the object's shadow.
shadowColorCSS Colorsee Colors
fontSizeNumberFont size in Pixels.
fontSizeWCNumberFont size in World Coordinates.
fontWeightNumberFont weight 100..900
fontFamilyStringFont Family in HTML font name format
bgFillColorCSS ColorIf set Text will be rendered as box text with background filled with 'bgFillColor' color, see Colors
imgWidthNumber
(World Coords)
Width of an Img object. Aspect ratio is maintained if imgHeight is not set.
imgHeightNumber
(World Coords)
Height of an Img object. Aspect ratio is maintained if imgWidth is not set.
lorgNumber
(1,2,3,4,5,6,7,8,9)
Specifies the location of the drawing origin.
1=upper-left, 2=upper-mid, ... 9=lower-right

Notes

Preserving Aspect Ratio with the "iso" property

The Cango graphics context allows independent X and Y axis world coordinate scaling. Applications usually want Shapes to have their aspect ratio preserved. But plotting a line graph would use a Path object with the X and Y coordinates will often require different scaling. To give complete control of the aspect ratio Path, Shape and ClipMask objects have an iso property. Setting "iso":true will ensure that the aspect ratio is preserved independent of differing X and Y world coordinates (X axis scaling is used for both X and Y coordinates). Setting "iso":false will allow different X and Y world coordinate scaling to be applied when rendered. For Shape, ClipMask, Text and Img objects the default value of 'iso' is true, Path objects have their default 'iso' value false.

Object Drawing origin and the "lorg" property

All Obj2D dimensions are expressed in world coordinates referenced to the drawing origin (0,0). If no obj.translate(x, y) transform is applied the object will be rendered with its 'drawing origin' at the world coordinate origin (0,0). If a obj.translate(x, y) method is applied then the object is drawn with its drawing origin positioned at (x,y).

Text and Img objects' drawing origin is determined by the object's lorg (locate origin) property. The 'lorg' property can take values from 1..9, where 1=top left, 2=top center, and so on to 9=bottom right. When a obj.translate(x,y) is applied then it is this point that is positioned at (x,y). The lorg value of an Img or Text object can be set by the constructor's 'options' parameter or by using the obj.setProperty method.

Drop shadows

All objects support drop shadows. The shadow is defined by properties shadowOffsetX, shadowOffsetY, shadowBlur and shadowColor. By default the shadow dimensions are set to 0 so no shadow is drawn. All dimensions are measured in world coordinates. The drop shadow properties can be set by assigning key-value pairs to the constructor's 'options' parameter or by using the obj.setStyleProperty method. Drop shadow dimensions scale with world coordinate changes (eg. zoom and pan) they are not altered by obj.scale transform.

Note: drop shadows translate and scale along with the object that they shadow but they do not rotate with the object. This is because drop shadows are meant to provide a 3D effect to 2D objects so they should align with the theoretical light source. If the object rotates the x and y offsets of the drop shadow don't change.

Borders

Shape, Text or Img object may be drawn with a border which can be a continuous or dashed outline. To enable a border set the border property true. The color of the border are set by strokeColor property which can be simple color or a color gradient. The width of the border is determined by the object's line width value.

Line width

A Path object's outline and the border width of other object types is drawn with line width set by either the lineWidthWC property or lineWidth property. The 'lineWidthCW' sets line width in world coordinate units. This line width value will scale with 'scl' option property, obj.scale method and with zoom calls.

The lineWidth property sets line width in pixels, this line width stays fixed regardless of scale transforms that may be applied to the object but it will track the behavior of zoom calls.

If both lineWidth and lineWidthWCproperties have been assigned a value then the lineWidthWC takes precedence. If neither has been specified, then the current Cango property default value of lineWidth (pixel value) is used. This default value may be changed with the Cango.setPropertyDefault method.


Groups

Cango provides the Group object to enable multiple Obj2D and Group to be treated as a single entity for transformations and rendering to the canvas. Since other Groups can be added to a group, it provides the mechanism for inheritance of any transforms applied to parent groups.

Children of a Group are always rendered in series even if an element is an Img object which may be loaded asynchronously. Rendering will await the loading of all elements before rendering them in the order of insertion. This ensures that ClipMasks affect only those children added after the ClipMask and also ensures overlapping objects are always drawn in the same order.

Group constructor

Syntax:

const obj = new Group(...);

Description:

Creates a Group object comprising all the objects or groups passed as parameters. References to these objects are stored as the elements of the Group's 'children' property. After construction more objects can be added to the group using the addObj method.

Parameters:

. . .   :Obj2D, Group or arrays or either - Arrays of objects are expanded to add their elements to the grp.children array recursively. Group objects are added without expanding their children array to ensure correct inheritance of applied transforms.

Group methods

addObj

Syntax:

grp.addObj(...);

Description:

The method adds Objects or Groups to grp. The arguments can be single Obj2D or Group or nested arrays of either. Object can only be members of one Group, if the Obj2D or Group to be added is a child of another Group, then it is deleted from the previous Group and 'grp' becomes its new parent. If objects of the same construction are to be added to multiple Groups then duplicates should be made using the object's "dup" method and a duplicate added to each of the multiple Groups.

Parameters:

. . .   : Path, Shape, Img, Text, ClipMask, Group objects. Cango Extension objects which are sub-classes of Group can be added as they qualify as type Group. Arrays of these types can also be passed as arguments. Any array structure is expanded and the individual Obj2D or Groups are added to the grp.children array.

deleteObj

Syntax:

grp.deleteObj(obj);

Description:

If 'obj' is a child of the Group 'grp' then it is link to the parent Group is removed and then the object is deleted from the Group's children array.

Parameters:

obj: Obj2D or Group - The object to be removed from the Group.

dup

Syntax:

grp.dup();

Description:

Creates a new Group whose children are duplicates of the original Group 'grp'.

Parameters:

none

Returns:

Group: A new Group object.

Transform methods

translate

Syntax:

grp.translate(x, y);

Description:

Applies a translate matrix to grp's transform matrix which will move all the descendent Obj2D by the offsets of 'x' and 'y'. Transforms are applied in the order of insertion. The transform matrix is inherited by children of the Group and applied recursively to the descendent Obj2D when they are rendered to the canvas. These transforms do not change the child Obj2D definitions, the transform matrix is reset to the identity matrix after the descendent Obj2D are rendered.

Parameters:

x, y: Numbers - The distance in the X and Y directions respectively that the group will be moved relative to the world coordinate origin.

Returns:

grp: The original Group which allows transform chaining.

rotate

Syntax:

grp.rotate(degs);

Description:

Applies a rotate matrix to grp's transform matrix which effectively rotates all the Group's descendent children by 'deg' degrees centered on world coordinate drawing origin. Transforms are applied in the order of insertion. The transform matrix is inherited by children of the Group and applied recursively to the descendent Obj2D when they are rendered to the canvas. These transforms do not change the child Obj2D definitions, the transform matrix is reset to the identity matrix after the descendent Obj2D are rendered.

Parameters:

degs: Number - The angle of rotation measured in degrees positive anti-clockwise in RHC coordinate grids and clockwise in SVG coordinate grids.

Returns:

grp: The original Group which allows transform chaining.

scale

Syntax:

grp.scale(xScale[, yScale]);

Description:

Applies a scale matrix to grp's transform matrix which effectively scales the X dimensions of the Group's descendent Obj2D by a factor 'xScale' and if yScale is defined, scales the Y dimensions by 'yScale'. Transforms are applied in the order of insertion. The transform matrix is inherited by children of the Group and applied recursively to the descendent Obj2D when they are rendered to the canvas. These transforms do not change the child Obj2D definitions, the transform matrix is reset to the identity matrix after the descendent Obj2D are rendered.

If yScale is undefined then the Y dimensions are scaled by xScale ie. isotropic scaling. The descendent object's dimensions enlarge or contract relative to the world coordinate drawing origin.

If descendent Obj2D border property is set 'true' and obj.lineWidthWC is defined then the width of the border will be scaled by 'xScale'. If the lineWidthWC is undefined then the width used for the border will remain unaffected by this scale method.

Parameters:

xScale: Number - A number by which descendent Obj2D X dimensions are scaled, negative numbers will flip the objects horizontally if the num.

yScale: Number - (optional) A number by which descendent Obj2D Y dimensions are scaled, negative numbers will flip the objects vertically.

Returns:

grp: The original Group which allows transform chaining.

skew

Syntax:

grp.skew(degH, degV);

Description:

Applies a skew matrix to Group's transform matrix which when inherited by the descendent Obj2D at render time, distorts the shape of the Obj2D by offsetting the outline X coordinates progressively at an angle of 'degH', and progressively offsetting the Y coordinates at an angle of 'degV'.

The transform matrix is applied recursively to the descendent Obj2D of the group when they are rendered to the canvas. These transforms do not change the child Obj2D definitions, the transform matrix is reset to the identity matrix after the descendent Obj2D are rendered.

Parameters:

degH: Number - Horizontal skew angle measured in degrees counter-clockwise from the Y axis for RHC grids and clockwise for SVG grids.

degV: Numbers - Vertical skew angle measured in degrees counter-clockwise from the X axis for RHC grids and clockwise for SVG grids.

Returns:

grp: The original Group which allows transform chaining.

addTransformProperty

addTransformProperty

Syntax:

grp.addTransformProperty(propertyName, value);

Description:

Adds the 'propertyName' transform to all the group's children recursively. The 'propertyName' and 'value' arguments are passed on unaltered. Transforms added to the descendent objects accumulate and are all applied in the order of addition. They are permanent properties of the object, applied every time the object is rendered.

Parameters:

propertyName: String - The transform property to be added. The string is not case sensitive and may take any of the 'x', 'y', 'rot', 'scl' or 'flip'. If the property is not one of these strings the call is ignored.

value: Number or String - The value to be passed as the the transform's argument.

Pointer Event methods

enableDrag

Syntax:

grp.enableDrag(dragCallback [, grabCallback] [, dropCallback]);

Description:

Calls the enableDrag method on all grp's children recursively. The three user defined call back functions 'dragCallback', ''grabCallback', dropCallback' are passed to each child's 'enableDrag' method.

Parameters:

dragCallback: Function or null - This function to be called when a 'mousemove' event occurs after the mouse down event has occurred with the outline of the grp's descendent object.

grabCallback: (optional) Function or null - This function to be called when a 'mousedown' event occurs within the outline of any of the grp's descendent objects.

dropCallback: (optional) Function or null - This function to be called when a mouseup or mouseout event occurs after the mouse down event.

The callback functions are called in the scope of the Cango context that rendered the target object are passed an EventData object which has properties, target, pointerPos, dragPos and dragAngle. See EventData properties section for details.

disableDrag

Syntax:

grp.disableDrag();

Description:

Sets the grp.dragNdrop property to 'null' and removes the reference to grp's children from the array of Obj2D to be checked for a hit on mousedown events.

Parameters:

none

enableClick

Syntax:

grp.enableClick(clickCallback);

Description:

Calls the enableClick method on all grp's children recursively. The user defined call back function 'clickCallback' is passed to each child's 'enableClick' method.

Parameters:

clickCallback:Function or null - This function to be called when a click event occurs ie. a mouse up event occurring after the mouse down event. The callback function is called in the scope of the Cango context that rendered the target object are passed an EventData object which has properties: target, pointerPos, dragAngle etc. See EventData properties section for details.

disableClick

Syntax:

grp.disableClick();

Description:

Sets the grp.dragNdrop property to 'null' and removes the reference to grp's children from the array of Obj2D to be checked for a hit on a click event.

Parameters:

none

transformRestore

Syntax:

grp.transformRestore();

Description:

When an object has been rendered to the canvas its array of accumulated transforms that were to be applied are cleared. Hence to redraw an object in the same position and orientation requires the transforms to be reapplied. To simplify the code to do this, the transformRestore method is available to apply a minimal set of transforms to re-position the target as it was most recently rendered onto canvas.

This method is useful in drag and drop handlers where objects that are not being dragged can be simply redrawn and appear unchanged.

Parameters:

none

Group properties

Property NameTypeDescription
childrenArrayArray elements are the Obj and/or Group objects forming the Group.

Cango Extension Objects

Cango Extension Objects are pre-written extension objects that can add capability to the core Cango library. These extension objects are sub-classes of the Cango 'Group' class, the Group 'children' elements are instances of the basic Cango objects Path, Shape, Img, Text, ClipMask or Group objects. Cango Extension Objects can have their own style properties, methods and event handlers. They still behave as core objects in that they can be transformed with scale, translate, rotate methods and behave like core objects when zoom-and-pan is applied.

Extension Objects don't draw themselves, the should be drawn using the Cango context's render method. If they are active element, such as sliders, buttons etc they have private event handlers to respond to mouse events but are always passed a user callback function. The callback should redraw the object and then do any additional work in response to the new state of the active Extension Object.

Application code can build Extension Objects by handling any specific style properties and, if information about the rendering environment is required, give the object a 'preRender' method which is called by the render method passing a reference to the Cango context. The 'preRender' method may then use information about the calling context, world coordinate system etc., to configure various properties of the children.

The list of available Extension Objects currently includes:

Axes
BoxAxes
Xaxis
Yaxis
Arrow
ArrowArc
HTMLText
MathText
TextOnPath
VectorText
ExpNotationText
SciNotationText


SVG data syntax

The outlines for Path, Shape and ClipMask objects can be defined by a string or array containing SVG path data format. The path is defined as a series of segments each comprises a single letter command such as 'M' for move, 'L' for a line segment, 'C' for a cubic Bezier curve, etc and 'Z' for a close path instruction. the commands are followed by their associated coordinates.

Commands are case sensitive, uppercase command coordinates are interpreted as absolute i.e. measured from the world coordinate origin (0,0). Lowercase command coordinates are interpreted as being relative to the current pen position i.e. the end point of previous command. The SVG standard requires the first command must always be a move command ('M') followed by the x, y values of the starting point of the path in world coordinates. This is followed by an arbitrarily long set of segments comprising a command and its associated parameters and coordinates.

In Left Handed Cartesian coordinate systems, the SVG standard, the segment coordinates are interpreted as having Y coordinate values increase DOWN the canvas and angles increase clockwise. In Right Handed Cartesian coordinate systems, coordinates are interpreted as having Y values increase UP the canvas and angles increase counter-clockwise.

SVG path data syntax details

Command
Parameters
Description
M
x,y
moveto: Moves the pen to a new location. No line is drawn. All path data must begin with a 'moveto' command.
Line Commands
L
x,y
lineto: Draws a line from the current point to the point (x,y).
H
x
horizontal lineto: Draws a horizontal line from the current point to x.
V
y
vertical lineto: Draws a vertical line from the current point to y.
Cubic Bezier Curve Commands
C
x1 y1 x2 y2 x y
curveto: Draw a cubic Bezier curve to the point (x,y) where the points (x1,y1) and (x2,y2) are the start and end control points, respectively.
S
x2 y2 x y
shorthand/smooth curveto: Draw a curve to the point (x,y) where the point (x2,y2) is the end control point and the start control point is the reflection of the last point's end control point.
Quadratic Bezier Curve Commands
Q
x1 y1 x y
quadratic Bezier curveto: Draw a quadratic Bezier between the last point and point (x,y) using the point (x1,y1) as the control point.
T
x y
shorthand/smooth quadratic Bezier curveto: Draw a quadratic Bezier between the last point and point (x,y) using the reflection of the last control point as the control point.
Elliptical Arc Curve Commands
A
rx, ry,
x-rotation,
large-arc-flag,
sweep-flag,
x, y
elliptical arc: Draws and arc starting from the current point and ending at (x, y). The ellipse has the two radii (rx, ry). The x-axis of the ellipse is rotated by 'x-axis-rotation' relative to the x-axis of the world coordinate system. The 'large-arc-flag' and the 'sweep-flag' together define which way the arc joins to start and end point.

In RHC coordinates the 'x-axis-rotation' is positive anti-clockwise and 'sweep-flag = 1' is interpreted as the arc sweeping in an anti-clockwise direction.

In Left Hand Cartesian, SVG standard coordinate systems the 'x-axis-rotation' as positive clockwise and 'sweep-flag = 1' flag is interpreted as the arc sweeping in a clockwise direction.
End Path Commands
Z
-
closepath: Closes the path. A line is drawn from the last point to the first.

Relative coordinates:

To use path end point and control point coordinates relative to the last pen position use a lowercase letter for the command, eg. 'a' rather than 'A'.

As an example, here is the array of commands to draw a unit square with the drawing origin (0,0) at its center.

const cgoSquare = ['M', 0.5,-0.5, 'l',0,1, -1,0, 0,-1, 'z'];
const svgSquare = "M 0.5 -0.5 l 0 1 -1 0 0 -1 z";

Numerical path data

Cango allows a concession to the SVG command format, by accepting an array of data values with no command strings as a valid path definition. The numbers are considered as a series of x,y coordinate pairs. The initial 'M' command to move to the location of the first x,y pair is assumed, and the succeeding pairs are assumed to be preceded by an 'L' command. An example of storing coordinates values in this format:

  ...
  const data = [];
  for (let i=0; i<n; i++)
  {
    data.push(xFn(i), yFn(i)); // xFn producing x values, yFn producing y values
  }
  g.drawPath(data);   // draw line starting at data[0],data[1] then n-1 straight line segments

lorg (locate origin)

Location of the drawing origin within the bounding box of a Text or Img object is set by the parameter 'lorg'. The 'lorg' property can take integer values 1..9, lorg>=1 locates the top,left of the text box or image at the (x, y) position, lorg=2 locates the top, center of the box at the (x, y) position, and so on. Fig. 9 shows the effect of each 'lorg' value on where a text object is drawn. Each text object in the figure is drawn at the x,y coordinates of the adjacent grid intersection, the text string itself specifies which lorg value was used when drawing the text.

Figure 9. Examples of the 9 possible values of lorg.
Each label is drawn at the coordinates of its nearest grid intersection.
The orange labels demonstrate that the lorg position is also the center of rotation.


Colors

The 'fillColor', 'strokeColor' or 'bgFillColor' parameters of Cango objects may be specified either by a string representing the color in one of the CSS color formats or by a reference to a LinearGradient and RadialGradient object.

CSS Color formats

There are five different formats that can be used to define a color for use in the canvas:
- 6 Digit RGB hex notation, '#rrggbb', where 'rr' sets the Red level (00 to ff), 'gg' sets the Green and 'bb' sets the Blue level.
- 3 Digit RGB hex notation '#rgb', this is converted into six-digit form (#rrggbb) by replicating digits, not by adding zeros. For example, #fb0 expands to #ffbb00. - RGBA notation 'rgba(r, g, b, a)' where r, g and b are decimal numbers in the range 0 to 255 representing the Red, Green and Blue levels respectively and a is the Alpha or transparency value, 0 being fully transparent and 1.0 fully opaque.
- RGB notation "rgb(r, g, b)" where r, g and b are decimal numbers in the range 0 to 255 representing the red, green and blue levels respectively. This is a suitable format for entering dynamic color values. The calculated r, g and b values may be passed to drawing methods by the string 'rgb('+r+','+g+','+b+')'.
- Predefined colors names specified by the Extended CSS Color List eg. 'red', 'blue', 'maroon', 'palegoldenrod', 'wheat' etc. There are 143 standard colors named in the list.

LinearGradient and RadialGradient Objects

The LinearGradient and RadialGradient objects encapsulates the instructions from making canvasGradient objects just as if ctx.createLinearGradient or ctx.createRadialGradient had been called. The difference is that they expect the coordinates passed as parameters to be in world coordinates not pixels. If the 'fillColor' or 'strokeColor' property of an object is assigned to be a LinearGradient or RadialGradient object then the coordinates defining the gradient are relative to the drawing origin of the object, so if the object is translated then the gradient fill will move with the object. The gradients will also scale and rotate with the object

The LinearGradient and RadialGradient constructors are global and are independent of any particular Cango instance.

LinearGradient or RadialGradient objects may be used as the fill color for cgo.clearCanvas and fillGridbox methods. The gradient coordinates will be referenced to the current world coordinate drawing origin 0,0.

Example 1:

An example of the LinearGradient is:

Figure 10. LinearGradient example.

const gradObj = new LinearGradient(-2,2, 2,-2);
gradObj.addColorStop(0, 'yellow');
gradObj.addColorStop(0.5, 'green');
gradObj.addColorStop(1, 'black');

g.setWorldCoordsRHC(-2, -2, 4);  // 4x4 square, 0,0 in center

g.drawShape(PathSVG.square(4), {fillColor:gradObj});

Example 2:

An example of the RadialGradient is :

Figure 11. RadialGradient example.

const grad = new RadialGradient(0, 0, .5, 1, 1, 2.5);
grad.addColorStop(0, '#aabbff');
grad.addColorStop(1, '#00f');

g.setWorldCoordsRHC(-2, -2, 4);  // 4x4 square, 0,0 in center

g.drawShape(PathSVG.square(4), {fillColor:grad});

.


Zoom and Pan Utility

Support for zoom and pan of Cango drawings is provided by the CangoZoomPan extension. This module supplies the global function initZoomPan which draws a semi-transparent set of controls in the top right corner of a transparent canvas layer. When these control buttons are clicked the Cango contexts nominated will have their world coordinates modified to zoom or pan the canvas drawing. The initZoomPan function should be called after all the canvas drawing layers have been created ensuring that the zoom and pan controls will be on the top layer of the stack and thus given priority for any mouse click events.

initZoomPan

Syntax:

initZoomPan(gc, reDraw);

Description:

This function creates an overlay canvas and draws Zoom and Pan controls in the top right corner of a canvas element. Any or all the Cango contexts defined on any of the canvases in the stack can be zoomed and panned by clicking on these controls. The Cango contexts to be affected by zooming and panning are set by the 'gc' parameter. 'gc' may be a single Cango context or an array of contexts. Clicking the zoom controls will re-scaling the world coordinates of these contexts by 20% per click. Clicking the pan controls will add or subtract 50 pixels per click to the corresponding coordinate offset. When the scaling or position offsets have been applied, the Cango drawings on the canvas must be re-drawn to show the effect. The callback function to do this re-draw is also passed as the 'reDraw' argument.

Parameters:

gc:Cango context or Array of Cango contexts - This is the Cango graphics context that will have all its drawing zoomed or panned. If several Contexts are present on the background canvas or any canvas layer they may be passed as an array of Cango contexts, all will be zoomed or panned together as the control buttons are clicked.

reDraw:Function - The user defined function 'redraw' will be called to redraw all the objects on all the canvases in their new zoomed or panned size or position.

Example:

Figure 12. Example of zoom and pan controls, click on the buttons in the top right corner to zoom or pan the drawing. Clicking on the 'X' button returns the drawing to its original size and position.

The code for the zoom and pan example is shown below. Note that the line width of the Img border is set in world coordinates using the 'lineWidthWC' property so the border scales with zooming, whereas the border width of the yellow shape is set in pixels using the 'lineWidth' property and so doesn't scale with zooming.

function zoomPanTest(cvsID)
{
  const xmin = -300, ymin = -100, xspan = 750,
  Arc3 = "M0,50 h-150 a150,150,0,1,0,150,-150 z M-25,25 v-150 a150,150,0,0,0,-150,150 z";

  const g = new Cango(cvsID);
  g.setWorldCoordsRHC(xmin, ymin, xspan);

  const gL1 = new Cango(g.createLayer());
  gL1.dupCtx(g);

  const jane = new Img("Images/JaneAvril2.jpg", {
    scl: 2,
    imgHeight: 100,
    border:true,
    lineWidthWC:6,
    strokeColor:'sienna',
    shadowOffsetX:8,
    shadowOffsetY:-8,
    shadowBlur:4,
    shadowColor:'grey' });

  const txt = new Text("Caption", {
    fillColor:"red",
    fontSize:20,
    border:true,
    lineWidth:1 });

  const arcsObj = new Shape(Arc3, {
    scl: 0.5,
    border:true,
    strokeColor:"red",
    lineWidth:2,       // pixels
    fillColor:"yellow" });

  function drawBits()
  {
    jane.translate(100, 250);
    g.render(jane, true);
    txt.translate(100, 20);
    g.render(txt);
    gL1.render(arcsObj, true);
  }

  drawBits();
  initZoomPan([g, gL1], drawBits);
}