transition 相关记录(如何让子元素不受父元素影响)
当前情况:在某个文件统一对所有的页面 View 组件设置了 CSS3 动画,包括 transform 和 opacity,但是其中两个页面有 Navbar 组件(View 组件的子元素)希望是完全不受动画影响。
限制条件:不希望将 Navbar 单独拿出来作为 View 组件的兄弟。
由于通过使用的是 Reactcsstransitiongroup 添加的动画。所以我有几个解决的思路(不确定能成功的)
- 通过自带属性修改作用的 DOM 元素
- 修改 CSS 样式
- 修改 DOM 结构
- 通过 js 判断需要作用的 DOM
下面一个一个来尝试:
方式一:这个主要是想要查看 Reactcsstransitiongroup 组件本身是否有提供一些属性能够让子组件不受动画影响,查看了资料以后当然是发现没有;
方式二:修改 CSS 样式是要去修改子组件的样式让它不受父组件影响,这个也是后来成功的方式,待会儿再细说。
方式三:修改 DOM 的方法其实就是相当于将 Navbar 组件从 View 组件中拿出来,这样其实能够很快解决问题,但是问题在于这样一来页面结构不够清晰,代码就不太好维护。所以这个方式其实应该是放在最后的才考虑的。
方式四:这个方式没有去尝试,因为通过修改 CSS 样式就已经解决了问题,所以不确定此方式的可行性,这里列出只是记录一下。
(使用的工具其实很简单,就是 chrome 的 developer tools,新版浏览器的查看动画是在工具栏最右侧三个点,点开然后选择 More tools,第一个选项 Animations 就能查看到动画情况。)
现在主要讲一下修改 CSS 样式的这种方式,首先如果想要通过设置子元素 position: absolute 是绝对不可行的,是的,我有去傻傻尝试过。
我先考虑的是如何解决 transform 的问题,父元素的动画是 transform: translateY(10px);
到 transform: translateY(0);
,Y轴坐标从 10px 变换到 0px,其实仔细想想,只要对子元素做一个反向的动画就可以,所以我对子元素设置成 transform: translateY(10px);
到 transform: translateY(0);
,查看效果,并不会存在晃动的情况,而是十分平稳的不会有任何动作。但是需要注意的是子元素并没有 enter 和 leave 的动画,只有 appear 的动画,所以需要找到父元素对应的动画情况来做坐标的抵消,比如父元素的 appear 和 enter 都应该和子元素的 appear 进行抵消。
例如:
// 父元素 css
.enter {
transform: translateY(10px);
&.enterActive {
transform: translateY(0);
transition: all 400ms ease;
}
}
// 子元素 css
.appear {
transform: translateY(-10px);
&.appearActive {
transform: translateY(0px);
transition: all 400ms ease;
}
}
接着是 opacity 的问题,要明确一点的是 opacity 是无法进行抵消的,它的范围是 0 ~ 1,不论设置什么小于0的值,最后的取值都是 0,无论设置什么大于1的值,最后的取值都是1,如果父元素设置为0.5,子元素想要设置2来抵消动画行为是不可行的。子元素的 opacity 属性的设置,永远是建立在父元素的基础上,比如:
// 父元素 css
.enter {
opacity:0.5
}
// 子元素 css
.enter-child {
opacity: 1
}
// 父元素设置为 0.5,子元素设置为1,但是子元素看起来的效果和父元素是一样的
// 因为子元素是在 0.5 的基础上设置1,如果子元素也设置0.5,则子元素看到的就是 0.25 的效果。
网上有查询到其它的方法,还有另外两种,都是不使用 opacity,毕竟拿它没办法,一种是使用 background:rgba(0,0,0,0.5) 替代,当然并不一定 rgb 都是零,另外一种是使用半透明图片替代,这两种方法并不是针对动画中的半透明,而是针对静态情况下的半透明,但是感觉大同小异。总之对于我的项目并不是一个好的方式,毕竟我不仅仅需要背景半透明。
所以在对 opacity 的处理上,是让效果减少的最小,让它看起来没有很明显的动画,说白了也是在父组件和子组件之间取得平衡,父组件既不因为动画不明显而变化得太突兀,子组件也不会有很明显的有淡入淡出的效果,让 leave 和 enter 的动画衔接得很紧。
代码如下:
// 父组件 css
.appear {
opacity: 0.5;
transform: translateY(10px);
&.appearActive {
opacity: 1;
transform: translateY(0px);
transition: all 400ms ease;
}
}
.leave {
opacity: 1;
&.leaveActive {
opacity: 0;
transition: all 400ms ease;
}
}
// 子组件不需要设置 opacity