视差图得到视差
Recently I experimented with building a content slider (or carousel, if that’s your fancy) using React. I wanted to create some unique position-based cursor effects when the user hovers over the active slide. This eventually led to the parallax effect you’ll see in the final demo.
最近,我尝试使用React构建内容滑块(或轮播,如果您愿意的话)。 当用户将鼠标悬停在活动幻灯片上时,我想创建一些基于位置的独特光标效果。 这最终导致了您将在最终演示中看到的视差效果。
This post will dive into the details of the slider’s components, the dynamic CSS variables used for the parallax hover effect, and some of the other properties that brought this project to life.
这篇文章将深入探讨滑块组件的细节,用于视差悬停效果的动态CSS变量以及使该项目栩栩如生的其他一些属性。
See the Pen React Slider w/ Hover Effect by Ryan Mulligan (@hexagoncircle) on CodePen.light
请参阅CodePen .light上的Ryan Mulligan( @hexagoncircle )具有悬浮效果的Pen React Slider。
组件设置 (Component Setup)
This React slider consists of three components: Slider, Slide, and SliderControl. The SliderControl houses the button template used for the previous and next arrow controls. The Slider is the parent component that contains the methods for transitioning slides. Inside the Slider render template, an array of slide objects is iterated over and each slide’s data set is returned within a Slide child component using the map() method:
此React滑块由三个组件组成: Slider , Slide和SliderControl 。 SliderControl包含用于上一个和下一个箭头控件的按钮模板。 滑块是父组件,其中包含用于转换幻灯片的方法。 在Slider渲染模板内,迭代一个幻灯片对象数组,并使用map()方法在Slide子组件中返回每个幻灯片的数据集:
{slides.map(slide => {
return (
<Slide
key={slide.index}
slide={slide}
current={current}
handleSlideClick={this.handleSlideClick}
/>
)
})}
Each of these rendered slides has the following properties:
这些呈现的幻灯片均具有以下属性:
A unique
key
(learn more about keys in React here). This key grabsindex
from the slide’s data.唯一
key
(在此处了解有关React中键的更多信息)。 该键从幻灯片的数据中获取index
。A
slide
property equal to the slide object so the component can access that set of data.slide
属性等于幻灯片对象,因此组件可以访问该组数据。The
current
property grabs the Slider’scurrent
state value and controls the previous, current, and next classes being set on each slide.current
属性会获取Slider的current
状态值,并控制在每张幻灯片上设置的上一个,当前和下一个类。handleSlideClick
points to the Slider method of the same name to update thecurrent
value to the clicked slide’sindex
. This will animate the clicked slide into view.handleSlideClick
指向同名的Slider方法,以将current
值更新为单击的幻灯片的index
。 这将使单击的幻灯片进入视图。
更新幻灯片类 (Updating slide classes)
The Slide element has additional classes set based on the current slide.
Slide元素具有基于当前幻灯片设置的其他类。
if (current === index) classNames += ' slide--current'
else if (current - 1 === index) classNames += ' slide--previous'
else if (current + 1 === index) classNames += ' slide--next'
In the code above, when current
equals a slide’s index, that slide becomes active and is given a current class name. Adjacent sibling slides get previous and next class names. By adding these classes to their respective slides, unique hover styles can be applied.
在上面的代码中,当current
等于幻灯片的索引时,该幻灯片将变为活动状态并被赋予当前的类名称。 相邻的兄弟幻灯片获得上一个和下一个类的名称。 通过将这些类添加到其各自的幻灯片中,可以应用独特的悬停样式。
On hover, the cursor changes based on the direction of the slide and that hovered element is pulled towards the current slide along the x-axis. As a result, the user receives some additional visual cues when they are interacting with those neighboring slides.
悬停时,光标会根据幻灯片的方向发生变化,并将悬停的元素沿x轴拉向当前幻灯片。 结果,当用户与那些相邻的幻灯片交互时,用户会收到一些其他视觉提示。
滑动视差悬停效果 (Slide Parallax Hover Effect)
Now for the fun part! The Slide component contains methods that cast parallax magic. The onMouseMove
event attribute is using the handleMouseMove
method to update the x and y values as the user hovers over the slide. When the cursor is moved off of the slide, onMouseLeave
calls handleMouseLeave
to reset the x and y values and transition the slide elements back into place.
现在是有趣的部分! Slide组件包含投射视差魔术的方法。 当用户将鼠标悬停在幻灯片上时, onMouseMove
事件属性使用handleMouseMove
方法更新x和y值。 当光标从幻灯片上onMouseLeave
, onMouseLeave
调用handleMouseLeave
重置x和y值并将幻灯片元素过渡回原位。
The x and y coordinates are calculated by finding the user’s cursor in the viewport and where it’s hovering in relation to the center of the slide element. Those coordinate values are assigned to CSS variables (--x
and --y
) that are then used in transforms to move the child elements around in the slide. In the following pen, click on the “display coordinates” checkbox and hover over the slide to see how the x and y values update to reflect your cursor’s position and movement.
x和y坐标是通过在视口中找到用户的光标及其相对于滑动元素的中心的悬停位置来计算的。 这些坐标值被分配给CSS变量( --x
和--y
),然后在转换中使用它们来在幻灯片中移动子元素。 在下面的笔中,单击“显示坐标”复选框,然后将鼠标悬停在幻灯片上,以查看x和y值如何更新以反映光标的位置和移动。
See the Pen Cursor Movement Hover Effect by Ryan Mulligan (@hexagoncircle) on CodePen.light
请参见Ryan Mulligan( @hexagoncircle )在CodePen .light上的笔形光标移动悬停效果。
视差CSS (The Parallax CSS)
Let’s take a look at the CSS (Sass) being applied to some of these slide elements:
让我们看一下应用于其中一些幻灯片元素CSS(Sass):
.slide:hover .slide__image-wrapper {
--x: 0;
--y: 0;
--d: 50
transform:
scale(1.025)
translate(
calc(var(--x) / var(--d) * 1px),
calc(var(--y) / var(--d) * 1px)
);
}
The slide__image-wrapper
has overflow: hidden
set so that the image can move beyond its wrapper container and hide some of itself beyond the wrapper boundaries. The wrapper container also has a faster transition-duration
than the image. Now these elements animate at different speeds. I combined this with some fancy transform calculations and it developed some fluid, independent transitions.
slide__image-wrapper
已overflow: hidden
设置,以便图像可以移出其包装容器,并隐藏一些自身超出包装器边界的位置。 包装容器还具有比图像更快的transition-duration
。 现在这些元素以不同的速度动画。 我将其与一些奇特的变换计算结合起来,并开发了一些流畅,独立的过渡。
计算那些转换 (Calculate those transforms)
The translate(x, y)
values are computed using the CSS calc() function. On the slide__image-wrapper
, the --d
property (the divisor) is set to 50, which yields a lower coordinate value and less of a push from the slide’s center. Now check out the slide__image
transform:
translate(x, y)
值是使用CSS calc()函数计算的。 在slide__image-wrapper
,-- --d
属性(除数)设置为50,这将产生较低的坐标值,并减少了从幻灯片中心的推动。 现在查看slide__image
转换:
.slide__image.slide--current {
--d: 20;
transform:
translate(
calc(var(--x) / var(--d) * 1px),
calc(var(--y) / var(--d) * 1px)
);
}
The divisor is changed to 20 on the slide__image
so that the x and y values in the transform are higher and will push the image further away from the center of slide. Finally, the formula is multiplied by one pixel so that a unit gets applied to the value. Parallax achieved!
在slide__image
除数更改为20,以使变换中的x和y值更高,并将图像推离幻灯片中心更远。 最后,将公式乘以一个像素,以便将一个单位应用于该值。 实现视差!
Try playing around with the --d
values in the CSS and watch how the transitions change! Edit on Codepen.
尝试在CSS中使用--d
值,并观察过渡如何变化! 在Codepen上编辑。
Does it seem like the slide headline and button seem to move ever so slightly in the opposite direction of the image? Indeed they do! To achieve this, I multiplied the translate(x, y)
calculations by negative pixel values instead:
幻灯片标题和按钮看起来是否朝图像的相反方向稍微移动了一点? 确实是的! 为了实现这一点,我将translate(x, y)
计算结果乘以负像素值:
.slide__content {
--d: 60;
transform:
translate(
calc(var(--x) / var(--d) * -1px),
calc(var(--y) / var(--d) * -1px)
);
}
移动幻灯片(Moving the slides)
Check out the Slider component render code in the final demo:
在最终演示中查看Slider组件渲染代码:
See the Pen React Slider w/ Hover Effect by Ryan Mulligan (@hexagoncircle) on CodePen.light
请参阅CodePen .light上的Ryan Mulligan( @hexagoncircle )具有悬浮效果的Pen React Slider。
You’ll notice the slider__wrapper
element surrounding the slides. This wrapper transitions back and forth along the x-axis as the user interacts with the slider. The values for this transform are set after the current slide’s index is multiplied by the amount of slides divided into 100. I’ve added this in a variable on line 163 to keep the template a little cleaner:
您会注意到幻灯片周围的slider__wrapper
元素。 当用户与滑块交互时,此包装器将沿x轴来回转换。 在将当前幻灯片的索引乘以除以100的幻灯片数量后,即可设置此转换的值。我在163行的变量中添加了此值,以使模板更简洁:
'transform': `translateX(-${current * (100 / slides.length)}%)
In this example, there are 4 slides. Click the next arrow button or on the second slide (which has an index of 1) and it will pull the wrapper 25% to the left. Click on the third slide (index of 2), do the math (2 x 25), and watch it move the wrapper 50% to the left.
在本示例中,有4张幻灯片。 单击下一个箭头按钮或在第二张幻灯片(索引为1)上,它将把包装器向左拉25%。 单击第三张幻灯片(索引为2),进行数学运算(2 x 25),然后观察将包装纸向左移动50%。
其他一些花絮 (Some other tidbits)
These are a few other features I’d like to quickly call out:
这些是我想快速介绍的其他一些功能:
If a slide isn’t active, the
pointer-events
property is set to none. I chose to do this to avoid keyboard tab focusing on buttons inside inactive slides.如果幻灯片不处于活动状态,则将
pointer-events
属性设置为none。 我选择这样做是为了避免键盘标签集中在无效幻灯片中的按钮上。The parallax effect is only being applied to the current slide by declaring transforms when the
slide--current
class is present. Inactive slides have their own animations and shouldn’t have all that fun hover magic that the active slide has.视差效果仅被通过声明变换当施加到当前幻灯片
slide--current
类是否存在。 不活动的幻灯片具有自己的动画,不应具有活动幻灯片具有的所有有趣的悬停魔术。Images fade in when they are loaded using the
imageLoaded
method in the Slide component. This helps the initial load of a slide feel smoother instead of its image just popping in. A future iteration of this project will apply lazy loading as well (which is starting to roll out as a native browser feature; very exciting!)使用Slide组件中的
imageLoaded
方法加载图像时,图像会淡入。 这有助于使幻灯片的初始加载感觉更平滑,而不是突然弹出图像。此项目的未来迭代也将应用延迟加载(作为本机浏览器功能开始推广;非常令人兴奋!)
How would you extend or refactor this idea? I’d love to read your thoughts and comments. Leave them below or reach out to me on Twitter.
您将如何扩展或重构这个想法? 我很想阅读您的想法和评论。 将它们放在下面或在Twitter上与我联系。
翻译自: https://tympanus.net/codrops/2019/08/20/react-slider-with-parallax-hover-effects/
视差图得到视差