Javascript SVG 中的可拖动和可调整大小
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3614200/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Draggables and Resizables in SVG
提问by Boris Yeltz
I want to make an svg element (path, rect, or circle) be able to be draggable and give it resize handles.
我想让一个 svg 元素(路径、矩形或圆形)能够拖动并给它调整大小的句柄。
But unlike HTML DOM, not all elements have an upper left hand corner x,y coordinate and a width and height for a box surrounding the content. This makes it inconvenient to make a generic resize or drag procedure.
但与 HTML DOM 不同的是,并非所有元素都有左上角的 x,y 坐标以及围绕内容的框的宽度和高度。这使得进行通用调整大小或拖动过程变得不方便。
Is it a good idea to have each path or circle be drawn inside its own svg object to give me a box to play with?
将每个路径或圆绘制在其自己的 svg 对象内以给我一个可以玩的盒子是否是个好主意?
How is draggable/resizable typically implemented in SVG?
在 SVG 中通常如何实现可拖动/可调整大小?
回答by Peter Ajtai
Note: For both drag and resize, you'll have to make separate cases for certain different types of elements. Take a look in the example I provide later onthat handles the dragging of both ellipses and rectangles in the same set of functions.
注意:对于拖动和调整大小,您必须为某些不同类型的元素制作单独的案例。看看我稍后提供的示例,该示例处理同一组函数中椭圆和矩形的拖动。
To make an element dragable you use:
要使元素可拖动,请使用:
element.drag(move, start, up);
The three arguments are references to the functions that handle moving (dragging), starting (mouse down), and the stopping (mouseup).
这三个参数是对处理移动(拖动)、开始(鼠标按下)和停止(鼠标向上)的函数的引用。
For example to make a draggable circle (from the documentation):
例如制作一个可拖动的圆圈(来自文档):
window.onload = function() {
var R = Raphael("canvas", 500, 500);
var c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
});
var start = function () {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dx, cy: this.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
};
c.drag(move, start, up);
};?
jsFiddle example
jsFiddle 示例
In the above example, the oxand oyproperties are tacked on to the element to keep track of its location, and these properties in conjunction with dxand dyare used to change the location of the element as it's being dragged.
在上面的例子中,ox和oy属性被附加到元素上以跟踪其位置,这些属性与dx和dy一起用于在元素被拖动时更改元素的位置。
A more complicated drag and dropto answer this question.
To make an object resizeable, you would simply create a second set of drag and drop methods for the resizer and just adjust the target elements heightand widthbased on dragging the resizer.
要使对象可调整大小,您只需为调整器创建第二组拖放方法,只需调整目标元素height并width基于拖动调整器即可。
Here's a full of one drag and drop and resizeable box I wrote up:
这是我写的一个完整的拖放和可调整大小的框:
jsFiddle example of drag and drop and resizeable box
jsFiddle 拖放和可调整大小框的示例
window.onload = function() {
var R = Raphael("canvas", 500, 500),
c = R.rect(100, 100, 100, 100).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5,
cursor: "move"
}),
s = R.rect(180, 180, 20, 20).attr({
fill: "hsb(.8, .5, .5)",
stroke: "none",
opacity: .5
}),
// start, move, and up are the drag functions
start = function () {
// storing original coordinates
this.ox = this.attr("x");
this.oy = this.attr("y");
this.attr({opacity: 1});
this.sizer.ox = this.sizer.attr("x");
this.sizer.oy = this.sizer.attr("y");
this.sizer.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({x: this.ox + dx, y: this.oy + dy});
this.sizer.attr({x: this.sizer.ox + dx, y: this.sizer.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
this.sizer.attr({opacity: .5});
},
rstart = function () {
// storing original coordinates
this.ox = this.attr("x");
this.oy = this.attr("y");
this.box.ow = this.box.attr("width");
this.box.oh = this.box.attr("height");
},
rmove = function (dx, dy) {
// move will be called with dx and dy
this.attr({x: this.ox + dx, y: this.oy + dy});
this.box.attr({width: this.box.ow + dx, height: this.box.oh + dy});
};
// rstart and rmove are the resize functions;
c.drag(move, start, up);
c.sizer = s;
s.drag(rmove, rstart);
s.box = c;
};?
The included event handlers (you can use more of course in conjunction with .node()) and the drag and drop description is at the bottom of the page in the documentation.
包含的事件处理程序(您当然可以结合使用更多.node())和拖放描述位于文档页面的底部。
You would simply make one Raphael canvas, and then each item would be a different element. Just assign them to variables so you can handle them, like in the example above ( cwas used to refer to the created circle element ).
您只需制作一张 Raphael 画布,然后每个项目将是不同的元素。只需将它们分配给变量,以便您可以处理它们,就像在上面的示例中一样(c用于指代创建的圆元素)。
In response to comments here is a simple drag and drop + resize able circle. The trick is that circles use the attributes cxand cyfor positioning and rfor size. The mechanics are pretty much the same... an ellipse would be slightly more complicate, but again it's just a question of working with the right attributes.
为了回应评论,这里是一个简单的拖放+调整大小的圆圈。诀窍是圆圈使用属性cx以及cy定位和r大小。机制几乎相同......椭圆会稍微复杂一些,但这只是使用正确属性的问题。
jsFiddle example of drag and drop and resizeable circle
jsFiddle 拖放和可调整大小的圆圈示例
window.onload = function() {
var R = Raphael("canvas", 500, 500),
c = R.circle(100, 100, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5
}),
s = R.circle(125, 125, 15).attr({
fill: "hsb(.8, .5, .5)",
stroke: "none",
opacity: .5
});
var start = function () {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.sizer.ox = this.sizer.attr("cx");
this.sizer.oy = this.sizer.attr("cy")
this.attr({opacity: 1});
this.sizer.attr({opacity: 1});
},
move = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dx, cy: this.oy + dy});
this.sizer.attr({cx: this.sizer.ox + dx, cy: this.sizer.oy + dy});
},
up = function () {
// restoring state
this.attr({opacity: .5});
this.sizer.attr({opacity: .5});
},
rstart = function() {
// storing original coordinates
this.ox = this.attr("cx");
this.oy = this.attr("cy");
this.big.or = this.big.attr("r");
},
rmove = function (dx, dy) {
// move will be called with dx and dy
this.attr({cx: this.ox + dy, cy: this.oy + dy});
this.big.attr({r: this.big.or + Math.sqrt(2*dy*dy)});
};
c.drag(move, start, up);
c.sizer = s;
s.drag(rmove, rstart);
s.big = c;
};
回答by Elbert Alias
Have a look at Raphael.FreeTransformwhich seems to do what you're after.
看看Raphael.FreeTransform,它似乎可以满足您的需求。
回答by JS Rocker
Try Graphiti here is the link : Draw2d and Graphiti
尝试 Graphiti 这里是链接:Draw2d 和 Graphiti
It is based on Raphael and very easy to use.
它基于 Raphael,非常易于使用。

