Check if CSS3 transition is running - html

Is there a way to detect in my Javascript if an element is currently being animated with a CSS3 transition?
An "transitionstart"-event (equivalent to the 'transistionend' event) would also work out, but I can't find any mention of it in the specification.

Well, since there is only a transitionend event (http://www.w3.org/TR/css3-transitions/#transition-events) something ugly comes to my mind:
http://jsfiddle.net/coma/psbBg/6/
JS
$(function() {
var div = $('div');
var property = div.css('transition-property');
var lastValue = div.css(property);
setInterval(function() {
if(lastValue !== div.css(property)) {
console.log('changed!');
}
lastValue = div.css(property);
}, 10);
});
It can be improved implementing custom events, taking care of getting the correct transition property (or properties), and more ideas, but you get the picture right?
Maybe you need to take another path on solving your original problem...

Related

Why css transition happens when CSS properties are not changed?

At first I change "left" css property, then I add transition property which looks for "left" changes and it executes animation. Could someone explain me why does it happen? I thought that it should change position of element and then looks for transition, but it doesn't.
var button = document.getElementById('slide');
button.onclick = function() {
var view = document.getElementById('view');
view.style.left = '-100px';
// Why does transition happen? O_o
view.style.transition = 'left 500ms ease-out';
}
http://jsfiddle.net/martyn0FF/20kvbvua/
Redraw and animation operations are deferred until the currently executing thread of JS finishes so that the browser can examine everything that has changed and act on those changes just once rather than trying to keep up with every change as it is made.
As such, it seems your changes to style.transition and style.left are connected and seen at the same time.
If you want to disconnect them, you can force a relayout by requesting one of several interesting properties (such as .offsetHeight) that trigger a relayout after you've set the .left property, but before you've set the .style.transition property like this:
var button = document.getElementById('slide');
button.onclick = function() {
var view = document.getElementById('view');
view.style.left = '-100px';
// trigger layout by requestion offsetHeight
var x = view.offsetHeight;
view.style.transition = 'left 500ms ease-out';
}
Notice in this jsFiddle with this code that the new left value takes place immediately and it is not animated.

How to wait a while before adding elements in css? javascript?

I have a problem that I will explain.
I'm doing an animation in HTML5 and CSS3. My idea is that a plane is flying around and it launches a missile after a while. What I want to do is to make the missile appear after that time. I thought about doing that changing the z-Index property of my div (because I have the missile image into a div container) using javascript after a while (any time I choose). For doing that I found the sleep function at the bottom. I created the "appear" function that I know it works because It changes my zIndex value but it doesn't wait the 2 seconds I want.
I also thought I had the solution by using the visibility property, but I have the same problem, sleep function doesn't wait at all.
Any suggestions? Thanks
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function appear(object){
sleep(200000);
var objective = document.getElementById(object);
objective.style.zIndex=1;
You can pass a function to the setTimeout function which will call that function in x milliseconds.
function waitForMe() {
alert('triggered!');
}
// Call waitForMe in 200000ms
setTimeout(waitForMe, 200000);
So for your example, you would want to use 2000 (2 seconds), not 200000 (200 seconds):
function appear(object) {
setTimeout(function () {
var objective = document.getElementById(object);
objective.style.zIndex=1;
}, 2000);
}
Hiding and showing an element
You can hide and show a method in a few ways:
Use z-index as you suggest, probably not the best way as we can actually hide it instead of sending it to the back of the page.
objective.style.zIndex = 1;
Use display, this hide the object completely.
// hide
objective.style.display = 'none';
// show
objective.style.display = 'block';
Use visibility, this will hide the object but it will still take up space in the page. This wouldn't matter if you're using position:fixed or position:absolute.
// hide
objective.style.visibility = 'hidden';
// show
objective.style.visibility = 'visible';
You can either create a div around the objective, and add it in with javascript like this
document.getElementById('objectivespan').innerHTML=imagehere;
Other than that, you can use
objective.style.visibility='hidden';
and change it to
objective.style.visibility='visible';
for the delay, use
function sleep(){
alert('slept');
}
SetTimeout('sleep', 10000);

Kinetic.js don't lose grip on mouse out

When you drag an object and mouse is out of rendering area, dragging stops (firing an event) and user loses a grip.
It's extremelly inconvenient, taking into account that all other technologies (Flash, raw HTML5 Canvas, etc) allows to save the grip even if mouse is out.
Is there a way to solve the problem?
UPDATE: Up to the moment solved the problem by changing library file and binding listeners to the document, not to the container. I know that it's bad to hack into library files, but after inspecting the library's source code I haven't found out way around.
you could check if the element is out of sight and if so bring it back:
shape.on('dragend', function() {
var pos = shape.getPosition();
var layer = pos.getLayer();
if (pos.y < 0) {
pos.y = 0;
}
var maxY = layer.getHeight() - shape.getHeight();
if (pos.y > maxY) {
pos.y = maxY
}
shape.setPosition(pos);
}
Look at element.setCapture(). You can call it from within an event handler for a mouse event, eg. mousedown:
function mouseDown(e) {
e.target.setCapture();
e.target.addEventListener("mousemove", mouseMoved, false);
}
Although browser support is a bit spotty (IE and Firefox support it, not sure about other browsers), for cross browser use you would have to fall back to the binding on the document approach you've already hit upon.

Rotate a sprite using ActionScript3

I want to rotate a sprite in 3d using AS3. The example below, tells how to do rotate an image using MXML and AS3, however, I want to do it through pure AS3:
Example
thanks
Flex is AS3. Flex compiles down to actionscript. Often, it's just a declarative (as opposed to the imperative) way to get things done.
So the meat of that example is in the code snippets:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
target.play();
}
}
//snip...
<fx:Declarations>
<fx:Number id="rotY">0</fx:Number>
<s:Rotate3D id="fxRotate3DNeg" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
<s:Rotate3D id="fxRotate3DPos" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
</fx:Declarations>
What's doing the work is the "Animate" object in conjunction with the two "Rotate3D" objects. So to get this to work in pure AS3, the only tough thing that's required is linking to the flex libraries. Depending on your IDE, that's pretty easy to do.
From there all you have to do is create the objects you want, imperatively instead of declaratively. So instead of doing things like:
<fx:Number id="rotY">0</fx:Number>
You need to do:
var rotY:Number = 0;
Once you know that, converting from Flex to AS3 and vice versa is pretty straightforward. The translated flex code would look something like the following in ActionScript:
import spark.effects.Rotate3D;
var rotY:Number;
var fxRotate3DNeg:Rotate3D;
var fxRotate3DPos:Rotate3D;
rotY = 0;
fxRotate3DNeg = new Rotate3D(image);; //the constructor sets the "target" property
fxRotate3DNeg.angleYTo = rotY;
fxRotate3DNeg.autoCenterTransform = true;
fxRotate3DPos = new Rotate3D(image);
fxRotate3DPos.angleYTo = rotY;
fxRotate3DPos.autoCenterTransform = true;
Now, that's off the top of my head, glancing at the Rotate3D API and typing in this text editor so I'm sure it's not perfect but it should give you a clear idea on how to move forward. If you need more help, let me know and I could translate more of the example.
I hope that helps,
--gMale
EDIT:
As I look at the code, one other tricky point is that the angleYTo properties are bound to rotY. So to truly get this to work, you have to explicitly set those properties in the playEffect function. As in:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
//manually set properties
fxRotate3DNeg.angleYTo = fxRotate3DPos.angleYTo = rotY;
target.play();
}
}
Alternatively, you could imperatively create the data binding, which is pretty easy to do. Then, the playEffect function would require no modification.
Its like rotating the object as you usually do. However in 3d space you will have to use:
sprite.rotationY
Make sure you are exporting for flash 10 or later since the 3d functionality doesnt exist in earlier versions.

Flex DRAG_DROP Event - Is it possible to access the Image Being Dragged?

When you start a Flex drag action, you pass in a proxy image to be displayed when you drag across the screen. When the drop occurs, I want to be able to grab this proxy but I can't find a way to from the DragEvent object.
Is it possible? What I want is to actually drop the dragged image when the mouse button is released... Flex automatically does a nice shrinking animation on the proxy but I don't want that.
The Flex examples show what I don't want - the proxy is removed and a new image added but not in exactly the right place...
More info: I tried adding my Proxy Image as a data item to the DragSource. I was able to access this when the drop occurred and saw there is a class mx.managers.dragClasses.DragProxy which seems to have all the info I need... but this class is not documented?
So there's two questions really... how to get the proxy and find out the position of the mouse cursor within the proxy, and how to disable the Flex drop animation.
The dragProxy is a static getter on the DragManager and is scoped to mx_internal. So to reference it, you'd have to do something like this:
import mx_internal;
And in a drag event handler:
var p:* = DragManager.mx_internal::dragProxy;
I'm not sure how you could prevent the animation. If I find out, I'll let you know.
For disabling the animation in the s:List, in a dragCompleteHandler override, you can 'hack' into the DragManager to get the dragProxy and hide it.
override protected function dragCompleteHandler(e:DragEvent):void
{
DragManager.mx_internal::dragProxy.visible = false; // <- MAGIC!
super.dragCompleteHandler(e);
}
Probably applicable in other situations.
Only way to prevent the animation:
-You have to monkey patch the DragProxy class (i.e. create a new class with identical name, code, and package structure), and remove the effects code from the mouseUpHandler().
No other way to override it as far as I know, though the issue was been submitted as a bug to Adobe over a year ago.
As far as getting the mouse coords for the proxy to drop it in the correct location try this:
assuming you are initiating the drag on mouseDown get the coords using e.currentTarget.contentMouseX and e.currentTarget.contentMouseY in your handler. then add these to the dragSource ( I did it as an object ) like:
var drgSrc:DragSource = new DragSource();
drgSrc.addData( { x:e.currentTarget.contentMouseX, y:e.currentTarget.contentMouseY }, 'drgXY' );
then in your drop handler ( assuming you are dropping it into a Canvas named drpCvs ):
var newImg:Image = new Image();
newImg.x = drpCvs.contentMouseX - e.dragSource.dataForFormat( 'drgXY' ).x;
newImg.y = drpCvs.contentMouseY - e.dragSource.dataForFormat( 'drgXY' ).y;
I found this while looking for a way to get rid of the shrink animation, so thanks for that. Thought I'd RTF.
If you just want to prevent the animation, the easiest (hackiest) way is this: create you're own proxy and add a MOUSE_UP handler to the stage that when triggered sets the visible property of your proxy to false. It won't actually stop the animation, it will just hide the proxy while the animation is happening. Something like this:
var proxy:UIComponent = new UIComponent();
proxy.graphics.lineStyle(1);
proxy.graphics.beginFill(0xccddff);
proxy.graphics.drawRect(0, 0, main.width, main.height);
stage.addEventListener(MouseEvent.MOUSE_UP, function (e:MouseEvent):void {
proxy.visible = false;
});
#ykessler: Thank you, the monkey patch worked like a charm. SDK: DragProxy.as
#Alvaro: I believe this approach results in a race condition. I tried it, and it only worked sometimes.
Setting
event.dragInitiator.visible = false;
in the drag drop handler works for me!
My solution to turn off the animation, was to set visible=0 onMouseUp in my custom ListItemDragProxy component.
My solution is to remove the MouseUp-Handler on SandboxRoot and attach an own MouseUp-Handler in dragEnterHandler of the target like this:
protected function dragEnterHandler(event:DragEvent):void{
DragManager.acceptDragDrop(this);
this.dragProxy = DragManager.mx_internal::dragProxy;// get drag proxy
var sm:ISystemManager = event.dragInitiator.systemManager.topLevelSystemManager as ISystemManager;
var ed:IEventDispatcher = sm.getSandboxRoot();
this.sandboxRoot = sm.getSandboxRoot();
//remove
ed.removeEventListener(MouseEvent.MOUSE_UP, dragProxy.mouseUpHandler, true);
//attach own
ed.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler, true);
ed.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
this.dragInitiator = event.dragInitiator;}
In mouseUpHandler I've implemented the copy of function mouseUpHandler from original DragProxy.as and removed the Drop-Effect.