Mouse-position outside flash tutorial
Posted on March 17, 2008
Filed Under Flash Hacks, Flash Tips |
To use javascript with banners can be a true headache. I wan’t to share my exerience of the obstacles I found so far.
Before you start, make sure you have the permission to use javascript on the sites. Sometimes you can sneak in your javascript in the embed-code generated by the media agencies, the siteowner does’nt even have to know about it. But sometimes, when you need to fire some code on the onInit-event, you have to get access to the document header. However, with some workarounds you don’t really need that. In the following example you can put the script after the swfobject-embedding.
nbsp;
Javascript source:
var mouseY = 0;
var bannerX = 0;
var bannerY = 0;
document.onmousemove = updateMousePos;
function updateMousePos(e) {
if( !e ) {
if( window.event ) {
//IE
e = window.event;
}
else {
//Fails
return;
}
}
if( typeof( e.pageX ) == 'number' ) {
//most browsers
var xcoord = e.pageX;
var ycoord = e.pageY;
}
else if( typeof( e.clientX ) == 'number' ) {
//Internet Explorer and older browsers
//other browsers provide this, but follow the pageX/Y branch
var xcoord = e.clientX;
var ycoord = e.clientY;
var badOldBrowser = ( window.navigator.userAgent.indexOf( 'Opera' ) + 1 ) || ( window.ScriptEngine && ScriptEngine().indexOf( 'InScript' ) + 1 ) || ( navigator.vendor == 'KDE' );
if( !badOldBrowser ) {
if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
//IE 4, 5 & 6 (in non-standards compliant mode)
xcoord += document.body.scrollLeft;
ycoord += document.body.scrollTop;
} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
//IE 6 (in standards compliant mode)
xcoord += document.documentElement.scrollLeft;
ycoord += document.documentElement.scrollTop;
}
}
} else {
///Fails
}
mouseX = xcoord
mouseY = ycoord
}
//called from flash
function getParameters() {
//if not bannerpos is set, try to get it
if( bannerX == 0 && bannerY == 0) {
getBannerPos()
}
if( (bannerX == 0 && bannerY == 0) || (mouseX == 0 && mouseY == 0)) {
return "error"
}
else
return bannerX+":"+bannerY+":"+mouseX+":"+mouseY ;
}
function getBannerPos() {
var flashMovie = document.getElementById("projectorBanner");
if( flashMovie ) {
if( flashMovie.offsetParent ) flashMovie = flashMovie.offsetParent
if (flashMovie.offsetParent && flashMovie.tagName.toLowerCase() != 'body') {
do {
bannerX += flashMovie.offsetLeft;
bannerY += flashMovie.offsetTop;
} while (flashMovie = flashMovie.offsetParent);
}
}
}
Okey, we gonna follow the mouse, so here we go…
Begin by adding the onmousemove-event. This event is firing quite fast, so you don’t want to send data to the flash every time. Instead I pull the data from inside the flash via ExternalInterface.call().
The key to follow the mouse is to know where the banners top-left-position is. There aint no crossbrowser-property for this, so you recursive checks the positions via offsetTop and offsetLeft to the parent element. See getBannerPos-function. I noticed that firefox added the same offsetHeight twice for the embed-tag and the parentElement. This row fixed the problem:
if( flashMovie.offsetParent ) flashMovie = flashMovie.offsetParent
It’s a safe fix, because the offset to the object/embed-parent is zero in all other cases. We only need to check the position once. So we keep checking until we get a result. The onmousemove-event may be fired many times before the position can be measured. So while bannerX/bannerY is 0, keep checking. Be careful with Explorer, if we check the position to soon, we can get the left position before the top position is available (especially with floating css-divs), so wait for both parameters to be non-zero. Put the “getBannerPos()” in the method called from flash, and your home safe.
Next thing is to get the scroll position. Because this changes over time, I do that every time onmousemove fires. To get the scrollposition is a little more tricky due to all browsers different implemention, I just used a script I found at google.
So now we got the four variables with what we needed. MouseX, mouseY, bannerX, bannerY. Time for flash to do some magic.
actionscript source:
if( bMouseOver ) {
//internal position
bannerX = 0;
bannerY = 0;
//relative to browser
browserMouseX = this._xmouse + bannerX
browserMouseY = this._ymouse + bannerY
}
else {
//get from Javascript
var strParameters = ExternalInterface.call("getParameters");
arrPositions = strParameters.split(":");
if( strParameters != "error" && strParameters != undefined) {
bannerX = Number(arrPositions[0]);
bannerY = Number(arrPositions[1]);
browserMouseX = Number(arrPositions[2]);
browserMouseY = Number(arrPositions[3]);
}
}
//do what ever you want with it
updatePositions( bannerX,bannerY,browserMouseX,browserMouseY);
In order to have a smooth gap when rolling over and out the banner you have to setup a mouse-listener here as well. Otherwise, it will get jumpy or not working at all. Some browsers don’t fire mousemove-events when over a flash. There is a known problem to register a mouse leave from the stage. I checks if the mouseX and mouseY changes. If not, wait a few frames and then assume we don’t have the users attention anymore. This can certainly be made better by checking mouse position in javascript, but this worked good enough this time. So, when the flash mouse-position stops, we will listen to the javascript-position.
What to do with the knowledge of mouseposition is up to you. In my example I render a paralax-effect based on the values.
Leave a Reply