How can i add an svg image and a label to a custom shape dynamically mxgraph - mxgraph

`function Domain() {
mxCylinder.call(this);
}
/*
The next lines use an mxCylinder instance to augment the
prototype of the shape ("inheritance") and reset the
constructor to the topmost function of the c'tor chain.
*/
mxUtils.extend(Domain, mxCylinder);
Domain.prototype.redrawPath = function (
path: any,
x: any,
y: any,
w: any,
h: any
) {
var dy = this.extrude * this.scale;
var dx = this.extrude * this.scale;
path.moveTo(0, dy);
path.lineTo(dx, 0);
path.lineTo(w, 0);
path.lineTo(w, h - dy);
path.lineTo(w, h);
path.lineTo(0, h);
path.lineTo(0, dy);
path.lineTo(dx, 0);
path.close();
};
mxCellRenderer.registerShape("Domain", Domain);
export function main(container: any) {
if (!mxClient.isBrowserSupported()) {
mxUtils.error("Browser is not supported!", 200, false);
} else {
mxEvent.disableContextMenu(container);
var graph = new mxGraph(container);
graph.setCellsCloneable(true);
graph.setHtmlLabels(true);
graph.setPanning(true);
graph.setEnabled(false);
graph.centerZoom = false;
new mxRubberband(graph);
configureStylesheet(graph);
var parent = graph.getDefaultParent();
// Adds cells to the model in a single step
graph.getModel().beginUpdate();
try {
var v1 = graph.insertVertex(
parent,
null,
"RAN",
20,
20,
240,
120,
// 'image;image=icons/secure-gdpr-user-svgrepo-com.svg;selectable=0;connectable=0;editable=0;movable=0;fillColor=hsl(36deg 98% 51%)'
//here i'm regestering my shape how can i add an image and a label inside the shape "shape=Domain;startSize=30;fillColor=hsl(36deg 98% 51%);spacingLeft=10;align=left;fontColor=#FFFFFF;fontSize=18;shadow=0;strokeColor=none;whiteSpace=wrap;img;"
);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
}
}
i Used configure style sheet to add the image to the shape but when i do this
// style[mxConstants.STYLE_SHAPE] = "Domain";
the image disappears and i get only the sape
export function configureStylesheet(graph: any) {
var style: any = new Object();
style = mxUtils.clone(style);
// style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
// style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL;
// style[mxConstants.STYLE_SHAPE] = "Domain";
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL;
style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_CENTER;
style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
style[mxConstants.STYLE_IMAGE] = "icons/secure-gdpr-user-svgrepo-com.svg";
style[mxConstants.STYLE_IMAGE_WIDTH] = "48";
style[mxConstants.STYLE_IMAGE_HEIGHT] = "48";
style[mxConstants.STYLE_SPACING_TOP] = "80";
style[mxConstants.STYLE_SPACING] = "8";
graph.getStylesheet().putCellStyle("img", style);
Here's the approach i'm trying to do but the thing is that the image is overwriting the shape and not able to display the image in my customised shape. i need to have that custom shape taking the label and the image and dynamically for it to be implemented more than once`

Related

canvas elements aren't shown

I draw 3 elements on my canvas and it works fine on my page (https://lodysreizen.nl/route2.html). But when I implement that page in a index page(https://lodysreizen.nl/ route2 button), where I load in into a div, only the outline that I draw in my html code are shown.
The other 2 lines and the dot don't show. What am I doing wrong?
I changed the order of the code(first script and then html and the other way around)
function draw() {
var canvas = document.getElementById('japan_canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.strokeStyle = "red";
<!--2 lijnen-->
ctx.beginPath();
ctx.moveTo(125, 125); <!--tekst-->
ctx.lineTo(125, 45);
ctx.lineTo(45, 125);
ctx.lineTo(63, 200);
ctx.lineTo(200, 210);
<!--ctx.closePath(); dit trekt een lijn vanaf het laatste punt naar het begin punt-->
ctx.lineWidth = 2; <!--dikte van de lijn-->
ctx.lineJoin = "round" <!--hoe de lijn er uitziek waar ze een knik maakt.-->
ctx.stroke();
<!--de circels-->
ctx.strokeStyle = "red"; <!--deze kleur werkt nog niet-->
ctx.beginPath();
ctx.arc(125, 45, 5, 0, 2 * Math.PI); <!--circel met centrumpunt 125,45)-->
ctx.fill(); <!--de circel vullen-->
<!--Path2D-->
}
}
canvas {
border: 1px solid black;
}
<body onload="draw();">
<canvas id="japan_canvas" width="300" height="300"></canvas></body>
function createPaint(parent) {
var canvas = elt('canvas', {});
var cx = canvas.getContext('2d');
var toolbar = elt('div', {class: 'toolbar'});
// calls the every function in controls, passing in context,
// then appending the returned results to the toolbar
for (var name in controls)
toolbar.appendChild(controls[name](cx));
var panel = elt('div', {class: 'picturepanel'}, canvas);
parent.appendChild(elt('div', null, panel, toolbar));
}
/************************************************************************
* helper functions
***********************************************************************/
// creates an element with a name and object (attributes)
// appends all further arguments it gets as child nodes
// string arguments create text nodes
// ex: elt('div', {class: 'foo'}, 'Hello, world!');
function elt(name, attributes) {
var node = document.createElement(name);
if (attributes) {
for (var attr in attributes)
if (attributes.hasOwnProperty(attr))
node.setAttribute(attr, attributes[attr]);
}
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
// if this argument is a string, create a text node
if (typeof child == 'string')
child = document.createTextNode(child);
node.appendChild(child);
}
return node;
}
// figures out canvas relative coordinates for accurate functionality
function relativePos(event, element) {
var rect = element.getBoundingClientRect();
return {x: Math.floor(event.clientX - rect.left),
y: Math.floor(event.clientY - rect.top)};
}
// registers and unregisters listeners for tools
function trackDrag(onMove, onEnd) {
function end(event) {
removeEventListener('mousemove', onMove);
removeEventListener('mouseup', end);
if (onEnd)
onEnd(event);
}
addEventListener('mousemove', onMove);
addEventListener('mouseup', end);
}
// loads an image from a URL and replaces the contents of the canvas
function loadImageURL(cx, url) {
var image = document.createElement('img');
image.addEventListener('load', function() {
var color = cx.fillStyle, size = cx.lineWidth;
cx.canvas.width = image.width;
cx.canvas.height = image.height;
cx.drawImage(image, 0, 0);
cx.fillStyle = color;
cx.strokeStyle = color;
cx.lineWidth = size;
});
image.src = url;
}
// used by tools.Spray
// randomly positions dots
function randomPointInRadius(radius) {
for (;;) {
var x = Math.random() * 2 - 1;
var y = Math.random() * 2 - 1;
// uses the Pythagorean theorem to test if a point is inside a circle
if (x * x + y * y <= 1)
return {x: x * radius, y: y * radius};
}
}
/************************************************************************
* controls
***********************************************************************/
// holds static methods to initialize the various controls;
// Object.create() is used to create a truly empty object
var controls = Object.create(null);
controls.tool = function(cx) {
var select = elt('select');
// populate the tools
for (var name in tools)
select.appendChild(elt('option', null, name));
// calls the particular method associated with the current tool
cx.canvas.addEventListener('mousedown', function(event) {
// is the left mouse button being pressed?
if (event.which == 1) {
// the event needs to be passed to the method to determine
// what the mouse is doing and where it is
tools[select.value](event, cx);
// don't select when user is clicking and dragging
event.preventDefault();
}
});
return elt('span', null, 'Tool: ', select);
};
// color module
controls.color = function(cx) {
var input = elt('input', {type: 'color'});
// on change, set the new color style for fill and stroke
input.addEventListener('change', function() {
cx.fillStyle = input.value;
cx.strokeStyle = input.value;
});
return elt('span', null, 'Color: ', input);
};
// save
controls.save = function(cx) {
// MUST open in a new window because of iframe security stuff
var link = elt('a', {href: 'currentTab'}, 'Save');
function update() {
try {
link.href = cx.canvas.toDataURL();
} catch(e) {
// some browsers choke on big data URLs
// also, if the server response doesn't include a header that tells the browser it
// can be used on other domains, the script won't be able to look at it;
// this is in order to prevent private information from leaking to a script;
// pixel data, data URL or otherwise, cannot be extracted from a "tainted canvas"
// and a SecurityError is thrown
if (e instanceof SecurityError)
link.href = 'javascript:alert(' +
JSON.stringify('Can\'t save: ' + e.toString()) + ')';
else
window.alert("Nope.");
throw e;
}
}
link.addEventListener('mouseover', update);
link.addEventListener('focus', update);
return link;
};
/************************************************************************
* tools
***********************************************************************/
// drawing tools
var tools = Object.create(null);
// line tool
// onEnd is for the erase function, which uses it to reset
// the globalCompositeOperation to source-over
tools.Line = function(event, cx, onEnd) {
cx.lineCap = 'round';
// mouse position relative to the canvas
var pos = relativePos(event, cx.canvas);
trackDrag(function(event) {
cx.beginPath();
// move to current mouse position
cx.moveTo(pos.x, pos.y);
// update mouse position
pos = relativePos(event, cx.canvas);
// line to updated mouse position
cx.lineTo(pos.x, pos.y);
// stroke the line
cx.stroke();
}, onEnd);
};
// erase tool
tools.Erase = function(event, cx) {
// globalCompositeOperation determines how drawing operations
// on a canvas affect what's already there
// 'destination-out' makes pixels transparent, 'erasing' them
// NOTE: this has been deprecated
cx.globalCompositeOperation = 'destination-out';
tools.Line(event, cx, function() {
cx.globalCompositeOperation = 'source-over';
});
};
// initialize the app
var appDiv = document.querySelector('#paint-app');
createPaint(appDiv);
canvas {
border: 1px solid black;
}
<div id="paint-app"></div>

Picking under elements of an element in Autodesk Forge viewer

I would like to accomplish a feature that I can do in Three.js but cannot in Autodesk Forge viewer. Here is the link to test: http://app.netonapp.com/JavaScript/Three.js/select_inner_objects.html
The requirement is to select objects inside an object. This job can be done with THREE.Raycaster in the above demo, to use a raycaster to detect all elements which are on the line the ray going through. Then I can get objects behind or inner another object.
I tried this concept in Autodesk Forge viewer but having no success. Here is the code:
// Change this to:
// true to use original Three.js
// false to use Autodesk Forge Viewer API
var useThreeJS = true;
var container = $('div.canvas-wrap')[0];
container.addEventListener('mousedown', function (event) {
if (useThreeJS) {
var canvas = _viewer.impl.canvas;
var containerWidth = canvas.clientWidth;
var containerHeight = canvas.clientHeight;
var camera = _viewer.getCamera();
var mouse = mouse || new THREE.Vector3();
var raycaster = raycaster || new THREE.Raycaster();
mouse.x = 2 * (event.clientX / containerWidth) - 1;
mouse.y = 1 - 2 * (event.clientY / containerHeight);
mouse.unproject(camera);
raycaster.set(camera.position, mouse.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(objects);
if (intersects.length == 1) {
var obj = intersects[0].object;
obj.material.color.setRGB(1.0 - i / intersects.length, 0, 0);
} else if (intersects.length > 1) {
// Exclude the first which is the outer object (i == 0)
for (var i = 1; i < intersects.length; i++) {
var obj = intersects[i].object;
obj.material.color.setRGB(1.0 - i / intersects.length, 0, 0);
}
}
} else {
var vp = _viewer.impl.clientToViewport(event.canvasX, event.canvasY);
var renderer = _viewer.impl.renderer();
var dbId = renderer.idAtPixel(vp.x, vp.y);
if (dbId) {
console.debug("Selected Id: " + dbId);
_viewer.select(dbId);
_viewer.impl.invalidate(true);
}
}
}, false);
I found the Forge viewer has viewer.impl.renderer().idAtPixel method which is great to get an element at the picking pixel. However, I want it to do more, to select all elements (which are under or nested) at the picking pixel. How I can do it with the Forge Viewer API?
Based on the suggestion of Zhong Wu in another post, here is the final solution to select element which is under or inside another element. I created an Autodesk Forge viewer extension to use it easily.
///////////////////////////////////////////////////////////////////////////////
// InnerSelection viewer extension
// by Khoa Ho, December 2016
//
///////////////////////////////////////////////////////////////////////////////
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");
Autodesk.ADN.Viewing.Extension.InnerSelection = function (viewer, options) {
Autodesk.Viewing.Extension.call(this, viewer, options);
var _self = this;
var _container = viewer.canvas.parentElement;
var _renderer = viewer.impl.renderer();
var _instanceTree = viewer.model.getData().instanceTree;
var _fragmentList = viewer.model.getFragmentList();
var _eventSelectionChanged = false;
var _viewport;
var _outerDbId;
_self.load = function () {
_container.addEventListener('mousedown',
onMouseDown);
viewer.addEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
onItemSelected);
console.log('Autodesk.ADN.Viewing.Extension.InnerSelection loaded');
return true;
};
_self.unload = function () {
_container.removeEventListener('mousedown',
onMouseDown);
viewer.removeEventListener(
Autodesk.Viewing.SELECTION_CHANGED_EVENT,
onItemSelected);
console.log('Autodesk.ADN.Viewing.Extension.InnerSelection unloaded');
return true;
};
function onMouseDown(e) {
var viewport = viewer.impl.clientToViewport(e.canvasX, e.canvasY);
_viewport = viewport; // Keep this viewport to use in onItemSelected()
var dbId = _renderer.idAtPixel(viewport.x, viewport.y);
if (_outerDbId == dbId) {
_outerDbId = -1;
// Deselect everything
viewer.select();
} else {
_outerDbId = dbId;
// Hide outer element temporarily to allow picking its behind element
viewer.hideById(dbId);
_eventSelectionChanged = true;
}
viewer.impl.sceneUpdated(true);
}
function onItemSelected(e) {
if (_eventSelectionChanged) {
// Prevent self looping on selection
_eventSelectionChanged = false;
// Show outer element back
viewer.show(_outerDbId);
// Get inner element Id after the outer element
// was just hidden on mouse down event
var innerDbId = _renderer.idAtPixel(_viewport.x, _viewport.y);
if (innerDbId > -1) {
// Select the inner element when it is found
viewer.select(innerDbId);
console.debug("Selected inner Id: " + innerDbId);
} else if (_outerDbId > -1) {
// Select the outer element if the inner element is not found
viewer.select(_outerDbId);
console.debug("Selected outer Id: " + _outerDbId);
}
}
}
};
Autodesk.ADN.Viewing.Extension.InnerSelection.prototype =
Object.create(Autodesk.Viewing.Extension.prototype);
Autodesk.ADN.Viewing.Extension.InnerSelection.prototype.constructor =
Autodesk.ADN.Viewing.Extension.InnerSelection;
Autodesk.Viewing.theExtensionManager.registerExtension(
'Autodesk.ADN.Viewing.Extension.InnerSelection',
Autodesk.ADN.Viewing.Extension.InnerSelection);
As of now (Dec/16), when you select using mouse click, the Viewer will not ignore transparent elements, so it will select an element even if it is transparent. Below is a code I used to track what's under the cursor, maybe can be useful.
// use jQuery to bind a mouve move event
$(_viewer.container).bind("mousemove", onMouseMove);
function onMouseMove(e) {
var screenPoint = {
x: event.clientX,
y: event.clientY
};
var n = normalize(screenPoint);
var dbId = /*_viewer.utilities.getHitPoint*/ getHitDbId(n.x, n.y);
//
// use the dbId somehow...
//
}
// This is a built-in method getHitPoint, but the original returns
// the hit point, so this modified version returns the dbId
function getHitDbId(){
y = 1.0 - y;
x = x * 2.0 - 1.0;
y = y * 2.0 - 1.0;
var vpVec = new THREE.Vector3(x, y, 1);
var result = _viewer.impl.hitTestViewport(vpVec, false);
//return result ? result.intersectPoint : null; // original implementation
return result ? result.dbId : null;
}
function normalize(screenPoint) {
var viewport = _viewer.navigation.getScreenViewport();
var n = {
x: (screenPoint.x - viewport.left) / viewport.width,
y: (screenPoint.y - viewport.top) / viewport.height
};
return n;
}
I see method viewer.impl.renderer().idAtPixel works better than viewer.impl.hitTestViewport to select element on mouse pick. The first one can click through the hidden/ghost element to get the objectId of element behind. While the second cannot. Here is the code to test:
var container = $('div.canvas-wrap')[0];
container.addEventListener('mousedown', function (event) {
var clickThroughHiddenElement = true;
if (clickThroughHiddenElement) {
var vp = _viewer.impl.clientToViewport(event.canvasX, event.canvasY);
var renderer = _viewer.impl.renderer();
var dbId = renderer.idAtPixel(vp.x, vp.y);
if (!!dbId) {
_viewer.select(dbId);
}
console.debug("Selected Id: " + dbId);
} else {
var screenPoint = {
x: event.clientX,
y: event.clientY
};
var viewport = _viewer.navigation.getScreenViewport();
var x = (screenPoint.x - viewport.left) / viewport.width;
var y = (screenPoint.y - viewport.top) / viewport.height;
// Normalize point
x = x * 2.0 - 1.0;
y = (1.0 - y) * 2.0 - 1.0;
var vpVec = new THREE.Vector3(x, y, 1);
var result = _viewer.impl.hitTestViewport(vpVec, false);
if (!!result) {
var dbId = result.dbId;
_viewer.select(dbId);
console.debug("Selected Id: " + dbId);
}
}
}
However, they are not what I want, to click through transparent element to get elements behind. If user selects transparent element, it will be selected. If user selects inner elements, it will ignore outer transparent element to select the pick inner element.
I check Forge viewer uses THREE.Raycaster with element bounding box to detect intersection on mouse click. It seems my problem is doable with the Forge viewer like it does in my Three.js demo.

Cocoss2d-js Create the coloring effect by revealing the bottom layer

I have an Android app for kids that has a coloring screen, and I am trying to convert it to Cocos2d-js. The way I implemented this in Android is to have two pictures on top of each other: a colored one at the bottom, and a grayscale on top. When a touch is detected, the gray scale picture on top is erased on that location revealing the bottom picture.
I am looking at RenderTexture for coloring effect, and ClippingNode for revealing the bottom layer, but when I set the RenderTexture as the stencil for the ClippingNode, the top image is completely transparent (stencil is opaque?)
This is my code so far (top layer only, as the bottom layer is just a sprite that covers the entire screen):
var GrayScaleLayer = cc.Layer.extend({
winsize: null,
_brushs:null,
_target:null,
_lastLocation:null,
ctor:function () {
this._super();
this.init();
},
init:function () {
if ('touches' in cc.sys.capabilities){
cc.eventManager.addListener({
event: cc.EventListener.TOUCH_ALL_AT_ONCE,
onTouchesMoved:function (touches, event) {
event.getCurrentTarget().drawInLocation(touches[0].getLocation());
}
}, this);
} else if ('mouse' in cc.sys.capabilities)
cc.eventManager.addListener({
event: cc.EventListener.MOUSE,
onMouseDown: function(event){
event.getCurrentTarget()._lastLocation = event.getLocation();
},
onMouseMove: function(event){
if(event.getButton() == cc.EventMouse.BUTTON_LEFT)
event.getCurrentTarget().drawInLocation(event.getLocation());
}
}, this);
// Get the screen size of your game canvas
this.winsize = cc.director.getWinSize();
this._brushs = [];
this._lastLocation = cc.p(this.winsize.width, this.winsize.height);
// Create the RenderTexture object
var stencil = this.erase();
stencil.setPosition(cc.p(this.winsize.width/2, this.winsize.height/2));
// Create the clippingNode and add the RenderTexture as a stencil
var clipper = new cc.ClippingNode();
clipper.setPosition(cc.p(0,0));
clipper.stencil = stencil;
clipper.setInverted(true);
this.addChild(clipper);
// Create gray scale image and add it to the Clipping node
var grayItem = new cc.Sprite(res.image_gs_png);
var grayScale = this.winsize.width/grayItem.width;
grayItem.setScale(grayScale, grayScale);
grayItem.setPosition(cc.p(this.winsize.width/2, this.winsize.height/2));
clipper.addChild(grayItem);
},
erase:function () {
var target = new cc.RenderTexture(this.winsize.width, this.winsize.height);
this._target = target;
return target;
},
drawInLocation:function (location) {
var distance = cc.pDistance(location, this._lastLocation);
if (distance > 1) {
var locLastLocation = this._lastLocation;
this._target.begin();
this._brushs = [];
for(var i = 0; i < distance; ++i) {
var diffX = locLastLocation.x - location.x;
var diffY = locLastLocation.y - location.y;
var delta = i / distance;
var sprite = new cc.Sprite(res.brush_png);
sprite.attr({
x: location.x + diffX * delta,
y: location.y + diffY * delta,
rotation: Math.random() * 360,
color: cc.color(Math.random() * 255, 255, 255),
scale: Math.random() + 0.25,
opacity: 20
});
sprite.retain();
this._brushs.push(sprite);
}
for (var i = 0; i < distance; i++) {
this._brushs[i].visit();
}
this._target.end();
}
this._lastLocation = location;
},
onExit:function () {
for(var i in this._brushs){
this._brushs[i].release();
}
this._super();
}
});
I tried using the .clear(rgba) function on the RenderTexture to no avail.
I noticed that the ClippingNode example in the js-tests is adding a DrawNode object as a stencil, is there a way to "convert" the RenderTexture to a DrawNode?
You don't need to use clippingNode for this,
simply have the colored layer on bottom, and a greyscale rendertexture on top,
when touched, you erase the transparency by drawing a sprite onto the rendertexture with this blend func {src: gl_ZERO, dst: gl_ONE_MINUS_SRC_ALPHA}

How to identify shapes in Canvas?

If I define a canvas and draw few shapes onto it, then how can I pinpoint each of the shape or image so as to declare events and other properties on the each shape. Consider I have a Rectangle and a triangle. SO can I have some mechanism so as to define them as specific entity and can I deal with them individually. I know about KineticJS but I would like to implement this functionality on my own(For learning purpose). Can anyone pinpoint the way to do it. Or may be an algorithmic approach??
I would like explain pinpoint using mouse events
First of all you have to implement a method to get mouse position
function getMousePos(canvas, evt){
// get canvas position
var obj = canvas;
wrapper = document.getElementById('wrapper');
var top = 0;
var left = 0;
while (obj && obj.tagName != 'BODY') {
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
// return relative mouse position
var mouseX = evt.clientX - left + window.pageXOffset+wrapper.scrollLeft;
var mouseY = evt.clientY - top + window.pageYOffset+wrapper.scrollTop;
return {
x: mouseX,
y: mouseY
};
}
Rectangle
Say, we have a rectangle with following values x1, y1, w, h
$(canvas).mousemove(function(e){
//Now call the method getMousePos
var mouseX, mouseY;
var mousePos = getMousePos(canvas, e);
mouseX=mousePos.x;
mouseY=mousePos.y;
// check if move on the rect
if(mouseX>x1 && mouseX<x1+w && mouseY>y1 && mouseY<y1+h)
{
alert('mouse on rect')
}
});
Circle
Say, we have a circle with following values x, y, r
$(canvas).mousemove(function(e){
//Now call the method getMousePos
var mouseX, mouseY;
var mousePos = getMousePos(canvas, e);
mouseX=mousePos.x;
mouseY=mousePos.y;
// check if move on the rect
if(Math.pow(mouseX-x,2)+Math.pow(mouseY-y,2)<Math.pow(r,2))
{
alert('mouse on circle')
}
});
By this way we can pinpoint a object of canvas
You can't use any existing functionality in the DOM for that. So you have to write it yourself. You could start by making an object model like this:
function Shape(x, y) {
var obj = {};
obj.x = x;
obj.y = y;
obj.paint = function(canvasTarget) {
}
return obj;
}
function Rectangle(x, y, width, height) {
var obj = Shape(x, y);
obj.width = width;
obj.height = height;
obj.paint = function(canvasTarget) {
//paint rectangle on the canvas
}
return obj;
}
function Canvas(target) {
var obj = {};
obj.target = target
obj.shapes = [];
obj.paint = function() {
//loop through shapes and call paint
}
obj.addShape(shape) {
this.shapes.push(shape);
}
}
After making the object model you could use it to draw the shapes like this:
var cnv = new Canvas();
cnv.addShape(new Rectangle(10,10,100,100));
cnv.paint();
Then you can handle the onclick event on the canvas and determine which shape is clicked on.

dynamically draw circle preloader error 1061 when in document class

I found a tutorial on how to make a dynamic unfilled and filled circle. that will take input from a slider to dertermine how much of the circle is drawn. I wanted to use this for a preloader. Unlike the author I would like to use it inside of a document class. I am getting
1061: Call to a possibly undefined method createEmptyMovieClip through a reference with static type document. and 1120: Access of undefined property circ1. The second is caused from the first. How would I get this to work in my document class? Thanks in advance!
//original code
// x: circles center x, y: circles center y
// a1: first angle, a2: angle to draw to, r: radius
// dir: direction; 1 for clockwise -1 for counter clockwise
MovieClip.prototype.CircleSegmentTo = function(x, y, a1, a2, r, dir) {
var diff = Math.abs(a2-a1);
var divs = Math.floor(diff/(Math.PI/4))+1;
var span = dir * diff/(2*divs);
var rc = r/Math.cos(span);
this.moveTo(x+Math.cos(a1)*r, y+Math.sin(a1)*r);
for (var i=0; i<divs; ++i) {
a2 = a1+span; a1 = a2+span;
this.curveTo(
x+Math.cos(a2)*rc,
y+Math.sin(a2)*rc,
x+Math.cos(a1)*r,
y+Math.sin(a1)*r
);
};
return this;
};
// empty
this.createEmptyMovieClip("circ1",1);
circ1._x = 100;
circ1._y = 150;
circ1.radius = 35;
circ1.onEnterFrame = function(){
this.clear();
var endAngle = 2*Math.PI*percentLoaded;
var startAngle = 0;
if (endAngle != startAngle){
this.lineStyle(2,0,100);
this.CircleSegmentTo(0, 0, startAngle, endAngle, this.radius, -1);
}
}
//filled
this.createEmptyMovieClip("circ2",2);
circ2._x = 220;
circ2._y = 150;
circ2.radius = 35;
/* code in tutorial i left out since its for a second filled in circle
circ2.onEnterFrame = function(){
this.clear();
var endAngle = 2*Math.PI*slider.value/100;
var startAngle = 0;
if (endAngle != startAngle){
this.lineStyle(2,0,100);
this.beginFill(0xFF9999,100);
this.lineTo(this.radius,0);
this.CircleSegmentTo(0, 0, startAngle, endAngle, this.radius, -1);
this.lineTo(0,0);
this.endFill();
}
}
*/
That code you got was made using Actionscript 2, and you're building it for Actionscript 3, so you have to either recode it to Actionscript 3 or compile it for AS2.