I'm just going to explain the context so it is clearer.
I made this menu : my menu
I am looking to make an improved and more advanced version of the same menu.
I made an animation of waves on the cofee's surface and am looking to make it loop when the mouse is moving and to stop looping when it's not.
Sorry for the lack of specifications as I am quite new to actionscript, but I hope somebody will be able to help me. :)
Thanks,
Mathieu
Well, you said it - leverage MouseEvent.MOUSE_MOVE to set a conditional in your looping routine.
private var _isMoving:Boolean = false;
stage.addEventListener(MouseEvent.MOUSE_MOVE, checkMouse);
this.addEventListener(Event.ENTER_FRAME, doLoop);
private function checkMouse(e:MouseEvent):void
{
_isMoving = true;
}
private function doLoop(e:Event):void
{
trace("moving =" + _isMoving);
if(_isMoving)
{
// loop animation
}
_isMoving = false;
}
depending on how you want it to work I would do this as follows:
create an animation of wavy coffee
ensure the animation loops
note that clips loop by default, so all you have to do is match the first and last frames!
place the clip at the edge of your current coffee graphic
double click on the graphic to edit it
drag an instance of the looping animation from the library onto the "edge" of the graphic
OR just replace your entire light brown graphic with an animated one that loops
when the mouse is moving, call play on the animated loop clip
when the mouse stops, call stop on the animated loop clip
Some example code would be along the lines of:
public function init():void {
menuClip.addEventListener(MouseEvent.MOUSE_OVER, onMenuRollOver);
menuClip.addEventListener(MouseEvent.MOUSE_OUT, onMenuRollOut);
}
public function onMenuRollOver(event:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
/* do the stuff you're currently doing to animate the clip here.
something like: coffee graphic height = ease to mouseHeight */
}
public function onMenuRollOut(event:MouseEvent):void {
/* do the stuff you're currently doing to stop the clip here. */
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
coffeeClip.stop();
}
public function onMove(event:MouseEvent):void {
resetTimer();
coffeeClip.play(); //note: play has no effect when movie is playing (that's ideal in this case)
}
public function resetTimer():void {
if(mouseMovementTimer == null) createTimer();
mouseMovementTimer.reset();
mouseMovementTimer.start();
}
public function createTimer():Timer {
mouseMovementTimer = new Timer(DELAY, 1); //fiddle with the delay variable. Try 500, at first
mouseMovementTimer.addEventListener(TimerEvent.TIMER, stopAnimationLoop);
}
public function stopAnimationLoop(event:TimerEvent):void {
mouseMovementTimer.removeEventListener(TimerEvent.TIMER, stopAnimationLoop); //optional but recommended
mouseMovementTimer = null;
coffeClip.stop();
}
Of course, you would need to do things like call init() and import flash.utils.Timer and initialize variables like mouseMovementTimer, menuClip, coffeeClip and DELAY.
Warning: This code is off the top of my head and untested. So there's likely to be small bugs in it but you should get the general idea:
add a mouse listener when the user mouses over the menu
remove that listener if the user mouses out of the menu
have that listener play the looping movie clip
trigger an event that will stop the looping clip if movement hasn't been detected in a while
once the trigger goes of, stop the clip
The key is in detecting when the mouse stops moving. Flash detects interaction well but does not detect NON-INTERACTION for obvious reasons. One easy way to solve that is to trigger a timer that will go off once too much time has elapsed since the last activity. Then, when the timer triggers, you know action has stopped!
I think that's the key piece to solving your problem. I hope that helps someone in some way.
~gmale
Related
I am navigating from different class objects (screens) within my React Native App. Once I navigate to a given screen, I want to execute different functions including Activity Indicators to show that the function is still running.
Therefore is set up a focus Event Listener which is called every time I navigate back to my screen. My current problem is that my Activity Indicators are not updated within the focus Event but directly after, which is not my wanted behavior as I have to wait for my functions to end without any visual indicator.
class Homescreen extends Component {
constructor(props){
super(props};
this.state = {
showIndicator: false;
}
}
componentDidMount(){
this.props.navigation.addListener('focus', this._onFocus);
}
componentWillUnmount(){
this.props.navigation.removeListener('focus', this._onFocus);
}
_onFocus = async () => {
this.setState({showIndicator: true});
asyncFunc();
};
async asyncFunc(){
//calling a function from swift which calls a C function inside DispatchQeue.main.async
//inside my C function I successfully set my ActivityIndicator to false with an Event which calls
//this.setState({showIndicator: false});
}
render(){
console.log(this.state.showIndicator); // correct value is printed while I wait inside the ```focus``` Event to finish, but the UI is not updated.
return(
{this.state.showIndicator && <ActivityIndicator/>}
)
}
}
I receive the correct current status of showIndicatorbut before the focus Event is not finished, my render does not redraw.
To me it seems like the UI won't update until I am out of my focus Event. How can I reach my goal of displaying the ActivityIndicator before the focus Event or how do I call my function right after the focus Event?
I can achieve my wanted behavior by using the blurevent and setting my ActivityIndicator visible while moving to another screen and after moving back I wait until my function is finished and remove the ActivityIndicator but this seems like a bad workaround and also I can see the ActivityIndicator when moving which might be confusing.
You should replace curly braces around this statement {this.state.showIndicator && } and check.
If it doesn't work accordingly then let me know.
I couldn't find an implementation of a double tap for Appium that was straightforward and allowed you to pass in the element locator strategy, so here goes:
public static void doubleTapElementBy(By by) {
WebElement el = getDriver().findElement(by);
MultiTouchAction multiTouch = new MultiTouchAction(getDriver());
TouchAction action0 = new TouchAction(getDriver()).tap(el).waitAction(50).tap(el);
try {
multiTouch.add(action0).perform();
} catch (WebDriverException e) {
logger.info("Unable to do second tap on element, probably because element requieres single tap on this Android version");
}
}
You can also try below approach using tap method in TouchAction class.
TouchAction taction = new TouchAction(driver);
taction.tap(tapOptions().withElement(ElementOption.element(YOUR_WebElement))
.withTapsCount(2)).perform();
You will need to add below static import as well:
import static io.appium.java_client.touch.TapOptions.tapOptions;
This is a workaround in pseudocode and possibly there's a more "official" way to do it, but it should do the work if no other solution is available:
Interpretmessages(){
switch(msg)
{
OnClick:
{ if (lastClicked - thisTime() < 0.2) //if it was clicked very recently
{doubleTapped()} //handle it as a double tap
else{lastClicked = thisTime()} //otherwise keep the time of the tap
} //end of OnClick
} //End of Message Handler
}//End of switch
}//End of messageHandler
If you have access to ready timer functions, you can set a function to be executed 0.2s after the click has gone off:
OnClick: if (!functionWaiting) // has the timer not been set?
{
enableTimer(); // set a function to go off in x time
clicks = 0; //we'll tell it that there's been one click in a couple of lines
} //set it for the first click
clicks++; //if it's already clicked, it'll become 2 (double tap) otherwise it's just one
So, the idea is that when you get a tap, you check if there's been another one recently (a. by checking the relative times, b. by checking if the function is still pending) and you handle it dependingly, only note that you will have to implement a timer so your function fires a bit later so you have time to get a second tap
The style draws upon the Win32's message handling, I'm pretty sure it works there, it should work for you too.
Double tap and hold -- Use below code:
new TouchAction(driver).press(112,567).release().perform().press(112,567).perform();
Double tap -- Use below code:
new TouchAction(driver).press(112,567).release().perform().press(112,567).release().perform();
I have a 2d animation on scene.When I try to detect tap or click on the animation using OnMouseDown function it doesn't work.But it works using the following code
Input.GetMouseButtonDown(0)
it works but it detects tap on whole window and if I print the onject name like
Debug.log(this.name);
it prints the name of the animated sprite name.I want to detect tap only on the animated sprite.Please anyone help me..
You need to use Raycasting to detect that. Cast a 2D ray down from the input location and check if it hits something. Here's good info about it.
if (Input.GetMouseButtonDown(0))
{
var hit : RaycastHit2D = Physics2D.Raycast(cam.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if(hit != null)
{
Debug.Log("object clicked: "+hit.collider.tag);
}
}
I have a scroll bar ( fl.controls.UIScrollBar ), which i create dynamically in a class, and add it to the stage.
public class Slider extends Sprite
{
private var scroll:UIScrollBar = new UIScrollBar();
// etc.
// constructor
addChild(scroll);
scroll.setSize(15.75, 205.3);
scroll.direction = ScrollBarDirection.HORIZONTAL;
scroll.setScrollProperties(150, minScrollPos, maxScrollPos,snapInterval);
scroll.addEventListener(ScrollEvent.SCROLL, scrollHandler);
}
Then, I try to call
scroll.scrollPosition = 30;
My method call will not update the scroll thumb.Any ideas why?
Salut Mihai,
I found that odd at first. I expected setting the value would suffice.
If I set scrollPosition in an enter frame loop, it works, but not if I use the setter straight away. This probably means that if you make the calls right after creating/setting up the component, internally, it's not ready yet. UIComponents(like UIScrollBar) have a whole lifecycle to deal with. Jeff Kamerer has a nice set of devnet articles on this, if you're interested.
Long story short, the component is not ready right away, so the best bet is to wait for it to be ready by listening to the RENDER event:
scroll.addEventListener(Event.RENDER,rendered);
function rendered(event:Event):void {
scroll.removeEventListener(Event.RENDER,rendered);
scroll.scrollPosition = 30;
}
I use StackOverflow for the first time, so please be friendly and understanding.
Few days ago I got interested in ActionScript. I have downloaded FlashDevelop (a free IDE) and FlexSDK4. Then I have learned the basics from some tutorials.
For now I am not really developing any big project, I'm rather just doing tests.
Anyway, a solution to my problem is really important for me. I have looked for it, but I couldn't find any.
I have just one button and a background in my app. Both the button and the background (below: "bg") are objects of the Sprite class.
When I click the button, the background gets painted with 10x10px squares of random colours.
The problem is that the more times I click the button, the longer time I have to wait until the background changes. And that's not all! I can change the background exactly 54 times! At the 55th time it doesn't change at all.
package {
// some imports here
public class Main extends Sprite {
private var button:Sprite;
private var bg:Sprite;
public function Main ():void {
init();
}
private function init (e:Event=null):void {
addChild (bg);
// in the original code there are some lines here,
// in which the button is created
addChild (button);
button.addEventListener (MouseEvent.CLICK, btnClick);
}
private function btnClick (event:MouseEvent):void {
var x:uint, y:uint, color:uint;
for (y=0; y<30; y++) {
for (x=0; x<40; x++) {
color=Math.round(Math.random()*16777215);
bg.graphics.beginFill (color);
bg.graphics.drawRect (x*10, y*10, 10, 10);
bg.graphics.endFill ();
}
}
}
}
}
The code is so short, because I have removed many void lines. I have left only the important ones.
What is wrong with this code? Please help me.
Thanks in advance.
clear your graphics before the loop
var x:uint, y:uint, color:uint;
bg.graphics.clear();
for (y=0; y<30; y++) {//etc