Rotating flex graphic object around center - actionscript-3

I tried to create a rotating animation of an arc. Even after trying all those examples, I am not able to rotate it around the center. It is getting rotated around the top left corner.
private function init():void
{
var hgroup:Group=new Group();
this.addElement(hgroup);
arc1=new Graphic();
arc1.graphics.lineStyle(12,0xff0000,1,false,"normal",CapsStyle.SQUARE);
draw_arc(arc1,CENTER,CENTER,70,14,288,1);
hgroup.addElement(arc1);
var matrix:Matrix = arc1.transform.matrix;
var rect:Rectangle = arc1.getBounds(arc1.parent);
matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2)));
matrix.rotate((90/180)*Math.PI);
matrix.translate(rect.left + (rect.width/2), rect.top + (rect.height/2));
var rot:Rotate = new Rotate();
rot.angleBy = 360;
rot.duration = 1000;
rot.target = arc1;
rot.play();
}
public function draw_arc(movieclip:Sprite,center_x:Number,center_y:Number,radius:Number,angle_from:Number,angle_to:Number,precision:Number):void {
var angle_diff:Number=angle_to-angle_from;
var steps:Number=Math.round(angle_diff*precision);
var angle:Number=angle_from;
var px:Number=center_x+radius*Math.cos(angle*deg_to_rad);
var py:Number=center_y+radius*Math.sin(angle*deg_to_rad);
movieclip.graphics.moveTo(px,py);
for (var i:Number=1; i<=steps; i++) {
angle=angle_from+angle_diff/steps*i;
movieclip.graphics.lineTo(center_x+radius*Math.cos(angle*deg_to_rad),center_y+radius*Math.sin(angle*deg_to_rad));
}
}

you need this property:
rot.autoCenterTransform="true"
see the example at the bottom of the documentation: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/effects/Rotate.html

I had a similar issue (with a rotating arrow) and I fixed it like this:
<s:Group width="0" height="0" verticalCenter="0" right="14">
<s:Graphic id="arrow" rotation="90" rotation.selectedStates="0">
<s:Path data="M 0 0 L 5 5 L 0 10 Z" left="-2.5" top="-5">
<s:fill>
<s:SolidColor id="arrowFill"/>
</s:fill>
</s:Path>
</s:Graphic>
</s:Group>
The container Group has its size set to 0 as it serves only as an anchor point for the graphic it contains. The position of this Group is the rotating center point. The Path in the Graphic is positioned so that its anchor point is in its center (i.e. it's 5px wide and 10px heigh, so it's repositioned 2.5px to the left and 5px to the top).
The actual rotation is done through States and Transformations here, but an Effect does the same thing.

I've used this solution before; it works well and is very simple:
http://www.chadupton.com/blog/2008/02/rotate-on-center-in-adobe-flex/

To rotate image at the center you have to specify this properties
rot.autoCenterTransform="true";
rot.applyChangesPostLayout = false;

Related

Span Image or Display object across two canvas in Flex/as3

My Requirement given below:
I want to span same image across two canvas.
Like I have HBOX with two canvas as childs. I want to drag first canvas
display object into second canvas with half portion of that object in 1st canvas and half in second canvas.
Thanks in advance if someone has any idea.
You can split your image, after dropping it, using, for example, copyPixels() on the BitmapData of your image.
Take this example where I used two images in two Groups :
<s:VGroup x="0" y="0" width="300" height="500">
<s:Group id="group_top" width="200" height="200" >
<s:Image id="img_top" x="0" y="0" width="100%" height="100%"
source="assets/image.jpg"
mouseDown="img_top_mouseDownHandler(event)"
mouseUp="img_top_mouseUpHandler(event)"/>
</s:Group>
<s:Group id="group_bottom" width="200" height="200" >
<s:Image id="img_bottom" x="0" y="0" width="100%" height="100%" source=""/>
</s:Group>
</s:VGroup>
For the dragging and dropping, I used the old startDrag() and stopDrag() just for the example of course, you may need to use another way according to your needs.
protected function img_top_mouseDownHandler(event:MouseEvent):void
{
img_top.startDrag();
}
protected function img_top_mouseUpHandler(event:MouseEvent):void
{
img_top.stopDrag();
img_top.x = img_top.y = 0;
split_image();
}
And to split the image, I did like this :
protected function split_image():void
{
var bitmap_data_source:BitmapData = img_top.bitmapData;
var w:int = bitmap_data_source.width,
h:int = bitmap_data_source.height;
var bitmap_data_top:BitmapData = new BitmapData(w, h);
bitmap_data_top.copyPixels(
bitmap_data_source,
new Rectangle(0, 0, w, h/2),
new Point()
);
var bitmap_data_bottom:BitmapData = new BitmapData(w, h);
bitmap_data_bottom.copyPixels(
bitmap_data_source,
new Rectangle(0, h/2, w, h/2),
new Point()
);
var bitmap_top:Bitmap = new Bitmap(bitmap_data_top);
img_top.source = bitmap_top;
var bitmap_bottom:Bitmap = new Bitmap(bitmap_data_bottom);
img_bottom.source = bitmap_bottom;
}
Hope that can help.

How to center text within a container box in actionscript

I am stuck trying to center a text (RichEditableText) inside a container. My code so far looks like this
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<mx:Box id="myCustomBox" height="100%" width="100%" initialize="init();">
<fx:Script>
<![CDATA[
import mx.containers.Box;
import mx.containers.HBox;
import mx.containers.VBox;
import mx.controls.Button;
import mx.controls.Image;
import spark.components.RichEditableText;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.SpanElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.formats.TextAlign;
[Embed("dialog_error.png")]
private var myImage:Class;
public function init():void {
var img:Image = new Image();
img.source = myImage;
this.addElement(buildPane("Something went wrong", img));
}
private function buildPane(message:String, image:Image):Box{
var exPane:HBox = new HBox();
exPane.percentHeight = 100;
exPane.percentWidth = 100;
exPane.setStyle("horizontalGap","0");
//Image hosting pane
var imPane:VBox = new VBox;
imPane.setStyle("backgroundColor","blue");
imPane.percentHeight = 100;
imPane.explicitWidth = 50;
image.minHeight = 16;
image.minWidth = 16;
imPane.setStyle("paddingLeft",10);
imPane.setStyle("paddingRight",10);
var invisBtn1:Button = new Button();
invisBtn1.percentHeight = 40;
invisBtn1.visible = false;
imPane.addChild(invisBtn1);
image.percentHeight = 20;
imPane.addChild(image);
var invisBtn2:Button = new Button();
invisBtn2.visible = false;
invisBtn2.percentHeight = 40;
imPane.addChild(invisBtn2);
exPane.addChild(imPane);
//Text hosting pane
var txtPane:Box = new Box();
txtPane.setStyle("backgroundColor","yellow");
txtPane.percentHeight = 100;
//txtPane.setStyle("paddingBottom",10);
txtPane.setStyle("paddingLeft",0);
//txtPane.setStyle("paddingTop",30);
txtPane.setStyle("paddingRight",5);
//Specify text alignment
var errMsgLabel:RichEditableText = new RichEditableText;
var textFlow:TextFlow = new TextFlow();
var pCenter:ParagraphElement = new ParagraphElement();
var spanCenter:SpanElement = new SpanElement();
spanCenter.text = message;
pCenter.addChild(spanCenter);
pCenter.textAlign = TextAlign.CENTER;
textFlow.addChild(pCenter);
errMsgLabel.textFlow = textFlow;
errMsgLabel.percentHeight = 100;
errMsgLabel.percentWidth = 100;
errMsgLabel.multiline = true;
txtPane.addChild(errMsgLabel);
exPane.addChild(txtPane);
return exPane;
}
]]>
</fx:Script>
</mx:Box>
</s:WindowedApplication>
I would like the text to be at the same level as the dialog_error icon (Usual X mark icon). So if the text is taller, the icon needs to center itself in the middle of the text. Any pointers would be helpful.
Thank you.
I can think of no good reason why you would be writing all of this in ActionScript instead of MXML. You're just making things harder for yourself.
The whole 100 lines of code in your question can be reduced to this:
<s:HGroup width="100%" gap="0">
<s:VGroup width="50" height="100%" paddingLeft="10" paddingRight="10"
verticalAlign="middle">
<s:Image id="msgIcon" source="#Embed('dialog_error.png')"/>
<s:Button visible="false" includeInLayout="false"/>
<s:Button visible="false" includeInLayout="false"/>
</s:VGroup>
<s:RichEditableText id="errMsgLabel" width="100%"/>
</s:HGroup>
This code also contains the necessary fixes to center the error icon horizontally with respect to the error message's text height.
removed the 100% height on the HGroup; this caused the Image to be centered in the middle of the entire container, not just the text height.
added verticalAlign="middle" to the VGroup containing Image and Buttons; this property will align the content of this container to its vertical center.
added includeInLayout="false" to the invisible Buttons; if you just make the Buttons invisible, they will still take up space in the layout, pushing the Image up a little; setting this property to false will tell the VGroup container to act as if the Buttons really weren't there to do its layout.
removed the 100% height on the RichEditableText so that it is only as high as its text content, otherwise the icon will still be centered to the middle of the entire container.
removed a bunch of redundant containers.
Note that I assumed you applied the background colors only for testing purposes, to see how the containers are laid out.
I understand you want to dynamically change the icon. You can easily achieve this by setting its source property programatically afterwards:
msgIcon.source = otherEmbeddedImage;
Or even better, through data binding:
<s:Image source="{msgIcon}"/>
msgIcon = otherEmbeddedImage;

Can anyone help me out for side flip function using svg.js

I have written a flipUp function by using svg.js for fliping up and down an image. I need a side flip function also but I can not be able to implement side flip function by using scale(1,-1). Can anyone help me out?
function flipUp written in personalise.js as under:
function flipUp()
{
var angle = parseInt(target.trans.rotation,10) + 180;
//if(angle > 360) angle = angle -360
console.log(angle)
target.animate().rotate(angle)
//target.animate().transform('matrix' ,'-1,0,0,-1,0,0')
}
And the function is called from design.html as under:
<img src='flip_up.PNG' alt="" height="20" width="20" style='margin-top:-41px;margin-left:267px'>
You can accomplish this wouldn't the need for svg.js. You just need to use transform, in particular rotate. Also dont forget to add deg to the angle.
DEMO
HTML:
<img src='flip_up.PNG' alt="" height="20" width="20" style='margin-top:-41px;margin-left:267px'>
JAVASCRIPT:
// el is the anchor element (a)
// el.children[0] is the img
// however, this assumes the first child of the anchor element is the img
var angle = 15;
function flipUp(el){
el.children[0].style.transform = 'rotate(' + angle + 'deg)';
// add 15 degs on every click
angle += 15;
}
Hope this helps and let me know if you have any questions.

How can I make concentric circles in HTML respond to mouseOver properly?

On my web page, I'd like to have a group of several concentric circles of varying size, with each displaying a menu when they are moused over.
So far, I have created 4 pictures that is 100% transparent except for the circle and have layered them on top of each other. However, when I mouse-over the group of circles, the transparent part of the top image causes the mouse-over event to fire. How can I deal with this?
For reference, here is the code that I have so far.
<html>
<head>
<style type="text/css">
img
{
position:fixed;
left: 0;
bottom: 0;
}
</style>
<title>Circle Test</title>
</head>
<body>
<img src="Circle2.png" onMouseover="alert('Button2')"/>
<img src="Circle4.png" onMouseover="alert('Button4')"/>
<img src="Circle3.png" onMouseover="alert('Button3')"/>
<img src="Circle1.png" onMouseover="alert('Button1')"/>
</body>
</html>
This would be hard with pure images as it's difficult to tell when the mouse is actually over the circle part of the image. I would suggest a client side image map as they let you define clickable areas in non-rectangular shapes. Set the href to something like "javascript:circleClicked(); void 0;" :D
There's no way to tell that the mouse is over a transparent pixel of your circle: you must check if the mouse intersects with the actual circle (yeah, really). Actually, that's easier than it might seem. Considering your circle's diameter is your image's width (which appears quite possible to me), you just have to check that the mouse cursor is within the radius of the circle (which would be width / 2):
function intersectsCircle(diameter, center, mousePosition)
{
var radius = diameter / 2;
// compute the distance between mousePosition and center
var deltaX = mousePosition.x - center.x;
var deltaY = mousePosition.y - center.y;
return Math.sqrt(deltaX * deltaX + deltaY * deltaY) < radius;
}
And the you just have to pass the required informations (my Javascript's rusty so what follows might not be exactly accurate, especially double-check the events part):
function intersects(target, event)
{
var center = {x: target.x + target.width / 2, y: target.y + target.height / 2};
var mousePosition = {x: event.clientX, y: event.clientY};
if(intersectsCircle(target.width, center, mousePosition))
alert('Foo');
}
<img onmouseover="intersects(this, event)" src="circle.png" />

How do I dynamically position a swf in flex relative to its parent container?

How do I position a child relative to its containing box?
The Code:
<mx:Script>
<![CDATA[
thisMap.scaleX = scaleFactor;
thisMap.scaleY = scaleFactor;
thisMap.x = thisMap.x - thisMap.mouseX * 1.3;
thisMap.y = thisMap.y - thisMap.mouseY * 1.3;
]]>
</mx:Script>
<mx:Box id="mapHolder" x="0" y="30">
<mx:SWFLoader id="thisMap" source="MyWorld1.swf" />
</mx:Box>
To access thisMap it is not necessary to go through mapHolder.
A box is a container that manages positioning for you in a horizontal or vertical stack (see VBox or HBox). It looks like you are trying to position thisMap as if it was in a canvas. Try
<mx:Script>
<![CDATA[
thisMap.scaleX = scaleFactor;
thisMap.scaleY = scaleFactor;
thisMap.x = thisMap.x - thisMap.mouseX * 1.3;
thisMap.y = thisMap.y - thisMap.mouseY * 1.3;
]]>
</mx:Script>
<mx:Canvas id="mapHolder" x="0" y="30">
<mx:SWFLoader id="thisMap" source="MyWorld1.swf" />
</mx:Canvas>
Also i'm not sure how this will look by positioning it relative to the mouse coordinates... it looks like you are trying to achieve some sort of drag functionality. However the canvas should solve the original problem.
I am creating a zoom functionality. When the user clicks thisMap, it zooms into the point that was clicked. I scale this map and adjust for the scaling and centering by offsetting its x, y position. This works fine in the main app, but I can't figure out how to put the swf in some kind of container.