jquery - raphael drawing javascript
Combinando Raphael y jQuery para lograr la compatibilidad del navegador (5)
Tras haber descubierto que IE no maneja javascript onmouseout
, estoy determinado a usar jQuery para que la compatibilidad entre navegadores se cumpla automáticamente. Estoy haciendo que un área definida por una ruta svg se ilumine cuando el mouse se cierne sobre ella, y adapté el código provisto en el sitio web de Raphael del ejemplo de Australia .
En este código, cada estado de Australia está definido por un camino de Rafael, por ejemplo Tasmania:
aus.tas = R.path("...").attr(attr);
Esta ruta (''st'') se pasa luego a la función:
st[0].onmouseover = function () {
...
};
Al contrario de lo que esperaba, el código es st[0].onmouseover
en comparación con simplemente st.onmouseover
. Por lo tanto, la ruta debe ser realmente una matriz, y st[0]
, sea lo que sea, es lo que está sobrevolado.
Para reemplazar onmouseover
con el equivalente de jQuery (que creo que es .mouseout()
), necesito asignar una clase a st[0]
para que pueda referirme a ella con jQuery. Mi pregunta es, ¿cómo hago eso? Si el código fue st.onmouseover
, sería sencillo, pero ¿por qué la ruta ( st
) es una matriz? ¿Qué es exactamente st[0]
? ¿Y cómo diablos lo hago?
En mi caso, el problema real era llamar al .toFront cada milisegundo, porque .hover (fooFunction, outFunction) llama a foofunction con cada desplazamiento del cursor del mouse. En realidad, el nombre sugiere que se trata de una llamada por desplazamiento, no un mouseenter :)
Entonces, el truco es asegurarse de que su foofunción, o el contenido de la misma, se ejecute solo una vez (onmouseenter). Incluso en IE esto funciona perfectamente para mí, sin tener que acceder a ningún nodo DOM o intentar acceder a otras cosas que no quiero tocar:
var MouseEventHelper = {
hover: function (el, funcIn, funcOut) {
var entered = false;
el.hover(
function (e) {
if (entered) {
return;
}
funcIn(e);
entered = true;
},
function (e) {
funcOut(e);
entered = false;
}
);
}
}
Luego reemplace sus llamadas estacionario de esta manera:
var el = paper.rect(...);
MouseEventHelper.hover(
el,
function (e) {
// do whatever you want!
el.toFront();
}
function (e) { }
);
Esto es un poco de trucos de javascript, se pasa st. Mire el código JS en el ejemplo de australia.
(function (st, state) {
.. some code referring to st[0] in here ..
})(aus[state], state);
Entonces st [0] en este código se refiere a la ruta del nodo DOM desde aus [state] .
Pruébelo usted mismo con este sencillo ejemplo en una consola Firebug:
(function(a,b) {alert(a); })("hello", "b");
hth
No necesita asignarle una clase para exponerlo a jQuery. Ciertamente no. Simplemente puede pasar su elemento DOM a jQuery y hará la magia para usted ...
$(st[0]).mouseout(function() {
alert("That mouse is outta here!");
};
Estás viendo la sintaxis de la matriz porque, en general, es así como las bibliotecas de Javascript mantienen una referencia al elemento original (básicamente solo "envolviéndolo" y agregando funcionalidad). Explicación de pseudo-código ...
st == Raphael element
st[0] == DOM element
Nota: Esa demostración se hizo con una versión anterior de Rafael. Ahora Raphael tiene sus propios controladores de eventos personalizados, incluidos .mouseover()
y .hover()
.
A falta de eso:
Simplemente ajuste el objeto DOM para crear un objeto jQuery, o use los controladores de eventos personalizados creados por Raphael:
$(st[0]).mouseover( ... ); // This uses the jQuery .mouseover() method
O, probablemente más conveniente, y IE compatible:
$(st[0]).hover( ... ); // This uses the jQuery .hover() method
O bien, utilizando un método Raphael incorporado en el controlador de eventos :
st.mouseover( ... ); // This uses the Raphael .mouseover() method
st.hover( ... ); // This uses the Raphael .hover() method
El largo de eso:
Puede obtener la referencia al objeto DOM para trabajar utilizando node
o [0]
, ya que RaphaelObject[0]
siempre es la referencia al elemento DOM:
aus.tas = R.path("...").attr(attr);
// aus.tas is a Raphael object
// aus.tas[0] is aus.tas.node is the reference to the DOM Object
$(aus.tas[0]).mouseover(function() { // Could have also use aus.tas.node
...
});
// Raphael now has custom event handlers
aus.tas.mouseover(function() {
...
});
aus.tas.hover(function() {
...
}, function() {
...
});
Entonces, con tu función:
(function (st, state) {
// st is a Raphael Object
// st[0] is st.node is the reference to the DOM Object
// This is now using jQuery for mouseover!
$(st[0]).mouseover(function() {
...
});
...
})(aus[state], state);
Además, sugeriría buscar en la función jQuery .hover()
, que maneja IE bastante bien:
(function (st, state) {
// This is now using jQuery not Raphael for hover!
$(st[0]).hover(function() {
... // the mouseenter function
}, function() {
... // the mouseleave function
});
...
})(aus[state], state);
Como demostración simplificada, aquí se muestra cómo vincular mouseenter
y mouseout
usando .hover()
a un elemento Raphael ( probado en IE 8 ):
$(function() {
var elie, paper = Raphael("canvas", 500, 500);
// Create Raphael element
elie = paper.rect(0,0,100,100).attr("fill","#000");
// Get reference to DOM object using .node and bind
// mouseover and mouseout to it:
$(elie[0]).hover(function() {
elie.attr("fill","#FFF");
},function() {
elie.attr("fill","#000");
});
});
Pruébalo con este jsFiddle
Además, el .hover()
Raphael .hover()
parece funcionar en IE también.
Si termina copiando el código que usa la demostración de Australia, se encontrará con problemas de IE sin importar qué manejador (hover, mouseover, etc.) utilice.
Después de golpear mi cabeza por un tiempo, parece que el st.toFront () en las funciones de entrada / salida anula el evento "mouse out" en IE. Borre esas líneas del código de ejemplo y debería estar bien.