PDA

View Full Version : Mouse exit stage


V-go
06-05-2003, 11:33 PM
Hi y'all!

I'm having a pretty common problem i would think, i'm sure there's a neat solution that everyone know..

Anyhow, I want to run a function when the mouse leaves the flash stage. I can't use _xmouse/_ymouse because it stops checking when the mouse isn't there.

I can't use a button because there are other buttons that can't be interferred with their own rollOut mechanisms..

Is hitTest the solution? I'm not so knowledgable about it but perhaps..

Any tips? Thanks!

Viggo

CyanBlue
06-06-2003, 02:58 AM
Howdy...

Try this file... ;)

V-go
06-06-2003, 09:11 AM
That example file works just like the check _xmouse / _ymouse with stage coordinates that i've already tried.
Problem is that it's waay to unreliable. If users drag the mouse quickly out of the stage flash doesn't record the new coordinates.

Is there no other way of doing this?

My alternate solution is to check if the coordinates havn't changed for like one second and then assume the user is outside of the stage or has suddenly dropped dead.

Thanks CyanBlue for your reply!

tost
06-06-2003, 09:59 AM
i wouldn't do that, one second is not very long. people will think you are hacking their cursor! :D
btw, i think we are all very happy that not every itch of movement is tracked, we wouldn't get very high framerates if it did. i don't think it's a problem really, it's not normal user behaviour to break the speed limits with the cursor :)
grtz_
tost

V-go
06-06-2003, 10:05 AM
No no, this is a serious problem. For example, when i tried the example file, maybe 1 out of 20 times the "off stage" code triggered. It would be useless on a website where it's required to work.

sneeuwitje
06-06-2003, 10:56 AM
check out this link @
artificialcolors.com (http://www.artificialcolors.com/experiments/mouseCaptureToFlash.html)

maybe this could work for you.

i shouldn't really be posting this link: Only works for Win IE5+ (as far as i know).
But maybe someone can get it to work properly. My JavaScript is lousy, so i'm not gonna try now.

ThePudge
03-08-2005, 08:52 PM
Hey V-go,

I suspect after 2 yrs you have found the answer lol.. but for all those who are looking for an answer and only find useless answers here I will show a nice trick.

I really dislike it when people give an answer to the wrong question or start complaining about framerates or mock your issue which only shows that they have no clue how to solve it.

What I do to check if the mouse has left the flash stage is to make use of a first-order predictor, like in finite element grid solvers.

For instance I used an object that followed the mouse pointer.. and in it i had the following code:

// function called whenever mouse moves (on stage)
this.onMouseMove = function() {
// calculate 1st order predictor (= 'velocity' of mouse pointer)
this.predX = _root._xmouse - this._x;
this.predY = _root._ymouse - this._y;
// sets this mouse following object to position of mouse
this._x = _root._xmouse;
this._y = _root._ymouse;
}

// somewhere in your code you can check if the mouse pointer left the stage
// by adding the 1st order predictor to the current mouse position
if (_root._xmouse+ this.predX > 800) { trace("outside stage"); }


The predictor assures that if you move your mouse too fast off the stage it will still register if it has left the stage, you can tweak it a bit, by for instance adding only half the predictor or twice the predictor if you find it is not completely accurate.

Sure tests aren't framerate friendly.. but these days you need 2GHz to type a letter in MsOffice ;) , so you can expect ppl will use decent pcs to check out your hip website.

Good Luck,
Pudge

CyanBlue
03-09-2005, 12:42 AM
Can you post the sample, if you don't mind, Pudge??? Love to see how it works... :)

sneeuwitje
03-09-2005, 09:05 AM
I feel upto it now ;)

Hey Pudge: nice thinking, but you leave Stage.scaleMode: 'noScale' unaccounted for. In effect this only works if your movie is 800px width and it scales with the Stage. But your idea tickled me a lot though, so I happily coded an adaption to 100% movie-scales (was time I did that Universal StageMargin Object anyways ... so here it is ... finally):Stage.scaleMode = "noScale";
var SA = Stage.align = "LC"; // deliberately set wrong scaleMode
//
var movieWidth = 550;// default for new .fla
var movieHeight = 400;// default for new .fla
with (_root) {lineStyle(1,0,100); moveTo(0,0); lineTo(0,movieHeight); lineTo(movieWidth,movieHeight); lineTo(movieWidth,0); lineTo(0,0);};
// _________________________
// BEGIN Universal StageMargin Object
// for all alignments with scaleMode:'noScale'
// -- private vars
var scaleModes = ['T', 'B', 'L', 'R', 'TL', 'TR', 'BL', 'BR'];
var correctScaleMode = false;
for (var n in scaleModes) if (SA === scaleModes[n]) correctScaleMode = true;
if (correctScaleMode === false) trace("***Error*** Stage.scaleMode has illegal value:"+SA+"\\n\\t\\tStageMargin Object will render unusable. Please enter one of these:"+scaleModes);
var Vcenter = SA.length * Number(SA.indexOf("L") >= 0 || SA.indexOf("R") >= 0) / 2;
var Hcenter = SA.length * Number(SA.indexOf("T") >= 0 || SA.indexOf("B") >= 0) / 2;
var Tdiv = (SA == 'B') ? 1 : Number(SA.indexOf("T") < 0) * Vcenter;
var Bdiv = (SA == 'T') ? 1 : Number(SA.indexOf("B") < 0) * Vcenter;
var Ldiv = (SA == 'R') ? 1 : Number(SA.indexOf("L") < 0) * Hcenter;
var Rdiv = (SA == 'L') ? 1 : Number(SA.indexOf("R") < 0) * Hcenter;
// -- NEW GLOBAL: StageMargin
_global.StageMargin = {left:0, right:0, top:0, bottom:0}
var stageListener = {};
stageListener.onResize = function () {
var Hdiff = Stage.width-movieWidth;
var Vdiff = Stage.height-movieHeight;
StageMargin.right = Rdiv * Hdiff;
StageMargin.left = Ldiv * Hdiff;
StageMargin.top = Tdiv * Vdiff;
StageMargin.bottom = Bdiv * Vdiff;
};
Stage.addListener (stageListener);
stageListener.onResize();
// ##END Universal StageMargin Object
// _________________________
// BEGIN mouseListener for Stage-exit
//
var mouseTrack = this.createEmptyMovieClip("mouseTrack", 101);
with (mouseTrack) {beginFill(0,100); moveTo(-5,-5); lineTo(-5,5); lineTo(5,5); lineTo(5,-5); lineTo(-5,-5); endFill();};
var mouseListener = {};
var predX, predY;
mouseListener.onMouseMove = function () {
// calculate 1st order predictor (= 'velocity' of mouse pointer)
predX = _root._xmouse - mouseTrack._x;
predY = _root._ymouse - mouseTrack._y;
// sets this mouse following object to position of mouse
mouseTrack._x = _root._xmouse;
mouseTrack._y = _root._ymouse;
};
Mouse.addListener(mouseListener);
// ##END mouseListener for Stage-exit
//
// somewhere in your code you can check if the mouse pointer left the stage
// by adding the 1st order predictor to the current mouse position
//
// -- this onEnterFrame checks if it went off-Stage at the right side
//
var counter = 0;
mouseTrack.onEnterFrame = function () {
if (_root._xmouse + predX > movieWidth+StageMargin.right) {
predX = 0;
trace ((counter++) + ": outside stage");
}
}Code should work when pasted on 1st frame of new FLA.

ThePudge
03-09-2005, 10:03 AM
Sneeuwwitje,

of course, your addition makes it complete, thanks.
I just tried to keep my example concise and simple. :D

Ciao.

sneeuwitje
03-09-2005, 10:35 AM
pity that it only works when you move mouse fast enough (and not too fast back in ... too fast out&in again will trigger Stage-exit aswell :()

sneeuwitje
03-09-2005, 10:43 AM
I just tried to keep my example concise and simple. :DYeah, I know ... it's CyanBlue's fault really that I maybe went a little over the top ... he wanted the example :D ;)

sneeuwitje
03-09-2005, 10:47 AM
To exagerate a little more I expanded the onEnterFrame for all sides of the Stage, and make it center the mouseTracker for feedBack online:// -- mouseTrack.onEnterFrame checks if mouse went off-Stage at the any side
//
var counter = 0;
mouseTrack.onEnterFrame = function () {
if (_root._xmouse + predX > movieWidth+StageMargin.right) {
predX = 0;
mouseTrack._x = movieWidth/2
trace ((counter++) + ": outside stage [ right ]");
}
if (_root._xmouse + predX < - StageMargin.left) {
predX = 0;
mouseTrack._x = movieWidth/2
trace ((counter++) + ": outside stage [ left ]");
}
if (_root._ymouse + predY > movieHeight+StageMargin.bottom) {
predY = 0;
mouseTrack._y = movieHeight/2
trace ((counter++) + ": outside stage [ bottom ]");
}
if (_root._ymouse + predY < - StageMargin.top) {
predY = 0;
mouseTrack._y = movieHeight/2
trace ((counter++) + ": outside stage [ top ]");
}
}Just to keep CB satisfied ;)

CyanBlue
03-09-2005, 04:26 PM
Now, I want to see a monkey jumping around when the mouse goes off stage... :D

Thanks, guys... :)

sneeuwitje
03-09-2005, 07:28 PM
you'd like that, wouldn't you? ... how about a monkey jumping off the Stage, when the mouse goes up your nose and tickles you a little?

CyanBlue
03-09-2005, 10:09 PM
Sounds good as long as I can slap the monkey whenever I want to... :D

sneeuwitje
03-11-2005, 03:21 PM
I've found that defining 'onMouseOut' and 'onMouseIn' for the SWF while it's embedded in a HTML-page's object-tag fires just fine, so that would (online only :() be a real neat solution.
Especially because it also works when the mouse rolls 'out to' / 'in from' another window that is over of the flash-movie!

:( ... only I can't get my JavaScript to pass the 'movement' String ('in' / 'out') to the SWF ... anyone know how to do this? Include example: look for function mouseMoved in the head of HTML.

sneeuwitje
03-12-2005, 09:14 PM
I musted to know again ... just couldn't let of ;) Some googling on javascript flash "SetVariable is not a function" ('SetVariable' seems the way to go for JS talking to any HtmlObject, but doesn't work for Flash ...) got me this:

hiveminds thread (http://www.hiveminds.info/phpBB/viewtopic.php?p=44458)
MustardLab.Developer ready-made JS2FlashCommunicator (http://www.mustardlab.com/developer/flash/jscommunication)

... and a lot of other links that made clear that JS talking to Flash is *no smooth road to paradise* by itself. Hence the somewhat awkward solution MustardLab came up with ... but it works :)

Made a exit/enter Stage Movie with the MustardLab solution to top this off (download the zip).

I just can't help feeling that it should be possible to do this far far easier, if it weren't for software developers shoving responsibilities on other's plates :( (almost asif time == money *what a world*)

Steel Rat
01-23-2006, 02:46 PM
I found that using a button scaled to the size of the stage allowed it's onRollOut to identify when the mouse has left the movie.

sneeuwitje
01-23-2006, 02:53 PM
That's a cool idea, but it does leave you with having to create a custom mouse-pointer unless you like the app pointing fingers at you all the time ;)

Guess you might weigh the burdon of the one against the other

eggnogg
06-22-2009, 03:12 AM
well,b umping up this posts two years later again
thats a pretty cool solution Steel Rat.
so far, its looks perfect, and to top the simplicity, i just used useHandCursor = false on te button and it there's no fingers pointed at you
:)
only problem is that you can't have easy clickable buttons
but use the mouse listener and that should do the trick

Imjake9
06-22-2009, 03:01 PM
I sure hope whoever posted this a long time ago has found a solution, but in AS3 you can check when the mouse has exited the stage:
import flash.events.MouseEvent;
import flash.events.Event;

var onStage:Boolean = false;
stage.addEventListener(Event.MOUSE_LEAVE,mouseLeft );
stage.addEventListener(MouseEvent.MOUSE_MOVE,mouse Moved);

function mouseLeft(e:Event):void{
if(onStage){
trace("Left stage.");
onStage = false;
}
}
function mouseMoved(e:MouseEvent):void{
if(!onStage){
trace("Entered stage.");
onStage = true;
}
}

Don't know if you're using AS3, but here's an easy way! ;)