Added option to link curved segment control points in pathedit mode
git-svn-id: http://svg-edit.googlecode.com/svn/trunk@985 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
@@ -533,6 +533,16 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
|
<g id="link_controls">
|
||||||
|
<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="none" stroke="#8dd35f" d="m12.4375,22.75c-4.75,-12.625 -0.375,-14.375 10.375,-11.5" id="svg_102"/>
|
||||||
|
<line x1="4" y1="19" x2="19" y2="4" id="svg_109" stroke="#606060" fill="none"/>
|
||||||
|
<circle cx="11.5" cy="11.5" r="2.17578" id="svg_111" fill="#00ffff" stroke="#0000ff"/>
|
||||||
|
<circle cx="19" cy="4" r="2.26172" fill="#00ffff" stroke="#0000ff" id="svg_121" stroke-width="0.5"/>
|
||||||
|
<circle cx="4" cy="19" r="2.26172" fill="#00ffff" stroke="#0000ff" stroke-width="0.5" id="svg_123"/>
|
||||||
|
</svg>
|
||||||
|
</g>
|
||||||
|
|
||||||
<g id="reorient">
|
<g id="reorient">
|
||||||
<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
@@ -232,6 +232,9 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="path_node_panel">
|
<div id="path_node_panel">
|
||||||
|
<div class="tool_sep"></div>
|
||||||
|
<div class="tool_button" id="tool_node_link" title="Link Control Points"></div>
|
||||||
|
<div class="tool_sep"></div>
|
||||||
<label class="path_node_tool">x:</label>
|
<label class="path_node_tool">x:</label>
|
||||||
<input id="path_node_x" class="path_node_tool attr_changer" title="Change node's x coordinate" size="3" data-attr="x"/>
|
<input id="path_node_x" class="path_node_tool attr_changer" title="Change node's x coordinate" size="3" data-attr="x"/>
|
||||||
<label class="path_node_tool">y:</label>
|
<label class="path_node_tool">y:</label>
|
||||||
|
|||||||
@@ -364,8 +364,10 @@ function svg_edit_setup() {
|
|||||||
// Get BBox vals for g, polyline and path
|
// Get BBox vals for g, polyline and path
|
||||||
if($.inArray(elname, ['g', 'polyline', 'path']) != -1) {
|
if($.inArray(elname, ['g', 'polyline', 'path']) != -1) {
|
||||||
var bb = svgCanvas.getStrokedBBox([elem]);
|
var bb = svgCanvas.getStrokedBBox([elem]);
|
||||||
x = bb.x;
|
if(bb) {
|
||||||
y = bb.y;
|
x = bb.x;
|
||||||
|
y = bb.y;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
x = elem.getAttribute('x');
|
x = elem.getAttribute('x');
|
||||||
y = elem.getAttribute('y');
|
y = elem.getAttribute('y');
|
||||||
@@ -900,6 +902,12 @@ function svg_edit_setup() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var linkControlPoints = function() {
|
||||||
|
$('#tool_node_link').toggleClass('push_button_pressed');
|
||||||
|
var linked = $('#tool_node_link').hasClass('push_button_pressed');
|
||||||
|
svgCanvas.linkControlPoints(linked);
|
||||||
|
}
|
||||||
|
|
||||||
var clonePathNode = function() {
|
var clonePathNode = function() {
|
||||||
if (svgCanvas.getNodePoint()) {
|
if (svgCanvas.getNodePoint()) {
|
||||||
svgCanvas.clonePathNode();
|
svgCanvas.clonePathNode();
|
||||||
@@ -1012,7 +1020,7 @@ function svg_edit_setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var clickWireframe = function() {
|
var clickWireframe = function() {
|
||||||
$('#tool_wireframe').toggleClass('push_button_pressed');
|
$('#tool_wireframe').toggleClass('push_button_pressed');
|
||||||
$('#workarea').toggleClass('wireframe');
|
$('#workarea').toggleClass('wireframe');
|
||||||
|
|
||||||
if(supportsNonSS) return;
|
if(supportsNonSS) return;
|
||||||
@@ -1380,6 +1388,7 @@ function svg_edit_setup() {
|
|||||||
$('#tool_delete').click(deleteSelected);
|
$('#tool_delete').click(deleteSelected);
|
||||||
$('#tool_delete_multi').click(deleteSelected);
|
$('#tool_delete_multi').click(deleteSelected);
|
||||||
$('#tool_reorient').click(reorientPath);
|
$('#tool_reorient').click(reorientPath);
|
||||||
|
$('#tool_node_link').click(linkControlPoints);
|
||||||
$('#tool_node_clone').click(clonePathNode);
|
$('#tool_node_clone').click(clonePathNode);
|
||||||
$('#tool_node_delete').click(deletePathNode);
|
$('#tool_node_delete').click(deletePathNode);
|
||||||
$('#tool_move_top').click(moveToTopSelected);
|
$('#tool_move_top').click(moveToTopSelected);
|
||||||
@@ -2208,6 +2217,7 @@ function setSVGIcons() {
|
|||||||
'#tool_move_top':'move_top',
|
'#tool_move_top':'move_top',
|
||||||
'#tool_move_bottom':'move_bottom',
|
'#tool_move_bottom':'move_bottom',
|
||||||
'#tool_topath':'to_path',
|
'#tool_topath':'to_path',
|
||||||
|
'#tool_node_link':'link_controls',
|
||||||
'#tool_reorient':'reorient',
|
'#tool_reorient':'reorient',
|
||||||
'#tool_group':'group',
|
'#tool_group':'group',
|
||||||
'#tool_ungroup':'ungroup',
|
'#tool_ungroup':'ungroup',
|
||||||
|
|||||||
@@ -861,6 +861,7 @@ function BatchCommand(text) {
|
|||||||
var current_path_pt_drag = -1;
|
var current_path_pt_drag = -1;
|
||||||
var current_path_oldd = null;
|
var current_path_oldd = null;
|
||||||
var current_ctrl_pt_drag = -1;
|
var current_ctrl_pt_drag = -1;
|
||||||
|
var link_control_pts = false;
|
||||||
var current_zoom = 1;
|
var current_zoom = 1;
|
||||||
// this will hold all the currently selected elements
|
// this will hold all the currently selected elements
|
||||||
// default size of 1 until it needs to grow bigger
|
// default size of 1 until it needs to grow bigger
|
||||||
@@ -1928,7 +1929,7 @@ function BatchCommand(text) {
|
|||||||
// Currently only one node can be selected at a time, should allow more later
|
// Currently only one node can be selected at a time, should allow more later
|
||||||
// Should point be the index or the grip element?
|
// Should point be the index or the grip element?
|
||||||
|
|
||||||
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
|
var is_closed = pathIsClosed();
|
||||||
|
|
||||||
if(is_closed && point == current_path_pts.length/2 - 1) {
|
if(is_closed && point == current_path_pts.length/2 - 1) {
|
||||||
current_path_pt = 0;
|
current_path_pt = 0;
|
||||||
@@ -2647,40 +2648,39 @@ function BatchCommand(text) {
|
|||||||
} else if (current_ctrl_pt_drag != -1 && current_path) {
|
} else if (current_ctrl_pt_drag != -1 && current_path) {
|
||||||
// Moving the control point. Since only one segment is altered,
|
// Moving the control point. Since only one segment is altered,
|
||||||
// we only need to do a pathSegList replace.
|
// we only need to do a pathSegList replace.
|
||||||
|
|
||||||
var data = current_ctrl_pt_drag.split('c');
|
var data = current_ctrl_pt_drag.split('c');
|
||||||
var index = data[0]-0;
|
var index = data[0]-0;
|
||||||
var ctrl_num = data[1]-0;
|
var ctrl_num = data[1]-0;
|
||||||
var c_item = current_path.pathSegList.getItem(index+1);
|
var pt_index;
|
||||||
|
var pt_count = current_path_pts.length/2;
|
||||||
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
|
updateCurvedSegment(mouse_x, mouse_y, index, ctrl_num);
|
||||||
if (angle) {
|
if(link_control_pts) {
|
||||||
// calculate the shape's old center that was used for rotation
|
var is_closed = pathIsClosed();
|
||||||
var box = selectedBBoxes[0];
|
if(ctrl_num == 1) {
|
||||||
var cx = round(box.x + box.width/2) * current_zoom,
|
ctrl_num = 2;
|
||||||
cy = round(box.y + box.height/2) * current_zoom;
|
index--;
|
||||||
var dx = mouse_x - cx, dy = mouse_y - cy;
|
pt_index = index+1;
|
||||||
var r = Math.sqrt( dx*dx + dy*dy );
|
|
||||||
var theta = Math.atan2(dy,dx) - angle;
|
if(index < 0) {
|
||||||
current_path_pts[i] = mouse_x = cx + r * Math.cos(theta);
|
index = pt_count - 2;
|
||||||
current_path_pts[i+1] = mouse_y = cy + r * Math.sin(theta);
|
if(!is_closed) break;
|
||||||
x = mouse_x / current_zoom;
|
}
|
||||||
y = mouse_y / current_zoom;
|
} else {
|
||||||
}
|
ctrl_num = 1;
|
||||||
|
index++;
|
||||||
c_item['x' + ctrl_num] = x;
|
pt_index = index;
|
||||||
c_item['y' + ctrl_num] = y;
|
|
||||||
replacePathSeg(6, index+1, [c_item.x,c_item.y, c_item.x1,c_item.y1, c_item.x2,c_item.y2]);
|
if(index >= pt_count - 1) {
|
||||||
|
index = 0;
|
||||||
updateSegLine(true);
|
if(!is_closed) break;
|
||||||
|
}
|
||||||
var grip = document.getElementById("ctrlpointgrip_" + current_ctrl_pt_drag);
|
}
|
||||||
if(grip) {
|
|
||||||
grip.setAttribute("cx", mouse_x);
|
|
||||||
grip.setAttribute("cy", mouse_y);
|
|
||||||
|
|
||||||
var line = document.getElementById("ctrlLine_"+current_ctrl_pt_drag);
|
var pt = getPathPoint(pt_index, true);
|
||||||
line.setAttribute("x2", mouse_x);
|
var new_x = pt[0] - (mouse_x - pt[0]);
|
||||||
line.setAttribute("y2", mouse_y);
|
var new_y = pt[1] - (mouse_y - pt[1]);
|
||||||
|
updateCurvedSegment(new_x, new_y, index, ctrl_num, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -3203,6 +3203,11 @@ function BatchCommand(text) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var pathIsClosed = function() {
|
||||||
|
if(!current_path) return;
|
||||||
|
return current_path.getAttribute('d').substr(-1,1).toLowerCase() == 'z';
|
||||||
|
}
|
||||||
|
|
||||||
var updateSegLine = function(next_node) {
|
var updateSegLine = function(next_node) {
|
||||||
// create segment line
|
// create segment line
|
||||||
var segLine = document.getElementById("segline");
|
var segLine = document.getElementById("segline");
|
||||||
@@ -3247,7 +3252,7 @@ function BatchCommand(text) {
|
|||||||
var x = mouse_x / current_zoom;
|
var x = mouse_x / current_zoom;
|
||||||
var y = mouse_y / current_zoom;
|
var y = mouse_y / current_zoom;
|
||||||
|
|
||||||
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
|
var is_closed = pathIsClosed();
|
||||||
|
|
||||||
var i = current_path_pt_drag * 2;
|
var i = current_path_pt_drag * 2;
|
||||||
var last_index = current_path_pts.length/2 - 1;
|
var last_index = current_path_pts.length/2 - 1;
|
||||||
@@ -3257,7 +3262,7 @@ function BatchCommand(text) {
|
|||||||
// if the image is rotated, then we must modify the x,y mouse coordinates
|
// if the image is rotated, then we must modify the x,y mouse coordinates
|
||||||
// and rotate them into the shape's rotated coordinate system
|
// and rotate them into the shape's rotated coordinate system
|
||||||
// we also re-map mouse_x/y and x/y into the rotated coordinate system
|
// we also re-map mouse_x/y and x/y into the rotated coordinate system
|
||||||
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
|
var angle = canvas.getRotationAngle(current_path, true);
|
||||||
if (angle) {
|
if (angle) {
|
||||||
// calculate the shape's old center that was used for rotation
|
// calculate the shape's old center that was used for rotation
|
||||||
var box = selectedBBoxes[0];
|
var box = selectedBBoxes[0];
|
||||||
@@ -3392,6 +3397,55 @@ function BatchCommand(text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var updateCurvedSegment = function(mouse_x, mouse_y, index, ctrl_num) {
|
||||||
|
var list = current_path.pathSegList;
|
||||||
|
if(index+1 >= list.numberOfItems) {
|
||||||
|
index = -1;
|
||||||
|
}
|
||||||
|
var c_item = list.getItem(index+1);
|
||||||
|
|
||||||
|
// Only do curves
|
||||||
|
if(c_item.pathSegType != 6) return;
|
||||||
|
|
||||||
|
ctrl_pt_drag = index + 'c' + ctrl_num;
|
||||||
|
|
||||||
|
var x = mouse_x / current_zoom;
|
||||||
|
var y = mouse_y / current_zoom;
|
||||||
|
|
||||||
|
var angle = canvas.getRotationAngle(current_path, true);
|
||||||
|
|
||||||
|
// TODO: Make sure this works for linked control points
|
||||||
|
if (angle) {
|
||||||
|
// calculate the shape's old center that was used for rotation
|
||||||
|
var box = selectedBBoxes[0];
|
||||||
|
var cx = round(box.x + box.width/2) * current_zoom,
|
||||||
|
cy = round(box.y + box.height/2) * current_zoom;
|
||||||
|
var dx = mouse_x - cx, dy = mouse_y - cy;
|
||||||
|
var r = Math.sqrt( dx*dx + dy*dy );
|
||||||
|
var theta = Math.atan2(dy,dx) - angle;
|
||||||
|
mouse_x = cx + r * Math.cos(theta);
|
||||||
|
mouse_y = cy + r * Math.sin(theta);
|
||||||
|
x = mouse_x / current_zoom;
|
||||||
|
y = mouse_y / current_zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
c_item['x' + ctrl_num] = x;
|
||||||
|
c_item['y' + ctrl_num] = y;
|
||||||
|
replacePathSeg(6, index+1, [c_item.x,c_item.y, c_item.x1,c_item.y1, c_item.x2,c_item.y2]);
|
||||||
|
|
||||||
|
updateSegLine(true);
|
||||||
|
|
||||||
|
var grip = document.getElementById("ctrlpointgrip_" + ctrl_pt_drag);
|
||||||
|
if(grip) {
|
||||||
|
grip.setAttribute("cx", mouse_x);
|
||||||
|
grip.setAttribute("cy", mouse_y);
|
||||||
|
|
||||||
|
var line = document.getElementById("ctrlLine_"+ctrl_pt_drag);
|
||||||
|
line.setAttribute("x2", mouse_x);
|
||||||
|
line.setAttribute("y2", mouse_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var getPathPoint = function(index, raw_val) {
|
var getPathPoint = function(index, raw_val) {
|
||||||
var len = current_path_pts.length;
|
var len = current_path_pts.length;
|
||||||
var pt_num = len/2;
|
var pt_num = len/2;
|
||||||
@@ -3791,7 +3845,7 @@ function BatchCommand(text) {
|
|||||||
// Every path point must be rotated into the rotated coordinate system of
|
// Every path point must be rotated into the rotated coordinate system of
|
||||||
// its old center, then determine the new center, then rotate it back
|
// its old center, then determine the new center, then rotate it back
|
||||||
// This is because we want the path to remember its rotation
|
// This is because we want the path to remember its rotation
|
||||||
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
|
var angle = canvas.getRotationAngle(current_path, true);
|
||||||
|
|
||||||
if (angle) {
|
if (angle) {
|
||||||
var box = canvas.getBBox(current_path);
|
var box = canvas.getBBox(current_path);
|
||||||
@@ -3875,7 +3929,7 @@ function BatchCommand(text) {
|
|||||||
call("changed", [current_path]);
|
call("changed", [current_path]);
|
||||||
|
|
||||||
// If connected, last point should equal first
|
// If connected, last point should equal first
|
||||||
if(current_path.getAttribute('d').toLowerCase().indexOf('z') != -1) {
|
if(pathIsClosed()) {
|
||||||
current_path_pts[current_path_pts.length-2] = getPathPoint(0,true)[0];
|
current_path_pts[current_path_pts.length-2] = getPathPoint(0,true)[0];
|
||||||
current_path_pts[current_path_pts.length-1] = getPathPoint(0,true)[1];
|
current_path_pts[current_path_pts.length-1] = getPathPoint(0,true)[1];
|
||||||
}
|
}
|
||||||
@@ -4556,6 +4610,10 @@ function BatchCommand(text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.linkControlPoints = function(linkPoints) {
|
||||||
|
link_control_pts = linkPoints;
|
||||||
|
}
|
||||||
|
|
||||||
this.clonePathNode = function() {
|
this.clonePathNode = function() {
|
||||||
|
|
||||||
var pt = current_path_pt, list = current_path.pathSegList;
|
var pt = current_path_pt, list = current_path.pathSegList;
|
||||||
@@ -5045,7 +5103,7 @@ function BatchCommand(text) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO: do we need to sum up all rotation angles?
|
// TODO: do we need to sum up all rotation angles?
|
||||||
this.getRotationAngle = function(elem) {
|
this.getRotationAngle = function(elem, to_rad) {
|
||||||
var selected = elem || selectedElements[0];
|
var selected = elem || selectedElements[0];
|
||||||
// find the rotation transform (if any) and set it
|
// find the rotation transform (if any) and set it
|
||||||
var tlist = canvas.getTransformList(selected);
|
var tlist = canvas.getTransformList(selected);
|
||||||
@@ -5053,7 +5111,7 @@ function BatchCommand(text) {
|
|||||||
while (t--) {
|
while (t--) {
|
||||||
var xform = tlist.getItem(t);
|
var xform = tlist.getItem(t);
|
||||||
if (xform.type == 4) {
|
if (xform.type == 4) {
|
||||||
return xform.angle;
|
return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -5206,7 +5264,7 @@ function BatchCommand(text) {
|
|||||||
var index = grip[0].id.split('_')[1] - 0;
|
var index = grip[0].id.split('_')[1] - 0;
|
||||||
|
|
||||||
var last_index = current_path_pts.length/2 - 1;
|
var last_index = current_path_pts.length/2 - 1;
|
||||||
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
|
var is_closed = pathIsClosed();
|
||||||
|
|
||||||
if(!is_closed && index == last_index) {
|
if(!is_closed && index == last_index) {
|
||||||
return; // Last point of unclosed path should do nothing
|
return; // Last point of unclosed path should do nothing
|
||||||
@@ -5346,10 +5404,10 @@ function BatchCommand(text) {
|
|||||||
|
|
||||||
// var box=canvas.getBBox(elem), left=box.x, top=box.y, width=box.width,
|
// var box=canvas.getBBox(elem), left=box.x, top=box.y, width=box.width,
|
||||||
// height=box.height, dx = width - old_w, dy=0;
|
// height=box.height, dx = width - old_w, dy=0;
|
||||||
// var angle = canvas.getRotationAngle(elem);
|
// var angle = canvas.getRotationAngle(elem, true);
|
||||||
// if (angle) {
|
// if (angle) {
|
||||||
// var r = Math.sqrt( dx*dx + dy*dy );
|
// var r = Math.sqrt( dx*dx + dy*dy );
|
||||||
// var theta = Math.atan2(dy,dx) - angle * Math.PI / 180.0;
|
// var theta = Math.atan2(dy,dx) - angle;
|
||||||
// dx = r * Math.cos(theta);
|
// dx = r * Math.cos(theta);
|
||||||
// dy = r * Math.sin(theta);
|
// dy = r * Math.sin(theta);
|
||||||
//
|
//
|
||||||
@@ -5497,7 +5555,7 @@ function BatchCommand(text) {
|
|||||||
var gbox = g.getBBox(),
|
var gbox = g.getBBox(),
|
||||||
gx = gbox.x + gbox.width/2,
|
gx = gbox.x + gbox.width/2,
|
||||||
gy = gbox.y + gbox.height/2;
|
gy = gbox.y + gbox.height/2;
|
||||||
var gangle = canvas.getRotationAngle(g) * Math.PI / 180.0;
|
var gangle = canvas.getRotationAngle(g, true);
|
||||||
while (g.firstChild) {
|
while (g.firstChild) {
|
||||||
var elem = g.firstChild;
|
var elem = g.firstChild;
|
||||||
var oldNextSibling = elem.nextSibling;
|
var oldNextSibling = elem.nextSibling;
|
||||||
@@ -5519,7 +5577,7 @@ function BatchCommand(text) {
|
|||||||
// now we add the angle that the element was rotated by
|
// now we add the angle that the element was rotated by
|
||||||
// if it's non-zero, we need to set the new transform
|
// if it's non-zero, we need to set the new transform
|
||||||
// otherwise, we clear it
|
// otherwise, we clear it
|
||||||
var angle = gangle + canvas.getRotationAngle(elem) * Math.PI / 180.0;
|
var angle = gangle + canvas.getRotationAngle(elem, true);
|
||||||
var changes = {};
|
var changes = {};
|
||||||
changes["transform"] = elem.getAttribute("transform");
|
changes["transform"] = elem.getAttribute("transform");
|
||||||
if (angle != 0) {
|
if (angle != 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user