Jump to content
GreenSock

mtos8622

Throwprops on movieclip with clickable movieclips within

Recommended Posts

Hi, we've purchased membership at my work to get the Throwprops plug-in and so far we love it.

 

I'm just hoping someone can help me with a query. I've applied the code from the 'Flick-scrolling example' on the Throwprops web page to a large movieclip with a list of clickable movieclips within it to make a scrollable list.

 

It works perfectly except that when I drag the large movieclip, whichever movieclip my finger touche, which resides within the large movieclip is activated.

 

I'm hoping to have it work like it does on a device where the movieclip would only be activated if you tap it... not if you scroll the list as such.

 

Thanks

Link to comment
Share on other sites

You could implement logic in your MouseEvent handling so that when the MouseEvent.MOUSE_DOWN event is dispatched, you record the stageX and stageY from the event and then in your MovieClips' MouseEvent.CLICK event handlers, you check to see if the event's stageX and stageY are within a pixel or two of the recorded values (from the MOUSE_DOWN) and if so, proceed. Otherwise, ignore it because you can assume the user was flick-scrolling.

 

Just an idea.

 

Glad to hear you're enjoying the ThrowPropsPlugin so far. Thanks for joining Club GreenSock.

Link to comment
Share on other sites

Hey, thanks for replying. Sounds like an awesome solution...

 

Not sure how to approach it though... if you've got a second to show me some code, that'd be really appreciated.

 

Thanks

Link to comment
Share on other sites

Okay, so I'm capturing the mouse position with an event listener but I'm not sure how to feed this into the mouse handler for the Throwprops script to query whether the mouse has moved or not.

 

stage.addEventListener(MouseEvent.MOUSE_MOVE, reportStageMouse);

 

function reportStageMouse(event:MouseEvent):void {

var myStageX:Number = Math.round(event.stageX);

var myStageY:Number = Math.round(event.stageY);

Link to comment
Share on other sites

I don't mean to de-rail this thread or step on GreenSock's toes, but I came up with a solution that was easy for me to implement (whether its bullet proof remains to be seen).

 

using the example in the documentation with the vertical scrolling of the super long text I decided to check the yVelocity which is used to determine the speed and direction of the throw to see if a flick or click took place.

 

if Math.abs(yVelocity) is greater than 0, i do the whole throwProps thing AND set a boolean isThrown to true. onComplete of the throw i set isThrown back to false.

in my button's click handler i wrap all the actions inside a conditional so that the actions only take place if isThrown = false.

 

in the mouse_down handler that stops the tween i also se isThrown back to false.

 

so far it works. check the file attached (no greensock code, use your own). there is a blue shape (btn) in the scrollable area. if you do a regular click on this blue shape it traces ("clicked"), if you drag and throw it will not trace anything.

 

here is some of the code

 

function mouseUpHandler(event:MouseEvent):void {
mc.stopDrag();
mc.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
mc.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
var time:Number = (getTimer() - t2) / 1000;
var yVelocity:Number = (mc.y - y2) / time;
var yOverlap:Number = Math.max(0, mc.height - bounds.height);

if(Math.abs(yVelocity)>0){


	ThrowPropsPlugin.to(mc, { throwProps:{
							 y:{velocity:yVelocity, max:bounds.top, min:bounds.top - yOverlap, resistance:300}
						 }, ease:Strong.easeOut, onComplete:switchIsThrown
				}, 10, 0.3, 1);


	isThrown = true;
	}


}




function switchIsThrown():void{
trace("throwDone");
isThrown = false;
}	


function btnClick(e:MouseEvent):void{
if(!isThrown){
trace("clicked");
}
}

 

the only bad-ish thing seems to be that if you catch the thrown clip over a button, the click will fire when you release.

Link to comment
Share on other sites

Hey Carl, thanks for sharing that code... it's almost perfect, except when I put it onto the iPad it doesn't feel great unfortunately.

 

In theory (and even practice to some extent) your solution is awesome. Whats seems to happen on a real device though is that even a tap is a slight movement on the device so so it captures the velocity rather than the click event.

 

I'm really impressed by the idea but I think Greensocks idea of calculating minor movement compared to a toss would do the trick. I'm not sure how to go about this though.

 

Thanks for chiming in and passing on your code... really neat idea :)

Link to comment
Share on other sites

I appreciate you reporting back and I'm glad it sort of worked.

 

it makes sense that a device would be more sensitive to movement. I didn't account for that.

 

Perhaps you can add some tolerance in the conditional statement?

 

if(Math.abs(yVelocity)>4)

 

maybe you could place a textfield in that displays the yVelocity on a "sloppy tap" so that you can get an idea how much wiggle-room you need.

 

just an idea.

Link to comment
Share on other sites

  • 1 month later...

I just got throwprops and this is the first question I cam up with while using it in an iPad app. Has anyone come up with any solutions or further ideas?

 

Thanks! :D

Link to comment
Share on other sites

Your code worked great!! Thanks! One thing is that if you finish dragging really slow it fires the button... Maybe fix it up with a timeCheck? /Mats

Link to comment
Share on other sites

  • 1 month later...

//if the mouse up is not within 10 pixels of the mouse down, we can ignore it as a click and just work on it as a throw...
	private function _mouseLogic():void
	{
		if (Math.abs(mouseDX - mouseUX) > tolerance)

		{
			trace("Mouse up was not within range of mouse down (10px), so is not a button press");
		}
		else if (Math.abs(mouseDX - mouseUX) < tolerance)
		{
			trace("Mouse up was within range of mouse down (10px), so is a button press :)");
		}

	}

 

You'll need the vars to record the mouse down and up and the tolerance var sets the distance away from mouse down allowed to still consider it a click.

 

I still can't purchase Shockingly Green as the payment page won't load, but when I do and get the throw props class I'll try this and post an example if it works. It should I think.

Link to comment
Share on other sites

I still can't purchase Shockingly Green as the payment page won't load, but when I do and get the throw props class I'll try this and post an example if it works. It should I think.

I'm so sorry you're having trouble with the payment page - I'm not aware of any issues and others seem to be able to make a purchase just fine today. Could you explain what's happening and what browser/OS you're on? I'd definitely like to make sure any problems are fixed.

Link to comment
Share on other sites

Hello.

 

I'm using Chrome and Safari on OSX 10.7 and 10.6. My ISP is Virgin Media but I've also tried Bee which use BT Internets lines (although I'm stealing that connection from down the road so it's not too reliable).

 

As for the process, I fill out the form and submit and get a blank page which never moves forwards. I can confirm I'm not being charged. I've contacted my ISP who are looking into it.

 

UPDATE: It worked, I just purchased. It's 100% my ISP and/or my location. I'm in my local pub using wifi and the payment page was super fast. If my ISP ever get back to me I'll forward on what they say in case it can help.

Link to comment
Share on other sites

Hello.

 

OK, now I have managed to purchase (happy face) I gave this a go. It's not perfect, and I just tacked it onto some previous experiment so there may be code in there thats not doing anything, but anyway:

 

package
{

import flash.display.MovieClip;
import flash.events.*;
import flash.utils.getTimer;
import com.greensock.loading.*;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.display.ContentDisplay;
import com.greensock.TweenMax;
import com.greensock.*; 
import com.greensock.easing.*;
import com.greensock.plugins.*;
TweenPlugin.activate([ThrowPropsPlugin]);


public class Panels extends MovieClip
{
	public var pWidth:Number;
	public var pHeight:Number;

	//test throw vars - how many?!?!???!?!?!
	public var tolerance:Number = 10;  //tolerance for mouse down up tracking
	public var mouseDX:Number;
	public var mouseUX:Number;
	public var bounds:Object = {top:400, bottom:400};
	public var currentY:Number;
	public var lastY:Number;
	public var vy:Number = 0;
	public var dragging:Boolean = false;
	public var offset:Number;

	public var newMC:MovieClip = new MovieClip();

	public function Panels()
	{
		var xmlLoader:XMLLoader = new XMLLoader("assets/panels.xml", {onComplete:xmlCompleteHandler});
		xmlLoader.load();
		pWidth = 320;
		pHeight = 181;
		addChild(newMC);

		newMC.addEventListener(MouseEvent.MOUSE_DOWN, _mouseDownHandler, false, 0, true);
		newMC.addEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler, false, 0, true);

		currentY = newMC.y;
		lastY = newMC.y;
	}

	private function xmlCompleteHandler(event:LoaderEvent):void
	{
		//take the panel tags from the xml and put them in an xml list array
		var panels:XMLList = event.target.content.panel;
		var panelsText:XMLList = event.target.content.dText;
		var queue:LoaderMax = new LoaderMax({maxConnections:1});
		//run through a loop for each panel item
		for (var i:int = 0; i < panels.length(); i++)
		{
			queue.append(new ImageLoader("assets/" + panels[i].@file, {name:"panel" + i, description:panels[i].@dText, numb:[i], onComplete:setupPanels}) );
		}
		queue.load();
	}

	private function setupPanels(event:LoaderEvent):void {
		var pane:panel= new panel(event.target.content, event.target.vars.description);
		pane.y = (event.target.vars.numb * pHeight);
		pane.alpha = 0;
		newMC.addChild(pane);

		TweenMax.to(pane, 1,{alpha:1, delay:0.25});
	}

	private function _mouseDownHandler(event:MouseEvent):void
	{
		TweenMax.killTweensOf(newMC);
		dragging = true;  //i am now dragging
		offset = newMC.mouseY;  //setting the offset from the origin
		addEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
		mouseDX = mouseY;
	}


	private function _mouseUpHandler(event:MouseEvent):void
	{
		dragging = false;  //i am not dragging
		removeEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
		mouseUX = mouseY;
		_mouseLogic();
	}

	private function _mouseMoveHandler(event:MouseEvent):void
	{
		newMC.y = mouseY - offset;  //move the movieclip withthe mouse (in Y only) taking into account that offset
	}

	//if the mouse up is not within 10 pixels of the mouse down, we can ignore it as a click and just work on it as a throw...
	private function _mouseLogic():void
	{
		lastY = currentY;
		currentY = mouseY;
		vy = currentY - lastY;

		if (Math.abs(mouseDX - mouseUX) > tolerance)

		{
			trace("Mouse up was not within range of mouse down (10px), so is not a button press");
			ThrowPropsPlugin.to(newMC, {throwProps:{y:{velocity:vy, min:bounds.top, max:bounds.bottom}, resistance:50}, ease:Strong.easeOut});
		}
		else if (Math.abs(mouseDX - mouseUX) < tolerance)
		{
			trace("Mouse up was within range of mouse down (10px), so is a button press :)");
		}
	}


}
}

 

This lets you drag, when you release it checks the distance between mouse down and up and if it's within tolerance it considers it a click, otherwise it doesn't. The Throwprops is fed last and currentY (which are actually the same as mouseUX and mouseDX so I should reuse them - doh) and from that you can get the throwing. Like I say, it's not great and needs me to spend more than 30 minutes on it.

 

Current problems I'm having are the drag performance isn't too great and I need to work out which nester movie clip I'm over if a click is considered a click. I may roll the mouse logic into something that gets and event so I can grab the currentTarget. I think that would work? I'm still very new to Flash so feel free to laugh but know each time you do a Mongoose dies ;)

Link to comment
Share on other sites

Hello.

 

Tidied it a little bit, maybe I should start a new thread but this is all to do with the same thing I guess?

 

package
{

import flash.display.MovieClip;
import flash.events.*;
import flash.utils.getTimer;
import com.greensock.loading.*;
import com.greensock.events.LoaderEvent;
import com.greensock.loading.display.ContentDisplay;
import com.greensock.TweenMax;
import com.greensock.*; 
import com.greensock.easing.*;
import com.greensock.plugins.*;
TweenPlugin.activate([ThrowPropsPlugin]);


public class Panels extends MovieClip
{
	public var pWidth:Number;
	public var pHeight:Number;

	public var tolerance:Number = 10;  //tolerance for mouse down up tracking
	public var mouseDX:Number;
	public var mouseUX:Number;
	public var bounds:Object = {top:50, bottom:-150};
	public var vy:Number = 0;
	public var dragging:Boolean = false;
	public var offset:Number;

	public var newMC:MovieClip = new MovieClip();

	public function Panels()
	{
		var xmlLoader:XMLLoader = new XMLLoader("assets/panels.xml", {onComplete:xmlCompleteHandler});
		xmlLoader.load();

		pWidth = 320;
		pHeight = 181;
		addChild(newMC);

		newMC.addEventListener(MouseEvent.MOUSE_DOWN, _mouseDownHandler, false, 0, true);
		newMC.addEventListener(MouseEvent.MOUSE_UP, _mouseUpHandler, false, 0, true);

		mouseDX = newMC.y;
		mouseUX = newMC.y;
	}

	private function xmlCompleteHandler(event:LoaderEvent):void
	{
		var panels:XMLList = event.target.content.panel;
		var panelsText:XMLList = event.target.content.dText;
		var queue:LoaderMax = new LoaderMax({maxConnections:1});

		for (var i:int = 0; i < panels.length(); i++)
		{
			queue.append(new ImageLoader("assets/" + panels[i].@file, {name:"panel" + i, description:panels[i].@dText, numb:[i], onComplete:setupPanels}) );
		}
		queue.load();
	}

	private function setupPanels(event:LoaderEvent):void {
		var pane:panel= new panel(event.target.content, event.target.vars.description);
		pane.y = (event.target.vars.numb * pHeight);
		pane.alpha = 0;
		newMC.addChild(pane);
		TweenMax.to(pane, 1,{alpha:1, delay:0.25});
	}

	private function _mouseDownHandler(event:MouseEvent):void
	{
		TweenMax.killTweensOf(newMC);
		dragging = true;  //i am now dragging
		offset = newMC.mouseY;  //setting the offset from the origin
		addEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
		mouseDX = mouseY;
	}

	private function _mouseMoveHandler(event:MouseEvent):void
	{
		newMC.y = mouseY - offset;  //move the movieclip with the mouse (in Y only) taking into account that offset
	}


	private function _mouseUpHandler(event:MouseEvent):void
	{
		dragging = false;  //i am not dragging
		removeEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
		mouseUX = mouseY;
		//_mouseLogic();

		//here we go, let's make this better... or really screw things up
		mouseUX = mouseDX;
		mouseDX = mouseY;
		vy = mouseDX - mouseUX;

		if (Math.abs(mouseDX - mouseUX) > tolerance)

		{
			trace("Mouse up was not within range of mouse down (10px), so is not a button press");
			ThrowPropsPlugin.to(newMC, {throwProps:{y:{velocity:vy, min:bounds.top, max:bounds.bottom}, resistance:20}});
		}
		else if (Math.abs(mouseDX - mouseUX) < tolerance)
		{
			trace("Mouse up was within range of mouse down (10px), so is a button press :)");

			//and will it work?
			trace("the detected button press was on: " + event.target);
		}
	}
}
}

 

It all works apart from:

 

a: cannot get to which nested movie clip has been clicked on and b: I don't like the motion of the throw. I need to read up more about the properties it needs.

 

Anyway, if anyone has any suggestions... :)

Link to comment
Share on other sites

Replace my last function with this, very small change here, and it works...

 

private function _mouseUpHandler(event:MouseEvent):void
	{
		removeEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);
		mouseUX = mouseDX;
		mouseDX = mouseY;
		vy = mouseDX - mouseUX;

		if (Math.abs(mouseDX - mouseUX) > tolerance)

		{
			trace("Mouse up was not within range of mouse down (10px), so is not a button press");
			ThrowPropsPlugin.to(newMC, {throwProps:{y:{velocity:vy*2, min:bounds.top, max:bounds.bottom}, resistance:20}}, 10, 0.25, 1);
		}
		else if (Math.abs(mouseDX - mouseUX) < tolerance)
		{
			trace("Mouse up was within range of mouse down (10px), so is a button press :)");

			//and will it work? No!
			trace("the detected button press was on: " + event.target.name);
		}
	}

 

So you can use ThrowProps (which rocks) along with nested sprites or movie clips and know which button you clicked if you are within a range you can set, otherwise it'll be a throw with an ignored button press.

 

Flash is so much fun :D I'm now going to make something much less ugly.

Link to comment
Share on other sites

  • 2 months later...

@MrEmpty

 

How would I accomplish this in my project.

 

Here is my project code

var blitMask:BlitMask = new BlitMask(sectionB_mc, sectionB_mc.x, sectionB_mc.y, sectionB_mc.width, sectionB_mc.height, true);




blitMask.bitmapMode = false;

var t1:uint, t2:uint, y1:Number, y2:Number;

blitMask.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);




function mouseDownHandler(event:MouseEvent):void {





  trace("bitmapMode is now FALSE");
  blitMask.bitmapMode = false;
  TweenLite.killTweensOf(sectionB_mc);
  y1 = y2 = sectionB_mc.y;
  t1 = t2 = getTimer();

  sectionB_mc.startDrag(false, new Rectangle(0, -99999, 0, 99999999));
  sectionB_mc.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
  sectionB_mc.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);


}

function enterFrameHandler(event:Event):void {
  y2 = y1;
  t2 = t1;
  y1 = sectionB_mc.y;
  t1 = getTimer();
  //blitMask.scrollX = 0;
  blitMask.update();


}

function enableBitMapMode():void{

  trace("bitmapMode is now TRUE");
  blitMask.bitmapMode = false;


}




function mouseUpHandler(event:MouseEvent):void {



  sectionB_mc.stopDrag();
  sectionB_mc.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
  sectionB_mc.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
  var time:Number = (getTimer() - t2) / 1000;
  var yVelocity:Number = (sectionB_mc.y - y2) / time;
  var yOverlap:Number = Math.max(0, sectionB_mc.height - sectionB_mc.height);




  ThrowPropsPlugin.to(sectionB_mc, {throwProps:{
                        y:{velocity:yVelocity, max:0, min:-768, resistance:100}

                     }, onUpdate:blitMask.update, ease:Strong.easeOut, onComplete:enableBitMapMode
                    }, 10, 0.3, 0.2);

      }

 

 

Wouldn't I need some extra code for my button events so that buttons arent triggered while you are trying to scroll ?

Link to comment
Share on other sites

Hello.

 

So you are trying to have items click-able inside of a throwprops movieclip?

 

The way I did it was to store the mouse position on mouse down, then again on mouse up. At that point I would compare the two, if it was within n number of pixels I would consider it a click, otherwise it was considered a throw. It was handled inside of a conditional.

 

The function shown in my post above yours has everything in it you'd need to get it working. If I still have my test project I'll zip and share it on here.

Link to comment
Share on other sites

Yes that is exactly what I'm trying to do.

 

The part I don't understand is that I don't see any special code to go in the button handler.

 

How does the application know to give preference to throwprops over the button instance ?

Link to comment
Share on other sites

Just to be clear .. I'm not having an issue with clicking on a button within a throwprops movieclip. I'm having the opposite.

 

When I drag on a button that is inside a throwprops movieclip I dont want the button event to be fired. I only want that event fired if its a tap ( not a drag )

 

Sorry if I'm not making sense. ;)

Link to comment
Share on other sites

You're making sense :)

 

I have a number (I'l call is Bob), I use 20 but anything sensible will do, that is a buffer I check against to see if the user is dragging or tapping. With touch screen software 20 is god, for software being accessed by a mouse, you could go with 5 or lower. I record the down click of the mouse as a number, then record the up click position as a second number. I then check to see if the second number is within Bob pixels of the first number, if it is I register it as a mouse event, if it's not I say it's a throw props event.

 

Now I don't do anything clever here, I don't have custom handlers or anything (I do now, but that's a longer story), I simply trigger the appropriate function. If it's a click, throw the click function that does whatever a click would do, or get the Throwprops working if it's not.

 

private function _mouseUpHandler(event:MouseEvent):void  //this function is called when the mouse up event happens on the throw props movie clip
     {
        removeEventListener(MouseEvent.MOUSE_MOVE, _mouseMoveHandler);  //remove the listener
        mouseUX = mouseDX;  //these variables are the same ones we use to send a speed of throw to throwprops
        mouseDX = mouseY;
        vy = mouseDX - mouseUX;

        if (Math.abs(mouseDX - mouseUX) > tolerance)  //tolerance here is Bob, if the distance between down and up is greater than Bob...

        {
           trace("Mouse up was not within range of mouse down (10px), so is not a button press");
           ThrowPropsPlugin.to(newMC, {throwProps:{y:{velocity:vy*2, min:bounds.top, max:bounds.bottom}, resistance:20}}, 10, 0.25, 1);  //... send the numbers to props and watch is glide
        }
        else if (Math.abs(mouseDX - mouseUX) < tolerance)  //otherwise, if it's within the range of Bob
        {
//act as if it was a click
           trace("Mouse up was within range of mouse down (10px), so is a button press :)");

           trace("the detected button press was on: " + event.target.name);
        }
     }

 

But it depends on what you're doing I guess. Post a sketch :)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×