Arrastrar y soltar en SVG
Arrastrar y soltar en SVG
Una de las cosas divertidas que podemos hacer en SVG es mover objetos. Empezamos con un ejemplo fácil: después de dibujar un rectángulo vamos a arrastrarlo y soltarlo por ahí.
Algunas cosas necesarias
Primero necesitamos establecer algunas variables:
var SVG_NS, de hecho una constante, define el espacio de nombres en SVG. La necesitamos para crear un nuevo elemento SVG.
var svg: representa el elemento <svg>
, el lienzo en el cual dibujamos.
var svgRaton: la posición del ratón relativo al lienzo SVG.
var rectRaton: la posición del ratón relativo al rectángulo.
var distInicial: la posición inicial del rectángulo.
var arrastrar: un booleano que por ahora es false
, o sea no podemos arrastrar.
La función oMousePos() detecta la posición del ratón encima de un determinado elemento del DOM, y devuelve un objeto con las coordinadas x e y de este.
Dibujar un rectángulo
Dibujar un rectángulo en SVG es muy fácil, peró ya que quiero moverlo por ahí, y quiero dibujarlo y actualizarlo una y otra vez, de manera dinámica, voy a escribir una función que crea un objeto rectángulo: function Rect()
.
El objeto que queremos crear necesita varias propiedades ( es como llamamos las variables dentro de un objeto JavaScript ) y métodos ( o sea funciones ).
Propiedades del rectángulo
this.att: un rectángulo SVG tiene varios atributos ( x
, y
, width
, height
, . . . etc ), y por lo tanto el objeto rectángulo que queremos crear debe tener una propiedad, de hecho un objeto, que guarda el valor de estos atributos.
this.att = { /* por ahora un objeto vacío */ }
this.elemento: representa el elemento (no el objeto) rectángulo que aparce en el DOM.
Métodos del rectángulo
this.dibujar: necesitamos un método para poder dibujar el rectángulo. Prácticamente creamos un nuevo elemento "rect"
this.dibujar = function(elementoPadre) {
var elmt = document.createElementNS(SVG_NS, "rect");
for (var name in this.att) {
if (this.att.hasOwnProperty(name)) {
elmt.setAttributeNS(null, name, this.att[name]);
}
}
elementoPadre.appendChild(elmt);
this.elemento = elmt;
}
y lo dotamos con los atributos necesarios
this.dibujar = function(elementoPadre) { var elmt = document.createElementNS(SVG_NS, "rect"); for (var name in this.att) { if (this.att.hasOwnProperty(name)) { elmt.setAttributeNS(null, name, this.att[name]); } } elementoPadre.appendChild(elmt); this.elemento = elmt; }
Al final, muy importante, adjuntamos ( con appendChild
) el rectángulo al elementoPadre
y guardamos una referencia: this.elemento = elmt;
this.dibujar = function(elementoPadre) { var elmt = document.createElementNS(SVG_NS, "rect"); for (var name in this.att) { if (this.att.hasOwnProperty(name)) { elmt.setAttributeNS(null, name, this.att[name]); } } elementoPadre.appendChild(elmt); this.elemento = elmt; }
this.actualizar: es una función ( en realidad un método ) que translada el rectángulo en una nueva posición. De hecho actualiza el valor del atributo transform
de acuerdo con la posición del ratón:
this.actualizar = function(x,y){ this.elemento.setAttributeNS(null, "transform", "translate("+x+","+y+")"); }
Crear un nuevo rectángulo
Ahora que ya lo tenemos todo, crear un nuevo rectángulo es pan comido.
// crea un nuevo objeto rectángulo var oRect = new Rect(); // establece los atributos del nuevo rectángulo oRect.att = {x:80,y:94,width:80,height:50, transform:"translate(0,0)",fill:"gold"}; // dibuja el nuevo rectángulo y lo adjunta al svg ( el elemento padre ) oRect.dibujar(svg);
Eventos del ratón utilizados:
Para arrastrar y soltar necesitamos:
1. Presionar el botón del ratón, para "coger" el objeto. El evento del ratón involucrado en este caso es mousedown ( literalmente : ratón abajo ).
2. Mantener presionado y arrastrar el ratón a la ubicación deseada. El evento del ratón involucrado en este caso es mousemove (literalmente : ratón moviendose).
3. Soltar el objeto arrastrado, soltando el botón del ratón. El evento del ratón involucrado en este caso es mouseup. ( literalmente : ratón arriba ).
4. Si queremos podemos también tomar en consideración la salida del ratón del <canvas>: mouseout (literalmente : ratón fuera).
var num = 0; // un contador rectangulo.addEventListener("mousedown", function(evt){ num++; // detecta la posición del ratón en el lienzo SVG svgRaton = oMousePos(svg, evt); // detecta la posición del ratón en el rectángulo (this) rectRaton = oMousePos(this, evt); if(num == 1){// calculado solo una vez, en el primer clic // recupera la posición inicial del rectángulo distInicial.x = svgRaton.x - rectRaton.x; distInicial.y = svgRaton.y - rectRaton.y; } // podemos arrastrar arrastrar = true; }, false); rectangulo.addEventListener("mousemove", function(evt) { // si podemos arrastrar if (arrastrar) { // detecta la posición del ratón en el lienzo SVG svgRaton = oMousePos(svg, evt); // y actualiza la posición del rectángulo en función de la posición del ratón var x = svgRaton.x - rectRaton.x - distInicial.x; var y = svgRaton.y - rectRaton.y - distInicial.y; oRect.actualizar( x, y); } }, false); rectangulo.addEventListener("mouseup", function(evt) { // al soltar el objeto arrastrado ya no podemos arrastrar arrastrar = false; }, false); rectangulo.addEventListener("mouseout", function(evt) { // al salir fuera ya no podemos arrastrar arrastrar = false; }, false);
Vea este ejemplo en codepen.io
Arrastre el rectángulo amarillo.
See the Pen SVG drag shape translate by Gabi (@enxaneta) on CodePen.