Want a smoother animation when resizing images javascript - javascript

I have two images which are inside a container. The images are uploaded, so I won't know their sizes ahead of time. I used this function to resize the images to fit their container. The resizing works fine, but the animation is choppy. I was wondering if there was a way to make it look smoother.
$(window).load(function() {
window.SurveyCreator = new SurveyCreator();
setTimeout(function() {
equalheight('.options-container');
}, 1000);
});
$(window).resize(function() {
equalheight('.options-container');
});
equalheight = function(container) {
var currentTallest = 0,
currentRowStart = 0,
rowDivs = new Array(),
$el,
topPosition = 0;
$(container).each(function() {
$el = $(this);
$($el).height('auto')
topPostion = $el.position().top;
if (currentRowStart != topPostion) {
for (currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
rowDivs.length = 0; // empty the array
currentRowStart = topPostion;
currentTallest = $el.height();
rowDivs.push($el);
} else {
rowDivs.push($el);
currentTallest = (currentTallest < $el.height()) ? ($el.height()) : (currentTallest);
}
for (currentDiv = 0; currentDiv < rowDivs.length; currentDiv++) {
rowDivs[currentDiv].height(currentTallest);
}
});
}
Here's the html:
<div id="options-box" class="options-box">
<div class="options-container">
<img class="question-option" id="question-option-a">
</div>
<div class="options-container">
<img class="question-option" id="question-option-b">
</div>
</div>
Here's the css:
.question-option {
width: 100%;
}
.options-container {
width: 48%;
float: left;
background-color: #F2F1F5;
padding: 30px;
text-align: center;
margin: 0 1%;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
}
.options-box {
margin-top: 25px;
}

try adding a transition to the css of the container.
.options-container {
transition: 1s;
}
you may want to add browser specific versions of "transition" as well:
.options-container {
transition: 1s;
-moz-transition: 1s;
-webkit-transition: 1s;
-ms-transition: 1s;
}
also, to only animate height write "height 1s" instead of "1s".

Have you considered refactoring this to use .animate()? If you were to do that you could utilize VelocityJS which would make it smoother.

Related

scroll markers not triggered

In my scroll event listener I loop through all my .project elements then add or remove a class depending on their current position from the top of the viewport. I want to add a class to an element when it is at 80% of viewport height and remove it at 100% and 0%.
The logic I have should work fine, but the class rarely gets added at all.
var projects = document.querySelectorAll(".project");
var counter = document.getElementById("counter");
var viewH = window.innerHeight || document.documentElement.clientHeight;
window.addEventListener(
"scroll",
function() {
for (var i = 0; i < projects.length; i++) {
var project = projects[i];
// get dist from top of viewport
distTop = project.getBoundingClientRect().top;
distPercent = Math.round(distTop / viewH * 100);
// play at 80%
if (distPercent == "80") {
project.classList.add("play");
counter.innerHTML = i + 1;
}
// stop at 0%
if (distPercent == "0") {
project.classList.remove("play");
}
// stop if off screen
if (distPercent =="100") {
project.classList.remove("play");
}
}
},
false
);
window.addEventListener('resize', function () {
viewH = window.innerHeight || document.documentElement.clientHeight;
})
#half {
position:fixed;
top:50%;
height: 1px;
background: red;
width: 100%;
}
#projects {
padding-top:60vh;
width: 50vw;
margin: 0 auto;
}
#counter {
position: fixed;
top:20px;
left: 20px;
font-size:20px
}
.project {
background:pink;
height: 50vh;
width: 50vw;
margin-bottom:100px;
transition: background 0.3s ease-in-out;
}
.play {background:red}
* {
padding:0;
margin:0;
}
<div id="half"></div>
<div id="counter">0</div>
<div id="projects">
<div class="project">1</div>
<div class="project">2</div>
<div class="project">3</div>
<div class="project">4</div>
<div class="project">5</div>
</div>

How to make an html div to swiftly move to right (for less than 1 second) and disappear?

I would like to make an html div to swiftly move to right (e.g. for less than 1 second) and disappear. Then appear again directly at the position the div was at the very beginning of this process after 1 second. This process will be triggered by a button click and repeat by 10 times.
I tried to use transition-property in CSS to achieve this, but the result is not what I wanted. The div will directly disappear instead of disappearing after moving to right.
Could it be that what I want to do is impossible to achieve with CSS? If it is the case, what should I use?
The css code:
#box1 {
width: 100px;
height: 100px;
background: red;
-webkit-transition-property: left, right; /* Safari */
-webkit-transition-duration: 2s; /* Safari */
transition-property: left, right;
transition-duration: 2s;
position:absolute;
left: 0;
}
#box1:hover {
transition-delay:1s;
left: 100px;
transition-delay:1s;
opacity:0;
}
Javascript code:
var elem = document.getElementById("box1");
$('#b').click(function(){
var i = 0;
while (i < 10){
setTimeout(function(){
elem.setAttribute("style","left: 1000px;");
}, 500);
setTimeout(function(){
elem.setAttribute("style"," opacity: 0;");
}, 500);
i ++;
}
})
You can achieve this in so many ways :
1-using transition and css jQuery method:
//changing the style of the box using css method of jQuery
var animationDuration = 800;
var animationRepetition = 10;
//this array will be used to clear timeouts if user click while animation still going
var timeoutIds = [];
$("#css_method").click(function() {
for (var i = 0; i < timeoutIds.length; i++) {
clearTimeout(timeoutIds[i]);
}
timeoutIds = [];
for (var i = 0; i < animationRepetition; i++) {
var index = i;
var id1 = setTimeout(function() {
$("#box1").addClass("left-opacity-transition").css({
left: 500,
opacity: 0
});
}, 2 * index * animationDuration)
var id2 = setTimeout(function() {
$("#box1").removeClass("left-opacity-transition").css({
left: 0,
opacity: 1
});
}, ((2 * index) + 1) * animationDuration);
timeoutIds.push(id1, id2);
}
});
#box1 {
width: 100px;
height: 100px;
background-color: red;
position: relative;
left: 0;
}
button {
margin-top: 30px;
}
.left-opacity-transition {
-webkit-transition-property: left, opacity;
/* Safari */
-webkit-transition-duration: .8s;
/* Safari */
transition-property: left, opacity;
transition-duration: .8s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div id="box1"></div>
<button id="css_method" type='button'>use css method</button>
2-using animate jQuery method :
//using the animate method of jQuery you can remove the transition from style
var animationDuration = 800;
var animationRepetition = 10;
$("#animate_method").click(function() {
var $box1 = $("#box1");
$box1.finish();
for (var i = 0; i < animationRepetition; i++) {
$box1.animate({
left: 500,
opacity: 0
}, 800, function() {
$box1.css({
left: 0,
opacity: 1
});
});
}
});
#box1 {
width: 100px;
height: 100px;
background-color: red;
position: relative;
}
button {
margin-top: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div id="box1" class="fade-in-left"></div>
<button id="animate_method" type='button'>use animate method</button>
3-using translate in a css class :
//using the translateX you also can change the element position in X axis
var animationDuration = 800;
var animationRepetition = 10;
//this array will be used to clear timeouts if user click while animation still going
var timeoutIds = [];
$("#translate_button").click(function() {
for (var i = 0; i < timeoutIds.length; i++) {
clearTimeout(timeoutIds[i]);
}
timeoutIds = [];
for (var i = 0; i < animationRepetition; i++) {
var index = i;
var id1 = setTimeout(function() {
$("#box1").addClass("transform-opacity-transition translate-fade-left");
}, 2 * index * animationDuration);
var id2 = setTimeout(function() {
$("#box1").removeClass("transform-opacity-transition translate-fade-left");
}, ((2 * index) + 1) * animationDuration);
timeoutIds.push(id1, id2);
}
});
#box1 {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
button {
position: absolute;
top: 150px;
}
.translate-fade-left {
transform: translateX(500px);
-webkit-transform: translateX(500px);
opacity: 0;
}
.transform-opacity-transition {
-webkit-transition-property: transform, opacity;
/* Safari */
-webkit-transition-duration: .8s;
/* Safari */
transition-property: transform, opacity;
transition-duration: .8s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<div id="box1"></div>
<button id="translate_button" type='button'>use translate</button>

multiple slideshow on one page works bad

a beginner here : )
I know it's been asked before but I couldn't find a solution yet. I have two automatic slideshows running one beneath the other on one page. they both work, but work awfully bad, the timing is not as set and it's not looping as it should be. but - if I keep only one slideshow in the page, it works perfectly fine. I'm struggling with it for hours already.
this is my html:
<div class= "gallry">
<ul id="slides" dir="rtl" onclick="nextSlide">
<li class="slide showing"> <img id="firstImg" src=".img.jpg"> </li>
<li class="slide"> <img src=".img1.jpg"></li>
<li class="slide"><img src=".img2.jpg"></li>
</ul>
</div>
<div class="gallery">
<ul id="slides2" dir="rtl">
<li class="slidetwo showing"> <img id="firstImg2" src=".img3.jpg"></li>
<li class="slidetwo"><img src=".img4.jpg"></li>
<li class="slidetwo"><img src=".img5.jpg"></li>
</ul>
</div>
this is my css
#slides {
position: relative;
height: 100%;
padding: 0;
margin:0;
list-style-type: none;
}
#slides2 {
position: relative;
height: 100%;
padding: 0;
margin:0;
list-style-type: none;
}
.slide {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
.slidetwo {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
img {
max-height: 95vh;
max-width: calc(100vw - 80px);
}
.showing {
opacity: 1;
z-index: 2;
}
and this is my javascript:
var slides = document.querySelectorAll('#slides .slide');
var currentSlide = 0;
var slideInterval = setInterval(nextSlide,3000);
function nextSlide() {
slides[currentSlide].className = 'slide';
currentSlide = (currentSlide+1)%slides.length;
slides[currentSlide].className = 'slide showing';
}
var slides2 = document.querySelectorAll('#slides2 .slidetwo');
var currentSlide = 0;
var slideInterval = setInterval(nextSlideTwo,1000);
function nextSlideTwo() {
slides2[currentSlide].className = 'slidetwo';
currentSlide = (currentSlide+1)%slides2.length;
slides2[currentSlide].className = 'slidetwo showing';
}
thanks a lot !
So the first thing I see is that you're trying to reuse the same global variables for both slideshows. What's happening is that when both of those calls in the setInterval() are running, they're addressing the same variables, which would result in the images being displayed out of order, timing issues, and other similar things.
What I'd recommend trying would be trying to separate the variables out, so that nextSlide() and nextSlideTwo() are addressing and updating different things as they run. For example:
var slides = document.querySelectorAll('#slides .slide');
var currentSlide = 0;
var slideInterval = setInterval(nextSlide,3000);
function nextSlide() {
slides[currentSlide].className = 'slide';
currentSlide = (currentSlide+1)%slides.length;
slides[currentSlide].className = 'slide showing';
}
var slides2 = document.querySelectorAll('#slides2 .slidetwo');
var currentSlide2 = 0;
var slideInterval2 = setInterval(nextSlideTwo,1000);
function nextSlideTwo() {
slides2[currentSlide2].className = 'slidetwo';
currentSlide2 = (currentSlide2+1)%slides2.length;
slides2[currentSlide2].className = 'slidetwo showing';
}
Will throw this in a fiddle shortly to see how it runs and if any additional tweaks are needed.

CSS slide in from left animation

I'm working on a slideshow and it works, except for the animations. The animation for sliding out works fine but the animation for sliding in from the left does not. The left margin gets set to 0% but there is no animation, even though it is set to -100% at first.
Javascript:
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
]
function slideShow(startAt){
var holder = document.getElementById("currentImage");
var img = document.createElement("img");
img.src = images[startAt];
holder.appendChild(img);
nextPicture(startAt, img);
}
function nextPicture(current, currentElement){
var holder = document.getElementById("currentImage");
setTimeout(function(){
currentElement.className = "translateLeft";
current += 1;
var img = document.createElement("img");
img.src = images[current];
img.style.marginLeft = "-100%";
holder.appendChild(img);
img.className = "translateIn";
if (current == 5){
current = -1;
nextPicture(current, img);
} else {
nextPicture(current, img);
}
}, 5000)
}
slideShow(0);
CSS:
.translateLeft {
transition: 3s;
margin-left: 100% !important;
}
.translateIn {
transition: 3s;
margin-left: 0% !important;
}
Here is a solution for you.
https://jsfiddle.net/smaefwrp/2/
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
html,
body,
img {
position: absolute;
top:0;
left: 0;
margin: 0;
padding: 0;
height: 100%;
overflow-x: hidden;
}
#currentImage {
height: 100%;
width: 1920px;
}
.translateOrigin {
transition: none;
transform: translate3d(-100%, 0, 0) !important;
}
.translateLeft {
transition: transform 3s;
transform: translate3d(100%, 0, 0) !important;
}
.translateIn {
transition: transform 3s;
transform: translate3d(0, 0, 0) !important;
}
</style>
</head>
<body>
<div id="currentImage">
</div>
<div id="buttons">
</div>
<script type="text/javascript">
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
];
var imageEle = [];
var currImage = 0;
var holder = document.getElementById("currentImage");
function imagesPreload() {
for (var i = 0; i < images.length; i++) {
var img = new Image();
img.src = images[i];
img.className = "translateOrigin";
holder.appendChild(img);
imageEle.push(img);
}
}
imagesPreload();
document.onkeydown = function(event){
if(event.keyCode === 13) {
nextPicture();
}
};
function slideShow(startAt) {
var holder = document.getElementById("currentImage");
imageEle[currImage].className = "translateIn";
nextPicture();
}
function nextPicture() {
setTimeout(function () {
var img = imageEle[currImage];
img.addEventListener("transitionend", transitionEnd, false);
img.className = "translateLeft";
if (currImage == 5) {
currImage = 0;
} else {
currImage++;
}
imageEle[currImage].className = "translateIn";
/* Reset the image to original position */
function transitionEnd() {
img.className = "translateOrigin";
img.removeEventListener("transitionend", transitionEnd, false);
nextPicture();
}
}, 5000)
}
slideShow(currImage);
</script>
</body>
</html>
To create a nice slideshow I suggest to use css transform property rather than the margin. The idea is to create the placeholder element currentImage with relative position, and then create all images inside it with position set to absolute. Then by default all images are translated out of the placeholder element, and adding/removing classes show and hide you can place them inside the view and then outside of it, like this:
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
];
// Get the holder
var holder = document.getElementById("currentImage");
// Create the images
images.forEach(function(url) {
var img = document.createElement("img");
img.src = url;
holder.appendChild(img);
});
// Image counter
var counter = 0;
// Slide show interval
var slideshow = setInterval(function() {
// When we reach the end of images we shut down the slide show
// or you can reset the counter to start over
if(counter === images.length) {
clearInterval(slideshow);
return;
}
// Get all images
var nodes = holder.getElementsByTagName("img");
// Hide previous image
if(nodes[counter - 1]) {
nodes[counter - 1].className = "hide";
}
// Show next image
nodes[counter].className = "show";
counter++;
}, 2500);
#currentImage {
background: gray;
width: 300px;
height: 300px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
#currentImage img {
width: 100%;
position: absolute;
transform: translateX(-110%);
-webkit-transition: -webkit-transform 1.0s ease 0s;
-moz-transition: -moz-transform 1.0s ease 0s;
-o-transition: -o-transform 1.0s ease 0s;
transition: transform 1.0s ease 0s;
}
#currentImage img.show {
transform: translateX(0%);
}
#currentImage img.hide {
transform: translateX(110%);
}
<div id="currentImage">
</div>
You can try something like:
// HTML
<div id="currentImage">
<div class="window">
<div class="image-list">
<div>
<img src="http://i.imgur.com/ByyUANz.png" />
</div>
<div>
<img src="http://i.imgur.com/S5FfOOB.png" />
</div>
<div>
<img src="http://i.imgur.com/EuefPdv.png" />
</div>
<div>
<img src="http://i.imgur.com/Ucvm4pJ.png" />
</div>
<div>
<img src="http://i.imgur.com/pK5WBHN.png" />
</div>
<div>
<img src="http://i.imgur.com/nuOLVpy.png" />
</div>
</div>
</div>
</div>
And CSS
// CSS
img {
height: 50px;
width: 50px
}
.window {
position: absolute;
height: 50px;
width: 50px;
border: 2px solid red;
overflow: hidden
}
div {
display: inline-block
}
.image-list {
list-style-type: none;
display: inline-block;
padding-left: 0px;
margin: 0px;
width: 350px;
animation: slidingli 30s ;
}
#keyframes slidingli {
0% {
transform: translateX(0px)
}
16% {
transform: translateX(-50px)
}
32% {
transform: translateX(-100px)
}
48% {
transform: translateX(-150px)
}
64% {
transform: translateX(-200px)
}
80% {
transform: translateX(-250px)
}
100% {
transform: translateX(-300px)
}
}
Checkout this fiddle. Also there are many libraries out there which provide what need For example: http://fotorama.io/customize/autoplay/

The Jquery image slider doesn't work in Chrome

I added a Jquery image slider to my website. But it doesn't work on Google Chrome. It works perfectly in Firefox. Any idea why? The site url : http://lit-falls-8182.herokuapp.com/
Can you see the last image smaller than the rest? and all the images disappear and never come back. It need to loop.
HTML code :
<div id="scroller" >
<div class="innerScrollArea">
<ul>
<% #slideimages.each do |simage| %>
<li><%= image_tag simage.gsub("app/assets/images/", ""), alt: "Slide Image", class: "slide-image" %></li>
<% end %>
</ul>
</div>
</div>
Css code :
#scroller {
border-bottom: 2px solid #FF9500;
box-shadow: 0 2px 20px #C4C4C4;
height: 160px;
position: relative;
width: 100%;
z-index: 19;
.innerScrollArea {
overflow: hidden;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
ul {
padding: 0;
margin: 0;
position: relative;
}
li {
padding: 0;
margin: 0;
list-style-type: none;
position: absolute;
}
.slide-image{
z-index: 1;
padding: 2px;
display: block;
opacity:0.8;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
-ms-transition: all 0.5s ease;
transition: all 0.5s ease;
&:hover {
z-index: 2;
border: 2px solid #FF9500;
transform: scale(1.1);
opacity:1;
padding: 0px;
}
}
}
Javascript code :
$(function(){
var scroller = $('#scroller div.innerScrollArea');
var scrollerContent = scroller.children('ul');
scrollerContent.children().clone().appendTo(scrollerContent);
var curX = 0;
scrollerContent.children().each(function(){
var $this = $(this);
$this.css('left', curX);
curX += 224;
});
var fullW = curX / 2;
var viewportW = scroller.width();
// Scrolling speed management
var controller = {curSpeed:0, fullSpeed:1};
var $controller = $(controller);
var tweenToNewSpeed = function(newSpeed, duration)
{
if (duration === undefined)
duration = 600;
$controller.stop(true).animate({curSpeed:newSpeed}, duration);
};
// Pause on hover
scroller.hover(function(){
tweenToNewSpeed(0);
}, function(){
tweenToNewSpeed(controller.fullSpeed);
});
// Scrolling management; start the automatical scrolling
var doScroll = function()
{
var curX = scroller.scrollLeft();
var newX = curX + controller.curSpeed;
if (newX > fullW*2 - viewportW)
newX -= fullW;
scroller.scrollLeft(newX);
};
setInterval(doScroll, 20);
tweenToNewSpeed(controller.fullSpeed);
});
In your css file you have this bit of code:
img{
max-width:100%;
height:auto
}
Remove max-width:100%; to fix both of your problems.
I see your issue in Chrome, but I tried to replicate it on my system by pulling your scripts and it's not the same.
Having said that, you can see if you 'Inspect Element' that the images are there but just progressively smaller after the ones that show on the screen until they can't be seen. It could be related to screen size (which is why most commenters can't see it)
I'd try adding an explicit image size to the img tags width='220' height='165' or setting it in the javascript (jQuery) with something like:
$(".slide-image").width(220);
$(".slide-image").height(165);
before, during and/or after the scroll.

Categories

Resources