graphics-vml.js revision 4a96b3331820ea474b8474f7cd7a7f2f28dae602
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Drawing.html">`Drawing`</a> class.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * `VMLDrawing` is not intended to be used directly. Instead, use the <a href="Drawing.html">`Drawing`</a> class.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * capabilities, the <a href="Drawing.html">`Drawing`</a> class will point to the `VMLDrawing` class.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @module graphics
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @class VMLDrawing
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @constructor
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Current x position of the drqwing.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @property _currentX
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @type Number
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Current y position of the drqwing.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @property _currentY
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @type Number
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a bezier curve.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @method curveTo
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cp1x x-coordinate for the first control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cp1y y-coordinate for the first control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cp2x x-coordinate for the second control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cp2y y-coordinate for the second control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} x x-coordinate for the end point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} y y-coordinate for the end point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe curveTo: function(cp1x, cp1y, cp2x, cp2y, x, y) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this._path += ' c ' + Math.round(cp1x) + ", " + Math.round(cp1y) + ", " + Math.round(cp2x) + ", " + Math.round(cp2y) + ", " + x + ", " + y;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a quadratic bezier curve.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @method quadraticCurveTo
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cpx x-coordinate for the control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} cpy y-coordinate for the control point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} x x-coordinate for the end point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} y y-coordinate for the end point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a rectangle.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @method drawRect
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} x x-coordinate
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} y y-coordinate
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} w width
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} h height
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe drawRect: function(x, y, w, h) {
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.lineTo(x + w, y);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.lineTo(x + w, y + h);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.lineTo(x, y + h);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe return this;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a rectangle with rounded corners.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @method drawRect
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} x x-coordinate
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} y y-coordinate
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} w width
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} h height
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} ew width of the ellipse used to draw the rounded corners
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} eh height of the ellipse used to draw the rounded corners
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.quadraticCurveTo(x, y + h, x + ew, y + h);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.quadraticCurveTo(x + w, y + h, x + w, y + h - eh);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this.quadraticCurveTo(x + w, y, x + w - ew, y);
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe return this;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a wedge.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @method drawWedge
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} x x-coordinate of the wedge's center point
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} y y-coordinate of the wedge's center point
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} startAngle starting angle in degrees
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} arc sweep of the wedge. Negative values draw clockwise.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} radius radius of wedge. If [optional] yRadius is defined, then radius is the x radius.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * @param {Number} yRadius [optional] y radius for wedge.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe drawWedge: function(x, y, startAngle, arc, radius, yRadius)
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe this._path += " m " + x + " " + y + " ae " + x + " " + y + " " + radius + " " + yRadius + " " + startAngle + " " + arc;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe return this;
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe * Draws a line segment using the current line style from the current drawing position to the specified x and y coordinates.
ed22c7109fc5dd9e1b7a5d0333bdc7ad2718e2abYuri Pankov * @method lineTo
ed22c7109fc5dd9e1b7a5d0333bdc7ad2718e2abYuri Pankov * @param {Number} point1 x-coordinate for the end point.
ed22c7109fc5dd9e1b7a5d0333bdc7ad2718e2abYuri Pankov * @param {Number} point2 y-coordinate for the end point.
c10c16dec587a0662068f6e2991c29ed3a9db943Richard Lowe if (typeof point1 === 'string' || typeof point1 === 'number') {
moveTo: function(x, y) {
if(!this._path)
this._trackSize(x, y);
this._currentX = x;
this._currentY = y;
_closePath: function()
this._fillChangeHandler();
this._strokeChangeHandler();
if(path)
if(stroke)
if(path)
this._updateTransform();
end: function()
this._closePath();
clear: function()
_trackSize: function(w, h) {
if (w > this._right) {
this._right = w;
if(w < this._left)
this._left = w;
if (h < this._top)
this._top = h;
if (h > this._bottom)
this._bottom = h;
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Shape.html">`Shape`</a> class.
* `VMLShape` is not intended to be used directly. Instead, use the <a href="Shape.html">`Shape`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Shape.html">`Shape`</a> class will point to the `VMLShape` class.
VMLShape = function()
this._transforms = [];
init: function()
var host = this,
this._updateHandler();
createNode: function()
var node,
id,
type,
fill,
nodestring = '<' + type + ' xmlns="urn:schemas-microsft.com:vml" id="' + id + '" class="' + classString + '" style="behavior:url(#default#VML);display:inline-block;position:absolute;left:' + x + 'px;top:' + y + 'px;width:' + w + 'px;height:' + h + 'px;"';
nodestring += ' stroked="t" strokecolor="' + stroke.color + '" strokeWeight="' + stroke.weight + 'px"';
strokestring = '<stroke class="vmlstroke" xmlns="urn:schemas-microsft.com:vml" on="t" style="behavior:url(#default#VML);display:inline-block;"';
if(endcap)
if(joinstyle)
if(miterlimit)
if(dashstyle)
if(fill)
if(this._strokeNode)
if(this._fillNode)
this._strokeFlag = false;
this._fillFlag = false;
getXY: function()
_getStrokeProps: function()
var props,
val,
len,
props = {};
dash = [];
return props;
_strokeChangeHandler: function(e)
if(!this._strokeFlag)
val,
len,
if(!this._strokeNode)
dash = [];
if(this._strokeNode)
this._strokeFlag = false;
_getFillProps: function()
filled = false;
if(fill)
props = {};
filled = true;
fillstring = '<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" opacity="' + fillOpacity + '"';
for(i in gradient)
filled = true;
props.node = '<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" type="solid" opacity="' + fillOpacity + '"/>';
return props;
_fillChangeHandler: function(e)
if(!this._fillFlag)
filled = false,
if(fill)
filled = true;
if(this._fillNode)
for(i in gradient)
fillstring = '<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;"';
for(i in gradient)
filled = true;
if(this._fillNode)
fillstring = '<fill xmlns="urn:schemas-microsft.com:vml" class="vmlfill" style="behavior:url(#default#VML);display:inline-block;" type="solid" opacity="' + fillOpacity + '"/>';
else if(this._fillNode)
this._fillFlag = false;
if(!this._fillNode)
var gradientProps = {},
stop,
oi,
r = fill.r,
pct,
for(;i < len; ++i) {
return gradientProps;
if(this.initialized)
this._updateTransform();
_updateTransform: function()
key,
cx,
cy,
dx,
dy,
tx,
ty,
keys = [],
for(; i < len; ++i)
if(key)
this._transforms = [];
x += dx;
y += dy;
translate: function(x, y)
this._translateX += x;
this._translateY += y;
translateX: function(x)
this._translateX += x;
translateY: function(y)
this._translateY += y;
skew: function(x, y)
skewX: function(x)
skewY: function(y)
scale: function(x, y)
_draw: function()
_updateHandler: function(e)
var host = this,
this._draw();
return DOCUMENT.createElement('<' + type + ' xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);display:inline-block;" class="vml' + type + '"/>');
_getDefaultFill: function() {
_getDefaultStroke: function()
* @param {String|Object} name The name of the attribute. Alternatively, an object of key value pairs can
* @param {Any} value The value to set the attribute to. This value is ignored if an object is received as
set: function()
var host = this;
* Calculates the a new bounding box from the original corner coordinates (base on size and position) and the transform matrix.
var wt,
bounds = {},
a = matrix.a,
b = matrix.b,
c = matrix.c,
d = matrix.d,
return bounds;
destroy: function()
if(this.node)
if(this._fillNode)
if(this._strokeNode)
if(parentNode)
* An array of x, y values which indicates the transformOrigin in which to rotate the shape. Valid values range between 0 and 1 representing a
valueFn: function()
* <p>A string containing, in order, transform operations applied to the shape instance. The `transform` string can contain the following values:
* <p>Applying transforms through the transform attribute will reset the transform matrix and apply a new transform. The shape class also contains corresponding methods for each transform
* that will apply the transform to the current matrix. The below code illustrates how you might use the `transform` attribute to instantiate a recangle with a rotation of 45 degrees.</p>
transform: {
len,
for(;i < len; ++i)
if(this.initialized)
this._updateTransform();
return val;
getter: function()
return this._transform;
id: {
valueFn: function()
return Y.guid();
if(node)
return val;
width: {
height: {
visible: {
value: true,
if(node)
return val;
* <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the fill. The default value is 1.</dd>
* <p>If a `linear` or `radial` is specified as the fill type. The following additional property is used:
* <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the stop. The default value is 1. Note: No effect for IE 6 - 8</dd>
* <dt>rotation</dt><dd>Linear gradients flow left to right by default. The rotation property allows you to change the flow by rotation. (e.g. A rotation of 180 would make the gradient pain from right to left.)</dd>
* <p>The x-coordinate of the center of the gradient circle. Determines where the color stop begins. The default value 0.5.</p>
* <p>The y-coordinate of the center of the gradient circle. Determines where the color stop begins. The default value 0.5.</p>
fill: {
fill,
if(val)
for(i in val)
this._fillFlag = true;
return fill;
* <dt>opacity</dt><dd>Number between 0 and 1 that indicates the opacity of the stroke. The default value is 1.</dd>
* <dt>dashstyle</dt>Indicates whether to draw a dashed stroke. When set to "none", a solid stroke is drawn. When set to an array, the first index indicates the
* <dt>miter limit</dt><dd>An integer specifying the miter limit of a miter linejoin. If you want to specify a linejoin of miter, you simply specify the limit as opposed to having
stroke: {
wt,
if(val)
for(i in val)
this._strokeFlag = true;
return stroke;
autoSize: {
value: false
node: {
readOnly: true,
getter: function()
return this.node;
graphic: {
readOnly: true,
getter: function()
return this._graphic;
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Path.html">`Path`</a> class.
* `VMLPath` is not intended to be used directly. Instead, use the <a href="Path.html">`Path`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Path.html">`Path`</a> class will point to the `VMLPath` class.
VMLPath = function()
_updateHandler: function()
var host = this;
width: {
getter: function()
return this._width;
return val;
height: {
getter: function()
return this._height;
return val;
path: {
readOnly: true,
getter: function()
return this._path;
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Rect.html">`Rect`</a> class.
* `VMLRect` is not intended to be used directly. Instead, use the <a href="Rect.html">`Rect`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Rect.html">`Rect`</a> class will point to the `VMLRect` class.
VMLRect = function()
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Ellipse.html">`Ellipse`</a> class.
* `VMLEllipse` is not intended to be used directly. Instead, use the <a href="Ellipse.html">`Ellipse`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Ellipse.html">`Ellipse`</a> class will point to the `VMLEllipse` class.
VMLEllipse = function()
xRadius: {
lazyAdd: false,
getter: function()
return val;
return val;
yRadius: {
lazyAdd: false,
getter: function()
return val;
return val;
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Circle.html">`Circle`</a> class.
* `VMLCircle` is not intended to be used directly. Instead, use the <a href="Circle.html">`Circle`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Circle.html">`Circle`</a> class will point to the `VMLCircle` class.
radius: {
lazyAdd: false,
width: {
return val;
getter: function()
return val;
height: {
return val;
getter: function()
return val;
VMLPieSlice = function()
_draw: function(e)
this.clear();
this.end();
cx: {
cy: {
startAngle: {
arc: {
radius: {
* <a href="http://www.w3.org/TR/NOTE-VML">VML</a> implementation of the <a href="Graphic.html">`Graphic`</a> class.
* `VMLGraphic` is not intended to be used directly. Instead, use the <a href="Graphic.html">`Graphic`</a> class.
* If the browser lacks <a href="http://www.w3.org/TR/SVG/">SVG</a> and <a href="http://www.w3.org/TR/html5/the-canvas-element.html">Canvas</a>
* capabilities, the <a href="Graphic.html">`Graphic`</a> class will point to the `VMLGraphic` class.
VMLGraphic = function() {
* Whether or not to render the `Graphic` automatically after to a specified parent node after init. This can be a Node instance or a CSS selector string.
render: {},
id: {
valueFn: function()
return Y.guid();
if(node)
return val;
shapes: {
readOnly: true,
getter: function()
return this._shapes;
* Object containing size and coordinate data for the content of a Graphic in relation to the coordSpace node.
readOnly: true,
getter: function()
return this._contentBounds;
node: {
readOnly: true,
getter: function()
return this._node;
width: {
if(this._node)
return val;
height: {
if(this._node)
return val;
* Determines how the size of instance is calculated. If true, the width and height are determined by the size of the contents.
* If false, the width and height values are either explicitly set or determined by the size of the parent node's dimensions.
autoSize: {
value: false
resizeDown: {
getter: function()
return this._resizeDown;
this._redraw();
return val;
getter: function()
return this._x;
if(this._node)
return val;
getter: function()
return this._y;
if(this._node)
return val;
* Indicates whether or not the instance will automatically redraw after a change is made to a shape.
autoDraw: {
value: true
visible: {
value: true,
return val;
getXY: function()
xy;
if(node)
return xy;
_resizeDown: false,
this._shapes = {};
this._contentBounds = {
if(render)
this.setSize(w, h);
destroy: function()
this.clear();
return shape;
this._redraw();
removeAllShapes: function()
for(i in shapes)
this._shapes = {};
var child;
clear: function() {
this._removeAllShapes();
if(shapes)
for(i in shapes)
setSize: function(w, h) {
w = Math.round(w);
h = Math.round(h);
setPosition: function(x, y)
x = Math.round(x);
y = Math.round(y);
_createGraphic: function() {
var group = DOCUMENT.createElement('<group xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);display:block;zoom:1;" />');
return group;
return DOCUMENT.createElement('<' + type + ' xmlns="urn:schemas-microsft.com:vml" style="behavior:url(#default#VML);display:inline-block;zoom:1;" />');
if(shape)
return shape;
return val;
_shapeClass: {
this._redraw();
_getDocFrag: function()
if(!this._frag)
return this._frag;
var shapeBox,
box;
this._redraw();
_redraw: function()
if(this._frag)
this._frag = null;
_getUpdatedContentBounds: function()
var bounds,
box = {
for(i in queue)
return box;