【问题标题】:Make div fly with animation to another DOM position使 div 与动画一起飞到另一个 DOM 位置
【发布时间】:2017-09-26 14:22:44
【问题描述】:

我正在将一个 <img> 元素(章鱼)从上方的大灰色 <div> (#large) 移动到下方的小橙色 <div> (#small),使用

$(document).on("click", "#large > img", function() {
  $(this).appendTo("#small");
});

这很好用,但我希望它平稳过渡并“飞”过,这样它会慢慢插入其坐标和大小

我尝试添加 CSS 过渡

img { transition: all 3s; }

发给我的<img>,但这不起作用,因为图像被读取到 DOM 并且没有移动。

如何建立这样的动画?

JS Fiddle

【问题讨论】:

  • 您不能为appendTo 设置动画。您必须通过将其位置设为绝对位置来将图像从页面流中取出,获取另一个框的 x/y 坐标,然后使用 transition 或 jQuery animate 之类的东西将其滑动到那里。
  • 您可以将其过渡到该地点并延迟将其添加到新地点的时间与过渡持续时间相同,这应该使它看起来在过渡,但实际上仍在移动
  • 用新的解决方案检查我的答案。我认为它的响应速度更快,您正在寻找的东西更多
  • 我相信我已经发布了正确的答案。你看过了吗?

标签: javascript jquery css animation


【解决方案1】:

您需要计算图像的当前尺寸、目标尺寸,并计算所需的变换。

为方便起见,我将计算使新元素(克隆的元素)看起来仍在当前位置所需的变换。

稍后,一个标准动画(只是重置比例和位置)就可以解决问题。

我避免使用 jQuery,所以解决方案更容易移植

function func (target) {
    var image = document.getElementById('image');
    var current = image.parentNode;
    var rectImage = current.getBoundingClientRect();
    var rectTarget = target.getBoundingClientRect();
    evalRect (rectImage);
    evalRect (rectTarget);

    var scaleX = rectImage.width / rectTarget.width;
    var scaleY = rectImage.height / rectTarget.height;
    var translateX = rectImage.centerX - rectTarget.centerX;
    var translateY = rectImage.centerY - rectTarget.centerY;

    var dup = image.cloneNode();
    var scale = 'scale(' + scaleX + ', ' + scaleY + ') '; 
    var translate = 'translate(' + translateX + 'px, ' + translateY + 'px) ';
    target.appendChild(dup);
    dup.style.transform = translate + scale;
    current.removeChild(image);
}

function evalRect (rect) {
    rect.centerX = rect.left + rect.width * 0.5;
    rect.centerY = rect.top + rect.height * 0.5;
}
.container {
  border: solid 1px black;
  position: relative;
  display: inline-block;
}

#container1 {
  width: 200px;
  height: 100px;
}

#container2 {
  width: 400px;
  height: 200px;
}

#container3 {
  width: 200px;
  height: 200px;
}

#image {
  background: linear-gradient(45deg, yellow, tomato);
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0px;
  top: 0px;
  animation: adjust 1s forwards;
}

@keyframes adjust {
  to {transform: translate(0px, 0px);}
}
<div id="container1" class="container" onclick="func(this)">click me
    <div id="image"></div>
</div>
<div id="container2" class="container" onclick="func(this)">click me</div>
<div id="container3" class="container" onclick="func(this)">click me</div>

【讨论】:

  • @web-tiki 谢谢!好像OP不喜欢,不知道为什么……
【解决方案2】:

appendto 不接受动画,但这个问题可能对你有帮助

appendTo() animation

【讨论】:

    【解决方案3】:

    我使用 JQ 制作了一个响应式解决方案(我认为)。看看下面或jsFiddle

    首先我缓存了所有必要的选择器,以使代码更简洁。

    -20 是因为div { margin-top:20px}` 在那里我计算了两个 div 相对于文档的 TOP 偏移量,然后得到了小 div 的宽度和高度

    首先在 click 函数中,我得到了图像的顶部偏移量,因此我可以将其与 #small 的偏移量进行比较。

    所以如果图像到顶部的距离小于#small 到顶部的距离,这意味着 img 在 #large div 中,所以我使用 transform:translate 移动它,给它一个 Y 轴值等于#small Div 的 TOP 偏移量,所以 img offset.top ( iOffset ) 将等于 #small offset.top ( sOffset )

    还将#small div 的宽度和高度添加到图像中

    else(如果 iOffset 为 = 或大于 sOffset )则表示图像不在大 div 中,因此我需要将其转换回 #large div 的偏移量并添加 width:100% 和 height :100%

    希望我做对了并正确解释。 如果有帮助,请告诉我

    var Large = $("#large"),
      Small = $("#small"),
      lOffset = $(Large).offset().top - 20 + 'px',
      sOffset = $(Small).offset().top - 20 + 'px',
      sWidth = $(Small).width(),
      sHeight = $(Small).height()
    
    $(document).on("click", "img", function() {
      var iOffset = $(this).offset().top + 'px'
      if (iOffset < sOffset) {
        $(this).css('transform', 'translate(0,' + sOffset + ')')
          .width(sWidth).height(sHeight)
      } else {
        $(this).css('transform', 'translate(0,' + lOffset + ')')
          .width("100%").height("100%")
      }
    })
    div {
      margin: 20px;
      padding: 10px;
    }
    
    #large {
      width: 600px;
      height: 400px;
      background-color: gray;
    }
    
    #small {
      width: 120px;
      height: 90px;
      background-color: orange;
    }
    
    img {
      width: 100%;
      height: 100%;
      transition: 5s;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="large">
      <img src="https://ak.picdn.net/assets/cms/5bb580387901a83212e3028ab5a2fa8fb1153d7b-img_offset_2x.jpg" />
    </div>
    <div id="small">
    </div>

    【讨论】:

      【解决方案4】:

      只需添加一个过渡并更改大小和位置以匹配目标。在transitionend 事件中,将图像附加到目标元素。

      // when transition completes
      $('img').on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(){
        // place in container
        $('#target').append($('img'));
        // set to corner of container
        $('img').css({
          top: '0',
          left: '0'
        });
      });
      
      // position in corner of target and make size the same
      $('img').css({
      	position: 'absolute',
        top: $('#target').offset().top + 'px',
        left: $('#target').offset().left + 'px',
        height: $('#target').css('height'),
        width: $('#target').css('width')
      });
      #target {
        height: 150px;
        width: 150px;
        border: 1px solid grey;
        position: absolute;
        top: 350px;
        left: 5px;
        z-index: 1;
      }
      
      img {
        position: absolute;
        top: 0;
        left: 5px;
        transition: all 1s;
        height: 300px;
        width: 300px;
        z-index: 5;
      }
      <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
      <img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=300%C3%97300&w=300&h=300" />
      <div id="target">
      </div>

      【讨论】:

      • 我不是反对者之一,但也许是因为你应该把你的代码放在你的答案中。
      • 我现在有。我认为对某人投反对票是不礼貌的,因为他们不仅给了你你需要的代码。我不为这个人工作,我只是想帮助他。
      • @KthProg 我没有反对并同意你的看法。感谢您的 sn-p,它确实有很大帮助。
      • 原因是,当 JSFiddle 出现故障时(仅在过去一年中就发生过几次),链接到 JSFiddle 的答案会变得不那么有用,如果有用的话。
      【解决方案5】:

      使用 jQuery .append 方法将不允许您在两种状态之间为元素设置动画。

      这是一个使用 CSS 过渡和 scale() 函数的动画示例。此示例还使用 transform-origin 属性来更改图像在“大”状态下的位置。 Fiddle here.

      $(document).on("click", "img", function() {
        $(this).toggleClass("big");
      });
      div {
        margin: 20px;
        padding: 10px;
      }
      
      #large {
        width: 600px;
        height: 400px;
        background-color: gray;
      }
      
      #small {
        width: 120px;
        height: 90px;
        background-color: orange;
      }
      
      img {
        width: 100%;
        height: 100%;
        transition: transform .3s ease-out;
        transform-origin: 0 129px;
      }
      
      img.big {
        transform: scaleX(5) scaleY(4.4);
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <div id="large">
      
      </div>
      <div id="small">
        <img src="https://ak.picdn.net/assets/cms/5bb580387901a83212e3028ab5a2fa8fb1153d7b-img_offset_2x.jpg" />
      </div>

      请注意:

      • 您需要将供应商前缀添加到转换、转换和转换来源属性,具体取决于您需要支持的浏览器。
      • 此技术依赖于您使用硬值(以像素为单位)这一事实。可以使其具有响应性(使用宽度、边距和填充的百分比值),但需要更多计算。

      【讨论】:

      • 虽然该解决方案适用于这个具体案例,但更通用的解决方案会很棒......:/
      • @Frithjof 我同意你的观点,但动画一般不是直截了当的,每种情况都需要单独处理。
      猜你喜欢
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 2018-07-10
      • 2016-02-04
      • 1970-01-01
      • 2019-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多