使用JS mousemove性能更改CSS属性

时间:2017-09-28 15:05:39

标签: javascript jquery css performance animation

我有一个jQuery函数更改了background-position上三个元素的mousemove属性,这似乎导致了一些性能问题。

应该注意的是,这些元素的背景图像是SVG。

示例代码:

$(window).on('mousemove', function(event) {
    window.requestAnimationFrame(function() {

        $banner.find('.pattern').each(function(key) {

            var modifier = 20 * (key + 1);

            $(this).css({
                'background-position': (event.pageX / modifier)+'px '+(event.pageY / modifier)+'px'
            });

        });

    });
});

请在此处查看我的工作代码:https://codepen.io/thelevicole/project/full/DarVMY/

我正在使用window.requestAnimationFrame(),并且每个元素上都有will-change: background-position; css属性。

你可能会说,这种影响是滞后的。在更大的窗户尺寸上似乎会变得更糟。

我很确定这个问题是由于使用SVG代替PNG而导致的。我使用SVG的原因是因为高像素密度屏幕。

如果有人能够提供一些有关我如何在不使用非常棒的PNG的情况下改进FPS的见解。感谢。

2 个答案:

答案 0 :(得分:1)

成功。我的解决方案是一系列建议。

我现在正在更改每个元素的transform属性,但在执行此操作时遇到了另一个问题。我在这些相同的元素上有一个变换关键帧动画,并且忽略了JS应用的样式。

为了解决这个问题,我嵌套了关键帧动画元素,并使用JS来转换父元素。

我已应用@CristianTraìna的建议将window.requestAnimationFrame()移到mousemove

之外

您可以在我的原始链接上看到更新:https://codepen.io/thelevicole/project/full/DarVMY/

可悲的是,CodePen不允许对项目进行版本控制。

最终工作代码

(function($) {
	'use strict';
	
	var $banner = $('section.interactive');
	if ($banner.length) {
		var $patterns = $banner.find('.pattern');
		
		var x = 0,
			y = 0;
		
		// Bind animation to cursor
		$(window).on('mousemove', function(event) {
			x = event.pageX;
			y = event.pageY;
		});
		
		/**
		 * Tell the browser that we wish to perform an animation
		 * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
		 */
		window.requestAnimationFrame(function animation() {

			// Loop each pattern layer
			$patterns.each(function(key) {

				// Modify the x,y coords per element to give "depth"
				var modifier = 20 * (key + 1);

				// Move background position
				$(this).css({
					'transform': 'translate('+(x / modifier)+'px, '+(y / modifier)+'px)'
				});

			});
			
			window.requestAnimationFrame(animation);

		});
		
		
	}
	
})(jQuery);
section.interactive {
  position: relative;
  height: 100vh;
  background-image: linear-gradient(45deg, #6ac8ea 0%, #5de2c1 100%);
}

section.interactive .layers {
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.15) 0%, transparent 40%, transparent 60%, rgba(0, 0, 0, 0.1) 100%);
}

section.interactive .layers .pattern {
  position: absolute;
  top: -10px;
  left: -10px;
  bottom: -10px;
  right: -10px;
  background-position: top left;
  will-change: background-position;
  background-size: 1000px 1000px;
}

section.interactive .layers .pattern .inner {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
}

section.interactive .layers .pattern.pattern-1 .inner {
  background-image: url("http://www.inrialpes.fr/sed/people/boissieux/VEAD/out_Stars.svg");
  filter: blur(2px);
  opacity: 0.3;
  z-index: 1;
  animation: Floating 10s infinite;
  animation-delay: 2s;
  background-size: 800px 800px;
}

section.interactive .layers .pattern.pattern-2 .inner {
  background-image: url("http://www.inrialpes.fr/sed/people/boissieux/VEAD/out_Stars.svg");
  filter: blur(1px);
  opacity: 0.4;
  z-index: 2;
  animation: Floating 10s infinite;
  animation-delay: 1s;
  background-size: 900px 900px;
}

section.interactive .layers .pattern.pattern-3 .inner {
  background-image: url("http://www.inrialpes.fr/sed/people/boissieux/VEAD/out_Stars.svg");
  opacity: 0.4;
  z-index: 3;
  animation: Floating 10s infinite;
  background-size: 1000px 1000px;
}

@keyframes Floating {
  0% {
    transform: translate(-10px, 10px);
  }
  50% {
    transform: translate(10px, -10px);
  }
  100% {
    transform: translate(-10px, 10px);
  }
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Animation performance</title>
	<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css">
	<link rel="stylesheet" href="styles.processed.css">
</head>
<body>
	<section class="interactive">
		<div class="layers">
			<div class="pattern pattern-3">
				<div class="inner"></div>
			</div>
			<div class="pattern pattern-2">
				<div class="inner"></div>
			</div>
			<div class="pattern pattern-1">
				<div class="inner"></div>
			</div>
		</div>
	</section>
	<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</body>
</html>

答案 1 :(得分:0)

当您调用 on 方法时,您正在创建一个将侦听事件的异步函数,当此事件被触发时,您将创建另一个将侦听事件的异步函数。

然后,你正在做的是听一个事件( mousemove )并在第一个被触发时设置另一个事件( requestAnimationFrame ),但是如果mousemove是在短时间内激发两次,requestAnimationFrame仍然没有第一次执行其回调?

解决问题的更简洁方法是:

var x = 0;
var y = 0;
$patterns = $banner.find('.pattern');
$(window).on('mousemove', function(event) {
  x = event.pageX;
  y = event.pageY;
});

window.requestAnimationFrame(function moveBackground() {
  $patterns.each(function(key) {
    var modifier = 20 * (key + 1);
    $(this).css({
      'background-position': (x / modifier)+'px '+(y / modifier)+'px'
    });
  });
  window.requestAnimationFrame(moveBackground);
});

你可以看到我的工作项目(没有JQuery)clicking here