changeset 1356:339e406772f9

pluggable SVG shapes
author hertzhaft
date Sun, 15 Feb 2015 14:35:42 +0100
parents c37c6e67ef07
children c176dca2b62b
files webapp/src/main/webapp/jquery/jquery.digilib.vector.js
diffstat 1 files changed, 30 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/webapp/src/main/webapp/jquery/jquery.digilib.vector.js	Sun Feb 15 13:03:15 2015 +0100
+++ b/webapp/src/main/webapp/jquery/jquery.digilib.vector.js	Sun Feb 15 14:35:42 2015 +0100
@@ -59,8 +59,6 @@
     var defaults = {
         // is vector active?
         'isVectorActive' : true,
-        // implemented shape types
-        'supportedShapeTypes' : ['Line', 'Rectangle', 'LineString', 'Polygon', 'Circle', 'Ellipse'],
         // default SVG stroke
         'defaultStroke' : 'red',
         // default SVG stroke-width
@@ -326,7 +324,7 @@
         var svgAttr = function (shape) {
             var props = shape.properties;
             return {
-                'id': shape.id,
+                'id': shape.id || digilib.fn.createId(shape.id, css+'svg-'),
                 'stroke': props['stroke'] || settings.defaultStroke,
                 'stroke-width' : props['stroke-width'] || settings.defaultStrokeWidth,
                 'fill' : props['fill'] || settings.defaultFill,
@@ -337,6 +335,7 @@
         var factory = {
             'Point' : function (shape) {
                 var $s = $(svgElement('path', svgAttr(shape)));
+                shape.properties.maxvtx = 1;
                 $s.place = function () {
                     // point uses pin-like path of size 3*pu
                     var p = shape.properties.screenpos[0];
@@ -346,6 +345,7 @@
                 return $s;
                 },
             'Line' : function (shape) {
+                shape.properties.maxvtx = 2;
                 var $s = $(svgElement('line', svgAttr(shape)));
                 $s.place = function () {
                     var p = shape.properties.screenpos;
@@ -354,6 +354,7 @@
                 return $s;
                 },
             'Rectangle' : function (shape) {
+                shape.properties.maxvtx = 2;
                 var $s = $(svgElement('rect', svgAttr(shape)));
                 $s.place = function () {
                     var p = shape.properties.screenpos;
@@ -379,6 +380,7 @@
                 return $s;
                 },
             'Circle' : function (shape) {
+                shape.properties.maxvtx = 2;
                 var $s = $(svgElement('circle', svgAttr(shape)));
                 $s.place = function () {
                     var p = shape.properties.screenpos;
@@ -387,12 +389,13 @@
                 return $s;
                 },
             'Ellipse' : function (shape) {
+                shape.properties.maxvtx = 2;
                 var $s = $(svgElement('ellipse', svgAttr(shape)));
                 $s.place = function () {
                     var p = shape.properties.screenpos;
                     this.attr({'cx': p[0].x, 'cy': p[0].y,
                         'rx' : Math.abs(p[0].x - p[1].x),
-                    'ry' : Math.abs(p[0].y - p[1].y)});
+                        'ry' : Math.abs(p[0].y - p[1].y)});
                     };
                 return $s;
                 }
@@ -514,12 +517,16 @@
             renderShapes(data, layer);
             return;
         }
+        var shapeType = shape.geometry.type;
+        if (!isSupported(shapeType)) {
+            console.error("renderShape: unsupported shape type: "+shapeType);
+            return;
+        }
         // create the SVG
-        var shapeType = shape.geometry.type;
         var newSVG = data.svgFactory[shapeType];
         var $elem = newSVG(shape);
         shape.$elem = $elem;
-        // place the SVG
+        // place the SVG on screen
         createScreenCoords(data, shape);
         $elem.place();
         // render the SVG
@@ -565,8 +572,7 @@
         var $handle = (shape.$vertexElems != null) ? shape.$vertexElems[vtx] : $();
         var shapeType = shape.geometry.type;
         var imgRect = data.imgRect;
-        var hs = data.settings.editHandleSize;
-        var pStart, pt1, pt2; // convenience variables
+        var pStart; // save startpoint
 
         var dragStart = function (evt) { // start dragging
             // cancel if not left-click
@@ -575,11 +581,6 @@
             shape.properties.startpos = pStart;
             shape.properties.vtx = vtx;
             $(data).trigger('positionShape', shape);
-            if ($.inArray(shapeType, ['Rectangle', 'Circle', 'Ellipse']) > -1) {
-                // save screen points of coordinates
-                pt1 = data.imgTrafo.transform(geom.position(shape.geometry.coordinates[0]));
-                pt2 = data.imgTrafo.transform(geom.position(shape.geometry.coordinates[1]));
-            }
             $document.on("mousemove.dlVertexDrag", dragMove);
             $document.on("mouseup.dlVertexDrag", dragEnd);
             $document.on("dblclick.dlVertexDrag", dragEnd);
@@ -590,49 +591,14 @@
             var pt = geom.position(evt);
             pt.clipTo(imgRect);
             shape.properties.screenpos[vtx] = pt;
+            $handle.moveTo(pt);
             $(data).trigger('positionShape', shape);
-            $handle.moveTo(pt);
-            // update shape SVG element
-            if (shapeType === 'Line') {
-                if (vtx == 0) {
-                    $shape.attr({'x1': pt.x, 'y1': pt.y});
-                } else if (vtx == 1) {
-                    $shape.attr({'x2': pt.x, 'y2': pt.y});
-                }
-            } else if (shapeType === 'Rectangle') {
-                var rect;
-                if (vtx == 0) {
-                    rect = geom.rectangle(pt, pt2);
-                } else if (vtx == 1) {
-                    rect = geom.rectangle(pt1, pt);
-                }
-                $shape.attr({'x': rect.x, 'y': rect.y,
-                    'width': rect.width, 'height': rect.height});
-            } else if (shapeType === 'Polygon' || shapeType === 'LineString') {
-                var points = $shape.attr('points');
-                var ps = points.split(' ');
-                ps[vtx] = pt.x + ',' + pt.y;
-                points = ps.join(' ');
-                $shape.attr('points', points);
-            } else if (shapeType === 'Circle') {
-                if (vtx == 0) {
-                    $shape.attr({'cx': pt.x, 'cy': pt.y, 'r' : pt.distance(pt2)});
-                } else if (vtx == 1) {
-                    $shape.attr({'r': pt.distance(pt1)});
-                }
-            } else if (shapeType === 'Ellipse') {
-                if (vtx == 0) {
-                    $shape.attr({'cx': pt.x, 'cy': pt.y,
-                        'rx': Math.abs(pt.x - pt2.x),
-                        'ry': Math.abs(pt.y - pt2.y)});
-                } else if (vtx == 1) {
-                    $shape.attr({'rx': Math.abs(pt.x - pt1.x), 'ry': Math.abs(pt.y - pt1.y)});
-                }
-            }
-            // update shape object and trigger drag event
             if (isSupported(data, shapeType)) {
+                // update shape object and trigger drag event
                 var p = data.imgTrafo.invtransform(pt);
                 shape.geometry.coordinates[vtx] = [p.x, p.y];
+                // update shape SVG element
+                shape.$elem.place();
                 $(data).trigger('dragShape', shape);
             }
             return false;
@@ -640,18 +606,11 @@
 
         var dragEnd = function (evt) { // end dragging
             var pt = geom.position(evt);
-            shape.properties.screenpos[vtx] = pt;
-            $(data).trigger('positionShape', shape);
             if ((pt.distance(pStart) < 5) && evt.type === 'mouseup') {
             	// not drag but click to start
                 return false;
             }
-            pt.clipTo(imgRect);
-            var p1 = data.imgTrafo.invtransform(pt);
-            // update shape object
-            if (isSupported(data, shapeType)) {
-                shape.geometry.coordinates[vtx] = [p1.x, p1.y];
-            }
+            dragMove(evt);
             // remove move/end handler
             $document.off("mousemove.dlVertexDrag", dragMove);
             $document.off("mouseup.dlVertexDrag", dragEnd);
@@ -677,7 +636,7 @@
      * @param shapeType shapeType to test
      */
     var isSupported = function (data, shapeType) {
-        return $.inArray(shapeType, data.settings.supportedShapeTypes) > -1;
+        return data.svgFactory[shapeType] != null;
     };
 
     /** 
@@ -729,9 +688,11 @@
             // vertex drag end handler
             var vertexDragDone = function (data, shape, evt) {
                 var coords = shape.geometry.coordinates;
-            	if (shapeType === 'LineString' || shapeType === 'Polygon') {
+                var max = shape.properties.maxvtx;
+            	if (max == null || vtx < max-1) {
+            	// multipoint shape (e. g. Polygon, LineString)
             		if (evt.type === 'mouseup') {
-	            		// single click adds next line to LineString/Polygon
+	            		// single click adds next point
 	            		unrenderShape(data, shape);
 	            		// copy last vertex as starting point
 	            		coords.push(coords[vtx].slice());
@@ -742,10 +703,10 @@
 	            		getVertexDragHandler(data, shape, vtx, vertexDragDone)(evt);
 	            		return false;
             		} else if (evt.type === 'dblclick') {
-            		    // double click ends LineString/Polygon
+            		    // double click ends multipoint shape
+            		    var rerender = false;
             		    // remove duplicate vertices (from mouseup)
-            		    var rerender = false;
-	            		while (coords[vtx][0] === coords[vtx-1][0] && 
+	            		while (coords[vtx][0] === coords[vtx-1][0] &&
 	            				coords[vtx][1] === coords[vtx-1][1]) {
                             coords.pop();
                             vtx -= 1;
@@ -762,11 +723,11 @@
             	}
             	shapeDone(data, shape);
             };
-            if (shapeType === 'Point') {
-            	// just this one vertex
+            if (vtx === shape.properties.maxvtx) {
+            	// last vertex
             	shapeDone(data, shape);
             } else {
-            	// execute vertex drag handler on second vertex
+            	// execute vertex drag handler on next vertex
             	getVertexDragHandler(data, shape, vtx, vertexDragDone)(evt);
             }
             return false;