Cropping/Clipping A Sprite - apache-flex

How is cropping/clipping accomplished on a Sprite in Flex?
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="Init()">
<mx:Script>
<![CDATA[
public function Init():void {
var spr:Sprite=new Sprite();
uic.addChild(spr);
uic.graphics.lineStyle(2,0);
uic.graphics.moveTo(22, 22);
uic.graphics.lineTo(2222, 2222);
}
]]>
</mx:Script>
<mx:Panel title="StackOverflow">
<mx:UIComponent width="200" height="200" id="uic"/>
</mx:Panel>
</mx:WindowedApplication>
Notice that the lineTo completely leaves the UIComponent and Panel.
How can I cause my UIComponent or Sprite, Or Panel for that matter, to be cropped/clipped?
(source: liquidfeline.com)
I realize I could just change the hard-coded 2222's to something more reasonable, but I need a generalized solution to this, since the actual project doesn't involve hard-coded values that I can alter, but works with dynamic data.

You should also try using scrollRect, this will be faster in performance than a mask. Introduction to the scrollRect from Grant Skinner.

Use a mask.
var mask:Shape = new Shape();
with(mask.graphics)
{
beginFill(0xFFFFFF, 1); // white, opaque
drawRect(0, 0, width, height);
endFill();
}
uic.mask = mask;

Related

Flex spark list to render images

I am new in flex. Currently i am going to build a flex album, but I get a problem about
the render in image by spark list.
the problem is this last 2~3 thumbs can not be properly displayed, as you can see as follows:
http://www.j-rich.com/Problem
and it will look like:
http://www.j-rich.com/Problem/show.jpg
for the source code, you can right click and choose view source in the demo
Any suggestion will be appreciated, thank you very much.
Sincerely,
Yuan-Hsu Liao
Add cachePolicy="on" to your Image control in ItemRenderer. But I don't recomend to use this kind of huge images as thumbnails. Looks like Flash has some limitations in this field.
This is correct for me, my resolution is 1920*1080. I use FLEX SDK4.5.1, flashplayer 11.8.
By the way, you should better override the set data function in the ItemRenderer, and set img source in the function, like this:
<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
override public function set data(value:Object):void {
super.data = value;
var url:String = value as String;
img.source = url;
positionImg();
}
private function positionImg():void
{
this.ima.width = 136;
this.ima.height = 105;
this.ima.x = 0;
this.ima.y = 0;
}
]]>
</fx:Script>
<s:Group id="group" x="0" y="0" width="170" height="85">
<s:Image id="img" x="0" y="0" scaleMode="letterbox"/>
</s:Group>
</s:ItemRenderer>
ItemRenderer is recycled, so it's better to do some stuff in the set data()
Check whether ur Padding given is Correct...or else Adjust the same.

Flex: rounded corners for dynamic created images

there a better way as this example
to create round corners for dynamic (addChild or addElement) created Images?
ok, here is a custom class http://santobay.blogspot.com/2010/04/rounded-corner-image-in-flex.html . save this code as com/RoundedImage.as , create new mxml file with this code
<mx:Application name="Image_mask_test"
xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:custom="com.*"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:HBox id="hbox" width="100%">
<custom:RoundedImage source="images/test.jpg" width="250" height="250" cornerRadius="15"/>
</mx:HBox></mx:Application>
and compile. For create images dynamic use this code:
<fx:Script>
<![CDATA[
import com.RoundedImage;
public function createImage():void {
var newImage:RoundedImage = new RoundedImage();
newImage.source = "images/test.jpg";
newImage.cornerRadius = 20;
hbox.addChild(newImage);
}
]]>
</fx:Script>
No, you must use a mask, if you add it dynamically.
However, you could add a 'frame' on top of the image, if the background is solid, you can use this trick.

Flex 4.5.1 Add a simple Bitmap or Sprite on new application?

Maybe it is a bad habit which I still have since Flash Professional, but I'm trying to add a simple Sprite or/and Bitmap I just created to an empty Application and it's not happening.
<?xml version="1.0" encoding="utf-8"?>
<s:Application 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="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event : FlexEvent ) : void
{
var s:Sprite = new Sprite();
s.graphics.beginFill( 0xFF0000, 0.5 );
s.graphics.drawRect( 0, 0, 100, 100 );
s.graphics.endFill();
this.addChild( s );
}
]]>
</fx:Script>
</s:Application>
Could someone tell me what I am doing wrong and help me correct it?
Try putting your sprite in UIComponent or SpriteVisualElement.
This works for me:
<?xml version="1.0" encoding="utf-8"?>
<s:Application 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="955" minHeight="600"
creationComplete="test()">
<fx:Script>
<![CDATA[
import spark.core.SpriteVisualElement;
private function test():void
{
var sprCont:SpriteVisualElement = new SpriteVisualElement();
sprCont.horizontalCenter = 0;
sprCont.verticalCenter = 0;
var spr:Sprite = new Sprite();
spr.graphics.beginFill(0xFF0000);
spr.graphics.drawCircle(0,0, 100);
spr.graphics.endFill();
sprCont.addChild(spr);
addElement(sprCont);
}
]]>
</fx:Script>
</s:Application>
For some reasons the 's:Application' tags are not shown, but they are there.
HTH,
FTQuest
There are a few things to consider. You don't specify a height or width for your sprite. Won't it default to a height and width of 0; effectively rendering it invisible?
The second thing to note is that I strongly recommend you make use of the Flex Component Lifecycle methods for creating children. Instead of using a creationComplete handler, override createChildren() to create the sprite and add it. It would be common to use updateDisplayList() for the drawing, sizing, and positioning of the component.
The second thing to note is that Application is actually a sprite. Depending on what you're trying to do you could do the drawing directly on the application:
this.graphics.beginFill( 0xFF0000, 0.5 );
this.graphics.drawRect( 0, 0, 100, 100 );
this.graphics.endFill();
I perceive it will be more flexible to use a sprite than to draw directly on the Application; but it depends what you're trying to accomplish.

Simulate includeInLayout=false in pure Actionscript code

If you know Flex, you probably know what the property "includeInLayout" does. If not, this property make the parent of your component disregard the bounds (like width and height) of your component in render their own bounds.
Description in reference below:
Specifies whether this component is
included in the layout of the parent
container. If true, the object is
included in its parent container's
layout and is sized and positioned by
its parent container as per its layout
rules. If false, the object size and
position are not affected by its
parent container's layout.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/UIComponent.html#includeInLayout
In Flex, for example:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="application1_creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event:FlexEvent ):void
{
trace( container.width, container.height ); // output: 200 200
}
]]>
</mx:Script>
<mx:Canvas id="container">
<mx:Button label="Test"
width="100"
height="100" />
<mx:Button label="Test2"
width="200"
height="200" />
</mx:Canvas>
</mx:Application>
Now if I set includeInLayout="false" in second button:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
creationComplete="application1_creationCompleteHandler(event)">
<mx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_creationCompleteHandler( event:FlexEvent ):void
{
trace( container.width, container.height ); // output: 100 100
}
]]>
</mx:Script>
<mx:Canvas id="container">
<mx:Button label="Test"
width="100"
height="100" />
<mx:Button label="Test2"
width="200"
height="200"
includeInLayout="false" />
</mx:Canvas>
</mx:Application>
I know of all framework architecture involved to implement this property and know than this property is a property from Flex Framework. What I wanna is this behavior in pure actionscript. For example:
import flash.display.Shape;
var myBox:Shape = new Shape();
myBox.graphics.beginFill(0xFF0000);
myBox.graphics.drawRect(0, 0, 100, 100);
myBox.graphics.endFill();
addChild(myBox);
trace(width, height); // output: 100 100
var myAnotherBox:Shape = new Shape();
myAnotherBox.graphics.beginFill(0xFF00FF, .5);
myAnotherBox.graphics.drawRect(0, 0, 200, 200);
myAnotherBox.graphics.endFill();
addChild(myAnotherBox);
trace(width, height); // output: 200 200
Is there some equivalent implementation in pure Actionscript to reproduce this behavior on "myAnotherBox"?
I already tried:
Change transform matrix;
Change transform pixelBounds;
Change scrollRect;
Apply masks;
And no successful.
Cheers...
You are trying to compare to different things.
In the first example, the width and height are from the UIComponent class, which actually represents a "measured" value, as provided by the Flex Framework.
In the second case, the width and height are the actual size of the rendered shape, as provided by the Flash Player.
If you open the UIComponent's implementation, you will notice that it is actually hiding the original meaning of width and height into $width and $height and provide their own implementation to it.
So to answer your question, you cannot achieve what you want working directly with Shapes (pure Flash components)
Every time you draw something in a graphics context, the width and height will update accordingly.
You options:
draw the first one in one graphics, and the second one in another graphics and measure only the first shape
compute the width and height yourself. This is what actually the containers do, and just skip the includeInLayout=false child components.
If you look up in the UIComponent source code, you'll find, that flag includeInLayout is used in invalidation mechanism (exatcly in size invalidation). If includeInLayout of the component is false, then its parent's size and its size is not recalculated.
Invalidation is native flex framework mechanism, which does not exist in pure AS projects.
You need to override width and height in your container:
override public function get width() : Number {
// place your code here
return 100;
}
override public function get height() : Number {
// place your code here
return 100;
}

Flex: Moving canvases between several ui elements

I need to animate a lable movement between 2 canvases...
The mxml example of the code is:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="main()" frameRate="1">
<mx:Script>
<![CDATA[
import mx.controls.Label;
public function main():void
{
onEnd();
}
private function onEnd():void
{
(canv1.getChildAt(0) as Label).move(canv2.x, canv2.y);
}
]]>
</mx:Script>
<mx:Panel x="208" y="0" width="190" height="200" layout="absolute" title="Panel2" id="d">
</mx:Panel>
<mx:Panel width="200" height="200" id="c" title="Panel 1">
<mx:Canvas width="135" height="56" id="canv1" label="c1" themeColor="#79B4DA" backgroundColor="#65D565">
<mx:Label text="Move me after event" y="10"/>
</mx:Canvas>
<mx:Canvas width="135" height="79" id="canv2" label="C2" backgroundColor="#E4CACA">
</mx:Canvas>
</mx:Panel>
</mx:Application>
Currently the problem is that the label actually do not leave borders of the first canvas (I see scrollbars instead of it).
I think this is related to globalToLocal conversion problems, but do not understand how to use it.
Also another question is how to animate the movement corretly, because move function performs movement without any visible action.
(The movement happens seamlessly).
I don't think the move function will solve this for you since it will only move the label within it's parent, just as Robusto has commented above.
The way to go about this would perhaps be to see to it that you first detach the label from its parent. Then move it, and add it as a child to the other canvas. Manipulating x,y coordinates will not implicitly change the parent for you. That will always have to be done explicitly, which is good...
So for example, to actually switch parent you would need to do something like this (pseudo code):
/**
* This function only switches the parent.
*/
private function moveLabel(label:Label) {
label.parent.removeChild(label);
canv2.addChild(label);
}
If you want this action to be animated you would first have to detach the label from the canvas and see to it that it is added to the parent of the canvas, in your case, the panel with id "c". Then you can tween it into position and add it to the correct canvas.
TweenLite is a great library for tweening. http://www.greensock.com/tweenlite/
But I guess the main lesson here is that manipulating coordinates will never result in a new parent for the component you are moving.
Update: Here's a complete example of how you could solve this, take into account that the code is not very nice looking, but it contains a simple example of animation.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="main()">
<mx:Script>
<![CDATA[
import mx.controls.Label;
import flash.geom.Point;
import gs.TweenLite;
import gs.easing.Expo;
public function main():void
{
onEnd();
}
private function onEnd():void
{
var label:Label = canv1.getChildAt(0) as Label;
var originX:int = label.localToGlobal(new Point(label.x, label.y)).x;
var originY:int = label.localToGlobal(new Point(label.x, label.y)).y;
label.parent.removeChild(label);
stage.addChild(label);
label.x = originX;
label.y = originY;
TweenLite.to(label, 1.5, {y: "80", ease:Expo.easeOut, onComplete:onFinishTween, onCompleteParams:[label]});
}
private function onFinishTween(label:Label):void {
stage.removeChild(label);
label.x = canv2.globalToLocal(new Point(label.x, label.y)).x;
label.y = canv2.globalToLocal(new Point(label.x, label.y)).y;
canv2.addChild(label);
}
]]>
</mx:Script>
<mx:Canvas width="135" height="56" id="canv1" label="c1" themeColor="#79B4DA" backgroundColor="#65D565" y="-1" x="9">
<mx:Label text="Move me after event" y="10"/>
</mx:Canvas>
<mx:Canvas width="135" height="79" id="canv2" label="C2" backgroundColor="#E4CACA" y="90" x="8">
</mx:Canvas>
</mx:Application>

Resources