Using hitTest instead of mouseOver / mouseOut - actionscript-3

Almost all of the Flex components have mouseOver/mouseOut or rollOver/rollOut events. Requires that these events called not the mouse cursor, but on the other element, such as Image or Bitmap.
For example, there is a Colomn Chart and image animations above it and I need to get the data (colomn value or index) when the image is over the column. If it were a component, then I would use hitTest. But what to do if it is chart?

Can't you tell the image/bitmap to not be mouseEnabled?

i can't understand your question properly, eventhough i m trying this...
if you add mouselisteners on the chart and whenever the event is dispatch check..
position.x = event.currentTarget.mouseX;
position.y = event.currentTarget.mouseY;
then you can try with hitTest.
or
if(obj.hitTestPoint(position.x,position.y)){
}
this might be work....

Related

Which implementation of InteractiveObject that is lightweight should I use to keep track of mousefocus in flex?

I have a spark List control that shows a side-list on ListEvent.ITEM_ROLL_OVER event. Basicaly it shows the contents of the item you are hovering. I would be also using ListEvent.ITEM_ROLL_OUT to hide it again but I want the user to be able to click on it (the sidelist) too.
So, i use MouseEvent.ROLL_OUT and check the event.relatedObject's id to see where the cursor went. I added an invisible Rectangle overlaying the sidelist that's a bit larger so it gains focus 1st. But it doesn't.
Googling around, I think that the Spark Rectangle cant gain focus as it doesn't implement InteractiveObject. What should I use?
My logic:
protected function listOUT(event:MouseEvent):void
{
var obj:Object = event.relatedObject;
if (obj.id != "focusRect")
{
sidelist.visible = false;
}
}
My struggle is to keep the side-list visible if the user moves the cursor from the main list to the sidelist.
Any other suggestions outside my approach are also welcome.
Update
(image link)
Red are the invisible Buttons
On roll_over select the item in the mainlist, display the sidelist
based on the selecteditem in the mainlist.
Hide the sidelist when there is no item selected in the main list.
Deselect items inthe mainlist if the sidelist loses focus.
Furthermore mx.core.UIComponent is the lightest component that dispatches focus events.

Flash Action Script 3: drag movie clip issue

I am new to as3. I create a rectangle and convert it to symbol. Then I go into the symbol and create two sliders. Also, I make the symbol draggable.
controlPanel_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragStartF);
controlPanel_mc.addEventListener(MouseEvent.MOUSE_UP, dragEndF);
function dragStartF(e:MouseEvent){
e.currentTarget.startDrag();
}
function dragEndF(e:MouseEvent){
e.currentTarget.stopDrag();
}
It works fine, but I can't use the slider. If I drag the slider, the entire movie clip moved. How can I solve this problem? Cheers!
Without more info on the structure of your FLA-file I assume that controlPanel_mc is the container containing the rectangle[background] and the two sliders.
What it seems like you did in your code was to add event listener to the container, what that means is that "if a click occures anywhere on this object, do the following". Since that clip "owns" the 2 sliders, the sliders will not get any MOUSE_DOWN-events since the parent is always the one handling the event first.
You probably want to convert the background into a symbol and add the eventListeners to that object instead.
bg.addEventListener(MouseEvent.MOUSE_DOWN, onBgClick);
bg.addEventListener(MouseEvent.MOUSE_UP, onBgRelease);
function onBgClick(e:MouseEvent){
controlPanel_mc.startDrag();
}
function onBgRelease(e:MouseEvent){
controlPanel_mc.stopDrag();
}
That should solve your issue :)

Move MovieClip and everything it contains

I have a MovieClip called navbar and it has buttons over it. How do I connect the buttons to the MovieClip so that when the MovieClip is moved the buttons move with it? I have been able to make the navbar draggable but the buttons aren't dragged with it.
I have tried the following:
navbar.addChild(button1);
This just made the button disappear.
Your approach is correct: adding the buttons as children to the MovieClip will allow them all to be moved as one item.
The button disappearing could be any number of reasons, for instance x and y now relative to new parent (i.e. setting button y to 600 is now 600 pixels down from the navbar, not from the stage or old parent).
Try commenting out any properties you have set on the button and see if that resolves the issue, from there you can determine which property is causing the button to disappear.
So you should basically just have something like this:
var button1:Button = new Button();
navbar.addChild(button1);
If even with that minimal code doesn't result in the button displaying on the navbar, you'll need to post more code so that we can see where the problem is occurring.
you can calculate distance from Movieclip's X,Y to buttons and you can write a code like this:
var diff1:int = navbar.x - example_button1.x;
stage.addEventListener(Event.ENTER_FRAME, function(event:Event):void{
example_button1.x=navbar.x-diff1;
});
you can duplicate example_buttons and diff variables.
or you can startDrag() sametime with same event listener,
navbar.addEventListener(someEvent.some, function(event:someEvent):void{
MovieClip(root).navbar.startDrag();
MovieClip(root).example_button1.startDrag();
});
MovieClip(root) allows you to effect main stage. With this property you can effect an object from inside of navbar for example.
As you supposed, if you want the navbar and the buttons to act like a unique element you need to put buttons inside the navbar and not just over it.
The reason the button is disappearing is due to the fact that it has been put on the stage in Designer so, when you add it to navbar, you have it into two different display stacks, and that's not allowed.
You should put buttons inside the navbar in Designer, or export them for AS and then instance them dynamically, as follow:
var btn:Button1 = new Button1()
navbar.addChild(btn)
Class name Button1 is assigned in the MovieClip properties window of the Library, under Export for ActionScript.

How to set mouse click to do not hit transparent pixels

Imagine a painting program. I have two imagens overlaping each other. I must be able to click on the image behind if I click on a transparent part of the above one.
I add an event listener on each image. So I must prevent the first one to dispatch click event in order to the behind one dispatch it.
(I mean, I already check for transparent pixels, but i can't cancel that event to the other imagem dispatch it.)
There is some dirty solution. Say your "images" are encapsulated in Sprites, otherwise you can't attach a listener to a Bitmap object or a Shape object. MovieClips - well, should still work, although checking alpha is a lot harder. You have your listeners attached to those sprites. First, that sprite in itself can check transparency, and if not transparent, proceed the event. To get what's behind, you can call stage.getObjectsUnderPoint(), this will return an Array of DisplayObjects, with foreground being on top. So you might have one single listener that would call this to enumerate what's under the point, then do as Roman Trofimov advises to determine that object's transparency. Once you'll find a non-transparent object, you do:
// "b" is a non-transparent DisplayObject found beforehand
while (b && (!(b is InteractiveObject))) b = b.parent;
if (b) {
var p:Point = new Point(e.stageX, e.stageY);
p = b.globalToLocal(p);
b.dispatchEvent(new MouseEvent('click', true, true, p.x, p.y));
}
This will dispatch a click event to the object that's able to receive events, and is opaque enough to obscure the background.
The MovieClip property 'mouseEnabled' can prevent click events from triggering on objects in front of other objects, for example, take two movie clips of the same size and same position:
mc1.addEventListener(MouseEvent.CLICK, click1);
function click1(e:MouseEvent) : void
{
trace("1");
}
mc2.addEventListener(MouseEvent.CLICK, click2);
function click2(e:MouseEvent) : void
{
trace("2");
}
mc1.mouseEnabled = false;
Output would be "2" as the click would essentially go 'through' mc1.
In flex you can add mouseEnabledWhereTransparent="false" to components. Not fully sure if that variable is available to you though
Generally, you will always get first event from first sprite (if it was not capture phase ot priority change). But as I understand, you need to check was it transparent and if not - stop bubbling this event.
To stop event - use event.stopImmediatePropagation() in event handler.
To determine transparency:
1) If it is just only the one bitmap, you can check its .bitmapData with method .getPixel32, it returns you alpha value.
2) If it is combined sprite (vector and bitmap), you need to manually render it to Bitmap using BitmapData.draw and then use solution from second case
3) To understand if it was absolutelly miss click, you can try this method: Check transparency

changing index position on startDrag()

I am making a dragable map and there are few thing on top of the map(UI). When the map is double clicked it enables drag. But it's changing the index position, basically, it going over the UI. what's the easiest way to control the index position of the map?
The click and drag event is controlled in mapZoom class.
this.addEventListener(MouseEvent.MOUSE_DOWN, enableDrag);
public function enableDrag(e:MouseEvent):void
{
this.startDrag();
}
i think the best way is to add two children to your root (main) clip. thee use the first (that is always below the second) for the map and the second for UI