2

NOTE: I chose to keep the history of the topic cause I think the searching process might be usefull to someone. If you want the solution go to the bottom of my post.

I searched but I didnt find my answer either on Google and StackOverflow (not even a single tutorial on it). I would like to create a rollover highlight on a button, like the windows 7 taskbar. The highlight moves and is function of where the mouse is on the button. I dont want any image on my button (only color gradient) to keep a standard component. How can I apply this rollover effect?

Back, I tried to run this code:

    <?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:mx="library://ns.adobe.com/flex/mx"
             minWidth="65" minHeight="22"
             creationComplete="GlassButtonSkin_creationCompleteHandler(event)"> 

    <fx:Metadata>[HostComponent("spark.components.Button")]</fx:Metadata>

    <fx:Declarations>

    </fx:Declarations>


    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;

            protected function GlassButtonSkin_creationCompleteHandler(event:FlexEvent):void{
                this.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler);
                this.addEventListener(MouseEvent.CLICK,mouseClickHandler);
            }

            private function mouseOverHandler(event:MouseEvent):void{
                this.overEffectRadialGradient.y = event.stageY;
                this.labelDisplay.text = "your in";
                this.commitProperties();
            }
            private function mouseClickHandler(event:MouseEvent):void{
                this.labelDisplay.text = "your in";
            }
        ]]>
    </fx:Script>


    <s:states>
        <s:State name="up"/> 
        <s:State name="over"/> 
        <s:State name="down"/> 
        <s:State name="disabled"/> 
    </s:states>

    <s:transitions>
        <s:Transition fromState="up" toState="over" autoReverse="true">
            <s:Fade target="{overEffect}" alphaFrom="0" alphaTo="1" duration="500"/>
        </s:Transition>
    </s:transitions>




    <!-- inner border --> 
    <s:Rect left="0" right="0" top="0" bottom="0" id="innerBorder" radiusX="4" radiusY="4">
        <s:stroke>     
            <s:SolidColorStroke id="innerBorderStroke" weight="1" color="#ffffff" />
        </s:stroke>
    </s:Rect>

    <!-- outer border --> 
    <s:Rect left="1" right="1" top="1" bottom="1" id="outerBorder" radiusX="4" radiusY="4">
        <s:stroke>     
            <s:SolidColorStroke id="outerBorderStroke" weight="1" color="#000000"/>
        </s:stroke>
    </s:Rect>

    <!-- fill -->
    <!--- Defines the appearance of the Button component's background. -->
    <s:Rect id="background" left="1" right="1" top="1" bottom="1">
        <s:fill>
            <s:SolidColor alpha="0.5" color="#000000"/>
        </s:fill>
    </s:Rect>

    <s:Rect id="backgroundTopPart" left="1" right="1" top="1" height="50%"
            includeIn="up,over,disabled">
        <s:fill>
            <s:LinearGradient rotation="90">
                <s:GradientEntry color="#ffffff" alpha="0.6"/>
                <s:GradientEntry color="#ffffff" alpha="0.2"/>
            </s:LinearGradient>
        </s:fill>
    </s:Rect>

    <s:Rect id="overEffect" left="1" right="1" bottom="1" height="50%" radiusX="4" radiusY="4"
            includeIn="over,down">
        <s:fill>        
            <s:RadialGradient id="overEffectRadialGradient" x="{width*0.5}" y="{height*0.5}" scaleY="{height}" scaleX="{width/1.5}">
                <s:GradientEntry color="#8dbdff" alpha="0.7" />
                <s:GradientEntry color="#8dbdff" alpha="0"/>
            </s:RadialGradient>
        </s:fill>
    </s:Rect>


    <s:Label id="labelDisplay"
             text="Send"
             textAlign="center" 
             verticalAlign="middle" 
             color="#FFFFFF"
             horizontalCenter="0" verticalCenter="1" 
             left="10" right="10" top="2" bottom="2">
    </s:Label>



</s:SparkSkin>

The problem is that no event is captured. I tried to change the label text on a click event to test but it just doesn't work at all (no event handle). It's really strange. Can you bring some help please?

EDIT 15/11/11 I found that my creationCompleteHandler needed a parent.mouseChildren = true; to capture the mouse events. I put it and now I can see that mouse events are captured but my rollovereffect is not displayed anymore even if i delete the transition of states and I play with the visible = true/false; of the effect in my mouse over handler.

LAST EDIT I finally found the solution of my problem, thanks to all. My solution:

 <?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" 
             xmlns:s="library://ns.adobe.com/flex/spark" 
             xmlns:mx="library://ns.adobe.com/flex/mx"
             minWidth="65" minHeight="22"
             creationComplete="GlassButtonSkin_creationCompleteHandler(event)"> 

    <fx:Metadata>[HostComponent("spark.components.Button")]</fx:Metadata>

    <fx:Declarations>

    </fx:Declarations>


    <fx:Script>
        <![CDATA[
            import mx.events.FlexEvent;
            import mx.graphics.RadialGradient;

            import spark.effects.Fade;
            import spark.effects.animation.RepeatBehavior;

            [Bindable]
            private var rectRollOverEffect:Rect = new Rect();
            private var radialGradientRollOverEffect:RadialGradient = new RadialGradient();
            private var gradientEntryRollOverEffect1:GradientEntry = new GradientEntry(0x8dbdff,NaN,0.7);
            private var gradientEntryRollOverEffect2:GradientEntry = new GradientEntry(0x8dbdff,NaN,0);
            private var indexOfRollOverEffect:int;
            private var myFade:Fade;

            protected function GlassButtonSkin_creationCompleteHandler(event:FlexEvent):void{
                parent.mouseChildren = true;
                this.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoveHandler,true);
                this.addEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler,true);
                this.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler,true);

                this.addElement(rectRollOverEffect);
                indexOfRollOverEffect = this.getElementIndex(rectRollOverEffect);
                this.removeElementAt(indexOfRollOverEffect);
            }

            private function mouseOverHandler(event:MouseEvent):void{
                if(this.currentState == "disabled")
                    return;

                createRollOverEffect(event,0);

                myFade = new Fade(this.getElementAt(indexOfRollOverEffect));
                myFade.alphaFrom = 0;
                myFade.alphaTo = 1;
                myFade.duration = 200;
                myFade.end();
                myFade.play();
            }

            private function mouseMoveHandler(event:MouseEvent):void{
                if(this.currentState == "disabled")
                    return;

                this.removeElementAt(indexOfRollOverEffect);
                createRollOverEffect(event,1);
            }

            private function mouseOutHandler(event:MouseEvent):void{
                if(this.currentState == "disabled")
                    return;

                this.removeElementAt(indexOfRollOverEffect);
            }

            private function createRollOverEffect(event:MouseEvent,alpha:int):void{
                rectRollOverEffect.alpha = alpha;
                rectRollOverEffect.left = 2;
                rectRollOverEffect.right = 2;
                rectRollOverEffect.bottom = 2;
                rectRollOverEffect.top = 2;
                rectRollOverEffect.radiusX = 4;
                rectRollOverEffect.radiusY = 4;

                radialGradientRollOverEffect.entries = [gradientEntryRollOverEffect1,gradientEntryRollOverEffect2];
                radialGradientRollOverEffect.x = event.localX;
                radialGradientRollOverEffect.y = height-2;
                radialGradientRollOverEffect.scaleX = width/1.5;
                radialGradientRollOverEffect.scaleY = height;

                rectRollOverEffect.fill = radialGradientRollOverEffect;

                this.addElementAt(rectRollOverEffect,indexOfRollOverEffect);
            }
        ]]>
    </fx:Script>


    <s:states>
        <s:State name="up"/> 
        <s:State name="over"/> 
        <s:State name="down"/> 
        <s:State name="disabled"/> 
    </s:states>

    <s:transitions>
        <s:Transition fromState="over" toState="disabled">
            <s:CallAction target="{this}" functionName="removeElement" args="{[this.rectRollOverEffect]}"/>
        </s:Transition>
    </s:transitions>



    <!-- outer border --> 
    <s:Rect left="0" right="0" top="0" bottom="0" id="outerBorder" radiusX="4" radiusY="4">
        <s:stroke>     
            <s:SolidColorStroke id="outerBorderStroke" weight="1" color="#ffffff" />
        </s:stroke>
    </s:Rect>

    <!-- inner border --> 
    <s:Rect left="1" right="1" top="1" bottom="1" id="innerBorder" radiusX="4" radiusY="4">
        <s:stroke>     
            <s:SolidColorStroke id="innerBorderStroke" weight="1" color="#000000"/>
        </s:stroke>
    </s:Rect>

    <!-- fill -->
    <!--- Defines the appearance of the Button component's background. -->
    <s:Rect id="background" left="1" right="1" top="1" bottom="1">
        <s:fill>
            <s:SolidColor alpha="0.5" color="#000000"/>
        </s:fill>
    </s:Rect>

    <s:Rect id="backgroundTopPart" left="1" right="1" top="1" height="50%"
            includeIn="up,over,disabled">
        <s:fill>
            <s:LinearGradient rotation="90">
                <s:GradientEntry color="#ffffff" alpha="0.5" ratio="0.1"/>
                <s:GradientEntry color="#ffffff" alpha="0.1"/>
            </s:LinearGradient>
        </s:fill>
    </s:Rect>


    <s:Label id="labelDisplay"
             text="Send"
             textAlign="center" 
             verticalAlign="middle" 
             color="#FFFFFF"
             horizontalCenter="0" verticalCenter="1" 
             left="10" right="10" top="2" bottom="2">
    </s:Label>

    <s:Rect id="disableForeground" left="0" right="0" top="0" bottom="0"
            includeIn="disabled">
        <s:fill>
            <s:LinearGradient rotation="90">
                <s:GradientEntry color="#7B7B7B" alpha="0.6" ratio="0.1"/>
                <s:GradientEntry color="#aaaaaa" alpha="0.3"/>
            </s:LinearGradient>
        </s:fill>
    </s:Rect>


</s:SparkSkin>
TheFrenchGuy
  • 233
  • 1
  • 3
  • 14
  • Can you link to a picture or a video of the effect you're trying to achieve? –  Nov 14 '11 at 15:05
  • 1
    Here is a link for tha W7 task bar effect : [capture]http://blogs.msdn.com/photos/mgrayson/images/1689351/500x36.aspx – TheFrenchGuy Nov 16 '11 at 08:14

1 Answers1

4

Here a few steps to get started:

  1. Create the gradient. Could be:
    • a predefined image
    • a circle, filled with an outer gradient color set to transparent. Maybe needs to be transformed into an ellipse.
  2. Mask the gradient with the area of the button.
  3. Listen for mouse over and mouse out events on the button's area. Update the position of the gradient to the mouse position (or only mouse.y) on mouse move.

I can't promise that it will look exactly like in the windows 7 taskbar, as it depends on the button's background and the shape of the gradient. I'm no sure if there are additional effects used there. You can spice up things a little bit by adding more gradients that change their transparency according to the mouse distance and experimenting with multiply blend mode which gives nice effects.


Update - I think this.overEffectRadialGradient.y = event.stageY; is using the wrong coordinates. It may works if the button is at 0,0 though. The local coordinates should be the correct ones: event.localY.

kapex
  • 28,903
  • 6
  • 107
  • 121
  • 1
    Ok thanks very much I will try with your ideas and if it renders good enough I will post th code there. – TheFrenchGuy Nov 14 '11 at 17:47
  • I'm blocked at the moment (see the edit of my post above). If you could help me I will be very grateful. – TheFrenchGuy Nov 16 '11 at 08:16
  • @TheFrenchGuy Updated. Sorry but I'm not sure I can be of much help, as I don't have much experience with flex, just with pure AS. Your code looks good as far as I can tell. If you run into problems and no one posts an answer, you should create new questions for the specific problem to attract more attention. – kapex Nov 16 '11 at 11:46