I am trying to add smooth move effect on img when user do a mousemove on image parent element (here .carousel-img) but I can't run it properly.
What am I doing wrong?
$('.carousel-img').on('mousemove', function(e){
$('.carousel-img img').css({'transform-origin': ((e.pageX - $('.carousel-img img').offset().left) / $('.carousel-img img').width()) * 100 + '% ' + ((e.pageY - $('.carousel-img img').offset().top) / $('.carousel-img img').height()) * 100 +'%'});
})
html, body{height:100%; width:100%;}
.box{position: relative; height:100%; width:100%;}
.carousel-img {
position: absolute;
right:0;
bottom:0;
left: 0;
top:0;
padding:100px;
}
.carousel-img img {
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
<img src="http://placehold.it/1920x600/fff/fff">
<div class="carousel-img">
<img src="http://placehold.it/200x150/ff0000/ff0000" >
</div>
</div>
You're changing the transform-origin property instead of the transform property. You want to use the translate(x,y) to define the movement you're looking for.
You also should include a transition to your img selector, so that the movement is smooth. I also added some other attributes that may be useful when adding more complex animations such as translate3D types.
Check the updated snippet below.
$('.carousel-img').on('mousemove', function(e) {
var translateX = ((e.pageX - $('.carousel-img img').offset().left) / $('.carousel-img img').width()) * 100;
var translateY = ((e.pageY - $('.carousel-img img').offset().top) / $('.carousel-img img').height()) * 100;
var translateProperty = 'translate(' + translateX + '%, ' + translateY + '%)';
$('.carousel-img img').css({
'-webkit-transform': translateProperty,
'-moz-transform': translateProperty,
'-ms-transform': translateProperty,
'-o-transform': translateProperty,
'transform': translateProperty
});
});
html,
body {
height: 100%;
width: 100%;
}
.box {
position: relative;
height: 100%;
width: 100%;
}
.carousel-img {
position: absolute;
right: 0;
bottom: 0;
left: 0;
top: 0;
padding: 100px;
}
.carousel-img img {
position: relative;
/* Add transition */
transition: all 0.2s ease;
-webkit-transition: all 0.2s ease;
/* Default values for transition to be possible */
transform: translate3d(0, 0, 0);
-webkit-transform: translate3d(0, 0, 0);
transform-style: preserve-3d;
-webkit-transform-style: preserve-3d;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
<img src="http://placehold.it/1920x600/fff/fff">
<div class="carousel-img">
<img src="http://placehold.it/200x150/ff0000/ff0000" >
</div>
</div>
Related
I am trying to build a simple web element that resembles the wheel contestants spin on The Price is Right (sample video). My question is: is there a more efficient way to achieve this effect than what I've cobbled together below?
My first attempt at this functionality basically decrements the translateY property of an element that contains the elements to be spun [codepen]:
setInterval(shiftCards, 100)
var translateY = -60,
cardIdx = 0,
startCards = 60,
wrap = document.querySelector('.wrap');
for (var i=0; i<startCards; i++) {
addCard()
}
function addCard() {
var div = document.createElement('div');
div.className = 'card';
div.style.top = (cardIdx * 12) + 'px';
wrap.appendChild(div);
cardIdx++;
}
function shiftCards() {
wrap.style.transform = 'translateY(' + translateY + 'px)';
translateY -= 12;
var cards = wrap.querySelectorAll('.card');
if (cards.length >= startCards) {
cards[0].parentNode.removeChild(cards[0]);
addCard();
}
}
.cards {
width: 80px;
height: 200px;
overflow: hidden;
background: #aaa;
}
.wrap {
position: relative;
transition: transform .25s;
}
.card {
width: 100%;
height: 10px;
margin: 2px 0;
background: red;
position: absolute;
left: 0;
right: 0;
}
<div class='cards'>
<div class='wrap'>
</div>
</div>
Is there a more efficient way to achieve this functionality? Can I create an element with n children and actually just spin them in the Z-dimension, rather than create an artificial spin as I've done above? Any guidance others can offer on this question will be very appreciated!
You can use css-animations for this: (They are probably more efficient)
/* only alignment */
body, html {
height: 100%;
margin: 0;
padding: 0;
}
.wrapper {
display:flex;
justify-content:center;
align-items:center;
height: 100%;
}
/* actual spinning */
img {
animation: spin 5s infinite linear;
/*
spin: the keyframes (=animation) we want to have
5s: how long it should take for one iteration
infinite: how often should it repeat
linear: the easing between the different key frames You can also try 'ease'
*/
}
#keyframes spin {
0% {transform: translateY(-60px);} /* Starting point */
100% {transform: translateY(-360px);} /* end point */
}
#-webkit-keyframes spin {
0% {transform: translateY(-60px);}
100% {transform: translateY(-360px);}
}
<div class="wrapper">
<img src="https://www.placecage.com/300/100" class="spin">
</div>
I added a ripple effect to happen when the user clicks anywhere on a div. It works well except that when the page is full screen, the element shake and go blurry for until the ripple disappears.
Here's the JS for the effect:
$("div").click(function(e) {
// Remove any old ripples
$(".ripple").remove();
// Setup
var posX = $(this).offset().left,
posY = $(this).offset().top,
buttonWidth = $(this).width(),
buttonHeight = $(this).height();
// Add the element
$(this).prepend("<span class='ripple'></span>");
// Make it round
if(buttonWidth >= buttonHeight) {
buttonHeight = buttonWidth;
} else {
buttonWidth = buttonHeight;
}
// Get the center of the element
var x = e.pageX - posX - buttonWidth / 2;
var y = e.pageY - posY - buttonHeight / 2;
// Add the ripples CSS and start the animation
$(".ripple").css({
width: buttonWidth,
height: buttonHeight,
top: y + 'px',
left: x + 'px'
}).addClass("rippleEffect");
});
And the CSS:
.ripple {
width: 0;
height: 0;
border-radius: 50%;
background: rgba(249, 107, 107, 0.8);
transform: scale(0);
position: absolute;
opacity: 1;
z-index: 100;
}
.rippleEffect {
animation: rippleDrop .4s linear;
}
#keyframes rippleDrop {
100% {
transform: scale(0.1);
opacity: 0;
}
}
Here's the fiddle but you can't see the issue as it's a minimized preview, so here's another link where you can see it.
Thank you for any help!
Change your code
FIRST:
<div style="visibility: visible; position: fixed;" id="choose" class="centered">
<div style="position: fixed; transform: translate(-50%, -50%); width: 100%; left: 50%; top: 50%;" id="choose-cont">
<h3>You are X, the computer is O.</h3>
<button id="okay">OK</button>
<button id="surprise">No</button>
</div>
</div>
2.
<div style="position: fixed; transform: translate(-50%, -50%); width: 100%; left: 50%; top: 50%;" id="choose-cont">
<h3>You are X, the computer is O.</h3>
<button id="okay">OK</button>
<button id="surprise">No</button>
</div>
You can also add that in your CSS i just paste to you that you can see cahanges!
NOTE - You need chack you YQ code, i can overwrite circle
picture:http://prntscr.com/clwp72
The problem is with this class:
.centered {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Cancel it and you will not have flickering.
I'm guessing that the problem is with the transform attribute. You insert and remove items into the DOM and it has to recalculate the position.
When I clear all styles from the class- flickering is gone:
Fiddle
I am struggling to get direction-aware hover and css transitions to work properly. Basically I am trying to have a grid of elements with a front and back face, and when on hover have a css transition to flip that element to show the back face.
Transition example (without direction-aware): fiddle
As you can see, no matter which way your mouse enters an element it always flips up. I want it to flip whichever way the mouse enters in/out.
Example:
And here is my attempt with direction-aware: fiddle
I am using jQuery to add classes relevant to the mouse in/out direction.
.hover-in-top {}
.hover-in-right {}
.hover-in-bottom {}
.hover-in-left {}
.hover-out-top {}
.hover-out-right {}
.hover-out-bottom {}
.hover-out-left {}
As you can see from the direction-aware example it kind of works but there are major glitches which I can't get my head round. (I've been overthinking this and my brain has just imploded.)
Anyway I hope this makes sense. Thanks.
I have a partial solution to your question.
But I needed to change some of the transitions to animations
$('.box-container .box').each(function() {
$(this).on('mouseenter mouseleave', function(e) {
var $this = $(this),
width = $this.width(),
height = $this.height();
var x = (e.pageX - $this.offset().left - (width / 2)) * (width > height ? (height / width) : 1),
y = (e.pageY - $this.offset().top - (height / 2)) * (height > width ? (width / height) : 1);
// top = 0, right = 1, bottom = 2, left = 3
var dir_num = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4,
directions = ['top', 'right', 'bottom', 'left'];
// If mouse enter
if (e.type === 'mouseenter') {
// Remove all hover out classes
$this.removeClass(function(index, css) {
return (css.match(/(^|\s)hover-out-\S+/g) || []).join(' ');
});
// Add in direction class
$this.addClass('hover-in-' + directions[dir_num]);
}
// If mouse leave
if (e.type === 'mouseleave') {
// Remove all hover in classes
$this.removeClass(function(index, css) {
return (css.match(/(^|\s)hover-in-\S+/g) || []).join(' ');
});
// Add out direction class
$this.addClass('hover-out-' + directions[dir_num]);
}
});
});
* {
box-sizing: border-box;
}
.box-container {
padding: 20px;
width: 600px;
}
.box-container:after {
content: '';
display: block;
clear: both;
}
.box-container .box {
float: left;
width: 50%;
height: 200px;
position: relative;
perspective: 600px;
border: 1px solid transparent;
}
.box-container .box .front, .box-container .box .back {
float: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
backface-visibility: hidden;
transition: all 1s ease-in-out;
color: white;
font-size: 60px;
}
.box-container .box .front {
background: blue;
transform: rotateX(0) rotateY(0);
z-index: 900;
}
.box-container .box .back {
background: red;
z-index: 800;
}
.box-container .box:hover .front {
z-index: 900;
}
.box-container .box:hover .back {
z-index: 1000;
transform: rotateX(180) rotateY(0);
}
.box-container .box.hover-in-top .front,
.box-container .box.hover-out-bottom .back {
transform: rotateX(-179deg) rotateY(0);
}
.box-container .box.hover-in-top .back,
.box-container .box.hover-out-bottom .front {
animation: Xminus 1s ease-in-out;
}
#keyframes Xminus {
from {transform: rotateX(179deg) rotateY(0);}
to {transform: rotateX( 0deg) rotateY(0);}
}
.box-container .box.hover-in-bottom .front,
.box-container .box.hover-out-top .back {
transform: rotateX(179deg);
}
.box-container .box.hover-in-bottom .back,
.box-container .box.hover-out-top .front {
animation: Xplus 1s ease-in-out;
}
#keyframes Xplus {
from {transform: rotateX(-179deg) rotateY(0);}
to {transform: rotateX( 0deg) rotateY(0);}
}
.box-container .box.hover-in-right .front,
.box-container .box.hover-out-left .back {
transform: rotateY(-179deg);
}
.box-container .box.hover-in-right .back,
.box-container .box.hover-out-left .front {
animation: Yminus 1s ease-in-out;
}
#keyframes Yminus {
from {transform: rotateX(0deg) rotateY(179deg);}
to {transform: rotateX(0deg) rotateY( 0deg);}
}
.box-container .box.hover-in-left .front,
.box-container .box.hover-out-right .back {
transform: rotateY(179deg);
}
.box-container .box.hover-in-left .back,
.box-container .box.hover-out-right .front {
animation: Yplus 1s ease-in-out;
}
#keyframes Yplus {
from {transform: rotateX(0deg) rotateY(-179deg);}
to {transform: rotateX(0deg) rotateY( 0deg);}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box-container">
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
<div class="box">
<div class="front">FRONT</div>
<div class="back">BACK</div>
</div>
</div>
The problem with animations if that if you leave the div before the animation has ended, the animation will break
But if move slowly, and stay on the divs until the animation ends, this will work ok.
I hope that somebody finds a better solution
I believe that the best way to approach the problem is not to use CSS transitions.
You can easily implement it using jQuery's animate, utilizing jQuery animations queue to keep all of your animations synced.
I modified your example to animate the transition in JavaScript.
Code example
In a previous question, I asked how to make a "cursor mirror," meaning if your cursor were to move around in the top portion of a site, a separate inversed image of a cursor would move in the inverse direction in the bottom portion of a site. Link to question here.
Continuing with this code, if the actual cursor in the top half hovered over a div to make it disappear (using CSS hover states), how would the mirror-image cursor achieve the same effect using Javascript without using the .mouseover event (since it's not mouse but a placed image)? Sorry if the title is vague, but the problem is hard to describe!
var $img = $('#mirror-image');
var imgHeight = $img.height() / 2;
function placeCursor(x, y){
$img.css({top: y + 'px', left: x+ 'px', position:'absolute'});
}
$(".top-half-black").mousemove(function(event){
var newY = $(this).height() - event.pageY - imgHeight;
placeCursor(event.pageX, newY);
});
body{
margin:0px 0px 0px 0px;
}
.top-half-black{
background-color:black;
width:100%;
height:50%;
}
.bottom-half-white{
position: relative;
}
#mirror-image{
left: 0;
top: 0;
position: absolute;
width: 17px;
height: 25px;
}
.rightside-up{
font-family:Arial;
font-size:36px;
color:white;
}
.rightside-up:hover{
opacity:0;
}
.upside-down{
font-family:Arial;
font-size:36px;
-webkit-transform: scaleY(-1);
-moz-transform: scaleY(-1);
-ms-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
}
<div class="top-half-black">
<div class="rightside-up">Blah blah blah</div>
</div>
<div class="bottom-half-white">
<img id="mirror-image" src="http://i.imgur.com/cjjNbk1.png" />
<div class="upside-down"> Blah blah blah</div>
</div>
You can do it like this:
function hideDiv() {
$(".upside-down").hide();
}
function showDiv() {
$(".upside-down").show();
}
$(".rightside-up").hover(hideDiv, showDiv);
You could use the onmousemove event on the whole document, and then check if the inverse cursor is over the element in question. Lets say you want to simulate a mouse move event for the inverse cursor over an element with ID hover.
//Save a reference to the element for speed.
var hover = $("#hover");
//When the mouse moves anywhere.
$(document).mousemove(function() {
//I assume you have the position of the inverse cursor in variables x and y.
//I guesse the solution to your previous question should give you that.
//Save the distance between the inverse cursor and the top left corner of #hover.
var diffX = hover.offset().left - x;
var diffY = hover.offset().top - y;
//Check if the shadow cursor is inside #hover.
if(diffX >= 0 && diffX <= hover.width() && diffY >= 0 && diffY <= hover.height()) {
//Things here will run if the inverse curser is inside hover.
}
else {
//Thigs here will run if the inverse cursor is not inside hover.
}
}
The code would be neater if you could use .elementFromPoint(), but Mozilla advises against using it as it is "experimental technology".
One option would be to use the adjacent sibling selector ~ to allow you to control the style of .upside-down when hovering over top-half-black. E.G:
.top-half-black:hover .rightside-up,
.top-half-black:hover ~ .bottom-half-white .upside-down {
opacity:0
}
var $img = $('#mirror-image');
var imgHeight = $img.height() / 2;
function placeCursor(x, y){
$img.css({top: y + 'px', left: x+ 'px', position:'absolute'});
}
$(".top-half-black").mousemove(function(event){
var newY = $(this).height() - event.pageY - imgHeight;
placeCursor(event.pageX, newY);
});
body{
margin:0px 0px 0px 0px;
}
.top-half-black{
background-color:black;
width:100%;
height:50%;
}
.bottom-half-white{
position: relative;
}
#mirror-image{
left: 0;
top: 0;
position: absolute;
width: 17px;
height: 25px;
}
.rightside-up{
font-family:Arial;
font-size:36px;
color:white;
}
/*.rightside-up:hover{
opacity:0;
}*/
.top-half-black:hover .rightside-up,
.top-half-black:hover ~ .bottom-half-white .upside-down {
opacity:0
}
.upside-down{
font-family:Arial;
font-size:36px;
-webkit-transform: scaleY(-1);
-moz-transform: scaleY(-1);
-ms-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
}
<div class="top-half-black">
<div class="rightside-up">Blah blah blah</div>
</div>
<div class="bottom-half-white">
<img id="mirror-image" src="http://i.imgur.com/cjjNbk1.png" />
<div class="upside-down"> Blah blah blah</div>
</div>
UPDATE...
Further to your comment, you could use document.elementFromPoint(x, y) to find the element under the mirrored cursor image and toggle its class name:
var $img = $('#mirror-image');
var imgHeight = $img.height() / 2;
function placeCursor(x, y){
$img.css({top: y + 'px', left: x+ 'px', position:'absolute'});
}
$(".top-half-black").mousemove(function(event){
var newY = $(this).height() - event.pageY - imgHeight;
var x = event.pageX,
y = $(this).height() + event.pageY;
$(".upside-down .hovered").removeClass("hovered");
placeCursor(x, newY);
var mirrorEl = document.elementFromPoint(x, y);
$(mirrorEl).addClass("hovered");
});
body{
margin:0px 0px 0px 0px;
}
.top-half-black{
background-color:black;
width:100%;
height:50%;
}
.bottom-half-white{
position: relative;
}
#mirror-image{
left: 0;
top: 0;
position: absolute;
width: 17px;
height: 25px;
}
.rightside-up{
font-family:Arial;
font-size:36px;
color:white;
}
.rightside-up span:hover{
opacity:0;
}
.upside-down span.hovered{
opacity:0;
}
.upside-down{
font-family:Arial;
font-size:36px;
-webkit-transform: scaleY(-1);
-moz-transform: scaleY(-1);
-ms-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="top-half-black">
<div class="rightside-up"><span>Blah</span> <span>blah</span> <span>blah</span></div>
</div>
<div class="bottom-half-white">
<img id="mirror-image" src="http://i.imgur.com/cjjNbk1.png" />
<div class="upside-down"><span>Blah</span> <span>blah</span> <span>blah</span></div>
</div>
I'm attempting to achieve a CSS 3 effect where when you click on an image in a bank of images, it expands to all the available area and flips over at the same time.
The way I was able to accomplish this was to clone the element and absolutely position it on top of the original then transform that. In the code below the cloned image is assigned the classes clone and activated.
All is well.
However, if I pre-flip all of the images in the series of images, activated using the flip all button (adding origflipped class, which has rotateY(180deg) so now the backs are showing) and then try the same effect (expand and now rotateY(0deg) to the front side), the animation somehow has unintended side effects.
It looks like when the rotateY transition is executing, half of the image in the rotation effect dips below the page in 3d space, behind the other images and out of view.
So how can I rotateY(0) from rotateY(180deg) without having half of the image floating underneath other things?
$(document).ready(function() {
var ALL_CARDS = [
['http://twitpic.com/show/thumb/26n3ms', 'http://twitpic.com/show/thumb/26n3mr'],
['http://twitpic.com/show/thumb/26n3ma', 'http://twitpic.com/show/thumb/26n3mq'],
['http://twitpic.com/show/thumb/26n3mb', 'http://twitpic.com/show/thumb/26n3mt'],
['http://twitpic.com/show/thumb/26n3mc', 'http://twitpic.com/show/thumb/26n3mu'],
['http://twitpic.com/show/thumb/26n3md', 'http://twitpic.com/show/thumb/26n3mv'],
];
var width = 100;
for (var i = 0; i < ALL_CARDS.length; i++) {
$(document.createElement('div'))
.addClass("card")
.append(
$('<img src="' + ALL_CARDS[i][0] + '" />')
.addClass("face front")
)
.append(
$('<img src="' + ALL_CARDS[i][1] + '" />')
.addClass("face back")
)
.width(width)
.height(width + 10)
.appendTo($('#target_area'))
.find('img').width('100%').height('100%');
}
$('#target_area .card')
.click(function(e) {
e.preventDefault();
var original = $(this);
var proxy = $(this).clone();
var body = $('body');
original.addClass("origshown");
proxy
.css({
'position': 'absolute',
'top': this.offsetTop,
'left': this.offsetLeft - 5
})
.click(function() {
original.removeClass("origshown");
$(this).remove();
})
.addClass("clone")
.appendTo($('#target_area'));
var border_width = 10;
proxy
.css({
'background-color': 'white',
'top': border_width,
'left': border_width,
'height': body.height() - (2 * border_width),
'width': body.width() - (2 * border_width),
})
.addClass('activated');
});
$('#flip_all').click(function(e) {
e.preventDefault();
$('.card').toggleClass('origflipped');
});
});
#target_area .face {
-webkit-backface-visibility: hidden;
position: absolute;
}
#target_area .face img {
vertical-align: middle;
height: 100%;
}
#target_area .face.back {
-webkit-transform: rotateY(180deg);
}
#target_area .card {
float: left;
margin-left: 5px;
-webkit-transform-style: preserve-3d;
-webkit-transition-property: all;
-webkit-transition-duration: 1s;
-webkit-transition-timing-function: ease-in;
}
#target_area .card.origshown {
-webkit-transition-property: none;
visibility: hidden;
}
#target_area .card.origflipped {
-webkit-transform: rotateY(180deg);
}
#target_area .card.clone {
float: none;
-webkit-box-shadow: 0px 2px 6px rgba(0, 0, 0, 0.5);
}
#target_area .card.clone.activated {
-webkit-transform: rotateY(180deg);
}
#target_area .card.clone.origflipped {
-webkit-transform: rotateY(180deg);
}
#target_area .card.clone.origflipped.activated {
-webkit-transform: rotateY(0deg);
}
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.js"></script>
</head>
<body>
<div id="target_area"></div>
<input type="button" value="flip all" id="flip_all" />
</body>
</html>
Hmm, Testing this works fine for me in chrome 5.0.375.99,
http://jsfiddle.net/Fhxb3/
so im not sure what you issue is, what browser are you using?
also, although im sure you know this, it is completly broken in firefox/ie (but thats cause your using -webkit styles