Batik Drag Tutorial: How to move shapes in the Canvas
The code provided is a snippet with suggestions, on how to implement a drag operation in a JSVGCanvas. It is identical as the post I submitted in the Batik Mail list. A more detailed drag tutorial is in the works, with explanations about how to handle draggable <g> elements and the transform/translate attribute.
The Post
You need to implement listeners for the mouseevents: public void registerListeners() { // Gets an element from the loaded document. // document is your SVGDocument elt = document.getElementById("The_Group_ID_That_holds_the_movable_Elements"); EventTarget t = (EventTarget)elt; // Adds 'mouseevent' listeners t.addEventListener("mousedown", new OnDownAction(), false); t.addEventListener("mousemove", new OnMoveAction(), false); t.addEventListener("mouseup", new OnUpAction(), false); t.addEventListener("mouseover", new OnOverAction(), false); t.addEventListener("click", new OnClickAction(), false); } Next, you need to register a global variable with the state of the DRAG operation, and the initial drag point: protected int drag; protected Element selectedItem; protected SVGOMPoint initialDragPoint; protected final int DRAG_UP = 0; protected final int DRAG_DOWN = 0; Next, in the onmousedown event, you set the "drag" variable to DRAG_DOWN: public class OnDownAction implements EventListener { public void handleEvent(Event evt) { //perform select, deselect operations, etc... // i.e. assign or validate that you have a draggable item // in the "selectedItem" object (And define "thisNode" element) //For example, "thisNode" can be: SVGLocatable thisNode = (SVGLocatable)evt.getTarget(); //End of example. The variable thisNode has the element // that is the draggableItem. It can be a single Element // or a G element. If you are interested in a G element // you may need a method to locate the desired parent // of your eventTarget (like parsing the ID attr.) because // the eventTarget may only be one single element of a // complex shape, and you want to drag the full complex shape. drag = DRAG_DOWN; // Set the initial drag point DOMMouseEvent elEvt = (DOMMouseEvent)evt; int nowToX = elEvt.getClientX(); int nowToY = elEvt.getClientY(); // Convert Screen coordinates to Document Coordinates. SVGOMPoint pt = new SVGOMPoint(nowToX, nowToY); SVGMatrix mat = thisNode.getScreenCTM(); // elem -> screen mat = mat.inverse(); // screen -> elem initialDragPoint = (SVGOMPoint)pt.matrixTransform(mat); } } Now, on mouse up, finalize the drag operation: public class OnUpAction implements EventListener { public void handleEvent(Event evt) { drag = DRAG_UP; } } And Finally, the core of the drag: public class OnMoveAction implements EventListener { public void handleEvent(Event evt) { if (drag == DRAG_DOWN) { //Cast the event onto a Batik Mouse event, //so we can get ccordinates DOMMouseEvent elEvt = (DOMMouseEvent)evt; int nowToX = elEvt.getClientX(); int nowToY = elEvt.getClientY(); //convert it to a point for use with the Matrix SVGOMPoint pt = new SVGOMPoint(nowToX, nowToY); //Get the items screen coordinates, and apply the transformation // elem -> screen SVGMatrix mat = ((SVGLocatable)evt.getTarget()).getScreenCTM(); mat = mat.inverse(); // screen -> elem SVGOMPoint dragpt = (SVGOMPoint)pt.matrixTransform(mat); /* Now to actually move the objects, there are several approaches: a.) If they are individual elements (i.e. no <g>´s), you can simply modify the element attributes X, Y. by: "element.setAttribute("x", ""+ dragpt.getX());" b.) You can iterate though all the elements in the selection (in case of multiple selections or <g> elements) and individually change the x, y attributes of each item, as in a.) c.) You can apply a transform on your selected element. To do so you need to perform a matrix transform from previous transforms this object has had. For example, the first time you drag an object, you will add a transform attribute such as: transform="translate(dragpt.x, dragpt.y)", but for subsequent drag operations you need to do, for each axis: oldtransformCoordinate + newCordinate For a fully functional example of this approach, you can see the Adobe SVGDraw application, found at: http://www.adobe.com/svg/demos/svgDraw/svgDraw/index.html Although this demo is purely Javascript-Adobe SVG Viewer application, you may learn a lot at how to handle the DOM and perform multiple operations. Pay specific attention to the Matrix transform methods. To analyze easily the Javascript code, i recommend the Eclipse IDE v3.0.2 with the jseditor plugin (sourceforge.net/projects/jseditor) */ } } }
Display
To do