Script to rotate an image and switch image halfway through animation - javascript

I am writing a script to rotate an image in the Y direction on hover, and switch the image to a different one at the 90 degrees point (the intended effect is that when the image is hovered, it flips round to show the "back" side).
My javascript is as follows:
$('.designthumb').on('mouseover', function(e) {
var x = this;
var img = $(this).attr('src');
var path1 = img.split('.png');
$(x).css('-webkit-transform','rotateY(90deg)');
$(x).css('transform','rotateY(90deg)');
$(x).on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function(e) {
if (path1[0].substr(path1[0].length - 4) == 'back') {var newpath = path1[0]+'.png';}
else {var newpath = path1[0]+'back.png';}
$(x).attr('src',newpath);
$(x).css('-webkit-transform','');
$(x).css('transform','');
e.stopPropagation();
});
$(x).on('mouseout', function(e) {
$(x).css('-webkit-transform','rotateY(90deg)');
$(x).css('transform','rotateY(90deg)');
$(x).on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd',
function(e) {
if (img.split('.png')[0].substr(img.split('.png')[0] - 4) == 'back') {var imgo = img.split('back')[0]+'.png';}
else {var imgo = img.split('.png')[0]+'.png';}
$(x).attr('src',imgo);
$(x).css('-webkit-transform','');
$(x).css('transform','');
});
});
});
I have created a fiddle, but, somehow, I am just fiddle-tarded and my fiddles never work properly, or in this case at all. Nonetheless you can view my somewhat simplified attempt here: http://jsfiddle.net/Xenthide/u6nauzqg/
The above code SORT OF works, the HTML is fairly trivial so I won't bother posting it, basically I have a selection of images classed as designthumb, with names such as image1.png, image2.png, with corresponding files image1back.png image2back.png, etc. The intended effect is that the user can hover over an image and see the back image.
However, it only really works if the user firmly moves the mouse onto the image, then stops moving it entirely. Otherwise the transition wobbles around, doesn't complete, and is just buggy as fuck. I'm not sure if that current version is still doing it but previous attempts of mine have somehow managed to get stuck on the back image even when the cursor is moved away from it. The possibly odd looking if/else statements are my efforts to prevent that.
Really I would like some way to FORCE the transition to complete, smoothly, as soon as the cursor touches that region, without the current annoying wobbly crap going on.
Any help would be much appreciated.

You could do this without javascript: DEMO
.design {
background:url(http://www.graphicsfuel.com/wp-content/uploads/2012/09/emoticon-sad.png) center no-repeat;
transition: 0.2s ease-in-out;
background-size:0 100%;
padding:0;
height:374px;
width:326px;
}
.design:hover {
width:0;
padding:0 163px ;
background-size:100% 100%;
}
here some more ideas with effects using same method : http://codepen.io/gc-nomade/pen/Joqzp
and a flip effect very close to what you try to do : http://codepen.io/gc-nomade/pen/cHirI

Related

Latency with animationiteration

So I've got this modal that I've designed to be opened via a checkbox input, but the problem with that was that I have my divs and section arranged in such a manner that #yt-modal-cont can't be in the same container as my input due to z-index issues. So I used javascript:
if(modalToggle.checked === true) {
oLay.style.display = 'block';}
Simple enough fix, however, that's not my issue. For the animation, the route I chose was:
#yt-modal-cont {
animation: fade-before 0.3s ease-out 0s 2 alternate-reverse;
}
#keyframes fade-before {
0%{opacity:1;}
100%{opacity:0;}
}
<script>
var oLay = document.getElementById('yt-modal-cont');
var modalToggle = document.getElementById('vids');
function fadein(){
oLay.style['animation-play-state'] = 'paused';
}
function isOpen(){
if(modalToggle.checked === true) {
oLay.style.display = 'block';}
oLay.addEventListener('animationiteration', fadein);
}
}
modalToggle.addEventListener('click', isOpen);
</script>
and then for the closing function I have it setting animation-play-state=running to play through to the end, but that's not relevant. My issue is that javascript seems to be catching the end of the first iteration--and thusly adding the style--too late, as when the modal opens it's opacity is faded slightly. What's weirder, is that it's only sometimes; I open it once and it's kinda faded, I open it again and it's full opacity, then again and it's really faded... I tried adding oLay.style.opacity = 1 to the fadein function to try and override the CSS but it's still hit-or-miss. After looking at
Lag in animated image array
I feel that requestAnimationframe might be the answer, but my js newb-iness makes it so that I don't really understand what that's all about... Is that the right track or is there a different solution?

JS Get Current Position of Animated Element

So I have an element that is using CSS3 transitions to move across the page. I'm trying to see how the actual output FPS of that animation on the page is (for instance, if the page is outputting at 5FPS, a div moving from 0px to 10px at a transition value of 1s should report back 2px, 4px, 6px, etc).
Instead, I just get whatever value I already set the div's position to.
// css has defined a transition of 10s on the moving div
document.getElementById("movingDiv").style.left = "0px";
console.log(document.getElementById("movingDiv").style.left); //outputs 0px
document.getElementById("movingDiv").style.left = "100px";
window.setTimeout(function(){
console.log(document.getElementById("movingDiv").style.left); //outputs 100px instead of, for instance, 43px or wherever the div would visually appear to be
}, 3000);
That's not the exact code, but just some that's generic enough to illustrate my point.
Restating the question, how would I find where an element visually appears to be during its transition between one position and another? I'm not using jQuery animations as many others have answered for, and don't just want to calculate where the element should be. I want to see where the element actually appears to be on the page. I would also like if this works off-screen as well (like to the left of or above the visible window).
To help see why I'm actually trying to do this, is that I'm trying to get the FPS output of the page. I have seen many cases where the page outputs terrible FPS but Javascript still outputs over 100 FPS because the Javascript can run faster than the page can render itself which I'm trying to avoid.
You can use window.requestAnimationFrame:
var moving = false,
el = document.getElementById("mover");
el.className = el.className + " move-right";
el.addEventListener('transitionend', function () {
moving = true;
});
function getPosition() {
var rect = el.getBoundingClientRect()
console.log(rect.top, rect.left);
if (!moving) {
window.requestAnimationFrame(getPosition);
}
}
window.requestAnimationFrame(getPosition);
http://jsfiddle.net/ob7kgmbk/1/

sliding image css3 only or javascript needed?

I'm stuck in a drupal project, I would like to know how to get this effect done please, the left image will expand to right on click and same I want to the right image which will expand left on click, I want to know if it can be done by css3 only or javascript needed and how please... here are two image for my issue, I am mainly as front-end developer and know little of backend, so if anyone can help please..!
http://s14.postimg.org/aahx57ke9/img.png
If you want the image to slide and stay in that position after letting go of the mouse button, you have to use JavaScript.
I recommend jQuery. Here is an example illustrating how you can use JavaScript to slide elements and seamlessly superimpose them over each other, with jQuery animations; the JFiddle link at the bottom will show you the HTML, CSS, and JavaScript. It should be perfectly applicable to your image situation, assuming the images are positioned absolute.
JavaScript:
var b1 = $('#block1');
var b2 = $('#block2');
function slide(block, left, callback)
{
block.animate({
'left': left
}, 750, function() {
// Do this after finished animating.
if (callback) callback();
});
}
b1.on('click', function() {
// Only slide if not already done.
if (b1.css('left') != '-50px') {
// First slide both elements so they meet at the,
// middle, then switching the z-index is not noticeable.
slide(b1, '-250px');
slide(b2, '250px', function() {
// After animating, superimpose b1 over b2
// by changing z-index order, then animate
// the rest of the way.
b1.css('z-index', '1');
b2.css('z-index', '0');
slide(b1, '-50px');
});
}
});
b2.on('click', function() {
// Same here but with right element.
if (b2.css('left') != '50px') {
slide(b1, '-250px');
slide(b2, '250px', function() {
b1.css('z-index', '0');
b2.css('z-index', '1');
slide(b2, '50px');
});
}
});
Check it out in action here: https://jsfiddle.net/86sr3okk/6/
Welcome to the wonderful world of JavaScript.

MooTools Tween Stutter/Hiccup

I am doing a rather simple Tween animation using MooTools. The opening animation is perfectly smooth. But then I added the closing animation (opposite of the opening animation), but it seems to stutter/hiccup at the end almost every time.
I tried the following with no success:
Removed all HTML content from the expanding DIV
Passing the Bounce settings directly to the Set function instead of using the variable
Commented the #content animation to be sure there is only 1 animation running
Commented the addClass and removeClass actions
I can't figure out what's causing the problem. Maybe someone else can have a look…
I put the test-case online here: http://dev.dvrs.eu/mootools/
window.addEvent('domready', function() {
// Set initial Div heights
$('sideBar').setStyle('height', window.getSize().y);
$('sideMenu').setStyle('height', window.getSize().y);
// Set Div heights on Window resize
window.addEvent('resize', function() {
$('sideBar').setStyle('height', window.getSize().y);
$('sideMenu').setStyle('height', window.getSize().y);
});
var bounce = {
transition: Fx.Transitions.Back.easeOut,
duration: 500
};
$$('.button.closeMenu').addEvent('click', function(event) {
event.preventDefault();
$$('.button').removeClass('active');
this.addClass('active');
$('sideMenu').set('tween', bounce);
$('sideMenu').tween('width', 0);
$('content').set('tween', bounce);
$('content').tween('margin-left', 90);
});
$$('.button.menu').addEvent('click', function(event) {
event.preventDefault();
$$('.button').removeClass('active');
this.addClass('active');
$('sideMenu').set('tween', bounce);
$('sideMenu').tween('width', 300);
$('content').set('tween', bounce);
$('content').tween('margin-left', 390);
});
});
Fiddle with example here
The transition you are using goes over the values defined as final value in the .set(property, value);. So when opening the final width is 300px but the transition/effect goes over that and than soft back to the final value.
This works great when opening because width can be 310px or more and then return to 300px, but when with has a transition under the with 0px, it doesn't work so good. It actually works ok if the final width is 10px (check here), but that's not the effect you want.
So my suggestion is to fix it with CSS, or change the transition when closing the sidebar, or use another effect altogether.
Option 1: fiddle - same transition opening, no easeout closing
Option 2: fiddle - same effect as you have but played with CSS and hidded 10px of the sidemenu under the sidebar. (z-index:3; on #sideBar and left:80px;width: 10px; on #sideMenu. Also 10px as the final value for the tween.)
To check different transitions at Mootools demo's look here.

How to resolve mouse hover on overlapping images in jQuery?

This question seems somewhat related to
How do I check if the mouse is over an element in jQuery?
jQuery check hover status before start trigger
but still not quite. Here's the thing: I'm writing a small gallery and at some point the user clicks on a thumbnail. The large version of the image shows as an inside of a full-screen . So far, so good. When the mouse hovers over that I show three images: close, left, right, intended to navigate through an album; when the mouse leaves the image or the navigation images, the three navigation images fade.
These three navigation images partially overlap with the main image, e.g. the close image is a circle in the upper left corner. And that's the tricky part.
The mouseleave triggers whenever the mouse moves from the main image off the side, or from the main image onto one of the three small overlapping images. The mouseenter triggers for each of the small overlapping images as expected.
However, this creates a funky blinking effect because on mouseleave of the main image I hide() the three small images, which immediately triggers a mouseenter for the main image because of the overlap and the mouse still being on top of the main image.
To avoid that, I tried to determine if, upon mouseleave of the main image, the mouse has moved onto one of the small overlapping images. For that, I used this code:
main_img.mouseleave(function() {
if (!hoverButtons()) {
doHideButtons();
}
});
function hoverButtons() {
return (close_img.is(":hover")) || (left_img.is(":hover")) || (right_img.is(":hover"));
}
This works great on Safari and Chrome, but not on FF and IE where the images still blink. Further noodling around posts, it seems that ":hover" is the problem here as it is not a proper selector expression but rather a CSS pseudo class?
I tried to work with switches that I flip on/off as I mouseenter/mouseleave the various images, but that doesn't work either because the events seem to trigger in different orders.
How do I go about this? Thanks!
EDIT: I might have to clarify: before the navigation buttons are shown, I set their respective left and top attributes in order to place them in dependence of the main image's position. That means I need to do some work before I can call .show() on a jQuery selector. I tried to add a new function .placeShow() but that didn't quite work with respect to selectors like $(".nav-button:hidden").placeShow().
You can try with this:
$("#main, #small").mouseenter(function() {
$("#small:hidden").show();
}).mouseleave(function(e) {
if(e.target.id != 'main' || e.target.id != 'small') {
$('#small').hide();
}
});
DEMO
Here is what I ended up doing. There are four images I use in my slide show: the main image, and then left, right, close button images.
main_img = $("<img ... class='main-photo slide-show'/>");
close_img = $("<img ... class='nav-button slide-show'/>");
left_img = $("<img ... class='nav-button slide-show'/>");
right_img = $("<img ... class='nav-button slide-show'/>");
The classes here are essentially empty, but help me to select based on above answers. The main image then shows without navigation buttons, and I attach these event handler functions:
$(".slide-show").mouseenter(function() {
$(".photo-nav:hidden").placeShow();
});
$(".slide-show").mouseleave(function() {
$(".photo-nav").hide();
});
where the placeShow() moves the navigation buttons into their respective places. This function is defined as follows:
$.fn.placeShow = function() {
var pos = main_img.position();
var left = pos.left;
var top = pos.top;
var width = main_img.width();
var height = main_img.height();
close_img.css({ "left":"" + (left-15) + "px", "top":"" + (top-15) + "px" }).show();
left_img.css({ "left":"" + (left+(width/2)-36) + "px" , "top": "" + (top+height-15) + "px" }).show();
right_img.css({ "left":"" + (left+(width/2)+3) + "px", "top":"" + (top+height-15) + "px" }).show();
}
This worked so far on Safari, IE, FF, Chrome (well, the versions I've got here...)
Let me know what you think, if I can trim this code more, or if there are alternative solutions that would be more elegant/fast. The final result of all this is on my website now.
Jens

Categories

Resources