I've used WAAPI to create an image slider for a (kind of) sing along game. The slider is linked with a song, so the animation timing is very important. Using WAAPI keyframes (which are very similar to CSS keyframes) the timing offset is on a scale of 0-1, hence the calculations necessary for creating the keyframes dynamically in the code pen below. The slider should continuously loop each next slide, including sliding from the last slide to the first slide again. The problem is that the animation doesn't seamlessly continue from slide5 back to slide0.
Here is how I dynamically set the keyframes:
var keyframes = []
var pause = 0.18
var anim = 0.02
var slideHeight = 150
var translateBy = 0
var a = {transform: 'translateY(0)'} //set initial keyframe before loop
keyframes.push(a)
var offsetPercent = 0 //offset var to increment by anim & pause vars.
for(let i=0; i<songVars.fileLength; i++) {
var b = {
offset: offsetPercent+= anim,
transform: 'translateY('+ translateBy +'px)'
}
var c = {
offset: offsetPercent+= pause,
transform: 'translateY('+ translateBy +'px)'
}
keyframes.push(b, c)
translateBy-= slideHeight;
}
var d = {transform: 'translateY('+ translateBy +'px)'};
keyframes.push(d)
This code pen shows that the image slider does not loop seamlessly from the last image back to the first image. That is because I can't find a way to achieve continuous, seamless looping with the WAAPI keyframes. The first slide (slide0) is initially out of view as the CSS is set to top: 100%; transform: translateY(-100%);. I did this because the slide should begin by sliding up from the bottom of the container div.
I originally had the slides beginning at position 0, so the slide0 does start from the bottom, but it doesnt work with the timing and runs out of time, and also takes a long time for the first slide to get into position: https://codepen.io/nancy-collins/pen/bGVKBQq
I also tried the slides beginning at position -300px, so the slide0 is in view and doesnt slide up from the bottom, but when it reaches slide5 it jumps to slide0, like this: https://codepen.io/nancy-collins/pen/vYNrvaa
I know that sliders are a common discussion on here but there are none with WAAPI. It's a very new API, but should surely be able to achieve a looping slider. Thanks.
For this effect I think there are a couple of approaches you could try. One is to generate different keyframes for each animation (example CodePen here).
However, I think you might find it easier if you position all the items on top of one another (using position: absolute; top: 0; left: 0 and using position: relative; width: 300px on the parent element). Then you can apply the same animation to each item but simply change the delay so that they are staggered appropriately.
Using this approach, the translation positions would not change based on the number of slides. You would position all the frames just below the viewport, then animate them up in three steps, and then return them to their original position just below the viewport. The keyframe offsets, however, would change based on the number of slides so that you could create a suitably long "flat" section at the end where you are waiting for the other slides to finish before repeating.
Related
I am trying to set a smooth transition for internal content when swiping (transform: scale). I added the required css rule. This works, but after switching the last slide, there is an abrupt scale change. (not smoothly).
In the source code of the library in the file swiper/src/core/loop/loopFix.js I found line number 28: const slideChanged = swiper.slideTo(newIndex, 0, false, true);
From this, I realized that the looping of the slides occurs according to the following principle: after the last slide, we instantly switch to the previous one (speed = 0) and an animation is produced that shows that we have passed the circle.
My code example: https://stackblitz.com/edit/swiper-demo-9-vertical-slider-x3g4my
Steps to reproduce the problem:
Swipe two slides down
Swipe a third time down and notice the sudden change in scale
Is there any way to fix this problem?
I had a similar issue with Swiper when looping the slide items and doing transitions/transforms on the active slide.
I found that I could add .swiper-slide-duplicate-active as well.
I tried updating your demo and if seems the following change makes the transition smooth.
.swiper-slide .content {
transform: scale(0.5);
}
.swiper-slide-active .content,
.swiper-slide-duplicate-active .content {
transform: scale(1);
}
Project: https://3milychu.github.io/criminal/
I have about 6000 divs in a horizontal scrolling parent container.
Each second, I scroll to the next div using the scrollTo method using behavior: 'smooth'
This results in an abrupt motion, stopping at each div before continuing to the next.
Is there a way to make the parent container scroll continuously at a consistent speed without stopping while keeping the target div at each second in the center of the viewport?
function sonify(data){
var counter = -1;
setInterval(function() {
if(counter<6172){
counter++
container = document.querySelector('#track1')
person = document.querySelector('#person'+counter)
hover(person)
target=person.offsetLeft - window.innerWidth/2;
container.scrollTo({
left: target,
behavior: 'smooth'
});
playVerdict(data,counter)
playPriors(data, counter)
playFelonies(data,counter)
playFemale(data,counter)
}
},808)
}
For something like that, your best bet is to roll your own with requestAnimationFrame and manually setting the container offset each frame. Basically think of a very simple game engine loop. Since it looks like you're syncing with audio, you need high precision, and css transitions can lag and probably will desync at some point.
You may have seen that in some games there's moving background that goes on diagonal. Take a look at this example of Megaman x Storm Eagle Stage https://youtu.be/Wfm3ZvcxOKQ?t=1m33s, the clouds are moving on from up to bottom, right to left (Diagonal). I need to achieve the same effect using CSS3 or any kind of javascript, with a tile texture.
Where can I find a tutorial teaching how to make that? I found some, but they are for creating dynamic objects.
Hi this could be solved using basic javascript or any javascript library. I will give a small working example or you can just jump to this js fiddle https://jsfiddle.net/lesshardtofind/a2Lx51xy/
In your html you just need one element.
<div class='background'></div>
The class is for us to select it. First with some css lets make it so we have a picture and can see it.
.background{
background-image: url('yourImageUrl.com/image.png');
height: 500px;
width: 500px;
}
So background image applies your texture, height, and width will apply values so that you can see the div otherwise it would be 0 with no actual markup inside.
Now for the fun part. JavaScript can grab this div element and apply a style. Normally I would do this in jQuery, but since you just specified javaScript I'll keep external libraries out of it.
var x = 0;
var y = 0;
var xSpeed = 5;
var ySpeed = 5;
var interval = setInterval(function(){
var xVal = x + 'px';
var yVal = y + 'px';
var bg = document.getElementsByClassName('background')[0].style.backgroundPosition = xVal + " " + yVal;
x-=xSpeed;
y+=ySpeed;
}, 100);
To explain this I set x and y which are my background coordinates to 0 as a start. It is good to set default values otherwise you will invite undefined behavior. xSpeed, and ySpeed are just variables you can change the value of speed up or slow down the animation. interval is the variable that stores the interval set by the setInterval function. setInterval accepts a function and a time value as arguments. The function will be called at each interval and the time is the amount of time to wait until calling the function again.
document.getElementsByClassname('background') returns an array which I access with the [0] index. Then style allows you to apply a value to your backgroundPosition. Notice that I applied the 'px' to the end of each number so that they would be a string such as "3px 5px" this is how they are expected.
Then speed is applied using -= and +=. Since the dom starts at 0, 0 in the left corner of your browser then adding to Y will move down and subtracting from X will move left.
Lastly this works because background is set by default to repeat so the image will continue to just driftdownward and to the left. If you supply a tiled image you won't see the seams in between one repeat and the next.
Edit: Add fullscreen
You can add the fullscreen to your child object by making sure that its parents also have a set width and height. So changing your css to.
body, html{
height: 100%;
width: 100%;
}
.background{
background-image: url('http://bgfons.com/upload/sky_texture1998.jpg');
height: 100%;
width: 100%;
border: 1px solid red;
}
On % heights you need a parent node to inherit height from.
I've been trying to adapt the following code to integrate with my CSS3 slider (animated and timed with keyframes) however as you can't use .animate in js when using css3 animations on the same element I either have to use one or the other.
JS I've adapted for my slider
The current js works in the sense that it navigates through the slides my only issue is that it doesn't 'slide' to each slide it jumps.
I'd really like to keep the slideshow as it is and just want to update my js so that the slide transition works. I'm not great with js so I've been finding it difficult to find a solution.
If anyone could give some advice or a solution to my problem it would be truly appreciated.
DEMO
JS
//grab the width and calculate left value
var item_width = $("#carousel .video-list li").outerWidth();
var left_value = item_width * (-1);
//if user clicked on prev button
$('#previous').click(function () {
//get the right position
var left_indent = parseInt($("#carousel .video-list").css('left')) + item_width;
//slide the item
$("#carousel .video-list").animate({'left' : left_indent}, function () {
//move the last item and put it as first item
$("#carousel .video-list li:first").before($("#carousel .video-list li:last"));
//set the default item to correct position
$("#carousel .video-list").css({'left' : left_value});
});
//cancel the link behavior
return false;
});
//if user clicked on next button
$('#next').click(function () {
//get the right position
var left_indent = parseInt($("#carousel .video-list").css('left')) - item_width;
//slide the item
$("#carousel .video-list").animate({'left' : left_indent}, function () {
//move the first item and put it as last item
$("#carousel .video-list li:last").after($("#carousel .video-list li:first"));
//set the default item to correct position
$("#carousel .video-list").css({'left' : left_value});
});
//cancel the link behavior
return false;
});
I don't see why .animate is needed, because I have used
transition: left 1s ease;
in my CSS to achieve the same things, with a smoother animation than I got with jQuery. I tried deleting the:
//slide the item
$("#carousel .video-list").animate(...
for the left and right. I also added some text to the html divs so that you can see how it's moving better. Sorry that I couldn't get it working, but I really feel that "transition" is what you need to look into. Here's the fiddle :)
...
I think your simplest solution would be to ditch the whole CSS animate, and build your own carousel:
Consider a film strip, which is a bunch of pictures lined up next to each other. Now consider a paper with a box cut-out, the size of one picture. We put the strip behind the paper, and see only one image. If we move the strip, we can change which image we see.
The film strip will be a div with { display: inline-block; } property, containing each of the videos. The box cut-out will be a div with { overflow: hidden } property. To move the strip, we simply use $('#strip').css({'left': positionofstripleft - widthofbox }) in our javascript. And for the animation, a simple setInterval(Nextfunction, 65000) to do what clicking next would do every 65 seconds.
Finally, a CSS transition will make the movements actually animated.
I have a vertical javascript marquee on my website (http://blogandthecity.net). I want it to be stuck at the screen. I think it is called "fixed". Right now the marquee stops at a certain point, but I want it to be the size of the whole screen/website.
I think there are two options:
1. make the marquee as long as possible (However some webpages are longer than others. And I don't know how I can make the marquee longer. I already tried some things)
2. make the position fixed. (I tried to put "position: fixed" in the code, but the result is that the marquee doesn't scroll anymore. So the movement stops. And the marquee doesn't fit the screen either..)
Do you know how I can solve this problem? If you need the css style, I will put it here too.
Below the code (I excluded the text part):
<script type="text/javascript" src="http://blogandthecity.net/js/marquee-packed.js" ></script>
<script type="text/javascript">
//create instance and call method horizontal for horizontal scrolling
var horizontal = new marquee("marquee").horizontal(
{
step:1, //how many pixels to move per interval (default: 1)
interval: 40, //how often to move pixels in miliseconds (default: 10)
stop_on_hover: true, //should marquee stop on mouse hover (default: true)
backwards: false, //rotate elements in opposite direction
});
<script type="text/javascript">
//create instance and call method horizontal for horizontal scrolling
var horizontal = new marquee("marquee2").horizontal(
{
step:1, //how many pixels to move per interval (default: 1)
interval: 40, //how often to move pixels in miliseconds (default: 10)
stop_on_hover: true, //should marquee stop on mouse hover (default: true)
backwards: false, //rotate elements in opposite direction
});
It is called position:fixed; Below the css for your marquees scrolling down and being full screen. You may need to go jQuery since they are styled inline (or modify the html?)
#marquee, #marquee2 {
position:fixed;
}
#marquee {
margin-top:140px;
}
#marquee2 {
margin-left:-520px;
}