Je veux qu'un élément svg (chemin, rect ou cercle) puisse être déplacé et lui donner des poignées de redimensionnement.
Mais contrairement au HTML DOM, tous les éléments ne possèdent pas une coordonnée x, y en haut à gauche, et une largeur et une hauteur pour une zone entourant le contenu. Cela fait qu'il est peu pratique de faire une procédure générique de redimensionnement ou de glisser.
Est-ce une bonne idée que chaque chemin ou cercle soit tracé à l'intérieur de son propre objet svg pour me donner une boîte avec laquelle jouer?
Comment est-ce que draggable/resizable est typiquement implémenté dans SVG?
Remarque: que vous souhaitiez faire glisser ou redimensionner, vous devrez créer des observations distinctes pour certains types d'éléments. Jetez un coup d'oeil dansl'exemple que je fournis plus tardqui gère le glissement des ellipses et des rectangles dans le même ensemble de fonctions.
Pour rendre un élément déplaçable, utilisez:
element.drag(move, start, up);
Les trois arguments sont des références aux fonctions qui gèrent le déplacement (glisser), le démarrage (souris vers le bas) et l’arrêt (mouseup).
Par exemple, pour créer un cercle déplaçable (à partir de la 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);
};
Dans l'exemple ci-dessus, les propriétés ox
et oy
sont ajoutées à l'élément pour garder une trace de son emplacement, et ces propriétés associées à dx
et dy
sont utilisées pour modifier l'emplacement de l'élément pendant son déplacement.
Un glisser-déposer plus compliquépour répondrecette question.
Pour rendre un objet redimensionnable, vous créez simplement un deuxième ensemble de méthodes de glisser-déposer pour le redimensionneur et vous ajustez simplement les éléments cibles height
et width
en fonction du glissement du resizer.
Voici une boîte pleine d'un glisser-déposer et redimensionnable que j'ai écrit:
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;
};
Les gestionnaires d’événements inclus (vous pouvez en utiliser plus en association avec.node()
) et la description du glisser-déposer se trouvent au bas de la pagedans la documentation.
Vous feriez simplement une toile Raphael et chaque élément serait un élément différent. Assignez-les simplement à des variables pour pouvoir les gérer, comme dans l'exemple ci-dessus (c
a été utilisé pour faire référence à l'élément de cercle créé).
En réponse aux commentaires, voici un simple glisser-déposer + cercle redimensionné. L'astuce est que les cercles utilisent les attributs cx
et cy
pour le positionnement et r
pour la taille. La mécanique est à peu près la même… une ellipse serait un peu plus compliquée, mais encore une fois, il s’agit simplement de travailler avec les bons attributs.
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;
};
Regardez Raphael.FreeTransform qui semble faire ce que vous cherchez.
Essayez Graphiti voici le lien: Draw2d et Graphiti
Il est basé sur Raphael et très facile à utiliser.
Il y a aussi ce plugin pour SVG.js.