Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

带突出三角形的下拉对话框动画实现 #3

Open
ryancui92 opened this issue Jul 16, 2017 · 0 comments
Open

带突出三角形的下拉对话框动画实现 #3

ryancui92 opened this issue Jul 16, 2017 · 0 comments

Comments

@ryancui92
Copy link
Owner

在很多时候需要实现一个弹出框,效果类似这样:

需求

要留意的是这个对话框有一个指示弹出位置的三角,并且需要实现下拉动画和上滑动画。

一个 box 加 :before

针对需求,有初步的方案

  • 指示三角:在 box 前加伪类 :before、三角形通过边框法实现 border-bottom
  • 动画:transition height 由于 box 高度可以固定,直接使用 height 做动画

关于边框法实现三角形可以自行 Google,原理很简单,就是把 box model 的内容去掉 width: 0; height: 0,利用四个 border 都是三角形设置三条边为透明即可。

这里要注意的是三角形的 top 应该是两倍的上下边框的 border-width

这里我们发现这个三角形没有出现,原因是我们在 box 上加了 overflow: hidden,这是为了让 box 的 height 变成 0 时,box 的内容不会溢出到 box 外(不然这个下拉动画就没用了)。由于要使用 transition height 就必须加上这个 overflow: hidden,那么所有要在 box 的 HTML 内部实现三角形的方法都不会 work,因为这个三角形实际上一定会 overflow 到 box 外。

分成两个 box

既然不能在 box 内部放这个三角形,那就放到外面呗,在 box 的同层加一层 div,额外放这个三角形。

具体实现时,把这个 before-box 的背景设成透明就 ok 了。

两个 box 后的 transition

分成两部分之后面临的第二个问题是,动画怎么办?当我还是一个 box 的时候,设置了 transition,js 要做的事就很简单:

// 下拉
ele.style.height = '200px'

// 收起
ele.style.height = '0px'

但分成两部分之后,如果简单得认为只需要在 before-box 上也设一个 transition height 然后这样:

// 下拉
before.style.height = '20px'
ele.style.height = '200px'

// 收起
before.style.height = '0px'
ele.style.height = '0px'

那就 TOO NAIVE 了,这时候你会发现这两个 div 是同步进行动画的,给人一种强烈的违和感。

既然我想有先后顺序,第一个想到的应该是 transition-delay,加个延迟就好了啊:

.before-box {
  transition: height 0.05s ease-out;
}

.box {
  transition: height 0.3s 0.05s ease-out;
}

下拉的时候很完美啊,但收起的时候就悲剧了,before-box 先收起,然后才是 box 的动画,违和感更强了。

这时我们知道,其实我们需要一种带方向性的 transition 机制,从 0 到 100px 和从 100px 到 0 我们希望能够 apply 不同的 transition 参数(这里是不同的 delay)。

于是找了一下,貌似 transition 并不支持这种方向性的机制。但是没关系,我们可以通过 js 自行创造,用不同的 class 来预定义不同的 transition 参数,然后在实际动画前变更这些 class 就可以实现带方向的 transition 了。

.triangle-show {
  transition: height 0.05s linear;
}

.triangle-hide {
  transition: height 0.05s 0.35s linear;
}

.box-show {
  transition: height 0.3s 0.05s ease-out;
}

.box-hide {
  transition: height 0.3s ease-out;
}

在 show/hide 之前切换 class

// 下拉
before.classList.add('triangle-show')
box.classList.add('box-show')
before.classList.remove('triangle-hide')
box.classList.remove('box-hide')
...

// 收起
before.classList.add('triangle-hide')
box.classList.add('box-hide')
before.classList.remove('triangle-show')
box.classList.remove('box-show')

当然如果不想定义这么多的 class 也可以直接选择在 js 中更改 transition 的属性 ele.style.transitionDelay = '0.35s'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant