3 Replies Latest reply on Aug 1, 2012 1:42 AM by creak45

    Why is SolidColorStroke acting acting that weird?

    creak45

      Hi everybody,

       

      (I posted this question on Stackoverflow, so if you want you can also read this post.)

       

      Recently I had to build an MXML component, that adds a border around an object. That object is some visual object that is passed to the component. I use a Rect to draw the border. That Rect has a SolidColorStroke as child. The thickness of the border (the stroke) is configured by setting the strokes weight. My first solution to this problem looked something like this.

       

      var borderThickness:Number = 10;   
      rect
      .x = object.x - borderThickness;
      rect
      .y = object.y - borderThickness;
      rect
      .width = object.width + (borderThickness * 2);
      rect
      .height = object.height + (borderThickness * 2);
      rectStroke
      .weight = borderThickness;

      //the MXML code
      <s:Rect id="rect">
       
      <s:stroke>
         
      <s:SolidColorStroke id="rectStroke" />
       
      </s:stroke>
      </
      s:Rect>

       

      I thought the x and y coordinate of the border is the x and y coordinates of the object minus the borderThickness. It seems that I was wrong because the border covers some parts of the object on the right and the bottom.

       

      The next solution I had was that the stroke grows by 50% to each side. That means that if you want to calculate the x and y coordinate you just subtract the half borderThickness. I hope it's clear what I mean.

       

      Also this didn't work correctly. I found out, that the stroke doesn't grow by 50% on each side but it grows by 75% to the inside and 25% to the outside. So now my code looks like this:

       

      var borderThickness:Number = 10;   
      rect
      .x = object.x - borderThickness;
      rect
      .y = object.y - borderThickness;
      rect
      .width = object.width + (borderThickness * 1.5);
      rect
      .height = object.height + (borderThickness * 1.5);
      rectStroke
      .weight = borderThickness;

      //the MXML code
      <s:Rect id="rect">
       
      <s:stroke>
         
      <s:SolidColorStroke id="rectStroke" />
       
      </s:stroke>
      </
      s:Rect>

       

      My question now is, am I using it correct? Does anyone experience a similar behavior? Is that the correct behavior? What am I doing wrong?

       

      kind regards

      Markus

        • 1. Re: Why is SolidColorStroke acting acting that weird?
          drkstr_1 Level 4

          I don't think you need to adjust the x/y positions manually. This is usually done automatically by the parent layout container. It really depends on what the rest of your code looks like though. My guess is you need to control a few things in your updateDisplayList method. Take a peek at the source for the spark PanelSkin.mxml for an example on how to control these kinds of things. If you are still stuck, post a complete example that demonstrates the issue.

          • 2. Re: Why is SolidColorStroke acting acting that weird?
            creak45 Level 1

            The problem is that this component can surround any object. And the object can be anywhere on the screen, so I need to adjust the x and y position manually. Also the Component lies on top of the application, so it is instantiated and positioned at runtime on top of all the other visual elements. The method I use to calculate the dimension of this rectangluar border looks like this:

             

             

            <s:Graphic xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"

                       creationComplete="creationCompleteHandler(event)">

                <fx:Declarations>

                    <!-- Place non-visual elements (e.g., services, value objects) here -->

                </fx:Declarations>

                <fx:Script>

                    <![CDATA[

             

                        // there are some other functions here but basically they are just getter and setter.

             

                        public function draw():void

                        {

                            if (_scannableObject == null)

                                return;

             

                            _draw = true;

                            setDimension();

                        }

             

             

                        private function setDimension():void

                        {

                            var offset:Number = borderThickness + (_borderOffset * 2);

             

                            width = _scannableObject.width + borderThickness * 1.5 + (_borderOffset * 2);

                            height = _scannableObject.height + borderThickness * 1.5 + (_borderOffset * 2);

             

                            if (_scannableObject.width == 0 || _scannableObject.height == 0)

                                border.visible = false;

                            else if (_draw)

                            {

                                x = -(offset / 2);

                                y = -(offset / 2);

                                border.visible = true;

                                borderStroke.weight = borderThickness;

                                borderStroke.color = color;

                            }

                        }

                      ]]>

                </fx:Script>

             

             

            <s:Rect id="border" visible="false" width="{width}" height="{height}">

                    <s:stroke>

                        <s:SolidColorStroke id="borderStroke" />

                    </s:stroke>

                </s:Rect>

            </s:Graphic>

             

             

             

            The _borderOffset is the space between the border and the object. The borderThickness is the object that holds the thickness of the border (the weight of the stroke) and the color holds the color of the stroke. The _draw variable specifies whether the border should be drawn or not (that can be configured from the outside) The _scannableObject is the object that should be surrounded by the border. This object is configured from the outside. The setDimension method is called either when the border should be drawn or the object is resized (what actually currently never happens).

             

            The _scannableObject that should get the border is always a spark button. The method to draw the border is called from the outside.

             

            I created some drawing that should show what I want and what I got in the past.

            What I want is something like this (what I get with the code above):

            Unbenannt-1.png

            My first try, when I thought the border would grow to the inside I got something like this.

            Unbenannt-4.png

            On the right and the bottom there was to much space. Then I thought the stroke grows 50% to the inside and 50% to the outside. That resulted in something like this:

            Unbenannt-2.png

            On the right and the bottom there was to little space. When I don't calculate the x and y position correctly I get something like this:

            Unbenannt-3.png

            On all sides, there is to little space (if I use the 50% 50% method for calculating the width and the height.

             

            The black rect here is the _scannableObject, i.e. the button that should get the border. As I said before it is a spark button with any skin. I hope it is clear what I did.

            • 3. Re: Why is SolidColorStroke acting acting that weird?
              creak45 Level 1

              I just got an answer on stackoverflow which doesn't explain why the stroke grows 75% to the inside but it is a solution that I like better than mine. Maybe someone has a clue why the SolidColorStroke acts like described above...