css背景视差_具有JavaScript和CSS转换的廉价视差

css背景视差

Recently a number of sites, including Bioware’s promotional page for Mass Effect Andromeda and Active Theory’s work for Under Armour have featured a parallax effect that ties mouse movement to the motion of a page element in the opposite direction. I was interested in recreating the effect using vanilla JavaScript and modern CSS, an example of which you can see above.

最近,包括Bioware的Mass Effect Andromeda促销页面Active Theory的Under Armour作品在内的许多站点都具有视差效果,该效果将鼠标移动与页面元素在相反方向上的运动联系起来。 我对使用香草JavaScript和现代CSS重新创建效果很感兴趣,您可以在上面看到一个示例。

入环 (Get In The Ring)

The markup consists of a <div> container, an image, a heading, and body text (extracted from the short story “A Piece of Steak” by Jack London) surrounded by another <div>:

标记由<div>容器图像标题和正文(由Jack London的短篇小说“ A Piece of Steak”摘录)和另一个<div>包围组成:

<div id="boxercontainer">
  <img src="boxer.png" alt>
  <div>
    <h1>The Boxer</h1>
    <p>Well, a man had only so many fights in him, to begin with…
  </div>
</div>

The boxer was extracted from his background and turned into an alpha-masked PNG, reduced in file size by converting it to a 16-bit image.

该拳击手是从他的背景中提取出来的,并变成了带有alpha蒙版的PNG ,通过将其转换为16位图像来减小文件大小。

The outer #boxercontainer element is styled: note that the background-image is made slightly larger than its container and positioned from its center, facts that will be important later:

外部的#boxercontainer元素具有样式:请注意,将background-image制作成比其容器稍大一点 ,并从其中心开始放置,这些事实稍后将很重要:

#boxercontainer {
  width: 80%;
  max-width: 900px;
  margin: 0 auto;
  background-image: url(concrete-background.jpg);
  position: relative;
  padding-bottom: 45%;
  background-size: 120% 120%;
  background-position: 50% 50%;
  overflow: hidden;
  min-height: 650px;
}

The inner div is given a transparent, slightly dark background color to increase the contrast of the text inside it:

内部div具有透明的,略暗的背景色,以增加内部文本的对比度:

#boxercontainer div {
  position: absolute;
  width: 60%;
  left: 20px;
  top: 20px;
  border: 1px solid #fff;
  padding: 2rem;
  background: rgba(0,0,0,0.2);
}

The image is also positioned absolutely (taking advantage of the absolute-position-inside-relative trick), dropped down so that the lower portion of the boxer’s legs are hidden by the overflow: hidden on the parent element. It’s also provided with a drop-shadow filter, making a far smaller image file size than baking the drop-shadow into the PNG; as we’ll see in a moment, this also createsfar more dynamic options for the image.

图像也绝对定位(利用绝对位置相对内幕技巧),向下放置,以使拳击手腿的下部被overflow: hidden物隐藏overflow: hidden在父元素上。 它还提供了一个drop-shadow过滤器 ,与将drop-shadow烘焙到PNG中相比,图像文件的大小要小得多。 稍后我们将看到,这还会为图像创建更多的动态选项。

#boxercontainer img { 
  position: absolute;
  bottom: -35px;
  right: 50px;
  width: 40%;
  filter: drop-shadow(-200px 200px 50px #000);
  padding: 1rem;
  z-index: 2;
}

The z-index value of 2 places the boxer visually above the div containing the text, but it also means that the shadow falls over the words. To correct that, I modified the appearance of the paragraph text:

z-index值为2使拳击手在视觉位于包含文本的div 上方 ,但这也意味着阴影落在单词上。 为了解决这个问题,我修改了段落文本的外观:

alt
Boxer image
拳击手形象
#boxercontainer p {
  position: relative;
  z-index: 3;
}

With a higher z-index, the shadow now falls under the text, but over the border on the div.

使用更高的z-index ,阴影现在落在文本下方 ,但位于div的border 上方

居中 (Getting Centered)

The core idea of the parallax effect is finding the center of the affected element. The cursor’s distance from this center will displace the element by the same distance in the opposite direction:

视差效果的核心思想是找到受影响元素的中心。 光标到该中心的距离将使元素在相反的方向上移动相同的距离:

Cursor over center of element (left); cursor moved away from element, with element offset an equal distance (original center marked with ×).
光标在元素中心上方(左); 光标从元素移开,元素偏移相等的距离(原始中心标记为×)。

To make this happen, the script starts by identifying the elements (using the fact that an id automatically turns into a reference in JavaScript, and using a querySelector for the boxer:

为此,脚本首先要标识元素(使用id自动变成JavaScript中的引用这一事实,然后对拳击手使用querySelector

const boxer = boxercontainer.querySelector("img"),
maxMove = boxercontainer.offsetWidth / 30,
boxerCenterX = boxer.offsetLeft + (boxer.offsetWidth / 2),
boxerCenterY = boxer.offsetTop + (boxer.offsetHeight / 2);

maxMove is the maximum distance we want the boxer to move, since we don’t usually want the image to move with complete freedom in response to the mouse being anywhere on the page.

maxMove是我们希望拳击手移动的最大距离,因为我们通常不希望图像完全自由地移动以响应鼠标在页面上的任何位置

We’ll also need to determine the position of the mouse inside boxercontainer, for which I’ll use a function:

我们还需要确定boxercontainer内鼠标的位置,为此我将使用一个函数

function getMousePos(xRef, yRef) {
  let panelRect = boxercontainer.getBoundingClientRect();
  return {
      x: Math.floor(xRef - panelRect.left) / 
        (panelRect.right - panelRect.left)*boxercontainer.offsetWidth,
      y: Math.floor(yRef - panelRect.top) / 
        (panelRect.bottom - panelRect.top) * boxercontainer.offsetHeight
    };
}

像蝴蝶一样漂浮 (Float Like a Butterfly)

Effects like this usually respond to mouse movement in the page:

这样的效果通常会响应页面中的鼠标移动:

document.body.addEventListener("mousemove", function(e) {
  let mousePos = getMousePos(e.clientX, e.clientY),
  distX = mousePos.x - boxerCenterX,
  distY = mousePos.y - boxerCenterY;
  if (Math.abs(distX) < 500 && distY < 200) {
  boxer.style.transform = 
    "translate("+(-1 * distX) / 12 + "px," + (-1 * distY) / 12 + "px)";
  }
})

distX is the horizontal distance between the current mouse position and the initial center of the boxer image; distY is the vertical distance. If the vertical difference (positive or negative) is less than 500px, and the horizontal distance less than 200px, then we move the boxer image using a CSS transform:

distX是当前鼠标位置和拳击手图像的初始中心之间的水平距离; distY是垂直距离。 如果垂直差异(正值或负值)小于500px,水平距离小于200px,则我们使用CSS变换移动拳击手图像:

  • both distances are multiplied by -1 (turning a positive distance into a negative, and a negative into a positive)

    两个距离都乘以-1 (将正距离变成负值,将负距离变成正值)

  • the result is then divided by 12, to reduce the ratio of movement between the mouse and the image (a 1:1 relationship between mouse position and image position would make movement far too confusing).

    然后将结果除以12,以减少鼠标与图像之间的移动比例 (鼠标位置与图像位置之间的1:1关系会使移动过于混乱)。

It should be noted at this point that I would never suggest using this technique for UI elements: trying to click a “moving target” can be very difficult to users with motion or visual issues. A potential solution to this is discussed below.

在这一点上应该指出的是,我永远不会建议对UI元素使用这种技术:对于有运动或视觉问题的用户,尝试单击“移动目标”可能非常困难。 一个潜在的解决方案将在下面讨论。

When we move our head position, it’s not only elements in the foreground that change position; objects in the background also shift, in the opposite direction. Think of an object placed a few feet in front of a wall: moving to the right will change your perspective on both.

当我们移动头部位置时,不仅是前景中的元素会改变位置,而且还会改变位置。 背景中的对象也会向相反的方向移动。 想像一下放在墙前几英尺的物体: 向右移动将改变您对两者的看法。

To recreate this effect, I also move the background-image of the concrete wall. The addEventListener callback has the following added at the end of the script:

为了重现这种效果,我还移动了混凝土墙的background-imageaddEventListener 回调在脚本末尾添加了以下内容:

boxercontainer.style.backgroundPosition = 
    `calc(50% + ${distX / 50}px) calc(50% + ${distY / 50}px)`;

To make the background move, I’m using calc to produce an offset from the background image’s default center position. (I’m also using template literals to make concatenation easier).

为了使背景移动,我使用calc来生成与背景图像默认中心位置的偏移量 。 (我也使用模板文字使连接更容易)。

I’m initiating movement based on mouse position, rather than touch, since adults tend not to have their fingertips constantly sliding across the screen.

我要根据鼠标位置而不是触摸来开始运动,因为成年人的指尖通常不会在屏幕上不断滑动。

数了 (Counted Out)

As a general rule, parallax effects work well on larger desktop and laptop screens, but not at all on smaller viewports. Because the effect is created with JavaScript, we must also detect the viewport width with JS, via matchMedia:

通常,视差效果在较大的台式机和笔记本电脑屏幕上效果很好,但在较小的视口上根本不起作用。 由于效果是使用JavaScript创建的,因此我们还必须通过matchMedia使用JS检测视口宽度:

let fluidboxer = window.matchMedia("(min-width: 726px)");

The if condition for moving the image and background changes to:

用于移动图像和背景的if条件变为:

if (Math.abs(distX) < 500 && distY < 200 && fluidboxer.matches) { … }

There are more changes in CSS @media queries to change the design at smaller viewport sizes; see the CodePen demo for more details.

CSS @media查询中有更多更改,可以在较小的视口尺寸下更改设计; 有关更多详细信息, 请参见CodePen演示

拳头醉 (Punch-Drunk)

Parallax effects can adversely affect users with vestibular disorders (sensitivity to visual motion and change) to the point of nausea and seizure; at the minimum, displaying a warning or some other indication that the page contains motion effects is a good idea. Browser vendors are currently working on a “reduce motion” user setting that will be detectable using an @media query in the near future; in response, features like parallax effects could be automatically turned off on the page for affected users.

视差效应可能会对前庭不适(对视觉运动和变化敏感)的使用者产生恶心和癫痫发作的不利影响; 最好至少显示警告或其他指示页面包含运动效果的指示。 浏览器供应商目前正在研究“减少运动”用户设置 ,不久以后可以使用@media查询检测到该设置 。 作为响应,视差效果之类的功能可能会在受影响的用户页面上自动关闭。

结论 (Conclusion)

Using CSS transforms with JavaScript mouse events can be a cheap and relatively easy way to achieve parallax effects, with a little math. In future articles, I’ll explore these kinds of effects further.

将CSS转换与JavaScript鼠标事件一起使用,是一种廉价且相对简单的方法,只需一点数学就可以实现视差效果。 在以后的文章中,我将进一步探讨这些影响。

翻译自: https://thenewcode.com/1162/Cheap-Parallax-with-JavaScript-and-CSS-Transforms

css背景视差

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值