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