How to make mouse over event of clip underneath still work? - actionscript-3

Hi was hoping someone could help me with this MOUSE_OVER event issue
I'm triggering the appearance of a tooltip via MOUSE_OVER on a button and I'm finding it keeps getting triggered if I keep the mouse pointer over the tooltip. Both the tooltip and button are MovieClips
How can I prevent this?
Here's a snippet of my code:
for(var i:Number=0; i < MapContainer.numChildren; i++) {
var Country:MovieClip = MapContainer.getChildAt(i) as MovieClip;
if(Country){ // make sure its a movieclip
trace('Found movieclip');
addInfoBubble(Country);
Country.addEventListener(MouseEvent.MOUSE_OVER, countryMouseOver);
Country.addEventListener(MouseEvent.MOUSE_OUT, countryMouseOut);
}
}
function showInfoBubble(Country:MovieClip){
var bubble = getChildByName(Country.name+"Info");
trace("bubble name " + bubble);
bubble.visible = true;
TweenLite.to(bubble, .5, {alpha:1});
}
function hideInfoBubble(Country:MovieClip){
var bubble = getChildByName(Country.name+"Info");
bubble.alpha = 0;
bubble.visible = false;
//removeChild(CountryInfo);
//CountryInfo = null;
}
function countryMouseOver(e:Event):void{
trace('countryMouseOver '+e.target);
var countryMc = e.target;
var localPos:Point = new Point(countryMc.x,countryMc.y);
var globalPos:Point = countryMc.localToGlobal(localPos);
trace('local pos: '+localPos+ ' global pos:'+globalPos);
TweenLite.to(countryMc, 1, {tint:mouseOverColor});
showInfoBubble(countryMc);
}
function countryMouseOut(e:Event):void{
trace('countryMouseOut '+e.target);
var countryMc = e.target;
var localPos:Point = new Point(countryMc.x,countryMc.y);
var globalPos:Point = countryMc.localToGlobal(localPos);
trace('local pos: '+localPos+ ' global pos:'+globalPos);
TweenLite.to(countryMc, 1, {tint:mouseOutColor});
hideInfoBubble(countryMc);
}
Thanks

Wherever you create the bubble MovieClip (looks like it's in addInfoBubble), set bubble.mouseEnabled = false;.
Also, as you can see from the StackOverflow syntax highlighting, by convention variables usually start with a lower-case name, classes with an upper-case name (Country parameters should be country).

Related

AS3 Editing event.target after being clicked befor executing gotoAndPlay("abc");

Greetings stackoverflow members,
i have 3 animated movieclips nested in a movieclip. What I'm trying to do is to get the name of the instance clicked and edit it befor applying gotoAndPlay. I can get the name but when ever I try to edit it I'm getting the Error:
Symbol 'Buttons MC', Layer 'Actions', Frame 1, Line 30 1061: Call to a possibly undefined method gotoAndPlay through a reference with static type String.
Here's my code so far:
[Bindable] var targetName:String;
var _userInput:String = new String();
_userInput = targetName;
//array for buttons
var btnArray:Array = [INS_Btn1, INS_Btn2, INS_Btn3];
//add eventlistiners
for(var i:uint=0; i<btnArray.length; i++) {
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.CLICK, bClick);
btnArray[i].buttonMode=true;
}
//btn over state
function bRollover(event:MouseEvent):void{
event.target.gotoAndPlay("Over");
}
//btn out state
function bOut(event:MouseEvent):void{
event.target.gotoAndPlay("Out");
}
//btn click state
function bClick(event:MouseEvent):void{
targetName = event.target +("_ani")
targetName.gotoAndPlay("Active");
}
What I want is that the MC clicked should go and play the animation of an onther MC. Best I should mention that I'm a beginner in AS3.
targetName is a String and of course you can't gotoAndPlay on a string :) Besides of that, event.target will return the object that you've clicked and not its name. And the targetName does not need to be bindable if you don't do anything special with it besides of this code.
So I assume you want a movieclip with the instance name INS_Btn1_ani to be played when you click on the INS_Btn1 button? First, make sure your buttons have the name property set (to make it easier, set the name as "INS_Btn1", "INS_Btn2" etc as well.
INS_Btn1.name = "INS_Btn1";
Then you would do it like that:
function bClick(event:MouseEvent):void
{
targetName = event.target.name + "_ani"; // this will become INS_Btn1 + _ani = INS_Btn1_ani
// Now you need to let the movieclip with the name "INS_Btn1_ani" play
this[targetName].gotoAndPlay("Active");
}
So after understanding the answer from Philarmon I've solved the problem. In case someone has the same/similar problem here's what I've done to get it working:
var targetName:String;
var _userInput:String = new String();
_userInput = targetName;
//array for buttons MCs
var btnArray:Array = [INS_btn1, INS_btn2];
var aniArray:Array = [INS_btn1_ani, INS_btn2_ani];
//add eventlistiners
for(var i:uint=0; i<btnArray.length; i++) {
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.CLICK, bClick);
btnArray[i].buttonMode=true;
}
//btn over state
function bRollover(event:MouseEvent):void{
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndPlay("Over");
}
//btn out state
function bOut(event:MouseEvent):void{
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndPlay("Out");
}
//on clicked
function bClick(event:MouseEvent):void{
//add listeners for unclicked
for (var i:uint=0;i<btnArray.length; i++){
btnArray[i].addEventListener(MouseEvent.ROLL_OUT, bOut);
btnArray[i].addEventListener(MouseEvent.ROLL_OVER, bRollover);
//stopping animation
aniArray[i].gotoAndStop("Out");
}
//remove Eventlistener when clicked
event.target.removeEventListener(MouseEvent.ROLL_OUT, bOut);
event.target.removeEventListener(MouseEvent.ROLL_OVER, bRollover);
targetName = event.currentTarget.name + "_ani";
this[targetName].gotoAndStop("Active");
}
As you can see I've added a "sticky" function to keep the mc on click state.

Trying to remove child on mouseover

I am not new to programming but I decided to learn Flash for fun this summer. I have a program that is printing Circles as children and I want it so when the user hovers over a certain circle it will remove that child. Pseudo code in case you don't get what I'm saying:
if ( mouse.x = onCircle && mouse.y = onCircle){
removeChild(thatCircle);
}
The problem is I don't know how to find what that specific child is and how to remove it.
here is my code so far:
//Import
import flash.utils.*;
//Vars
var circle:Shape = new Shape(); // The instance name circle is created
var alive;
alive = "true";
var challange;
challange = 1;
var ogtimer = setInterval(showCircle,1000*challange);
var circlesOnScreen: int;
circlesOnScreen = 0;
var cycles : int;
cycles = 0;
var base : int;
base = 0;
function showCircle(){
if (circlesOnScreen < 14){
//Variables
var ranX:Number = Math.ceil(Math.random()*475);
var ranY:Number = Math.ceil(Math.random()*790);
var circleSpriteVar:circleSprite = new circleSprite();
addChild(circleSpriteVar);
circleSpriteVar.x = ranX;
circleSpriteVar.y = ranY;
circlesOnScreen = circlesOnScreen + 1;
cycles = cycles + 1;
/*if (mouseisover circle){
circle.removeChildAt(0)
}*/
if (cycles > 3){
base = cycles * 1.15
challange = base / 10
}
}else{
gotoAndStop(3)
}
}
EDIT: Please correct your title or your description. Title says Mouse click and description says hover. These are different things.
You would need to add a MOUSE_OVER mouse listener to each of your circles and it will fire each time you hover the mouse over the circle. Then remove the circle over which the mouse is. Here's sample code (assuming Circle is a Sprite):
circle.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver,false,0,true);
protected function onMouseOver(event:MouseEvent):void
{
var circle:Sprite = event.currentTarget as Sprite;
circle.removeEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
removeChild(circle);
}
Hope this answers your question. Please accept the answer if it does, or let me know if you need more information. Thanks.

Changing color of objects based on the color as3

I have made simple drag-and-drop color buttons where if user drag the specific buttons, it will detects the color based on the what user drag and apply it to the object where user drop the color into. However, I can't figure it out why the color keep changing to black whenever I chose a button and drag and drop it to the single object in the scene, it will turn black even though I already have define the color of buttons.
How can I solve this?
Here is the code that I am using (I am using this on CS6):
var array_objects:Array = new Array(firstRectangle_mc, secondRectangle_mc, thirdRectangle_mc, fourthRectangle_mc);
var hit_object:Array = new Array();
var color_x:int;
var color_y:int;
addListeners(red_btn, black_btn, yellow_btn);
function addListeners(... objects):void
{
var color:Array = new Array("0xFF0000", "0x000000", "0xFFFF00");
for (var i:int = 0; i < objects.length; i++)
{
var input:TextField = new TextField();
input.text = color[i];
input.visible = false;
objects[i].addChild(input);
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
}
function onColorMouseDown(e:MouseEvent):void
{
hit_object = [];
color_x = e.currentTarget.x;
color_y = e.currentTarget.y;
e.currentTarget.startDrag();
}
function onColorMouseUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
for (var i:int = 0; i < array_objects.length; i++)
{
if (e.currentTarget.hitTestObject(array_objects[i]))
{
hit_object.push(array_objects[i]);
}
}
e.currentTarget.x = color_x;
e.currentTarget.y = color_y;
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.text;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}
Here is the link of the demo:
Link
Your answer much appreciated!
Thank you very much
Let's see at this line:
changeColor.color = e.currentTarget.text;
e.currentTarget is a circle. What is e.currentTarget.text? Circle doesn't have a text property. It has a child TextField. So, if you want to get text from TextField you must write:
e.currentTarget.getChildAt(1).text;
Circle have two children: Shape and TextField. So getChildAt(1) = TextField.
You can do it without TextField. See:
for (var i:int = 0; i < objects.length; i++)
{
objects[i].color = color[i];
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, onColorMouseDown);
objects[i].addEventListener(MouseEvent.MOUSE_UP, onColorMouseUp);
}
Circle it's a MovieClip. The MC it's a dynamic class, that means that you can add any property to it. In our case, we add a color property.
Next:
changeColor.color = e.currentTarget.color;
Understand?
In your code I have found a bug:
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
If you stop dragging circle and circle doesn't hitTest any boxes the error appears:
TypeError: Error #1010: A term is undefined and has no properties.
To avoid this, add condition:
if (hit_object.length)
{
var changeColor:ColorTransform = hit_object[hit_object.length - 1].transform.colorTransform;
changeColor.color = e.currentTarget.color;
hit_object[hit_object.length - 1].transform.colorTransform = changeColor;
}

How to get index of a Bitmap Image from bitmapdata(from an Array)?

I am wondering if i have an Array that push content that is Bitmap, how do i get index of a specific image when clicked. I tried to use indexOf but no luck, my codes are below.
Thanks for your time!
Code:
//First Part is where i add the URLRequest and add the image into contentHolder then onto Stage
function loadImage():void {
for(var i:int = 5; i < somedata.length; i++){
if(somedata[i]){
var loader:Loader = new Loader();
loader.load(new URLRequest("http://www.rentaid.info/rent/"+somedata[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
}
}
}
function onImageLoaded(e:Event):void {
loadedArray.push(e.target.content as Bitmap);
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
currentY1 += e.currentTarget.loader.content.height +300;
_contentHolder.mouseChildren = false; // ignore children mouseEvents
_contentHolder.mouseEnabled = true; // enable mouse on the object - normally set to true by default
_contentHolder.useHandCursor = true; // add hand cursor on mouse over
_contentHolder.buttonMode = true;
_contentHolder.addChild(loadedArray[i]);
addChild(_contentHolder);
_contentHolder.addEventListener(MouseEvent.CLICK, gotoscene);
}
}
// then the part where i try to get the index
function gotoscene(e:MouseEvent):void {
var index:Number;
index = loadedArray.indexOf(e.target);
trace(index);
}
Edit:
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
Your first question has very simple answer:
var image:Bitmap = new Bitmap();
var images:Array = new Array(image);
for (var i:uint = 0; i < images.length; i++) {
// images[i].bitmapData is the original image in your array
// image.bitmapData is searched one
if (images[i].bitmapData == image.bitmapData) {
// found
}
}
But your problem is bigger than this. I see you keep wandering around..
You should add listener to each child, not the content holder as one. I usually don't use Loaders, but get their Bitmaps and wrap them in Sprites or something, that I add into the scene. You should store either this Sprite or your Loader into that array, not the Bitmap. Then add listener to each of them (Sprite or Loader, not Bitmap) and get the target. Depending on what you've stored in the array, you can easily get it as:
function gotoscene(e:MouseEvent):void {
var index:uint = loadedArray(indexOf(e.target));
}
But it's important to store one specific type that will actually be clickable. Don't think about the Bitmap - it's only a graphic representation, and doesn't do much in the code.
**EDIT:
Okay I'm adding the code you need but it's important to understand what you are doing and not just rely on someone else's answer :)
function onImageLoaded(e:Event):void {
var bitmap:Bitmap = e.target.content as Bitmap; // get the Bitmap
var image:Sprite = new Sprite();
image.addChild(bitmap); // wrap it inside new Sprite
// add listener to Sprite!
image.addEventListener(MouseEvent.CLICK, gotoscene);
// gets url of current image (http://website.com/images/image1.jpg)
var url:String = e.target.loaderURL;
// get only the number from that url by replacing or by some other way
// this removes the first part and results in "1.jpg"
var name:String = url.replace("http://website.com/images/image", "");
// this removes the extension and results in number only - 1, 2, 3
// it's important to change this depending on your naming convention
name = name.replace(".jpg", "");
image.name = "button" + name; // results in "button1", "button2", "button3"
// store object, name, or whatever (not really needed in your case, but commonly used)
loadedArray.push(image.name);
image.x = counter * 100; // position so you can see them, at 100, 200, 300, etc.
_contentHolder.addChild(image); // add newly created Sprite to content
}
function gotoscene(e:MouseEvent):void {
var name:String = e.target.name;
// strips down "button" from "button1", and only the number remains,
// which is 1, 2, 3, etc. the number of the scene :)
var scene:uint = name.replace("button", "");
// you're the man now :)
}

Multiple sprites added in loop, but only last sprite clickable

I have multiple bitmap images added into sprites(each image added into 1 sprite) in a loop, then all the sprites added to 1 _contentHolder(Sprite) then that is added to a viewport.
What the problem is, the multiple sprites that are added inside the loop, everything displays with no problem but only the last sprite added is clickable. None of the sprite added before it is clickable. Wondering what the problem is, they are not overlapping and when i hover the mouse over the top of all the sprites, it turns into the mouse clicker but it just won't click.
Thanks for your time!
My code:
function onImageLoaded(e:Event):void {
loadedArray.push(e.target.content as Bitmap);
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
var image: Sprite= new Sprite;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
image.mouseChildren = true; // ignore children mouseEvents
image.mouseEnabled = true; // enable mouse on the object - normally set to true by default
image.useHandCursor = true; // add hand cursor on mouse over
image.buttonMode = true;
image.addChild(loadedArray[i]);
_contentHolder.addChild(image);
}
newArray.push(image);
var viewport:Viewport = new Viewport();
viewport.y = 0;
viewport.addChild(_contentHolder);
var scroller:TouchScroller = new TouchScroller();
scroller.width = 300;
scroller.height = 265;
scroller.x = 10;
scroller.y = 100;
scroller.viewport = viewport;
addChild(scroller);
image.addEventListener(MouseEvent.CLICK, gotoscene);
}
loadImage();
Edit:
function gotoscene(e: MouseEvent):void{
var index:Number;
index = newArray.indexOf(e.target);
trace(index);
blackBox.graphics.beginFill(0x000000);
blackBox.graphics.drawRect( -1, -1, stage.width, stage.height);
blackBox.alpha = 0.7;
addChild(blackBox);
var originalBitmap : BitmapData = loadedArray[index].bitmapData;
var duplicate:Bitmap = new Bitmap(originalBitmap);
duplicate.width = stage.width;
_contentHolder1.addChild(duplicate);
// Use counter here to only add _contentHolder1 once
//Assuming that `samedata` is a class member (I can't see the rest of your code)
addChild(_contentHolder1);
}
Edit2:
private var image:Array = new Array;
//In the For loop
image[i] = new Sprite();
image[i].addChild(loadedArray[i]);
image[i].addEventListener(MouseEvent.CLICK, gotoscene);
function gotoscene(e:MouseEvent):void{
index = image.indexOf(e.target);
trace(index);
}
You should move image.addEventListener(MouseEvent.CLICK, gotoscene); statement into the loop where you add child sprites. Once you do, the listener will be added to all of the sprites, not just the last one that's currently stored in image variable, and is the only one that responds to your clicks.
for(var i:int = 0; i < loadedArray.length; i++){
var currentY1:int = 200;
var image: Sprite= new Sprite;
e.currentTarget.loader.content.height =200;
e.currentTarget.loader.content.y += currentY1;
image.mouseChildren = true; // ignore children mouseEvents
image.mouseEnabled = true; // enable mouse on the object - normally set to true by default
image.useHandCursor = true; // add hand cursor on mouse over
image.buttonMode = true;
image.addEventListener(MouseEvent.CLICK, gotoscene); // <-- THIS
image.addChild(loadedArray[i]);
_contentHolder.addChild(image);
}
And for all that is holy, learn to indent your code, so that you will be able to visually find the start and end of your loops and see if a certain statement is within the loop or not.
I did work for a few years in AS3 and this was a weird an usual problem. I used to solve it with a function that adds the event to each clip:
function someFunction():void {
for (...) {
var image:Sprite = new Sprite();
addSceneListener(image);
}
}
function addSceneListener(mc:Sprite):void {
mc.addEventListener(MouseEvent.CLICK, gogoscene);
}