【问题标题】:Is there any way to animate transform-origin in combination with transform: scale?有什么方法可以结合 transform: scale 对 transform-origin 进行动画处理?
【发布时间】:2021-08-12 17:43:41
【问题描述】:

所以我有一个具有缩放功能的图像查看器,它通过transform: scale() 属性工作。

使用transition: transform .3s 动画缩放没有问题。

为了使鼠标滚轮上的缩放转到鼠标滚轮指向的位置,我计算了设置新原点的正确位置,但是当我设置它时,它只是跳到那里而没有动画。

我尝试过的:

  • transform-origin 属性设置transition → 不起作用
  • 在JS中手动使用setTimeout并慢慢将transform-origin设置在正确的位置→播放缩放动画然后跳转

有没有办法一次性为transform: scale()transform-origin 设置动画?

欺骗

由于最后一个问题已作为 How to have multiple CSS transitions on an element? 的副本关闭,这里是一个 sn-p,向您表明这不是我的问题。

const img = document.querySelector('#container img');

let on = true;

const toggleEffect = () => {
  if(on) {
    img.style.transform = 'scale(2.5)';
    img.style.transformOrigin = '80% 80%';
  } else {
    img.style.transform = 'scale(1.4)';
    img.style.transformOrigin = '20% 20%';
  }
  
  on = !on;
};
#container {
  width: 500px;
  height: 300px;
  overflow: hidden;
  background-color: red;
}

#container img {
  height: 100%;
  width: 100%;
  object-fit: contain;
  transform: scale(1.4);
  transform-origin: 20% 20%;
  transition: transform .3s, transform-origin .3s;
}
<div id="container">
  <img src="https://images.unsplash.com/photo-1482066490729-6f26115b60dc?ixlib=rb-1.2.1&auto=format&fit=crop&w=2004&q=80"/>
</div>
<button onclick="toggleEffect()">Toggle</button>

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    编辑:从技术上讲,这是duplicated。 (某些版本中的 Chrome 错误)

    - 同时使用transition

    body, div {
      width: 100%;
      height: 100vh;
      overflow: hidden;
    }
    
    div {
      background-color: gray;
      width: auto;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 30px;
      transform: scale(1.1);
      transform-origin: 50% -30px -100px;
      transition: transform-origin .2s ease-in-out, transform 4s ease-in-out;
    }
    div:hover {
      transform: scale(1.7);
      transform-origin: 100px 100px;
    }
    &lt;div&gt;Test&lt;/div&gt;

    - 使用@keyframes 的动画:

    body,div {
      width: 100%;
      height: 100vh;
    }
            div {
              width: auto;
              display: flex;
              justify-content: center;
              align-items: center;
              transform-origin: 0 0 0;
              animation: scale-origin 3s infinite;
              font-size: 30px;
             }
    
             @keyframes scale-origin {
                0% {
                  transform: scale(.5);
                   transform-origin: 100px 100px 1000px;
                }
               100% {
                 transform: scale(1.1);
                 transform-origin: left 500px -30px
                }
             }
    &lt;div&gt;Test&lt;/div&gt;

    【讨论】:

    • 感谢您的评论。是的,我读过这个,但不幸的是,原点是从 JavaScript 计算出来的,并且是动态的,取决于鼠标的位置。 @keyframe 是静态的,我不能从 JS 中设置它
    • @MauriceNino 哎呀。我添加了一个新的解决方案,可能对您有帮助。
    • 再次感谢,但它仍然会跳。这正是我尝试并放入我的sn-p,但transform-origin,似乎无法放入transition
    • @MauriceNino mmm 你当前的浏览器是什么?我的意思是,我可以清楚地看到 transition: transform-origin .2s ease-in-out, transform 4s ease-in-out;transition: transform 4s ease-in-out; 的区别:S
    • 知道了...这是一个 Chrome 错误。我使用 Firefox,它运行良好。 See your snippet in my browser。您也可以查看this question
    【解决方案2】:

    对我来说,解决此错误的唯一方法是确保在每个“动画”(在本例中为过渡)帧上重绘元素,您可以通过 getComputedStyle 清楚地看到变换原点已正确过渡!

    基本上,我为 transitionstart 和 transitionend 添加了事件监听器,并在每个动画帧上切换一些强制重绘的样式属性(例如,在我的例子中,margin-left 从 0 到 1 到 0px,直到动画完成)

    function forceRedraw(ts) {
      this.style.marginLeft = this.style.marginLeft == '1px' ? '0px':'1px';
      if (this.classList.contains('transitioning'))
        requestAnimationFrame(forceRedraw.bind(this));
    }
    

    在我的示例中,我同时转换旋转和变换原点(从左上角到左下角)。

    https://codepen.io/ftav/pen/QWvYEPj

    根据您修改的元素,这可能会对性能产生或多或少的影响。这对我来说可以。我只是希望他们能修复这个错误,并且这种解决方法可以消失。

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 1970-01-01
      • 2012-12-02
      • 1970-01-01
      • 2021-07-04
      • 2020-03-10
      • 2023-03-09
      • 2019-12-25
      • 2014-04-25
      相关资源
      最近更新 更多