HtmlObject class
The HtmlObject adds a regular HTML element to the display list. You can set all the well known DisplayObject properties like x, y, scaleX, scaleY, rotation or alpha which will be applied to the HTML element. Because the HtmlObject is still rendered by the browser it will appear on top of the Stage and can't be overlayed by regular DisplayObjects.
Please use this HTML configuration to get the correct results:
<div style="position: relative;">
  <canvas id="stage" width="800" height="600"></canvas>
  <div id="htmlObject">Hello World</div>
</div>
The HtmlObject will automatically set the following CSS properties for the element to control it's position and opacity:
position: absolute;
left: 0px;
top: 0px;
transformOrigin: 0% 0% 0;
opacity: (htmlObject.alpha)
visibility: (htmlObject.visible)
transform: (htmlObject.transformationMatrix)
Example:
var element = html.querySelector("#htmlObject");
var htmlObject = new HtmlObject(element);
htmlObject.x = 400;
htmlObject.y = 300;
stage.addChild(htmlObject);
class HtmlObject extends DisplayObject {
 final html.Element element;
 html.CssStyleDeclaration _style;
 String _styleOpacity = "";
 String _styleTransform = "";
 String _styleVisibility = "";
 HtmlObject(this.element) {
   _style = this.element.style;
   _style.position = "absolute";
   _style.left = "0px";
   _style.top = "0px";
   _style.transformOrigin = "0% 0% 0";
   _style.visibility = "hidden";
   this.onRemovedFromStage.listen(_onRemovedFromStage);
 }
 //-----------------------------------------------------------------------------------------------
 _hideElement() {
   _style.visibility = _styleVisibility = "hidden";
 }
 _onRemovedFromStage(Event e) {
   _hideElement();
 }
 set visible(bool value) {
   super.visible = value;
   if (value == false) _hideElement();
 }
 set off(bool value) {
   super.off = value;
   if (value) _hideElement();
 }
 //-----------------------------------------------------------------------------------------------
 void render(RenderState renderState) {
   var viewPortMatrix = renderState.renderContext.viewPortMatrix;
   var globalMatrix = renderState.globalMatrix;
   var globalAlpha = renderState.globalAlpha;
   var visibility = this.visible && this.off == false;
   _tmpMatrix.copyFrom(globalMatrix);
   _tmpMatrix.concat(viewPortMatrix.cloneInvert());
   var mxa = _tmpMatrix.a.toStringAsFixed(4);
   var mxb = _tmpMatrix.b.toStringAsFixed(4);
   var mxc = _tmpMatrix.c.toStringAsFixed(4);
   var mxd = _tmpMatrix.d.toStringAsFixed(4);
   var mxtx = _tmpMatrix.tx.toStringAsFixed(4);
   var mxty = _tmpMatrix.ty.toStringAsFixed(4);
   var styleOpacity = globalAlpha.toStringAsFixed(4);
   var styleTransform = "matrix($mxa,$mxb,$mxc,$mxd,$mxtx,$mxty)";
   var styleVisibility = visibility ? "visible" : "hidden";
   if (_styleVisibility != styleVisibility) {
     _style.visibility = _styleVisibility = styleVisibility;
   }
   if (_styleOpacity != styleOpacity) {
     _style.opacity = _styleOpacity = styleOpacity;
   }
   if (_styleTransform != styleTransform) {
     _style.transform = _styleTransform = styleTransform;
   }
 }
}
Extends
EventDispatcher > DisplayObject > HtmlObject
Constructors
new HtmlObject(Element element) #
Creates a new Object instance.
Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.
HtmlObject(this.element) {
 _style = this.element.style;
 _style.position = "absolute";
 _style.left = "0px";
 _style.top = "0px";
 _style.transformOrigin = "0% 0% 0";
 _style.visibility = "hidden";
 this.onRemovedFromStage.listen(_onRemovedFromStage);
}
Properties
num alpha #
num get alpha => _alpha;
set alpha(num value) {
 if (value is num) {
   if (value < 0.0) value = 0.0;
   if (value > 1.0) value = 1.0;
   _alpha = value;
 }
}
String compositeOperation #
String get compositeOperation => _compositeOperation;
set compositeOperation(String value) {
 _compositeOperation = value;
}
List<BitmapFilter> filters #
List<BitmapFilter> get filters {
 if (_filters == null) _filters = new List<BitmapFilter>();
 return _filters;
}
set filters(List<BitmapFilter> value) {
 _filters = value;
}
num height #
num get height => getBoundsTransformed(this.transformationMatrix).height;
void set height(num value) {
 this.scaleY = 1;
 num normalHeight = this.height;
 this.scaleY = (normalHeight != 0.0) ? value / normalHeight : 1.0;
}
Mask mask #
Mask get mask => _mask;
set mask(Mask value) {
 _mask = value;
}
final Point mousePosition #
Point get mousePosition {
 var stage = this.stage;
 return (stage != null) ? this.globalToLocal(stage._mousePosition) : null;
}
final num mouseX #
num get mouseX {
 var mp = this.mousePosition;
 return (mp != null) ? mp.x : 0.0;
}
final num mouseY #
num get mouseY {
 var mp = this.mousePosition;
 return (mp != null) ? mp.y : 0.0;
}
String name #
String get name => _name;
set name(String value) {
 _name = value;
}
final EventStream<Event> onAdded #
EventStream<Event> get onAdded => DisplayObject.addedEvent.forTarget(this);
final EventStream<Event> onAddedToStage #
EventStream<Event> get onAddedToStage => DisplayObject.addedToStageEvent.forTarget(this);
final EventStream<EnterFrameEvent> onEnterFrame #
EventStream<EnterFrameEvent> get onEnterFrame => DisplayObject.enterFrameEvent.forTarget(this);
final EventStream<ExitFrameEvent> onExitFrame #
EventStream<ExitFrameEvent> get onExitFrame => DisplayObject.exitFrameEvent.forTarget(this);
final EventStream<Event> onRemoved #
EventStream<Event> get onRemoved => DisplayObject.removedEvent.forTarget(this);
final EventStream<Event> onRemovedFromStage #
EventStream<Event> get onRemovedFromStage => DisplayObject.removedFromStageEvent.forTarget(this);
final EventStream<RenderEvent> onRender #
EventStream<RenderEvent> get onRender => DisplayObject.renderEvent.forTarget(this);
final DisplayObjectContainer parent #
DisplayObjectContainer get parent => _parent;
num pivotX #
num get pivotX => _pivotX;
set pivotX(num value) {
 if (value is num) _pivotX = value;
 _transformationMatrixRefresh = true;
}
num pivotY #
num get pivotY => _pivotY;
set pivotY(num value) {
 if (value is num) _pivotY = value;
 _transformationMatrixRefresh = true;
}
final DisplayObject root #
DisplayObject get root {
 DisplayObject currentObject = this;
 while (currentObject._parent != null)
   currentObject = currentObject._parent;
 return currentObject;
}
num rotation #
num get rotation => _rotation;
set rotation(num value) {
 if (value is num) _rotation = value;
 _transformationMatrixRefresh = true;
}
num scaleX #
num get scaleX => _scaleX;
set scaleX(num value) {
 if (value is num) _scaleX = value;
 _transformationMatrixRefresh = true;
}
num scaleY #
num get scaleY => _scaleY;
set scaleY(num value) {
 if (value is num) _scaleY = value;
 _transformationMatrixRefresh = true;
}
Shadow shadow #
Shadow get shadow => _shadow;
set shadow(Shadow value) {
 _shadow = value;
}
num skewX #
num get skewX => _skewX;
set skewX(num value) {
 if (value is num) _skewX = value;
 _transformationMatrixRefresh = true;
}
num skewY #
num get skewY => _skewY;
set skewY(num value) {
 if (value is num) _skewY = value;
 _transformationMatrixRefresh = true;
}
final Stage stage #
Stage get stage {
 DisplayObject root = this.root;
 return (root is Stage) ? root : null;
}
final Matrix transformationMatrix #
Matrix get transformationMatrix {
 /*
 _transformationMatrix.identity();
 _transformationMatrix.translate(-_pivotX, -_pivotY);
 _transformationMatrix.scale(_scaleX, _scaleY);
 _transformationMatrix.rotate(_rotation);
 _transformationMatrix.translate(_x, _y);
 */
 if (_transformationMatrixRefresh) {
   _transformationMatrixRefresh = false;
   num skewXrotation =  _skewX + _rotation;
   num skewYrotation =  _skewY + _rotation;
   num scaleX = _scaleX;
   num scaleY = _scaleY;
   num pivotX = _pivotX;
   num pivotY = _pivotY;
   // ToDo: https://bugzilla.mozilla.org/show_bug.cgi?id=661452
   if (scaleX > -0.0001 && scaleX < 0.0001) scaleX = (scaleX >= 0) ? 0.0001 : -0.0001;
   if (scaleY > -0.0001 && scaleY < 0.0001) scaleY = (scaleY >= 0) ? 0.0001 : -0.0001;
   if (skewXrotation == 0.0 && skewYrotation == 0.0) {
     _transformationMatrix.setTo(scaleX, 0.0, 0.0, scaleY, _x - pivotX * scaleX, _y - pivotY * scaleY);
   } else {
     num a, b, c, d;
     num cosX = cos(skewXrotation);
     num sinX = sin(skewXrotation);
     if (skewXrotation == skewYrotation) {
       a =   scaleX * cosX;
       b =   scaleX * sinX;
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     } else {
       a =   scaleX * cos(skewYrotation);
       b =   scaleX * sin(skewYrotation);
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     }
     num tx =  _x - (pivotX * a + pivotY * c);
     num ty =  _y - (pivotX * b + pivotY * d);
     _transformationMatrix.setTo(a, b, c, d, tx, ty);
   }
 }
 return _transformationMatrix;
}
var userData #
Gets or sets user-defined data associated with the display object.
dynamic userData = null
dynamic set visible(bool value) #
set visible(bool value) {
 super.visible = value;
 if (value == false) _hideElement();
}
num width #
num get width => getBoundsTransformed(this.transformationMatrix).width;
void set width(num value) {
 this.scaleX = 1;
 num normalWidth = this.width;
 this.scaleX = (normalWidth != 0.0) ? value / normalWidth : 1.0;
}
num x #
num get x => _x;
set x(num value) {
 if (value is num) _x = value;
 _transformationMatrixRefresh = true;
}
num y #
num get y => _y;
set y(num value) {
 if (value is num) _y = value;
 _transformationMatrixRefresh = true;
}
Methods
StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {bool useCapture: false, int priority: 0}) #
StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false, int priority: 0 }) {
 return this.on(eventType)._subscribe(eventListener, useCapture, priority);
}
void addTo(DisplayObjectContainer parent) #
void addTo(DisplayObjectContainer parent) {
 parent.addChild(this);
}
void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) #
void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) {
 var pixelRatio = Stage.autoHiDpi ? _devicePixelRatio : 1.0;
 if (_cacheTexture == null) {
   _cacheTexture = new RenderTexture(width, height, true, Color.Transparent, pixelRatio);
 } else {
   _cacheTexture.resize(width, height);
 }
 _cacheRectangle = new Rectangle(x, y, width, height);
 _cacheDebugBorder = debugBorder;
 refreshCache();
}
void dispatchEvent(Event event) #
void dispatchEvent(Event event) {
 List<DisplayObject> ancestors = null;
 if (event.captures || event.bubbles) {
   for(DisplayObject ancestor = parent; ancestor != null; ancestor = ancestor.parent) {
     if(ancestor._hasPropagationEventListeners(event)) {
       if (ancestors == null) ancestors = [];
       ancestors.add(ancestor);
     }
   }
 }
 if (ancestors != null && event.captures) {
   for(int i = ancestors.length - 1 ; i >= 0; i--) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.CAPTURING_PHASE);
     if (event.stopsPropagation) return;
   }
 }
 _dispatchEventInternal(event, this, EventPhase.AT_TARGET);
 if (event.stopsPropagation) return;
 if (ancestors != null && event.bubbles) {
   for(int i = 0; i < ancestors.length; i++) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.BUBBLING_PHASE);
     if (event.stopsPropagation) return;
   }
 }
}
Rectangle getBounds(DisplayObject targetSpace) #
Rectangle getBounds(DisplayObject targetSpace) {
 Rectangle returnRectangle = new Rectangle.zero();
 Matrix matrix = (targetSpace == null) ? transformationMatrix : transformationMatrixTo(targetSpace);
 return (matrix != null) ? getBoundsTransformed(matrix, returnRectangle) : returnRectangle;
}
Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) #
Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) {
 if (returnRectangle == null) returnRectangle = new Rectangle.zero();
 returnRectangle.x = matrix.tx;
 returnRectangle.y = matrix.ty;
 returnRectangle.width = 0;
 returnRectangle.height = 0;
 return returnRectangle;
}
Point globalToLocal(Point globalPoint) #
Point globalToLocal(Point globalPoint) {
 _tmpMatrix.identity();
 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }
 _tmpMatrix.invert();
 return _tmpMatrix.transformPoint(globalPoint);
}
bool hasEventListener(String eventType) #
bool hasEventListener(String eventType) {
 var eventStreams = _eventStreams;
 if (eventStreams == null) return false;
 var eventStream = eventStreams[eventType];
 if (eventStream == null) return false;
 return eventStream.hasSubscriptions;
}
DisplayObject hitTestInput(num localX, num localY) #
DisplayObject hitTestInput(num localX, num localY) {
 if (getBoundsTransformed(_identityMatrix).contains(localX, localY))
   return this;
 return null;
}
bool hitTestObject(DisplayObject other) #
bool hitTestObject(DisplayObject other) {
 var stage1 = this.stage;
 var stage2 = other.stage;
 if (stage1 == null || stage2 == null || stage1 != stage2) return false;
 var rect1 = this.getBounds(stage1);
 var rect2 = other.getBounds(stage2);
 return rect1.intersects(rect2);
}
bool hitTestPoint(num x, num y, [bool shapeFlag = false]) #
bool hitTestPoint(num x, num y, [bool shapeFlag = false]) {
 var stage = this.stage;
 if (stage == null) return false;
 if (shapeFlag) {
   var matrix = stage.transformationMatrixTo(this);
   if (matrix == null) return false;
   var stagePoint = new Point(x, y);
   var localPoint = matrix.transformPoint(stagePoint);
   return this.hitTestInput(localPoint.x, localPoint.y) != null;
 } else {
   var rect = this.getBounds(stage);
   return rect.contains(x, y);
 }
}
Point localToGlobal(Point localPoint) #
Point localToGlobal(Point localPoint) {
 _tmpMatrix.identity();
 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }
 return _tmpMatrix.transformPoint(localPoint);
}
EventStream<Event> on(String eventType) #
EventStream<Event> on(String eventType) {
 var eventStreams = _eventStreams;
 if (eventStreams == null) {
   eventStreams = new Map<String, EventStream>();
   _eventStreams = eventStreams;
 }
 var eventStream = eventStreams[eventType];
 if (eventStream == null) {
   eventStream = new EventStream._internal(this, eventType);
   eventStreams[eventType] = eventStream;
 }
 return eventStream;
}
void refreshCache() #
void refreshCache() {
 if (_cacheTexture == null) return;
 var x = _cacheRectangle.x;
 var y = _cacheRectangle.y;
 var width = _cacheRectangle.width;
 var height = _cacheRectangle.height;
 var canvas = _cacheTexture.canvas;
 var matrix = _cacheTexture.quad.drawMatrix..translate(-x, -y);
 var renderContext = new RenderContextCanvas(canvas, Color.Transparent);
 var renderState = new RenderState(renderContext, matrix);
 renderContext.clear();
 render(renderState);
 if (_filters != null) {
   var cacheBitmapData = new BitmapData.fromRenderTextureQuad(_cacheTexture.quad);
   var bounds = this.getBoundsTransformed(_identityMatrix)..offset(-x, -y);
   for(var filter in _filters) {
     var filterOverlap = filter.overlap;
     var filterBounds = bounds.clone();
     filterBounds.offset(filterOverlap.x, filterOverlap.y);
     filterBounds.inflate(filterOverlap.width, filterOverlap.height);
     filter.apply(cacheBitmapData, filterBounds.align());
   }
 }
 if (_cacheDebugBorder) {
   canvas.context2D
       ..setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
       ..lineWidth = 1
       ..lineJoin = "miter"
       ..lineCap = "butt"
       ..strokeStyle = "#FF00FF"
       ..strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
 }
 _cacheTexture.update();
}
void removeCache() #
void removeCache() {
 if (_cacheTexture != null) {
   _cacheTexture.dispose();
   _cacheTexture = null;
 }
}
void removeEventListener(String eventType, EventListener eventListener, {bool useCapture: false}) #
void removeEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false }) {
 this.on(eventType)._unsubscribe(eventListener, useCapture);
}
void removeEventListeners(String eventType) #
void removeEventListeners(String eventType) {
 this.on(eventType).cancelSubscriptions();
}
void removeFromParent() #
void removeFromParent() {
 if (_parent != null)
   _parent.removeChild(this);
}
void render(RenderState renderState) #
void render(RenderState renderState) {
 var viewPortMatrix = renderState.renderContext.viewPortMatrix;
 var globalMatrix = renderState.globalMatrix;
 var globalAlpha = renderState.globalAlpha;
 var visibility = this.visible && this.off == false;
 _tmpMatrix.copyFrom(globalMatrix);
 _tmpMatrix.concat(viewPortMatrix.cloneInvert());
 var mxa = _tmpMatrix.a.toStringAsFixed(4);
 var mxb = _tmpMatrix.b.toStringAsFixed(4);
 var mxc = _tmpMatrix.c.toStringAsFixed(4);
 var mxd = _tmpMatrix.d.toStringAsFixed(4);
 var mxtx = _tmpMatrix.tx.toStringAsFixed(4);
 var mxty = _tmpMatrix.ty.toStringAsFixed(4);
 var styleOpacity = globalAlpha.toStringAsFixed(4);
 var styleTransform = "matrix($mxa,$mxb,$mxc,$mxd,$mxtx,$mxty)";
 var styleVisibility = visibility ? "visible" : "hidden";
 if (_styleVisibility != styleVisibility) {
   _style.visibility = _styleVisibility = styleVisibility;
 }
 if (_styleOpacity != styleOpacity) {
   _style.opacity = _styleOpacity = styleOpacity;
 }
 if (_styleTransform != styleTransform) {
   _style.transform = _styleTransform = styleTransform;
 }
}
void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) #
void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) {
 if (x is num) _x = x;
 if (y is num) _y = y;
 if (scaleX is num) _scaleX = scaleX;
 if (scaleY is num) _scaleY = scaleY;
 if (rotation is num) _rotation = rotation;
 if (skewX is num) _skewX = skewX;
 if (skewY is num) _skewY = skewY;
 if (pivotX is num) _pivotX = pivotX;
 if (pivotY is num) _pivotY = pivotY;
 _transformationMatrixRefresh = true;
}
Matrix transformationMatrixTo(DisplayObject targetSpace) #
Matrix transformationMatrixTo(DisplayObject targetSpace) {
 if (targetSpace == _parent) {
   return this.transformationMatrix.clone();
 }
 if (targetSpace != null && targetSpace._parent == this) {
   return targetSpace.transformationMatrix.cloneInvert();
 }
 //------------------------------------------------
 Matrix resultMatrix = new Matrix.fromIdentity();
 DisplayObject resultObject = this;
 while(resultObject != targetSpace && resultObject._parent != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = resultObject._parent;
 }
 if (targetSpace == null && resultObject != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = null;
 }
 if (resultObject == targetSpace)
   return resultMatrix;
 //------------------------------------------------
 Matrix targetMatrix = new Matrix.fromIdentity();
 DisplayObject targetObject = targetSpace;
 while(targetObject != this && targetObject._parent != null) {
   targetMatrix.concat(targetObject.transformationMatrix);
   targetObject = targetObject._parent;
 }
 targetMatrix.invert();
 if (targetObject == this) {
   return targetMatrix;
 }
 if (targetObject != resultObject) {
   return null;
 }
 resultMatrix.concat(targetMatrix);
 return resultMatrix;
}