flash AS3 custom button rollover (стиль windows 7)

ПРИМЕЧАНИЕ. Я решил сохранить историю темы, потому что думаю, что процесс поиска может быть кому-то полезен. Если вам нужно решение, перейдите в конец моего сообщения.

Я искал, но не нашел своего ответа ни в Google, ни в StackOverflow (ни одного учебника по нему). Я хотел бы создать на кнопке выделение при наведении курсора, например на панель задач Windows 7. Выделение перемещается и зависит от того, где мышь находится на кнопке. Я не хочу, чтобы какое-либо изображение на моей кнопке (только цветовой градиент) сохраняло стандартный компонент. Как я могу применить этот эффект опрокидывания?

Вернувшись, я попытался запустить этот код:

    <?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>

Проблема в том, что никакое событие не фиксируется. Я попытался изменить текст метки в событии щелчка для проверки, но он просто не работает (нет дескриптора события). Это действительно странно. Не могли бы вы принести какую-нибудь помощь?

ИЗМЕНИТЬ 15/11/11. Я обнаружил, что моему createCompleteHandler нужен parent.mouseChildren = true; для захвата событий мыши. Я вставил его и теперь вижу, что события мыши фиксируются, но мой эффект ролловера больше не отображается, даже если я удаляю переход состояний и играю с visible = true / false; эффекта в моем обработчике мыши.

ПОСЛЕДНИЙ РЕДАКТИРОВАНИЕ Я наконец нашел решение своей проблемы, спасибо всем. Мое решение:

 <?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>

person TheFrenchGuy    schedule 14.11.2011    source источник
comment
Можете ли вы дать ссылку на изображение или видео эффекта, которого вы пытаетесь достичь?   -  person jedd.ahyoung    schedule 14.11.2011
comment
Вот ссылка на эффект панели задач W7: [захват] блогов. msdn.com/photos/mgrayson/images/1689351/500x36.aspx   -  person TheFrenchGuy    schedule 16.11.2011


Ответы (1)


Вот несколько шагов для начала:

  1. Create the gradient. Could be:
    • a predefined image
    • круг, заполненный внешним градиентным цветом, установленным на прозрачный. Может, нужно преобразовать в эллипс.
  2. Замаскируйте градиент областью кнопки.
  3. Прослушивайте наведение курсора и События наведения указателя мыши на область кнопки. Обновите положение градиента до положения мыши (или только mouse.y) на перемещение мыши.

Я не могу обещать, что он будет выглядеть точно так же, как на панели задач Windows 7, так как это зависит от фона кнопки и формы градиента. Не уверен, используются ли там дополнительные эффекты. Вы можете немного оживить вещи, добавив больше градиентов, которые меняют свою прозрачность в зависимости от расстояния мыши, и поэкспериментируя с режим наложения умножения, который дает хорошие эффекты.


Обновить. Думаю, this.overEffectRadialGradient.y = event.stageY; использует неправильные координаты. Это может сработать, если кнопка находится на 0,0. Местные координаты должны быть правильными: event.localY.

person kapex    schedule 14.11.2011
comment
Хорошо, большое спасибо, я попробую с вашими идеями, и если они будут достаточно хорошими, я отправлю туда код. - person TheFrenchGuy; 14.11.2011
comment
Я заблокирован на данный момент (см. Правку моего поста выше). Если бы вы могли мне помочь, я буду очень признателен. - person TheFrenchGuy; 16.11.2011
comment
@TheFrenchGuy Обновлено. Извините, но я не уверен, что могу сильно помочь, так как у меня нет большого опыта работы с flex, только с чистой AS. Насколько я могу судить, ваш код выглядит хорошо. Если у вас возникнут проблемы, и никто не отправит на них ответ, вам следует создать новые вопросы для конкретной проблемы, чтобы привлечь больше внимания. - person kapex; 16.11.2011