flex: Drag and drop- object centering - apache-flex

In a drag+drop situation using Flex, I am trying to get the object center aligned to the point of drop- somehow, irrespective of the adjustments to height and width, it is always positioning drop point to left top.
here is the code..
imageX = SkinnableContainer(event.currentTarget).mouseX;
imageY = SkinnableContainer(event.currentTarget).mouseY;
// Error checks if imageX/imageY dont satisfy certain conditions- move to a default position
// img.width and img.height are both defined and traced to be 10- idea to center image to drop point
Image(event.dragInitiator).x = imageX-(img.width)/2;
Image(event.dragInitiator).y = imageY-(img.height)/2
The last 2 lines don't seem to have any effect. Any ideas why-must be something straightforward, that I am missing...

You can use the following snippet:
private function on_drag_start(event:MouseEvent):void
{
var drag_source:DragSource = new DragSource();
var drag_initiator:UIComponent = event.currentTarget as UIComponent;
var thumbnail:Image = new Image();
// Thumbnail initialization code goes here
var offset:Point = this.localToGlobal(new Point(0, 0));
offset.x -= event.stageX;
offset.y -= event.stageY;
DragManager.doDrag(drag_initiator, drag_source, event, thumbnail, offset.x + thumbnail.width / 2, offset.y + thumbnail.height / 2, 1.0);
}
Here is one important detail. The snippet uses stage coordinate system.
If you use event.localX and event.localY, this approach will fail in some cases. For example, you click-and-drag a movie clip. If you use localX and localY instead of stage coordinates, localX and localY will define coordinates in currently clicked part of the movie clip, not in the whole movie clip.

Use the xOffset and yOffset properties in the doDrag method of DragManager.
Look here for an example.

Related

How to place a Plane geometry button on top of a row of cubes without displacing the button along z axis?

I have a grid of cubes and I need to show a button while hovering over a row. I have created the button with a plane geometry but while setting is position.y such that it stands right on top of the row, it displaces along the z axis and appears against another row at the back giving the wrong appearance. Please see the code below for the button and also a screenshot of the issue. The white button should appear right on top of the orange row.
I have tried to do what this post talks about. But inspite of all that, I am unable to fix it. Not sure why making the object high enough should affect the depth. I have not added any translation or rotation to it. Please help.
function createButtonForEachRow(numCols, width, offsetX, rowIndex, cubeSize , cubePadding)
{
var geometry = new THREE.PlaneGeometry( width, 1);
var material = new THREE.MeshBasicMaterial( {map: buttonTexture, side:THREE.DoubleSide } );
material.map.minFilter = THREE.LinearFilter;
var plane = new THREE.Mesh(geometry, material);
var referenceZPos = 1- (rowIndex * (cubeSize + cubePadding));
plane.position.x = offsetX + cubeSize + cubePadding * numCols + 3 ;
plane.position.y = cubeSize*3;
plane.position.z = referenceZPos;
// plane.rotation.x = 3 * Math.PI/2;
plane.visible = false;
return plane;
}
Screenshot
Creating 2 scenes and adding the button on the second scene worked. The link mentioned in the question actually worked. I had forgotten to set autoclear to false.

Twitter bootstrap carousel with pictures that are not uniform

Let me start with i am sorry for the long post.
I'm attempting to use the bootstrap carousel and unfortunately the pictures i have been given are NOT uniform. for example some are 100x200, doe are 150x100, etc. The aspect ratios are different, letter vs landscape. Ive attempted a number of things, including the using the following helper function on load of each of my images in the Carousel:
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
result.targetleft = Math.floor((targetwidth - result.width) / 2);
result.targettop = Math.floor((targetheight - result.height) / 2);
return result;
}
function OnImageLoad(evt) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).prop('naturalWidth');
var h = $(img).prop('naturalHeight');
//var tw = $(img).parent().width();
//var th = $(img).parent().height();
var tw = $(img).parent().parent().parent().parent().width();
var th = $(img).parent().parent().parent().parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, true);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
and using the following for each of my images for the carousel
<img src="~/Images/Img1_Tall.jpg" alt="Tall" id="firstImage" onload="OnImageLoad(event);" />
and for the FIRST image in the carousel it works great, but each one after that they seem to just end up their natural size and are horizontally centered but are just against the top boarder of the carousel.
I've even changed the "onload" to pass the values of the length and width of the image but that didn't work either, in debug it seems only the first image kicks off the "onload" event.
the effect i am going for is if the ratio of the container is 3:4 and the ratio of the image is 1:2, the image stretch to meet the left and right edges and would center vertically and have letter box above and below, but the container does not change so that the navigation buttons of the carousel do not move. if the image is 2:1, the image would stretch to meet the top and bottom centered horizontally with letterboxes on the right and left, again keeping the navigation buttons unmoved.
any help would be appreciated... including:
what you are trying to do is crazy
do you want to do something like http://jsbin.com/zotelasa/1 . With that code I can get the active items w,h or any other variables you used in your code to run scale image. Because of parent.parent codes it applies to carousels main divs but you can set your own container.
The quick and dirty solution would be to resize the images using an image editor, and save the properly-sized images to a folder named eg carousel_images. Then whenever you get new content you simply run the image through your editor. With a carousel you're most likely dealing with a number of images in the several to dozens range and not hundreds or thousands.
A more complicated solution is explain to your image provider that you need everything one size. The images aren't going to look right if you're stretching and skewing them on the fly, and you can show them an image with the aspect ratios wrong to explain what you mean.
Finally, as a technical solution, I would try to find out why your image resizer is only being run on the first image. From the sound of it, other images just aren't being run through your function. I think that the technical solution should be a last resort in this case because, like I said, the end results are just not going to be as good. You should at a minimum, if possible, handle each image by hand to make sure the result is adequate.
...And the answer is a little long too...
• I assume that the width’s image’s parent is a constant, and while you don’t change the width’s viewport that must remain.
A-. Get the width’s image’s parent…
(Because the id attribute I took the grand parent’s parameter, that is (must be) the same than the parent’s one).
B-. With the below value deduce the height’s image’s parent, including the preferred ratio (in this case 16x9…
C-. … And with this, set the images’ parents height collection (all the elements with class=”item”).
D-. In order to conserve your carousel’s responsive characteristic, you must add the $F_getAdjustImagesParents function to the window resize event.
E-. Set the slide’s images position to absolute (Note: That must be via JQuery because if you do it in Css the bootstrap carousel will not display correctly. I did it with a new class for the images ('myCarouselImgs').
• Bootstrap carousel’s event 'slide.bs.carousel' and 'slid.bs.carousel'.
As you know, after the ‘click’ event, the slide.bs.carousel event is one of the firsts events that imply the change from the present slide to the next one; while the 'slid.bs.carousel' one is the end of the process.
F-. In the first one (slide.bs.carousel event), using the ‘relatedTarget’ variable of the Bootstrap’s plugin, the item’s id attribute and a item’s data attribute, get the number of the next item (ensure that these last ones -id attribute and data attribute- be present).
G-. In the second one, 'slid.bs.carousel', get the image’s size. For that you need to identify the implied image. I gave an id to each one. With this and the value obtained in previus step, it can do it.
H-. Well, now you already have the four values required for the ScaleImage function. You can call it…
I-. … And apply the result with some effect
var $parentImgW = ' '
var $parentImgH = ' ';
var $myCarousel = $('#myCarousel')
var $carouseItems = $('.item');
function $F_getAdjustImagesParents(){
$parentImgW = $myCarousel.width(); // A
$parentImgH = ($parentImgW*9)/16; // B
$carouseItems.height($parentImgH+'px').css('max-height',$parentImgH+'px'); //C
console.log('$parentImgW ====> '+$parentImgW);
console.log('$parentImgH ====> '+$parentImgH)
};
$F_getAdjustImagesParents();
$(window).on('resize',function(){ // D
$F_getAdjustImagesParents();
});
$('.myCarouselImgs').css('position','absolute'); // E
$myCarousel.on('slide.bs.carousel', function(event) {// The slide’s change process starts
var $slideNum = $("#"+event.relatedTarget.id).data('slide_num'); // F
console.log('$lideNum ====> '+$slideNum)
$myCarousel.on('slid.bs.carousel', function(event) {//The slide’s change process ends
var $imgW = $('#myCarouselSlideImage'+$slideNum).width(); //G
var $imgH = $('#myCarouselSlideImage'+$slideNum).height(); //G
console.log('$imgW ====> '+$imgW);
console.log('$imgH ====> '+$imgH);
var $result = '';
$result = ScaleImage($imgW, $imgH, $parentImgW, $parentImgH, true); //H
console.log('$result.width ====> '+$result.width);
console.log('$result.height ====> '+$result.height);
console.log('$result.targetleft ====> '+$result.targetleft);
console.log('$result.targettop ====> '+$result.targettop);
$('#myCarouselSlideImage'+$slideNum).animate({ // I
width:$result.width+'px',
height:$result.height+'px',
left:$result.targetleft+'px',
top:$result.targettop+'px' },
300);
});
});
See it runnig at https://jsfiddle.net/nd90r1ht/57/ or at https://jsfiddle.net/omarlin25/nd90r1ht/59/

Rotate background-image in a rotated div?

I have a div shape with before: and after: so it looks like a cross shape (Rotated).
But now my problem is, that the background is logically also rotated. I'd like that the background image isn't rotated and the image should be the size of the div.
I already tried to add a transform rotate to the place where I added the background but it didnt rotate back. Also for the size I tried background-size to adjust it, didnt work either.
Here is my jsbin: http://jsbin.com/iYogaCE/29/edit
thanks in advance!
nick
Well, I tried for a while to get a version working with pure CSS and HTML, but I was unable to do so. I believe that double pseudo selectors, aka ::after and ::before, would allow it to be possible, but I don't think that you can do it in pure CSS in one object currently.
With that being said, the way I accomplished it using one element is the much more common way - by using a canvas. With canvas it becomes pretty simple. Hopefully the comments make it easy to understand
Live demo here
// Gets a list of all the canvases to create an X for
var canvases = document.getElementsByClassName('profile');
// Allows the X to be drawn on multiple canvases without being redrawn
var tempCanvas = drawX();
// Gives the canvases a background image (the person's profile)
// If you wanted different images for each you could easily create an array
// and iterate through it for each canvas
var background = new Image();
background.src = "http://asta-design.ch/gameotion/wp-content/uploads/2013/03/placeholder.jpg";
// Once the image has loaded, apply the Xs
background.onload = function() {
// Do it for each canvas
for(var i = 0, j = canvases.length; i < j; i ++)
{
// Gets the current canvas and context
var canvas = canvases[i];
var context = canvas.getContext('2d');
// Allows the portrait only to be shown through the generated X
context.globalCompositeOperation = "destination-atop";
// Draws the profile picture
context.drawImage(background, 0,0, canvas.width, canvas.height)
// Cuts out everything that is not within the X
context.drawImage(tempCanvas, 0, 0);
}
}
// Creates the X to use as the cut out
function drawX() {
// Creates a hidden canvas to draw the X on
var offscreenCanvas = document.createElement('canvas');
var offscreenCtx = offscreenCanvas.getContext('2d');
// The width/height of the original canvas, not sure why "canvas.width" doesn't work here...
var size = 200;
offscreenCanvas.width = size;
offscreenCanvas.height = size;
// Creates the rectangles sloped positively
offscreenCtx.save();
offscreenCtx.translate(3 * size / 4, 3 * size / 4);
offscreenCtx.rotate(Math.PI/4);
offscreenCtx.fillRect(-size/2, -size/2, size * .3, size);
// Loads the state before the first rectangle was created
offscreenCtx.restore();
// Creates the rectangles sloped positively
offscreenCtx.translate(3 * size / 4, 1 * size / 4);
offscreenCtx.rotate(-Math.PI/4);
offscreenCtx.fillRect(-size/2, -size/2, size * .3, size);
// Returns the canvas with the X
return offscreenCanvas;
}
You can't rotate a CSS background independently of the element it is attached to.
The only way you're going to be able to do this is to have the rotated content in an additional element inside your existing one, and only rotate the inner element.
eg:
<div> <-- background applied to this element
<div>....</div> <-- but this one is rotated
</div>
Now your background will remain static while the content inside it rotates.
If you can't have any extra markup, you could still achieve this without changing the HTML, by using CSS the :before selector to create an additional pseudo-element behind the main element. Apply the background to that instead of the main element; after that it's similar to what I described above with the extra markup.
Hope that helps.

HTML5 Canvas with Predefined Image

Recently I started working on HTML5 Canvas, I'm new to it.
I've a problem as follows:
I'm loading a Canvas with Body Chart Image (Predefined Image) and on that User will Draw some lines, shapes, etc.
After that I'll generate an image object as follows
var canvas = document.getElementById("MyCanvas");
var dataURL = canvas.toDataURL();
var image = new Image();
image.src = dataURL;
But, Here it generates only those elements which are drawn by users (lines, shapes) as PNG Image. It won't take that Predefined canvas background Image.
I need to generate a PNG image which should include both the Canvas background Image as well as User entered drawing elements.
How to do this?
Try to actually draw you image onto your canvas, utilizing these functions:
var canvas = document.getElementById("MyCanvas");
var img = new Image();
img.src = 'pathToYourImageHere';
canvas.drawImage(img,0,0); /* 0,0 is x and y from the top left */
When you now try to save it, it should also save your background image.
EDIT:
In response to your comment:
You can circument your layering problem by using two different canvases. One for the image, and one for your drawing. Then layer them on top of each other using absolute positioning.
You can read more here: Save many canvas element as image
EDIT2:
But actually you shouldn't have a layering problem, since the following code will first draw the image and then draw the arc, and the layering will be fine:
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = "somePathToAnImage";
context.drawImage(imageObj, 50, 50);
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var startAngle = 1.1 * Math.PI;
var endAngle = 1.9 * Math.PI;
var counterClockwise = false;
context.beginPath();
context.arc(x, y, radius, startAngle, endAngle, counterClockwise);
context.lineWidth = 15;
// line color
context.strokeStyle = "red";
context.stroke();
Even though the layering is fine, you will be better of by using two canvases, in case you would like to only save the drawing, without the background. You can always save both into a new canvas and save that, when you only use one canvas you'll have a hard time separating the drawing from the background.
This is because the image needs time to load, you have to use the onload function.
imgObj.onload = function() { context.drawImage(imageObj, 50, 50); imgLoaded = true;}
if (imgLoaded) { /*you draw shapes here */ }

A VBox with only one rounded corner and gradient background

I'm working with Flex 3.4 SDK.
I'm trying to programmatically(yep, must be this way) style/skin a VBox so that its top right corner is rounded, and it gets a two colors gradient brackground.
Modifying examples I found around I was able to accomplish both effects(corner and background) but only separately:
VBox with not all rounded corners: http://livedocs.adobe.com/flex/3/html/help.html?content=skinning_6.html
VBox with gradient background: http://butterfliesandbugs.wordpress.com/2007/06/08/generic-background-gradient-for-containers/
But what I need to do is to apply both at the same time. And all my coding attempts so far have failed silently.
Would anyone know how to go about doing this correctly?
I have a post on my blog on how to make this exact component Here.
You create a basic custom MXML component (extending in this case, VBox). You specify a programmatic skin, which is where the bevel and gradient gets applied.
The programmatic skin does all it's drawing in the updateDisplayList function.
Here is some of the code (the rest is on my blog, with a demo)
var g:Graphics = graphics;
var cn:Number = this.getStyle("cornerRadius");
var crtl:Number = this.getStyle("cornerRadiusTopLeft") > 0 ? this.getStyle("cornerRadiusTopLeft") : cn;
var crtr:Number = this.getStyle("cornerRadiusTopRight") > 0 ? this.getStyle("cornerRadiusTopRight") : cn;
var crbl:Number = this.getStyle("cornerRadiusBottomLeft") > 0 ? this.getStyle("cornerRadiusBottomLeft") : cn;
var crbr:Number = this.getStyle("cornerRadiusBottomRight") > 0 ? this.getStyle("cornerRadiusBottomRight") : cn;
var gradFrom:Number = this.getStyle("gradientFrom");
var gradTo:Number = this.getStyle("gradientTo");
var b:EdgeMetrics = borderMetrics;
var w:Number = unscaledWidth - b.left - b.right;
var h:Number = unscaledHeight - b.top - b.bottom;
var m:Matrix = verticalGradientMatrix(0, 0, w, h);
g.clear();
g.beginGradientFill("linear", [gradFrom, gradTo], [1, 1], [0, 255], m);
g.lineStyle(1,borderColor,1,true,LineScaleMode.NORMAL,CapsStyle.ROUND,JointStyle.ROUND);
GraphicsUtil.drawRoundRectComplex(g, b.left, b.top, w, h, crtl, crtr, crbl, crbr);
g.endFill();
}
for a demo, look Here. Hope this helps.
Follow the steps from your second link, but instead of using "drawRect", you should be able to use "drawRoundRectComplex". You may need to play around with some of the matrix settings though. I seem to remember having some problems.
Another option is to use degrafa. There can be a bit of a learning curve, but it's powerful and can do this.

Resources