删除列表中一个DOM,其余DOM动态过渡的方法

10 篇文章 0 订阅
8 篇文章 0 订阅

删除列表中一个DOM,其余DOM动态过渡的方法

效果图

在这里插入图片描述

效果DEMO

简易的DOM 过渡效果

全部代码

HTML

<ul class="box" id="box">
    <li class="rect" data-index="01">01</li>
    <li class="rect" data-index="02">02</li>
    <li class="rect" data-index="03">03</li>
    <li class="rect" data-index="04">04</li>
    <li class="rect" data-index="05">05</li>
    <!-- 一共36个为了减少篇幅只写几个个 -->
</ul>

CSS

.box {
    width: 336px;
    height: 336px;
    box-shadow: 0 0 3px pink;
    list-style: none;
    padding: 0;
}
.rect {
    width: 50px;
    height: 50px;
    box-shadow: 0 0 3px orange inset;
    margin: 3px;
    float: left;
    cursor: pointer;
    line-height: 50px;
    text-align: center;
}

JavaScript

var rectArr = Array.from(document.getElementsByClassName('rect'));

var box = document.getElementById('box')
var delay = 300
box.addEventListener('click', function(e){
	// 如果点击的box本身就不往下执行
    if(e.target === box) return
	
	// 获取当前dom index, 当然你也可以不通过data-index 保存的方式获取,不过下面的方法就要稍微调整一下
    let index = e.target.getAttribute('data-index')

	// 取出要移动的DOM
    var moveArr = rectArr.splice(index, rectArr.length)

    // 保存要移动的DOM 未移动前的位置
    moveArr.forEach(item => {
        item.preLeft = item.offsetLeft
        item.preTop = item.offsetTop
    })

	// 删除dom 删除后后续DOM 位置立即变化
    box.removeChild(e.target)

	// 给移动后的DOM 位移置之前的位置
    moveArr.forEach(item => {
        item.style.transform = `translate(${item.preLeft - item.offsetLeft}px,${item.preTop - item.offsetTop}px)`
    })
	
	// 设置一点延迟给DOM 渲染反应时间,如果不设置自行试试会出现什么问题吧
	// 添加过渡,并位移回dom 新位置
    setTimeout(() => {
        moveArr.forEach(item => {
            item.style.transition = `transform ${delay}ms ease`
            item.style.transform = `translate(0, 0)`
        })
    }, 1)

	// 位移完 删除过渡以及位移参数, 删除了下次才能正常位移
    setTimeout(() => {
      moveArr.forEach(item => {
        item.style.transition = ``
        item.style.transform = ''
      })  
    }, delay + 1)

	// 前面通过 splice 删除掉了原有数组中将要移动的 dom,现在还原。
    // 有个问题就是虽然删除了DOM,但是还保存再来数组中,每次循环计算都是以36的数量计算
    rectArr = [...rectArr, ...moveArr]
})

方法原理解释

删除DOM 后,后续DOM 立马出现在新的位置不会出现过渡,因此我们手动加过渡。

1 删除之前保存好未移动之前的位置

2 删除之后把位置重新赋值给移动的元素(这里通过位移的方式,简单计算一下就行)

3 赋值完成后 再 添加过渡属性 以及重新赋值 位移(因为只有这里添加了过渡属性,所以这个位移才会过渡,其他的看不出效果)

4 位移完成删除过渡属性

所以结论就是,其实这里过渡就是,从当前位置移动到目标位置(没过渡效果),再从目标位置移回来(没过渡效果),最后再移回目标位置(有过渡效果,就是页面中看到的效果)。

结语

发这篇文章的起因其实是在 Stack Overflow 上面回答别人的问题,说实话,我比较常用 Vue 。而它里面有过渡组件,也有例子,基本上不需要我考虑具体的过渡实现,看到这个同行问的问题,并且他要原生代码写的,刚开始我通过审查元素的方式查看DOM 是如果变化的,最后找了一个例子,扒了一下源码才发现具体的实现方式,也总算知道为啥我审查元素打断点看不到了,因为他前两个位移没过渡,最后一个位移才有,而打断点只能看到最后一个。基本上这种操作的过渡都是这种思路,希望大家能够很好的理解,好了就这样啦。

以上信息如有疏漏或错误,欢迎指正

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值