AS3 Drag and drop items on webcam - actionscript-3

I'm making a little thing in AS3, a "wanted" poster generator. I load the webcam inside my poster ("container") and put an attributesContainer next to it. There I have a hat, a mustache, ... people can drag and drop on the webcam instance. No problem here, but now I want to send it to Facebook. I know how that works, but I'm having some difficulties with keeping the position of the hat/mustache/... where the user wanted it.
For example: I drag the hat onto my head (middle of the poster), I hit the "take picture" button to draw Bitmapdata, and my hat is at coordinates 0,0 again. I believe I have to work with a Matrix, but I tried everything now and it just doesn't show up or stays at 0,0.
Any help? Here's some of my code.
private function sendHandler(e:MouseEvent):void {
var bmd:BitmapData;
var bmp:Bitmap;
// "container" contains poster+webcam img
bmd = new BitmapData(container.width, container.height, true);
bmd.draw(container);
//var hatMatrix:Matrix = new Matrix(1, 0, 0, 1, hat.x, hat.y);
bmd.draw(hat);
bmp = new Bitmap(bmd, "auto", true);
sendToFacebook();
}

You can make your life a little easier by structuring it different.
Have a top level container.
Add to that your webcam display
Also add to that your dropped items
Then you can just take a bitmap of the top level container instead of each piece and compositing them together.

Related

Building an web based image annotation tool - saving annotations to localStorage

I am building a web application for annotating images. The work flow is as follows:
Select a project - using : action = list all sub-projects
Click on a sub-project : action = fetch all the images within-sub project
Display the images as a horizontal scrollable thumbnail gallery
Onclick image thumbnail from the gallery, display the larger image for annotation.
I am using canvas to display larger image. I have used another canvas as a layer to the first one, and I am able to draw rectangles using mouse over regions of interest. I am saving it locally. However, when I move on to the next image, the rectangle also gets carried to the next image.
My question is, instead of using just one layer, do I have to dynamically create as many canvas layers as I have in the annotation dataset. I am not sure because in each sub project I have around 8000-9000 images. Though I wont be annotating on all of them, still creating as many canvases as layers doesn't really sound good for me.
The following is the code:
HTML Canvas
<div class="body"> <!-- Canvas to display images begins -->
<canvas id="iriscanvas" width=700px height=700px style="position:absolute;margin:50px 0 0 0;z-index:1"></canvas>
<canvas id="regncanvas" onclick="draw(this, event)" width=700px height=700px style="position:absolute;margin:50px 0 0 0;z-index:2"></canvas>
</div> <!-- Canvas to display images ends -->
Step 4 given above: OnClick display thumbnail
function clickedImage(clicked_id) {
var clickedImg = document.getElementById(clicked_id).src;
var clickedImg = clickedImg.replace(/^.*[\\\/]/, '');
localStorage.setItem("clickedImg", clickedImg);
var canvas = document.getElementById("iriscanvas");
var ctx = canvas.getContext("2d");
var thumbNails = document.getElementById("loaded_img_panel");
var pic = new Image();
pic.onload = function() {
ctx.drawImage(pic, 0,0)
}
thumbNails.addEventListener('click', function(event) {
pic.src = event.target.src;
});
}
Draw rectangles on second layer of canvas
window.onload=function(){
c=document.getElementById("regncanvas");
if (c) initCanvas(c);
};
function initCanvas(canvas){
// Load last canvas
loadLastCanvas(canvas);
}
function draw(canvas, event){
// Draw at random place
ctx=c.getContext("2d");
ctx.fillStyle="#ff0000";
ctx.beginPath();
ctx.fillRect (250*Math.random()+1, 220*Math.random()+1, 40, 30);
ctx.closePath();
ctx.fill();
// Save canvas
saveCanvas(canvas);
}
function saveCanvas(c){
localStorage['lastImgURI']=c.toDataURL("image/png");
}
function loadLastCanvas(c){
if (!localStorage['lastImgURI']) return;
img = new Image();
img.onload = function() {
ctx=c.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
};
img.src= localStorage['lastImgURI'];
}
Can someone guide me please?
The following is a screen grab of my application:
I have developed OCLAVI which is an image annotation tool with loads of features. It's still in beta but just after 3 weeks of release, it is gaining attraction quickly.
I have few advises for you.
HTML Canvas follow draw and forget strategy and every time redrawing the image is not a good idea. Be it 10 images or 10k, you should have one canvas for drawing the image and one canvas for drawing the shapes. Image canvas need be touched only when the image changes. Different shapes can share the same canvas.
You should integrate a data storage. Local storage is clearly not a good option to store this amount of data (especially if you have a team member who also would be annotating on the same image dataset.)
Isolate the code to a separate-separate file according to the shape. It will be very handy when you will think of adding support for Circle, Polygon, Cuboidal, Point interactions. Trust me following OOPs concepts will relive you from a lot of pain.
In terms of complexity
zooming with coordinates is easy
move with coordinates is of medium level difficulty
but you need to think with pen and paper to implement move on a zoomed image canvas (P.S. take care of the canvas flickering when the image moves
). How much the image can move in each direction also need to be calculated.
Take care of the image to canvas dimension ratio because at the end you need to have the coordinates scaled down to image level.
If your canvas size vs image size ratio is 1:1 then your job is simplified.
But this won't happen always because some images might be very small or very large to directly fit in window screen and you need to scale up and down accordingly.
The complexity increases if you like to use percentage width and height for canvas and your other team member annotating the image has a different screen size. So he drawing something will look something else on your screen.

flash actionscript 3.0 hide part of an image

I am working on a flash sound mixer application with multiple sound channels, and I am having trouble with the lights beside the volume knob.
Is there a way to hide just a part of an image?
On the image below, image-2 is on top of image-1 to create some kind of volume level indicator effect, and how much of image-2 is shown depends on the value of the volume.
image-url: http://s30.postimg.org/r3ow1g5bl/volume_lights_level.png
I've tried by just reducing the height of image-2, but it looks awful and distorted.
Is there something in flash that works closely the same as CSS's behavior.
example: I'll just make image-2 a background of a shape, and when I reduce the shape's height, the image-background does not get distorted or changes it's height as well.
By searching for solutions, I have come across the mask property, but I don't quite understand how it works, and most of the examples shown are images placed inside circles.
Is the mask property applicable in this situation?
I'm quite new to flash so I don't know a lot of things yet.
You can indeed use a mask.
How to programmatically create your mask
Put an occurrence of your image named myImage on the stage, and put over this occurrence a mask named myMask with the same dimensions. You can apply myMask mask to myImage using it's mask property like below:
Main Timeline
myImage.mask = myMask;
function mouseMoveHandler(e:MouseEvent):void {
myMask.height = myImage.y - e.stageY;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
You have just to adapt this code to your animation, in the function where you click your button.
I got it working now, many THANKS #VC.One. heres how I did it.
Imported img-2 to stage, converted it into symbol(type:Movie Clip), assigned instance name: img2_mc.
I created a new layer for the mask, drawn a rectangle using rectangle tool, converted it also to symbol(type:Movie Clip), assigned instance name: mask_mc.
Then applied the mask to img2_mc.
/* the code */
img2_mc.mask = mask_mc;
function onEnterFrame(event:Event):void{
var volumeKnob_y = volSliderKnobOn.y + 12; // adjust it to the center of the knob
mask_mc.height = volumeKnob_y;
}

How do I make a Progress bar (levelup bar) in flash cs6

I`m trying to build a simple game where you will view a map with 5 clickable objects.
When you click these objects you can navigate trough some pages and upon clicking the last button it returns to the map itself. Now everything is working as it should. Upon clicking this specific last button It has the following code.
jamenext2.addEventListener(MouseEvent.MOUSE_DOWN, gotomap2);
function gotomap2(event:MouseEvent):void {
gotoAndPlay("map2");
}
What I would like to have now is to have a bar on the Map itself, and when you have reached the button that has the above code attached, the bar increments by 20%, and so the same for the 4 other clickable buttons on the map. Upon 100% completion I would like it to play the next animation further on in the timeline.
I have tried the following, but I am not that good in writing code, and I`m not very sure where to place it exactly.
var total1 = 100;
_root.loaded1 = 0;
while(true) {
this.scaleX = _root.loaded1/total1;
}
_root.loaded1 = _root.loaded1 + 20;
gotoAndPlay("map2");
I have no idea on how to do this.
What your going to want to do is create a square or bitmap class for the progress bar. From there, create a square with a MouseEvent.MOUSE_DOWN for the buttons.
There is different ways of doing this. Judging from your sample code your using the timeline for scenes so you might want to put a button in there to scale in each scene.
You could size it at twenty percent and make it fully transparent and become viable on the first click. Then increment by twenty percent until a hundred percent visible. You could then also have another button that would roll back a page.
Mostly pseudo code but something like this:
(Example Reference link: http://www.actionscript.org/resources/articles/792/1/Drawing-Shapes-with-AS3/Page1.html )
import flash.display.Shape;
private var square:Shape;
main_method
{
square = new Shape();
//draw shape
square.graphics.beginFill(0x1111FF, 1);
square.graphics.drawRect(30, 30, 200, 200);
square.graphics.endFill();
square.alpha = .5;
addChild(square);
}
//somewhere in a MouseEvent.MOUSE_DOWN class
{
gotoAndPlay("map1");
}
}
It's also possible rather than creating a square in code to create a symbol instance name on the stage and and in the properties tab give it a name and reference it in code.

Actionscript 3: make certain objects in child A appear above child B while others appear under child B

Imagine I have a background and I want to show the background under the player object. This can be done with ease:
var player:Player = new Player();
addChild(player);
var background:Background = new Background();
addChildAt(background, 0);
However, imagine in this background I have transparent clouds which have to appear above the ship and non-transparent stars which need to appear under the ship. The above code would simply make all background objects go under the ship. Any tips?
Make a foreground layer that is rendered after the Player object. That is the easiest way to accomplish this effect.
i.e.
var foreground:* = ...;
addChildAt(foreground, 2);
I'd imagine you're going to have multiple objects that you want to appear between the foreground and background layers, so I would actually also recommend creating an "active" layer, which is the actual parent of your "player" object.
So the object hierarchy looks akin to this:
Scene
Background
Rolling hills
Active
Player Sprite
Enemies
Obstacles
Foreground
Clouds

Changing a sprites bitmap

As of right now, I am trying to create a tiling effect for a game I am creating. I am using a tilesheet and I am loading the tiles to the sprite like so...
this.graphics.beginBitmapFill(tileImage);
this.graphics.drawRect(30, 0,tWidth ,tHeight );
var tileImage is the bitMapData. 30 is the Number of pixels to move retangle. then tWidth and tHeight is how big the rectangle is. which is 30x30
This is what I do to change the bitmap when I role over the tile
this.graphics.clear();
this.graphics.beginBitmapFill(tileImage);
this.graphics.drawRect(60, 0,tWidth ,tHeight );
I clear the sprite canvas. I then rewrite to another position on tileImage.
My problem is....
It removes the old tile completely but the new tile positions farther to the right then where the old bitmap appeared.
My tile sheet is only 90px wide by 30px height. On top of that, it appears my new tile is drawn behind the old tile. Is there any better way to perfect this.
again, all i want is for the bitmap to change colors
You could try to load the whole tilesheet in your sprite, and then redefine the scrollRect property each time you need to.
this.scrollRect = new Rectangle( 30, 0, tWidth ,tHeight );
Note that you can't just edit scrollRect.x, .y, .width or .height ; you have to redefine a new Rectangle each time.
Using scrollRect will probably be much faster that redrawing part of the bitmap.
You can read this excellent article from Grant Skinner for more informations about scrollRect.