How to add width property to the canvas in flex 3 - actionscript-3

I need to add the width property to the canvas .By traceing the value iam geting its value as zero though it contain images and has a width.
//code of adding 5 canvases to the main canvas
public function addcanvas(canarr:Array):void
{
var can_arr:Array=new Array();
can_arr=canarr;
for(var c:int=0;c<can_arr.length;c++)
{
canvasA=new Canvas();
canvasA.id="canvasA";
trace("ccc:"+c);
canvasA.x=(c*10)+10;
canvasA.y=0;2
this.addChild(canvasA);
}
trace("canvasA.width: "+canvasA.width);
}
and next i will add images into each canvas
//enter code here
public function ClubCards(imgarr:Array):void
{
var Gimg_arr:Array = new Array();
Gimg_arr =imgarr;
for(var j:int=0;j < Gimg_arr.length;j++)
{
myimage1 = new Image();
myimage1.x=0+(j*20);
myimage1.y=40;
myimage1.source=gameModule.getStyle(Gimg_arr[j].toString());
GroupingImageListeners(myimage1);
canvasA.addChild(myimage1);
trace("canvasA.width: "+canvasA.width );
}
iam unable to know the width of the canvas which has images in it . can u please help me out.how can i get that canvas width
Thank you in advance

I can't add a comment, so I will add an answer saying this code should be triggered by a call to the updateDisplayList method (during the appropriate phase of the flex component life-cycle). I would suggest reading and understanding this update cycle before doing any further Flex development (it will save you a lot of time in the long-run).
More info can be found here: http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_2.html
UPDATE
Since you mentioned Canvas, I updated the link to point to the 3.x version of the article

You did not make your canvas invalidate its size. Without an order to redraw, I don't think you'll get the correct size. Without Event.RENDER dispatched your component will not calculate its size.
Maybe you should try:
canvas.invalidateSize();
before accessing its width and see the result. This should make your canvas call its method measure() and calculate its size.

Related

How to reset canvas context state entirely

I have a simple canvas animation, as follows:
function animate(){
var canvas = document.getElementById("canvas");
canvas.width = $(window).width();
canvas.addEventListener("click", replay, false);
var context = canvas.getContext("2d");
//animation code
function replay(e){
animate();
}
}
So my expectation is when the user clicks the canvas the animation will replay because I am reassigning the width:
canvas.width = $(window).width();
which will reset the entire context state ( read it here http://diveintohtml5.info/canvas.html)
It works the first time you click the canvas but after that it remembers the context transformation state and shows some weird animation.
I tried adding this:
context.setTransform( 1, 0, 0, 1, 0, 0 );
to explicitly reset the transformation matrix to identity matrix before re-drawing but has no effect.
It is different from this How to clear the canvas for redrawing
because it is about how to clear the display of context but I want to clear everything the display plus the context state.
I tried logging the state of each variable during the animation I get something weird with the ff code.
function moveHorizontal(x){
if(x < 100 ){
context.translate(1, 0);
console.log("x:"+x);
drawImage();
x += 1;
setTimeout(moveHorizontal,10,x);
}
}
I am calling this function initially as moveHorizontal(0).
so the log is as expected the first time:
x:0
x:1
x:2
.
.
x:99
when I click "replay" I get same thing as above:
x:0
x:1
x:2
.
.
x:99
which is correct but when I click "replay" the second time
I am getting this:
x:0
x:0
x:1
x:1
.
.
.
x:99
x:99
which triples the translation leading to unexpected effect.
any explanation?
Update
With the new information this may be the cause of the problem (there is not enough code to be 100% sure but it should give a good pointer as to where the problem is):
As the code is asynchronous and seem to share a global/parent variable x, what happens is that when, at some point, the replay is invoked before one earlier has stopped, the x is reset to 0 causing both (or n number of loops) to continue.
To prevent this you either need to isolate the x variable for each run, or using a simpler approach blocking the loop from running if it's already running using x from a previous invocation. You can use a flag to do this:
var x = 0,
isBusy = false;
function animation(x) {
if (isBusy) return;
if (x < 100) {
isBusy = true;
// ...
setTimeout(...); // etc.
}
else {
isBusy = false;
}
}
optionally, store the timeout ID from setTimeout (reqID = setTimeout(...)) and use clearTimeout(reqID) when you invoke a new loop.
Old answer
The only way to reset the context state entirely is to:
Set a new dimension
Replace it with a new canvas (which technically isn't resetting)
The latter should be unnecessary though.
According to the standard:
When the user agent is to set bitmap dimensions to width and height,
it must run the following steps:
Reset the rendering context to its default state.
...
In the example code in your post you are using a mix of jQuery and vanilla JavaScript. When working with canvas (or video element) I always recommend using vanilla JavaScript only.
Since you are not showing more of the code it is not possible for us to pinpoint to any specific error. But as neither setting an identity matrix nor setting a size for canvas seem to work, it indicates that the problem is in a different part of the code. Perhaps you have persistent offsets involved for your objects that are not reset.
Try to eliminate any possible errors coming from using jQuery to set width as well:
canvas.width = window.innerWidth; // and the same for height
Two other things I notice is that you set the size of canvas inside a function that appears to be part of a loop - if this is the case it should be avoided. The browser will have to, in essence, build a new canvas every time this happens. Second, this line:
canvas.addEventListener("click", replay, false);
can simply be replaced with (based on the code as shown):
canvas.addEventListener("click", animate, false);
You will need to post more code to get a deeper going answer though. But as a conclusion in regards to context: setting a new size will reset it. The problem is likely somewhere else in the code.

Optimize ItemRenderer For Flex Mobile Application

I made this class, which is an ItemRenderer class, used in a DataGroup ( mobile application ),
and I am not entirely sure if I did the right thing or not, my issues are :
Is there a better way to show the image, which is 80x80 and directly loaded from the server;
How to make the height of the row dynamic, I mean, depending on the height of the 3 StyleableTextFeild
Is this the right way to add the listener on the image, that will trigger a simple HTTPService,
Here is the functions from the class, Any help would be much appreciated !!
Image
Declared it as a simple image :
var logo:Image;
On override createChildren
logo = new Image();
addChild(logo);
And I added on set Data
logo.source = "http://192.168.0.15:3000/"+value.logo_thumb_url;
Size
override protected function measure():void {
measuredWidth = measuredMinWidth = stage.fullScreenWidth;
measuredHeight = measuredMinHeight = 100;
}
Listener
override public function set data(value:Object):void {
tel.text = String(value.Tel);
description.text = String(value.Descricao);
nome.text = String(value.Nome);
logo.addEventListener(MouseEvent.CLICK, function():void{
var service:HTTPService = new HTTPService();
service.url = value.targer;
service.method = "GET";
// setting headers and other variables ...
service.send();
});
}
You can use URLLoader or Loader for loading the image if you are planning to cache the image on the client side, if you cache the image, it wil help you not load the image again when the users scrolls through the list. (What you have done is Ok, but you will hit performance issues)
For variable row height, if Datagroup does not work, use List. find it here Flex 4: Setting Spark List height to its content height
There should be a buttonMode property for some items, make it buttonMode for the logo, for variable row height, find something related to wordWrap and variableRowHeight properties on the datagroup.
There are a few suggestions, what you have coded is good, but, instead of adding the listeners on set data, add it in creation complete, as it is more appropriate. Also, the event listeners has to be weak referenced, http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html#addEventListener()

Save un-scaled canvas with image background after changes were applied

I've got a big issue and it's almost a week trying to make it work so any help I would really appreciate - I am trying to create a simple image editor in html5, so I upload an image, load it into canvas and then paint on it -
I also want to be able to zoom in and zoom out- just that I can't figure out how should I save the canvas state - for the paint mouseevents I am using an array which saves canvas.toDataUrl, but this one will save only what it is visible in canvas, only a part of the scaled image, and not the entire one -
if anyone knows how can I un-scale the canvas together with the painting over it and save it in the stack from where I can retrieve it for other painting events, I'll appreciate a lot! Thanks
Saving state
The canvas' save() and restore() is not related to the pixels in the canvas at all. Save() only saves current pen color, fill color, transform, scale, rotation and so forth - parameter values only, not actual pixel data.
And so, the restore() will only restore these parameter values to the previous ones.
The canvas element is passive, meaning it only holds the pixels that you see on the screen. It does not keep a backup of anything so if you change its size, re-size browser window or open dialogs in the browser causing it to clear, you will need to update the canvas yourself.
This also applies when you change a parameter value such as scale. Nothing on the canvas will change setting a new value. The only thing that happens is that your next draw of what-ever will use these parameter values for the drawing (in other words: if you apply rotation nothing rotates, but the next thing you draw will be rotated).
Drawing on existing image
As you need to maintain the content it also means you need to store the image you draw on as well as what you draw.
When you draw for example lines you need to record every stroke to arrays. When the canvas needs an update (ie. zoom) you redraw the original image first at the new scale, then iterate through the arrays with lines and re-render them too.
Same for points, rectangles, circles and what have you..
Think of canvas as just a snapshot of what you have stored elsewhere (image object, arrays, objects) . Canvas is just a view-port for that data.
I would recommend to store as this:
var backgroundImage; //reference to your uploaded image
var renderStack = []; //stores all drawing objects (see below)
//example generic object to hold strokes, shapes etc.
function renderObject() {
this.type = 'stroke'; //or rectangle, or circle, or dot, ...
this.x1;
this.y1;
this.x2;
this.y2;
this.radius;
this.penWidth;
this.penColor;
this.fillColor;
this.points = [];
//... extend as you need or use separate object for each type
}
When you then draw a stroke (pseudo):
var currentRenderObject;
function mouseDown(e) {
//get a new render object for new shape/line etc.
currentRenderObject = new renderObject();
//get type from your selected tool
currentRenderObject.type = 'stroke'; //for example
//do the normal draw operations, mouse position etc.
x =..., y = ...
}
function mouseMove(e) {
//get mouse positions, draw as normal
x = ..., y = ...
//store the points to the array, here:
//we have a line or stroke, so we push the
//values to ourpoint-array in the renderObject
currentRenderObject.points.push(x);
currentRenderObject.points.push(y);
}
function mouseUp(e) {
//when paint is done, push the current renderObject
//to our render stack
renderStack.push(currentRenderObject);
}
Now you can make a redraw function:
function redraw() {
clearCanvas();
drawBackgroundImage();
for(var i = 0, ro; ro = renderStack[i]; i++) {
switch(ro.type) {
case 'stroke':
//... parse through point list
break;
case 'rectangle':
//... draw rectangle
break;
...
}
}
}
function zoom(factor) {
//set new zoom, position (scale/translate if you don't
//want to do it manually). Remember that mouse coords need
//to be recalculated as well to match the zoom factor.
redraw();
}
//when canvas is scaled for some reason, or the window
canvas.onresize = windows.onresize = redraw;
A bonus doing this here is you can use your render stack as a undo/redo stack as well...
Hope this helped to better understand how canvas works.

HTML5 webpage animation

Does anybody know how to achieve something like that?
http://teamviget.com/#!lift-off
I want to do something similar but I'm something new in html5 and all this stuff
Thanks!
Of course you can do. First of all the you gotta draw the background image. And provide two buttons on either side. Onclick of these buttons you call a function... which inturn calls an setInterval() function that animates(here in your case the image has to fade and a new image has to be formed) . For providing fading effect we have a popular parameter. ctx.globalAlpha(). In each animation step change the value of it. Lemme provide a sample code so that you can understand it properly.
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var ms = new Image();
ms.src = "images/asdf.jpg"
ctx.drawImage(ms,0,0); // Will draw the initial image (assume)
ctx1 = canvas.getContext("2d");
Now let me define the onclick function.
onclick="caller()";
The caller function should be made to call the animate function
function caller()
{
i=1;
inter=setInterval(animate(),500); // Calls the animate function every 500 msec
}
And the animate function would look as shown below
function animate()
{
i=i-0.1;
ctx1.globalAlpha=i;
if(i=0)
{
clearInterval(inter);
ctx1.drawImage(ms2,0,0); // This will draw the next image defined in ms2.
}
}
So the image will be faded out and a new image appears in 5 secs. Use an array if you have several images and definitely javascipts would help you to implement them all the way you want. Let me know if you need any more clarifications to a SPECIFIC problem that you are facing.

Is graphic object bitMapData type the same as bitmapData type?

The title might be a little misleading. Look at my code and I will explain
public static function loadTile(tileDir:String = "empty"):void
{
if(tileDir != "empty")
{
tPoint = new Point(0,0);
tRect = new Rectangle(0,0,30,30);
//load in tile sheet image
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT,tilesLoadInit);
loader.load(new URLRequest(tileDir));
}
}
private static function tilesLoadInit (e:Event):void {
tileImage = Bitmap(loader.content).bitmapData;
tileReady.dispatchEvent(new Event("TileReady"));
}
var tImage:BitmapData = new BitmapData(30,30);
tileNum = tileNumber;
tPoint.x = 0;
tPoint.y = 0;
tRect.x = 0;
tRect.y = 0;
tImage.copyPixels(tileImage,tRect,tPoint);
this.graphics.beginBitmapFill(tImage);
this.graphics.drawRect(0, 0,tWidth ,tHeight );
I create a empty bitMapData called tImage. I then take a predefined variable called tileImage which is a bitMapData as well and contains a picture of an image. tRect is predefined as well its width and height is 30x30. I copy a piece of the image and I put it in tImage. problem is that AS3 throws an error saying that tImage is a incorrect type
ArgumentError: Error #2015: Invalid BitmapData.
But clearly it isnt. my question is that is there something different about the data type of bitMapData and bitMapData type that the graphic object accepts ?
I am trying to do tiling with sprites. I want my tiles to be interactive, so that is why I am using the sprite object instead of using regular bitMaps to represent my tiles. You might be wondering why I wouldnt just use graphics.beginBitmapFill(tImage); and graphics.drawRect(0, 0,tWidth ,tHeight ); to pick out the tiles I want to use. Well reason being is because it turns out that drawRect() first and second parameters actually alter the location of where the actual sprite sits at.
So if I set the x and y properties of the sprite to x = 20, and y = 20. then I set my drawRect(20,20). it actually adds an extra 20 pixels to my x and y coords of my sprite. And I know the reason why, I just need to know a better way. Sorry for so much writing and thanks for your time!
It's not saying the type is wrong, it's saying the object is invalid. I expect you'd get a TypeError if the type was wrong.
You've also not stated where exactly the error is thrown, and are assuming the problem is with tImage on the 8th line. It looks more likely that the problem is with tileImage (which you've given no details about) on line 7.
This is probably because of Flash's inbuilt limit to the size of BitmapData objects. If the total number of pixels is larger than 16,777,215, Error #2015 is thrown.
You can read up on it in the docs: BitmapData, Right above "View the examples".
Here's a trick that used to work if you want to give it a shot: BitmapData workaround