I use several buttons to create motion, now i have a problem when i use marginLeft for move the element to left and right div#ball, it doesn't fit in the page and jumps out and exit form both left and right side. how i can set a limitation and avoid element from exiting ?
$(document).ready(function() {
$('#fastleft').click(function() {
$('#ball').toggleClass('rotated');
$('#ball').animate({
'marginLeft': "-=300px"
});
});
$('#moveleft').click(function() {
$('#ball').toggleClass('rotated');
$('#ball').animate({
'marginLeft': "-=20px"
});
});
$('#moveright').click(function() {
$('#ball').toggleClass('rotated');
$('#ball').animate({
'marginLeft': "+=20px"
});
});
$('#fastright').click(function() {
$('#ball').toggleClass('rotated');
$('#ball').animate({
'marginLeft': "+=300px"
});
});
});
#ball {
width: 50px;
height: 50px;
display: inline-block;
/*background-image: url(./boll.png);*/
background-color:red;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: relative;
}
.rotated {
animation-duration: 0.5s;
animation-name: ball;
}
#keyframes ball {
0% {
transform: rotate(100deg)
}
25% {
transform: rotate(200deg)
}
50% {
transform: rotate(300deg)
}
100% {
transform: rotate(360deg)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="butts">
<button id="fastleft" type="button">FastLeft</button></button>
<button id="moveleft" type="button">Left</button>
<button id="moveright" type="button">Right</button>
<button id="fastright" type="button">FastRight</button>
</div>
<br>
<div id="ball"></div>
</div>
Here's a more optimized version of your code using function and data attribute. Examine it and let me know if you have any questions understanding it.
var ball = $('#ball');
var position = 0;
var bw = ball.width();
var ww = $('body').width();
$('button').click(function() {
var speed = $(this).data('speed');
moveBall(speed);
});
function moveBall(px){
position+= px;
position = Math.min(position,ww-bw);
position = Math.max(position,0);
console.log(position);
ball.toggleClass('rotated').animate({
'marginLeft': position+"px"
});
}
#ball {
width: 50px;
height: 50px;
display: inline-block;
/*background-image: url(./boll.png);*/
background-color:red;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: relative;
}
.rotated {
animation-duration: 0.5s;
animation-name: ball;
}
#keyframes ball {
0% {
transform: rotate(100deg)
}
25% {
transform: rotate(200deg)
}
50% {
transform: rotate(300deg)
}
100% {
transform: rotate(360deg)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="butts">
<button data-speed="-300" id="fastleft" type="button">FastLeft</button>
<button data-speed="-20" id="moveleft" type="button">Left</button>
<button data-speed="20" id="moveright" type="button">Right</button>
<button data-speed="300" id="fastright" type="button">FastRight</button>
</div>
<br>
<div id="ball"></div>
</div>
Try using other CSS properties like float and align instead of giving such large values in pixel to margin or padding properties. This will almost always push your elements out of your page especially if you are working with small screen sizes . Also you should try using bootstrap. It will make your life much easier.
Related
I was searching a while but didn't found a post about this: I'm using jQuery fadeOut() to animate an element.
I want to fade out the element with a scale of 1.75 (175%) by using jQuery's fadeOut() function. At the moment it's a common fade out animation, but I'd like that the fade out animation scales out (element inflates).
I've made an example (the lightblue element) with a CSS animation using keyframes. I would like to solve the animation with fadeOut() (maybe you have to scroll down the snippet to see the example), is this possible? I hope this is clear enough.
$('.hide').click(function() {
$('.animate').fadeOut(500);
});
$('.show').click(function() {
$('.animate').fadeIn(500);
});
.animate {
width: 150px;
height: 150px;
background-color: lightcoral;
margin-top: 20px;
}
.animate--css {
background-color: lightblue;
}
.animate--css {
width: 150px;
height: 150px;
background-color: lightblue;
margin-top: 20px;
animation: zoomOut 1s infinite;
}
#keyframes zoomOut {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.75);
opacity: 0;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="hide">Fade out</button>
<button class="show">Fade in</button>
<div class="animate"></div>
<div class="animate--css"></div>
You can use start to apply a CSS before fading the element:
$('.hide').click(function() {
$('.animate').fadeOut({'start':function() {$(this).css('transform','scale(1.75)') },'duration':500});
});
$('.show').click(function() {
$('.animate').fadeIn({'start':function() {$(this).css('transform','scale(1)') },'duration':500});
});
.animate {
width: 150px;
height: 150px;
background-color: lightcoral;
margin-top: 20px;
transition:0.5s all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="hide">Fade out</button>
<button class="show">Fade in</button>
<div class="animate"></div>
I'm looking to add setTimeout to a JS function but inside this function I have another one, I'm aware that I can use onclick=setTimeout"(fooBar(), 2500);" but there's a loader inside my function, so to make it clear, I'd like to execute the function instantly (show loader div) when the button is clicked but setTimout to 2500 ms before running $.getJSON. Let's say I want to add a fake timeOut to the api request because that stuff is blazing fast.
Also, please let me know if my loading animation method with JS is ok, actually I think it's too much lines of code to show/hide div. I'm sure there's a better way to handle something like this. Thanks.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>JS Loader</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<style type="text/css" id="style">
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from { bottom:-100px; opacity:0 }
to { bottom:0px; opacity:1 }
}
#keyframes animatebottom {
from{ bottom:-100px; opacity:0 }
to{ bottom:0; opacity:1 }
}
#myDiv {
display: none;
text-align: center;
}
</style>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name" >Real-time Bitcoin Price</h1>
<div id="myloader"style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
<script type="text/javascript">
document.getElementById("refreshBtn").addEventListener("click", function () {
var x = document.getElementById('myloader');
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function (data) {
var x = document.getElementById('myloader');
if (x.style.display === 'none') {
x.style.display = 'block';
} else {
x.style.display = 'none';
}
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
})
});
</script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</body>
</html>
To delay the AJAX request simply wrap the $.getJSON call in a setTimeout(). Also note that you're using an odd mix of jQuery and native JS functions. I'd suggest using one or the other, something like this:
$("#refreshBtn").on("click", function() {
$('#myloader').show();
setTimeout(function() {
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function(data) {
$('#myloader').hide()
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
})
}, 2500);
});
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
#keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0px;
opacity: 1
}
}
#keyframes animatebottom {
from {
bottom: -100px;
opacity: 0
}
to {
bottom: 0;
opacity: 1
}
}
#myDiv {
display: none;
text-align: center;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name">Real-time Bitcoin Price</h1>
<div id="myloader" style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
Also I'd suggest that adding a 2.5 second delay is far too much. I'm aware that adding a slight delay to make it more obvious that data has loaded is a good idea for UX, however I'd say that 500ms would be more than enough.
First - objects/elements:
You should always cache elements that you use more than once. Means: Assign an object to a variable that can be accessed everywhere you need it. Why? Because you can use the variable as often as you like. This saves much time and processing power because you don't need to look for an element with a certain id or class again and again. This is in my case the var x.
Second - the loader:
There are easy things like show() and hide() in jQuery, but I used ternary operation. Why? It is extremely flexible and I use it all day since I knew about it. So I want to show you this as a handy option :-).
Third - the timeout:
Pretty straight forward, wrap your function in a setTimeout() and there you go.
Here is a working fiddle:
EDIT: Now you could wrap the x.style.display lines in a separate function and call this so you can reuse the code and don't have to write it twice, but I think for demonstration purpose this should be fine.
var x = document.getElementById('myloader');
document.getElementById("refreshBtn").addEventListener("click", function () {
x.style.display = (x.style.display === 'none') ? 'block' : 'none';
setTimeout(function(){
$.getJSON("https://api.coindesk.com/v1/bpi/currentprice.json", function (data) {
x.style.display = (x.style.display === 'none') ? 'block' : 'none';
$("#cointime").text(data.time.updated);
$("#dollar").text("USD : " + ' ' + data.bpi.USD.rate);
$("#gbp").text("GBP : " + ' ' + data.bpi.GBP.rate);
$("#euro").text("EUR :" + ' ' + data.bpi.EUR.rate);
});
},2500);
});
#myloader {
position: relative;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: 25% -50;
border: 16px solid #000;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Add animation to "page content" */
.animate-bottom {
position: relative;
-webkit-animation-name: animatebottom;
-webkit-animation-duration: 1s;
animation-name: animatebottom;
animation-duration: 1s
}
#-webkit-keyframes animatebottom {
from { bottom:-100px; opacity:0 }
to { bottom:0px; opacity:1 }
}
#keyframes animatebottom {
from{ bottom:-100px; opacity:0 }
to{ bottom:0; opacity:1 }
}
#myDiv {
display: none;
text-align: center;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container container-table">
<div class="row vertical-center-row">
<div class="col-md-4 col-md-offset-4">
<h1 id="name" >Real-time Bitcoin Price</h1>
<div id="myloader" style="display: none;"></div>
<p id="cointime"></p>
<div id="dollar"></div>
<div id="gbp"></div>
<div id="euro"></div><br>
<button id="refreshBtn" class="btn btn-primary">Load Data</button>
</div>
</div>
</div>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
var timeout = null
function refresh () {
function load () {
$.getJSON('https://api.coindesk.com/v1/bpi/currentprice.json', function (data) {
$('#cointime').text(data.time.updated)
$('#dollar').text('USD : ' + data.bpi.USD.rate)
$('#gbp').text('GBP : ' + data.bpi.GBP.rate)
$('#euro').text('EUR : ' + data.bpi.EUR.rate)
timeout = null
})
}
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(load, 2500)
}
document.getElementById('refreshBtn').addEventListener('click', refresh)
I have two boxes:
<div class='item' style='transform:translateY(100px)'>
</div>
<div class='item' style='transform:translateY(300px)'>
</div>
They both use the same class:
.item {
position:absolute;
background:red;
animation:float 3s ease-in-out infinite;
width:100px;
height:100px;
}
The animation looks like:
#keyframes float {
from, to { transform: translateY(-10px); }
50% { transform: translateY(10px); }
}
But this makes both boxes go between -10 and 10px. What I'd like is for it to be relative to the current value of the box.
So box1 at y:100px would animate from 90px to 110px
and box2 at y:300px would animate from 290px to 310px
Is it possible to do this in css? I'd rather not have a specific animation per box. Because I may have hundred of boxes.
jsfiddle:
https://jsfiddle.net/foreyez/1n1en8uk/
This shows that at the point of animation, both boxes are at the same place... but if it were relative animation they would just be floating up and down in their current place.
Note: please don't use top/left to get relative position I'm looking specifically for relative TRANSFORMS. (if you must know why I'm doing this in 3d for the z axis as x,y are already used).
You can set position of .item elements to relative; use :nth-of-type() pseudo selector to set the top property of each element to the initial position where element should be animated from between the 20px range in relation to its .item sibling.
.item {
position: relative;
background: red;
animation: float 3s infinite ease-in-out;
width: 100px;
height: 100px;
}
.item:nth-of-type(1) {
top: 100px;
}
.item:nth-of-type(2) {
top: 300px;
}
#keyframes float {
from, to {
transform: translateY(-10px);
}
50% {
transform: translateY(10px);
}
}
<div class="item">
</div>
<div class="item">
</div>
jsfiddle https://jsfiddle.net/1n1en8uk/3/
Here's a nasty javascript solution (yes, I'm looking for a CSS solution that's why I won't mark this as the answer) that injects a dynamic keyframe to the page:
As long as there are less than 100 boxes should work alright I guess.
https://jsfiddle.net/foreyez/6v7n4ro3/
function getTranslateY(obj)
{
var transformMatrix = obj.css("-webkit-transform") ||
obj.css("-moz-transform") ||
obj.css("-ms-transform") ||
obj.css("-o-transform") ||
obj.css("transform");
var matrix = transformMatrix.replace(/[^0-9\-.,]/g, '').split(',');
var x = matrix[12] || matrix[4];//translate x
var y = matrix[13] || matrix[5];//translate y
return parseInt(y);
}
function insertAnimation(idx, yy)
{
var style1 = document.documentElement.appendChild(document.createElement("style")),
rule1 = "#keyframes float" + idx + " {\
from, to { transform: translateY("+ (yy-10) +"px); }\
50% { transform: translateY(" + (yy+10) + "px); }\
}";
style1.sheet.insertRule(rule1, 0);
}
$(".item").each(function(idx) {
var currentTranslateY = getTranslateY($(this));
insertAnimation(idx, currentTranslateY);
$(this).css('animation','float' + idx + ' 3s ease-in-out infinite');
});
Note: please don't use top/left to get relative position I'm looking
specifically for relative TRANSFORMS.
You can adjust html to single .item element as child of a container element with transform set to translateY(100px), position set to absolute; utilize css :after pseudo element at .item element with transform set to translateY(200px)
.float {
transform: translateY(100px);
position: absolute;
}
.item {
animation: float 3s infinite ease-in-out;
}
.item, .item:after {
display: block;
position: relative;
background: red;
width: 100px;
height: 100px;
}
.item:after {
content: "";
transform: translateY(200px);
}
#keyframes float {
from, to {
transform: translateY(-10px);
}
50% {
transform: translateY(10px);
}
}
<div class="float">
<div class="item">
</div>
</div>
jsfiddle https://jsfiddle.net/1n1en8uk/5/
I know how to run the animation from point A to point B, so to speak, but do not know how to run continuously in a circle. Below is a small code prepared:
.bg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg) top left/30%;
animation: bg 2s cubic-bezier(0, -0.02, 1, 0.99);
}
#keyframes bg {
0% {
background-position: left -100px;
}
100% {
background-position: left 0px;
}
}
<div class="bg"></div>
help with script
If by:
run continuously in a circle
You mean run animation in a loop, then you can add the infinite animation-iteration-count property. In the shortcode you can just add infinite to your animation property. See demo:
.bg {
display: block;
position: absolute;
width: 100%;
height: 100%;
background: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg) top left/30%;
animation: bg 2s cubic-bezier(0, -0.02, 1, 0.99) infinite;
}
#keyframes bg {
0% {
background-position: left -100px;
}
100% {
background-position: left 0px;
}
}
<div class="bg"></div>
Edit: jQuery Solution
With jQuery you can use the animate() function to achieve the same effect.
// bg animation function
function bgAnimate(speed) {
// define bg div
var el = $('.bg');
// get current background y-axis position and convert to integer (strips `px`)
var posY = parseInt(el.css("background-position-y"));
// animate element
el.animate({
'background-position-y': posY + 100 // add 100px
},{
duration: speed,
easing: 'linear',
complete: function() {
bgAnimate(speed); // repeat aniamtion (loop)
}
});
}
bgAnimate(1000); // call function
html, body {padding: 0;margin: 0;}
.bg {
display: block;
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-image: url(http://www.dejurka.ru/wp-content/uploads/2015/06/watercolor-patterns4.jpg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="bg"></div>
I'm using the below; but the margin isn't nearly as approximate as text-align:center; is there anyway I could toggle text-align: center; to occur with a animation transition until it gets to the point of text-align: center; similar to that which is achieved with the below.
if ($(".resource-section").hasClass("resource-section--expanded")) {
$(".resources__header h2").animate({"marginLeft": "40%"}, "slow");
}
You can use a centering technique that allows you to horizontally center any element.
It can be animated using only CSS
.test {
position: absolute;
transform: translateX(0%);
left: 0%;
animation: center 2s infinite;
}
#keyframes center {
0%, 10% {
transform: translateX(0%);
left: 0%;
}
90%, 100% {
transform: translateX(-50%);
left: 50%;
}
}
<h1 class="test">TEST</h1>
You could animate center align using margin-left like this
var h1 = $('h1').width();
var parent = $('.container').width();
$('h1').animate({'margin-left':(parent/2-h1/2)}, 1500);
.container {
border: 1px solid black;
height: 100px;
}
h1 {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<h1>Text</h1>
</div>
From what i understood if you want to use the text-align:center property something like this could be of help to you, but the text-align property can't be animated
$(function(){
$('.resources_header h2').click(function(){
$(this).toggleClass('align-center');
});
});
.align-center{
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="resources_header">
<h2>HEADER</h2>
</div>
</div>
A problem with this is the animation so if what you want to achieve is to animate from left to center then why not:
$(function(){
$('.resources_header h2').click(function(){
var windowHalfWidth = $(window).width()/2;
$(this).css('position','absolute');
var elemHalfWidth = $(this).width()/2;
var left = windowHalfWidth - elemHalfWidth;
$(this).animate({
marginLeft: left
},"slow",function(){
$(this).css('position','static');
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="resources_header">
<h2>HEADER</h2>
</div>
</div>