How to identify shapes in Canvas? - html

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.

Related

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.

HTML5 / kineticJS getIntersection function implementation

I am learning kineticjs through tutorials provided at http://www.html5canvastutorials.com, things are good and easy to understand but, I am having issue in understanding the getIntersection function that i want to use among different objects while dragging to detect collision / overlapping objects.
As far as I have understood the example the getIntersection function expects a position and checks if its intersecting with any other object or not..
Though I got them but with some issues.
I am unable to accomplish this..
Below is the code that I have tried up to now..
<script>
var stage = new Kinetic.Stage({
container: 'container',
width: 1000,
height: 500,
opacity: 0.5
});
var layer = new Kinetic.Layer();
var previous_position;
var new_position;
var collision = false;
var colors = ['red', 'orange', 'yellow', 'green', 'blue', 'purple'];
var yellowBox = null;
for(var n = 0; n < 6; n++) {
// anonymous function to induce scope
(function() {
var i = n;
if(n < 3){
y = 50;
x = i * 100 + i * 10;
}else{
y = 150;
x = (i - 3) * 100 + (i - 3) * 10 ;
if(n == 3){
x = 0;
}
}
var box = new Kinetic.Rect({
x: x,
y: y,
width: 100,
height: 50,
fill: colors[i],
stroke: 'black',
strokeWidth: 4,
draggable: true,
name: colors[i]
});
box.on('dragstart', function() {
previous_position = {
x: this.attrs.x,
y: this.attrs.y
};
});
box.on('dragend', function() {
if(collision){
//this.setPosition(previous_position);
layer.draw();
collision = false;
}else{
//this.setPosition(new_position);
layer.draw();
}
});
box.on("dragmove", function(evt) {
console.log(layer.children.length);
if(layer.children.length > 1){
console.log('dragging');
new_position = {x: this.attrs.x,
y: this.attrs.y};
// var posBL = {x: this.attrs.x,
// y: this.attrs.height + this.attrs.y};
// var posTR = {x: this.attrs.x + this.attrs.width,
// y: this.attrs.y};
var posBR = {x: this.attrs.x + this.attrs.width,
y: this.attrs.y + this.attrs.height };
var collisionTL = this.getStage().getIntersections(new_position);
// var collisionBL = this.getStage().getIntersections(posBL);
// var collisionTR = this.getStage().getIntersections(posTR);
// var collisionBR = this.getStage().getIntersections(posBR);
console.log(collisionTL);
console.log(collisionTL.shapes);
// if(collisionTL.length > 1 || collisionBL.length > 0 || collisionTR.length > 0 || collisionBR.length > 0){
if(collisionTL.length > 1){
console.log(collisionTL.shapes);
collision = true;
}else{ //if(collisionBR.length > 0){
collision = true;
}
// for(i=0; i < collision.length; i++){
// // console.log(collision[i]._id);
// }
}
});
if(colors[i] === 'yellow') {
yellowBox = box;
}
layer.add(box);
})();
}
stage.add(layer);
</script>
in the dragmove event you guyz can see I get the four corner positions of the dragging box {commented right now} and with this I was able to detect the overlap / collision but it has 2 issues:
1. very slow with only 3 objects in my test
2. if non of the corner points intersect it didn't fire the collision stuff {for this one box can be bigger so it can cover the other entirely}
I would highly apreciate if anyone can please help me accomplish this stuff..
[A] Any object dragging if by any mean overlaps any other object I want it to show collision.
[B] If possible make getIntersection to work on a particular layer group whichever is possible
[C] any other workaround beside kineticJS to accomplish the above task
Regards
Ok, the developer of KineticJS is working on improving the .getIntersections() function... or at least he said he is. But until the function is improved you have to make your own collision detection function. Assuming that your objects are rectangles or can be broken into a series of points you should go with something like this:
Create a function which determines if a point is in a shape (if the corner of a rectangle is inside another rectangle) like so:
function checkCollide(pointX, pointY, objectx, objecty, objectw, objecth) { // pointX, pointY belong to one rectangle, while the object variables belong to another rectangle
var oTop = objecty;
var oLeft = objectx;
var oRight = objectx+objectw;
var oBottom = objecty+objecth;
if(pointX > oLeft && pointX < oRight){
if(pointY > oTop && pointY < oBottom ){
return 1;
}
}
else
return 0;
};
then you can do a big loop which iterates through all objects in a layer to check collision, like so:
var children = layer.getChildren();
for( var i=0; i<children.length; i++){ // for each single shape
for( var j=0; j<children.length; j++){ //check each other shape
if(i != j){ //skip if shape is the same
if(checkCollide(children[i].getX(), children[i].getY(), children[j].getX(), children[j].getY(), children[j].getWidth(), children[j].getHeight()))
alert('top left corner collided');
}
}
}
the checkCollide function I provided only checks the collision for the top left corner on each shape, so you have to modify the function to check all corners, it's not a long rewrite, and there are plenty tutorials even here on stackoverflow which deal with 'bounding rectangles collision detection'
This may seem like it is a very heavy function, but surprisingly it is still faster than .getIntersections(). Also, you should throw in extra if statements so that the function doesn't run through all the checks all the time.
I created a game myself and was using .intersects() and was having a lot of slow down. I switched over to this type of 'simpler' collision detection and now my game runs around 60FPS. http://cs.neiu.edu/~tsam/physics/index.phtml (test/test) if you want to check it out. You can view page source to see how I structured the collision detection to be more efficient (such as in checkIntersectsGoal() function.

Dragging with Actionscript 3.0, like moving camera in RTS games

I am trying to build a RTS game with Flash and doing some basic testing. I come across this site teaching me dragging objects. I am modified the code to simulate moving the game world of the game while clicking on it. The center circle is the focus point / center of camera. The rectangle board represents the game world.
I tried to change the function boardMove to click and move according to mouseX and mouseY. But every time I click, the mouseX and mouseY becomes the center of the board, which is not what I wanted. I want to make it relative to the mouse position, but I could only make the board flickering, or moves with its top left corner.
Any suggestions would be appreciated.
// Part 1 -- Setting up the objects
var board:Sprite = new Sprite();
var myPoint:Sprite = new Sprite();
var stageWidth = 550;
var stageHeight = 400;
var boardWidth = 400;
var boardHeight = 300;
var pointWidth = 10;
this.addChild(board);
this.addChild(myPoint);
board.graphics.lineStyle(1,0);
board.graphics.beginFill(0xCCCCCC);
board.graphics.drawRect(0,0,boardWidth,boardHeight);
board.graphics.endFill();
board.x = (stageWidth - boardWidth) / 2;
board.y = (stageHeight - boardHeight) / 2;
myPoint.graphics.lineStyle(1,0);
myPoint.graphics.beginFill(0x0000FF,0.7);
myPoint.graphics.drawCircle(0,0,pointWidth);
myPoint.graphics.endFill();
myPoint.x = (stageWidth - pointWidth) / 2;
myPoint.y = (stageHeight - pointWidth) / 2;
// Part 2 -- Add drag-and-drop functionality - Better Attempt
stage.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
function startMove(evt:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, boardMove);
}
// Revised definition of pointMove in Part II of our script
function boardMove(e:MouseEvent):void {
board.x = checkEdgeX(board.mouseX);
board.y = checkEdgeY(board.mouseY);
e.updateAfterEvent();
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopMove);
function stopMove(e:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, boardMove);
}
// Part III -- Check for boundaries
function checkEdgeX(inX:Number):Number {
var x = stageWidth / 2 - boardWidth;
if (inX < x) {
return x;
}
x = stageWidth / 2;
if (inX > x) {
return x;
}
return inX;
}
function checkEdgeY(inY:Number):Number {
var y = stageHeight / 2 - boardHeight;
if (inY < y) {
return y;
}
y = stageHeight / 2;
if (inY > y) {
return y;
}
return inY;
}
One option is to determine the relative movement of the mouse and move the board accordingly; something like:
private Point lastPosition;
function startMove(...) {
lastPosition = null;
...
}
function boardMove(e:MouseEvent):void {
Point position = new Point(stageX, stageY);
if (lastPosition != null) {
Point delta = position.subtract(lastPosition);
board.x += delta.x; // NOTE: also try -= instead of +=
board.y += delta.y; // NOTE: also try -= instead of +=
e.updateAfterEvent();
}
lastPosition = position;
}

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.

Translate an html5 canvas example to svg

I got familiarize with canvas with the help of lot of resources available online, and trying to compare the same with svg. My application needs to draw limited number of shapes, but need to be interactive. I think svg would be more suitable being the shapes are dom elements. it would be great help if someone can translate the canvas example (see demo) to svg with only dependency on jQuery and html5 (don't worry about IE)
In the example, I need to draw a rectangle using mouse (left click and drag). you may add each element to the dom (in canvas I may have to keep an array for the rect object, as the screen clears on each event).
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="draw.js"></script>
</head>
<body>
<canvas id="cvs" height="600" width="800"></canvas>
</body>
< /html>
$(document).ready(function() {
var cvs = $("#cvs"),
ctx = cvs.get(0).getContext("2d");
var v_bufX, v_bufY, v_bufW, v_bufH;
var box = function ( ctx, style, x, y, w, h ) {
ctx.beginPath();
ctx.rect( x, y, w, h );
ctx.closePath();
if ( style.fill ) {
ctx.fillStyle = style.fill;
ctx.fill();
}
if ( style.stroke ) {
ctx.strokeStyle = style.stroke;
ctx.lineWidth = style.width || 1;
ctx.stroke();
}
},
draw = function (res) {
var style = {fill:'rgba(96,185,206, 0.3)',stroke:'rgb(96,185,206)',width:.5};
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
box(ctx, style, res.x, res.y, res.w, res.h);
};
var rect = {
reset : function () {
this.x0 = this.y0 = this.x = this.y = this.w = this.h = -1;
this.started = this.dragging = false;
},
mousedown : function (e) {
this.reset();
this.started = true;
this.x0 = e._x;
this.y0 = e._y;
},
mousemove : function (e) {
if (!this.started) {
return;
}
var x = Math.min(e._x, this.x0),
y = Math.min(e._y, this.y0),
w = Math.abs(e._x - this.x0),
h = Math.abs(e._y - this.y0);
console.log(x, y, w, h);
if (!w || !h) {
return;
};
this.x = x;
this.y = y;
this.w = w;
this.h = h;
draw(this);
},
mouseup : function (ev) {
if (this.started) {
this.mousemove(ev);
this.started = false;
draw(this);
}
}
};
$(window).mousedown(function(e) {
var canvasOffset = cvs.offset();
e._x = Math.floor(e.pageX-canvasOffset.left);
e._y = Math.floor(e.pageY-canvasOffset.top);
rect.mousedown(e);
});
$(window).mousemove(function(e) {
var canvasOffset = cvs.offset();
e._x = Math.floor(e.pageX-canvasOffset.left);
e._y = Math.floor(e.pageY-canvasOffset.top);
rect.mousemove(e);
});
$(window).mouseup(function(e) {
var canvasOffset = cvs.offset();
e._x = Math.floor(e.pageX-canvasOffset.left);
e._y = Math.floor(e.pageY-canvasOffset.top);
rect.mouseup(e);
});
});
I'm not willing to rewrite an entire example, but here are some resources that might help:
Embedding SVG in XHTML5 - includes a simple JavaScript that creates some of the elements programmtically.
Dragging Transformed Elements - uses my own dragging code and accounts for translations in transformed hierarchies.
SVGPan - a nice library for panning and zooming
Raphael - a library designed to create SVG/VML (for old IE) from JavaScript, including its own draggable implementation.
KevLinDev - a venerable but incredibly-rich source of tutorials and code related to SVG.