javascript - library - La función Raphael.js attr establece el valor incorrecto
snap svg (3)
Encontré una solución interesante: puede evitar la situación si agrega un épsilon a this.original_x y this.original_y. El problema parece desaparecer si this.original_x y this.original_y no son exactamente iguales a las coordenadas iniciales. Consulte: http://jsfiddle.net/6ozsfdaf/13/
this.up = function() {
var ts;
this.original_x += 0.0000000001;
this.original_y += 0.0000000001;
var transformString = "t" + this.original_x + "," + this.original_y;
this.attr("transform", transformString);
console.log("transformString: " + transformString);
console.log("transformAttrib: " + this.attr("transform"));
this.attr({fill: "#fff"});
this.animate({r: 50, opacity: 1}, 500, ">");
};
EDITAR Encontró el problema. En Raphael, el resultado de Raphael.parseTransformString () se almacena en caché y se reutiliza. En su método move (), modifica la salida de Raphael.parseTransformString (), y Raphael intenta usar su matriz modificada cuando la proporciona con la misma cadena. Esto sucede cuando se registra el primer evento drag (). Le pide que analice el lugar actual y luego actualice el conjunto de matrices de salida con la nueva ubicación. Y luego, mucho más tarde, cuando se llama a this.up (), se proporciona Raphael.parseTransformString () con la misma cadena. Raphael luego usa su matriz modificada de matrices. Este es el violín fijo: http://jsfiddle.net/6ozsfdaf/16/
Y aquí está el código (use una nueva matriz de matrices para transformar cuando se mueve cada vez):
this.move = function(dx, dy) {
var ts = [];
ts.push(new Array(''t''));
ts[0][1] = this.original_x + dx;
ts[0][2] = this.original_y + dy;
this.attr({transform: ts.toString()});
};
Estoy implementando un sistema de arrastrar y soltar con Raphael.js. Para esto, estoy almacenando la posición original xey en el mousedown, y si hay una colisión en el mouseup, quiero restablecer la posición a la original. Aquí está el código que restablece ("esto" se refiere al objeto Rafael aquí):
var transformString = "t" + this.original_x + "," + this.original_y;
this.attr("transform", transformString);
Lo que es extraño es que después de establecer el atributo, la cadena de transformación cambia por un par de píxeles. Lo depuré con:
var transformString = "t" + this.original_x + "," + this.original_y;
this.attr("transform", transformString);
console.log("transformString: " + transformString);
console.log("transformAttrib: " + this.attr("transform"));
AFAIK, ambos valores registrados deberían ser iguales en cualquier caso. Pero a veces están tan lejos como 20px. ¿Alguien sabe lo que está pasando aquí?
E: Aquí hay una versión simplificada, sin las pruebas de colisión, que aún reproduce el error: http://jsfiddle.net/6ozsfdaf
No estoy muy seguro de por qué ese problema aún ocurre, pero me pregunto si esta puede ser una mejor solución de todos modos. En lugar de analizar las cadenas cada vez, simplemente almacene la transformación y use eso.
También lo cambié para usar el método transform (), en lugar del método attr (transform: ..). Aunque creo que eso normalmente funcionaría, no es del todo lógico, ya que los atributos SVG no toman una cadena de transformación de Rafael, pero supongo que Raph la interceptaría y la manejaría (pero tal vez sea más propensa a errores).
También vale la pena tener en cuenta en una cadena de transformación que ''t'' es una transformación relativa y ''T'' es una transformación absoluta (no creo que sea el problema, ya que no hay una transformación anterior, pero me preguntaba si también está relacionado) .
this.start = function() {
if (this.reference.static) return;
this.original_t = this.transform();
this.animate({r: 70, opacity: 0.25}, 500, ">");
};
this.move = function(dx, dy) {
this.transform( this.original_t + ''t'' + dx + '','' + dy);
};
this.up = function() {
this.transform( this.original_t );
console.log("transformString: " + this.original_t);
console.log("transformAttrib: " + this.transform());
this.attr({fill: "#fff"});
this.animate({r: 50, opacity: 1}, 500, ">");
};
No estoy seguro de por qué sucede esto. Intenté incluso capturar las coordenadas antes de onstart
con el evento onmousedown
, incluso eso no funcionó. También los diferentes métodos proporcionados por Raphael para obtener las coordenadas usando getBBox()
, accediendo directamente a y
, no ayudaron.
Entonces, lo que pensé es que deberíamos mantener y seguir las coordenadas manualmente. Así que he usado tus variables original_x
y original_y
que capturan la posición de <path>
después de crear y establecer con algún valor de transformación. A continuación está el código del mismo
Aquí está el violín de trabajo.
this.raph = R.path(svgPath).attr({
stroke: "hsb(0, 1, 1)",
fill: "#fff",
opacity: 1.0,
cx: 100,
cy: 900
}).transform("t" + x + "," + y);
this.raph.original_x = x;
this.raph.original_y = y;
//comment the lines in start method which captures original_x and original_y
//this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
//this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];
Más información sobre el seguimiento de las coordenadas:
Tendremos una coordenada más, digamos updated_x
y updated_y
, que se actualizará en el método move
. Método de finalización / encendido, podemos verificar si debemos actualizar la nueva posición o no. Aquí, simplemente pregunta si la nueva posición debe actualizarse o no y, según nuestra información, establece el resultado final.
Mira este violín :
this.start = function() {
if (this.reference.static) return;
//this.original_x = Raphael.parseTransformString(this.attr("transform"))[0][1];
//this.original_y = Raphael.parseTransformString(this.attr("transform"))[0][2];
this.animate({r: 70, opacity: 0.25}, 500, ">");
this.updated_x = this.original_x;
this.updated_y = this.original_y;
};
this.move = function(dx, dy) {
//var ts = Raphael.parseTransformString(this.attr("transform"));
this.updated_x = this.original_x + dx;
this.updated_y = this.original_y + dy;
//ts[0][1] = this.original_x + dx;
//ts[0][2] = this.original_y + dy;
this.attr({transform: ''t'' + this.updated_x + '','' + this.updated_y});
};
this.up = function() {
if(confirm("Shall I update the new position??")) {
this.original_x = this.updated_x;
this.original_y = this.updated_y;
}
var transformString = "t" + this.original_x + "," + this.original_y;
this.attr("transform", transformString);
this.attr({fill: "#fff"});
this.animate({r: 50, opacity: 1}, 500, ">");
};