I created a carousel with React.js, it was simple until I arrived at the animation problem. The carousel is classic, it is composed of "slides" of content, of small bullets indicating the current slide, and of small thumbnails for navigating between the slide.
The carousel component is data-driven, meaning that it is passed its content as a javascript array of objects. Each slide is a li tag within a ul, and just have to change the margin-left css property of the ul to move from one slide to another.
I'm wondering if I should use the ReactTransitionGroup or ReactCSSTransitionGroup to animate the transition from one slide to another. Basically the transition is a sliding effect from left to right when going from one slide to another.
My understanding is that the ReactTransitionGroups API is helpful when adding or removing some content. Here I won't add/remove any slide, change changing the visible one with an animation.
My difficulty wrapping my head around this is that I developped a static (aka without animation) carousel where the currently displayed slide is the only state saved in the component. This state is just the index of the slide in the array of slides. So when I click a thumbnail to navigate slide number n, the only thing I do is updating this internal state, then the rendering takes care of setting the left style property based on this index.
I don't see how I can add animation to this carousel. Any help/hint greatly appreciated.
The answer was fairly simple, no need to use ReactTransitionGroup or ReactCSSTransitionGroup. I simply used inline css with css3 transitions.
In the render function, we dynamically calculate the left property. As our slides all have the same fixed width, the slides are displayed inline and only one slide is made visible thanks to overflow: hidden on the parent element. Our dynamic class code looked like this :
var styles = {
position: "absolute",
top: 0,
left: IMG_WIDTH * (this.props.idx - this.props.activeIdx),
zIndex: 100,
transition: 'left 1s',
width: '100%'
};
Don't look at the formula too much, it's an implementation detail.
Further note, our carousel is "infinite", meaning that the transition always go one way - from left to right - even when on the first or last element. It was "just" a matter of playing with the indices of the array of content. This part was a bit harder than the carousel itself.
Side note (even troll) : even the hard part was better that doing tricky and cabalistic direct DOM manipulation since it was pure algorithms with data. No more jQuery for this stuff, and even for the rest of our website.
Related
I have an horizontal slider with lots of "cards".
The JS code that defines its CSS is as follows:
cardCarouselSlider: {
zIndex: 0,
overflow: 'hidden',
width: 300 * cardsNumber,
height: 200,
position: 'absolute',
left: (targetedPlanIndex >= 0)
? -281 * targetedPlanIndex + 40
: -281 * (targetedPlanIndex + 1) + 40,
transition: 'left 0.5s ease',
},
As the value of left shows, I can have the slider slide horizontally by changing the value of targetedPlanIndex.
However, my customer wants to have also a scrollbar (you see it in the image) to be able to scroll rapidly between the cards.
Problem is: when I increase targetedPlanIndex, the slider scrolls to the left, but the scrollbar remains always glued to its start position. See next image, where the index was increased by 1:
I'd like to see the scrollbar slide to the right as the slider goes left, as it would happen if I used the scrollbar to move the slider (see third image).
Any idea how I could do this?
My page is built with React, so basically I believe I am willing to attach some scroll event listener to my slider div, and not to the whole document. After that, there should be some useScrollPosition hook to tinker with.
After pursuing this quest for another couple of days, I haven't been able to find examples of React hooks that are able to detect/manage the scroll of individual components in page, let alone horizontal scroll.
I have solved my problem by leaving CSS aside and putting in place a JS/DOM-based solution, catering to the Element methods that control scroll.
These React solutions are all based on using a useRef hook tied to the page Element that is to be controlled, and accessing its methods through the current property of the reference.
The main drawback of these solutions is that (regardless of what the standards seem to promise) I cannot exploit CSS easing functions to implement a smooth scroll transition: for that I was forced to use a setInterval/setTimeout solution to perform many partial scrolls of my component.
How to make section sliding like on http://basharova.ru/?
Main question is how to make and follow scrolling if all elements have absolute position and top: 0?
I tried to make body.style.height = height of all sections, but how to do returning to previous section?
With blackout opacity i had idea to get opacity value from height of visible part of previous section.
It's called "Parallax" and there are libraries to get this done. This is a nice overview: https://cssanimation.rocks/parallax/
my question is how can I add specific movement to x-y axis for an HTML element according to mouse movements.
Look at the site here and scroll to second slide:
http://community.saucony.com/kinvara3/
How can i achieve such effect!?
If you're going to write the library-free version, you will need to start with the following:
Learn DOM-manipulation.
var myEl = document.querySelector("#my-el");
Learn the <element>.style interface.
myEl.style.position = "absolute";
Learn the CSS properties, their values and how to read/use them from the style interface.
myEl.style.left = 10 + "px";
You'll need to understand the following CSS properties at a minimum:
"display"
"position"
"top"
"left"
"z-index"
Learn how to parse numbers from strings, properly, in JS.
...this will be unimportant, working with the mouse,
but very important, working with the DOM.
Learn how to write event-handlers.
window.addEventListener("mousemove", function (evt) {/*mousemove event object*/});
Learn the properties of event-objects (specifically the event-types that are important, like mouse, keyboard, touch).
Learn how to manage events, and control the number/frequency of operations, based on an ideal framerate, when the browser won't do it for you.
Learn how to make all of these things happen in a cross-browser, IE8+ way.
Learn a little linear-algebra (honestly, learning enough of it to understand an inverted-axis scaled-parallax is just a tiny bit harder than Grade 6 geometry.
You can get a similar effect CSS only, no JS needed!
You can see an example here: Pure CSS 3D Meninas, by Román Cortés. In his blog, there is also the explanation.
Basically, you have to split the target element in small elements, and on hover, set the position of different background layers according to your trigonometric calculations.
From his explanation,
There are 80 vertical hover elements of 5*455 pixels each, covering
the full effect. Each hover element contains inside elements to define
every layer position, the background image and the lateral background
image. When the hover element is not active (without the mouse over
it), all is inside elements showing images are hidden, with display:
none.
When the hover element is active, the images are set to display:
block, and the position of these are set. These positions have been
calculated and are written in the CSS code for each layer and each of
the 80 vertical hover elements. This is what does the magic.
I've coded two small jQuery based scripts, one of accordions, and one of tabs, but then i realized that they were the same : get the clicked tab's index among other tabs, and only show the content that has the same index among contents.
But there's one annoying difference between the two : the animation. While tabs are only using the display property, accordions need to animate the height of content blocks.
Problem is that it is not possible to animate from height: 0; to height: auto;. There is a way to do it differently, using max-height, as described in [this] other SO question, but i don't really like this solution because it's hard-coded and doesn't always work.
Is there a way to animate a block's height from 0 to it's content height without using max-height or javascript ?
Thanks for your help !
No. CSS transitions can only go from a value (or no value indicating a zero value) to another value. They cannot go from a value (or zero value) to a non-zero undetermined value.
I'm very new to CSS/HTML/JS so I don't have lots of experience with CSS transitions.
I'm trying to animate a div elements on my page, but I can't achieve a desired result so far.
Here is my problem:
In my HTML I have a div container element that has 5 div elements inside of it. They look like simple boxes positioned in the middle of the screen and aren't visible for now. I also have 5 buttons in the corner of the screen.
What I'm trying to do is:
when I click a button (for example button 3) 3 of the divs on the left should disappear and be moved to the left behind the margin of the screen and 2 of the divs should do the same, but move to the right. After that I want 3 divs that are on the right slide back to the screen and 2 divs on the right should slide back as well. So it looks like they sliding towards each other to the positions they started from initially.
I'm trying to do this effect using CSS transitions (transform: translateX(Npx);). So in my JS file I have something like this:
$(document).ready(function() {
$(".button").click(function(){
// PART 1
// move 3 divs to the left using transform: translateX(Npx) (no animation)
// move 2 divs to the left using transform: translateX(Npx) (no animation)
// PART 2
// slide 3 divs to the left using transform: translateX(Npx) (with animation)
// slide 2 divs to the left using transform: translateX(Npx) (with animation)
});
So the problem is that in this case only the part one works and part two seems to be not working.....if I attach the part on code to a different event...like another click button...it works just fine.
So my question is if these two transitions can be done under one event?!?!
I have done this, and this kind of effect can look great. If I understand your question correctly, your issue is that you run the animation AFTER you moved the divs, so your animation function uses the wrong starting point.
What you need is:
Be sure you have a CSS position:relative; set on your divs so the animation can work.
Run your animation function moving your divs relative to their current position (i.e. top, left), and include a success callback. You may need to first use offset() and some math to figure out the distance traveled.
On the completion of your animation (success callback), change the relative position of your divs back to 0px (or whatever they were before) and simultaneously perform the function where you actually move the divs to their new position in the DOM using insertBefore(). I've never seen a flicker since these functions are near-instant, but if you see an issue you can set visibility to hidden while you reset the position and move the divs, and then reset the visibility afterward
You can even set custom z-indexes for your divs during the animation that you reset on the success callback, allowing you to determine which elements the divs pass over/under or specifying which is on top if they cross each other.