css SVG在左边距更改时抖动( Flink )(字幕效果)

dm7nw8vv  于 2022-12-15  发布在  Flink
关注(0)|答案(2)|浏览(203)

我尝试使用一个字幕效果与香草JS。效果的作品,但svg(和图像)是抖动的移动。

<div class="marquee">
  <h1>Nepal <svg version="1.1" viewBox="0 0 36 31" xmlns="http://www.w3.org/2000/svg"><path d="M8.80476 8.17844V12.3988H3.9993V4.25693H8.79846V8.17844H8.80476ZM32.4101 3.87271V0H20.0028V3.87271H16.0035V0H3.60252V3.87271H0V15.497H3.60252V19.76H7.60182V23.2485H11.6011V27.5115H15.6004V31H20.3996V27.5115H24.3989V23.2485H28.3982V19.76H32.3975V15.497H36V3.87271" fill="#DA2269"/></svg> Himalayas <svg version="1.1" viewBox="0 0 36 31" xmlns="http://www.w3.org/2000/svg"><path d="M8.80476 8.17844V12.3988H3.9993V4.25693H8.79846V8.17844H8.80476ZM32.4101 3.87271V0H20.0028V3.87271H16.0035V0H3.60252V3.87271H0V15.497H3.60252V19.76H7.60182V23.2485H11.6011V27.5115H15.6004V31H20.3996V27.5115H24.3989V23.2485H28.3982V19.76H32.3975V15.497H36V3.87271" fill="#DA2269"/></svg> Mountains <svg version="1.1" viewBox="0 0 36 31" xmlns="http://www.w3.org/2000/svg"><path d="M8.80476 8.17844V12.3988H3.9993V4.25693H8.79846V8.17844H8.80476ZM32.4101 3.87271V0H20.0028V3.87271H16.0035V0H3.60252V3.87271H0V15.497H3.60252V19.76H7.60182V23.2485H11.6011V27.5115H15.6004V31H20.3996V27.5115H24.3989V23.2485H28.3982V19.76H32.3975V15.497H36V3.87271" fill="#DA2269"/></svg> Everest</h1>
</div>

<style>
.marquee {
  overflow: hidden;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  display: flex;
}

.marquee h1{
  font-size: 5em;
  white-space: nowrap;
  text-transform: uppercase
}

.marquee h1 svg {
  width: auto;
  height: 60px;
}
</style>

<script>
function Marquee(selector, speed) {
  const parentSelector = document.querySelector(selector);
  const clone = parentSelector.innerHTML;
  const firstElement = parentSelector.children[0];
  let i = 0;
  console.log(firstElement);
  parentSelector.insertAdjacentHTML('beforeend', clone);
  parentSelector.insertAdjacentHTML('beforeend', clone);

  setInterval(function () {
    firstElement.style.marginLeft = `-${i}px`;
    if (i > firstElement.clientWidth) {
      i = 0;
    }
    i = i + speed;
  }, 0);
}

//after window is completed load
//1 class selector for marquee
//2 marquee speed 0.2
window.addEventListener('load', Marquee('.marquee', 0.2))

</script>

示例:https://codepen.io/diegosomar/pen/dyKBGWg
有人知道是否有一种方法可以防止svg抖动?

fcy6dtqo

fcy6dtqo1#

setInterval()替换为requestAnimationFrame()

正如@Jefferson的回答中指出的,您当前的setInterval()调用具有零毫秒延迟,导致动画/过渡抖动。
此外,它会导致不一致的计时,例如在Firefox和Chromium中。
requestAnimationFrame()确保,您的样式更改每帧应用一次-然而,setInterval()可能会尝试在”帧之间“更改样式属性(如果以毫秒为单位的间隔与帧不匹配)。

示例代码段

function Marquee(selector, speed) {
  const parentSelector = document.querySelector(selector);
  const clone = parentSelector.innerHTML;
  const firstElement = parentSelector.children[0];
  let i = 0;
  parentSelector.insertAdjacentHTML('beforeend', clone);
  parentSelector.insertAdjacentHTML('beforeend', clone);

  function scrollMarquee(timestamp) {
    timestamp = timestamp || new Date().getTime();
    firstElement.style.marginLeft = `-${i}px`;
    if (i >= firstElement.clientWidth ) {
      i = 0;
    }
    i += speed;
    requestAnimationFrame(scrollMarquee); 
  } 
  requestAnimationFrame(scrollMarquee);
}

//after window is completed load
//1 class selector for marquee
//2 marquee speed 0.2
window.addEventListener('load', Marquee('.marquee', 1))
.marquee {
  overflow: hidden;
  border-top: 1px solid #000;
  border-bottom: 1px solid #000;
  display: flex;
}

.marquee h1{
  font-size: 5em;
  white-space: nowrap;
  text-transform: uppercase
}

.marquee h1 svg {
  width: auto;
  height: 60px;
}
<div class="marqueeOuter">
  <div id="marquee" class="marquee">
    <h1> Nepal <svg viewBox="0 0 36 31">
        <path d="m9 8v4h-5v-8h5v4l0 0zm23-4v-4h-12v4h-4v-4h-12v4h-4v11h4v5h4v3h4v5h4v3h4v-3h4v-5h4v-3h4v-5h4v-11" fill="#DA2269" />
      </svg> Himalayas <svg viewBox="0 0 36 31" xmlns="http://www.w3.org/2000/svg">
        <path d="m9 8v4h-5v-8h5v4l0 0zm23-4v-4h-12v4h-4v-4h-12v4h-4v11h4v5h4v3h4v5h4v3h4v-3h4v-5h4v-3h4v-5h4v-11" fill="#DA2269" />
      </svg> Mountains <svg viewBox="0 0 36 31" xmlns="http://www.w3.org/2000/svg">
        <path d="m9 8v4h-5v-8h5v4l0 0zm23-4v-4h-12v4h-4v-4h-12v4h-4v11h4v5h4v3h4v5h4v3h4v-3h4v-5h4v-3h4v-5h4v-11" fill="#DA2269" />
      </svg> Everest</h1>
  </div>
</div>

动画首选整数值-如果可行

浮点数字递增样式属性可能会导致舍入错误-也会导致不希望的抖动过渡和性能问题。
这也适用于本文中描述的svgs。

ycggw6v2

ycggw6v22#

如果您将间隔设置为100 ms更新,如下所示:

setInterval(function () {
    firstElement.style.marginLeft = `-${i}px`;
    if (i > firstElement.clientWidth) {
      i = 0;
    }
    i = i + speed;
  }, 100);

你会清楚地看到发生了什么。不仅图像会抖动,单个字母也会抖动。这种抖动效果似乎是浏览器(至少是Chrome)渲染图像/字母的方式。
但是,我在查看CSS时注意到一些问题,当我将宽度更改为width: 70px时,“抖动”似乎停止了(我选择70 px是因为它更接近于最初的心脏图像大小)当我在Inspector上检查HeartSVG元素时,我发现当宽度设置为width: auto时,与width: 70px相比,宽度的变化过程有延迟,这使得它看起来抖动更大。
使用固定的width像素大小是解决这个问题的一个很好的方法,但是有一个更好更简单的方法可以解决这个问题。
不用每毫秒修改一次margin-left,你可以每秒修改一次,让CSS来处理平滑过渡,你可以在这里了解CSS transitions

<style>
.marquee h1 {
  transition: margin-left 1s linear;
}
</style>

<script>
function Marquee(selector, speed) {
  const parentSelector = document.querySelector(selector);
  const clone = parentSelector.innerHTML;
  const firstElement = parentSelector.children[0];
  let i = 0;
  console.log(firstElement);
  parentSelector.insertAdjacentHTML('beforeend', clone);

  setInterval(function () {
    firstElement.style.marginLeft = `-${i}px`;
    if (i > firstElement.clientWidth) {
      i = 0;
    }
    i = i + speed;
  }, 1000); //update every second
}

window.addEventListener('load', Marquee('.marquee', 100)) //every second -100 pixels will be added to `margin-left` of the element
</script>

通过在.marquee h1样式中添加transition,您可以立即看到不同之处。注意,您可能希望在i = 0之后处理transition,以防止从-2000px(firstElement.clientWidth大小)突然平滑跳变到0 px。

相关问题