如何以显示结尾为不透明度 0 制作过渡效果:无?
Posted
技术标签:
【中文标题】如何以显示结尾为不透明度 0 制作过渡效果:无?【英文标题】:how can I make a transition effect to opacity 0 with ending in display: none? 【发布时间】:2021-01-07 05:47:04 【问题描述】:使用此代码,我正在模拟sidemenu
,因此如果我单击包含overlay
的button
,则将打开包含sidemenu
并且sidemenu
向右移动。如果我click
outside
,overlay
消失,菜单返回到初始位置。
.html
<div class="menuside_container" (click)="fn_hideSideMenu()" [ngClass]="showSideMenuContainer?showSideMenuContainer:''">
<div class="menuside" [ngClass]="showmenu:showMenu, hidemenu:!showMenu">
<a class="menu-item d-block" style="height:46px">
option 1
</a>
<a class="menu-item d-block" style="height:46px">
option 2
</a>
<a class="menu-item d-block" style="height:46px">
option 3
</a>
<hr class="m-0">
</div>
</div>
<button (click)="fn_showSideMenu()">show menu</button>
.ts
showMenu: boolean = false;
showSideMenuContainer: any = "d-none";
fn_showSideMenu()
setTimeout(() =>
this.showMenu = true;
);
this.showSideMenuContainer = "d-block";
fn_hideSideMenu()
this.showMenu = false;
setTimeout(() =>
this.showSideMenuContainer = "d-none";
, 400);
.menuside
position: absolute;
top: 0px;
width: 304px;
transition: all 0.3s linear;
background-color: #eaeaea;
height: 100%;
.menuside_container
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 999;
.css
.showmenu
left: 0px;
.hidemenu
left: -500px;
此代码有效,但我认为我使事情复杂化了很多,也许我不需要将代码放在我的 .ts 中,但我的想法是,我只想知道我是否可以解决相同的效果有来自css
和/或html
的angular
代码
我希望当我单击button
以显示overlay
然后从sidemenu
向右过渡,当我单击覆盖显示后,它将显示从我的过渡sidemenu
到它的起点。
关于问题标题,我之所以这么说是因为如果我把一个display: none
开头的.menuside_container
,sidemenu
的过渡不会显示出来
谢谢。 我只是在为我的问题寻找最佳解决方案
这是我的实时代码(见app/app.component.
html/ts/css):
https://stackblitz.com/edit/angular-ng-bootstrap-wa3xto?file=app%2Fapp.component.html
注意:
我基本上想做 gif 中显示的内容,但以更优化的方式。我使用setTimeouts
来实现它。但正如问题所说,我对如何将具有不透明度效果的元素从 1 转换为 0 但最后具有属性 display: none
很感兴趣。为什么?我想完全隐藏一个元素,但是使用opacity: 0
它仍然会占据space
,即使它不可见
【问题讨论】:
嘿@yavg,你能澄清一下你的问题,或者至少进一步解释一下吗?? 我认为你应该使用角度动画,而不是 CSS 会更有效。 @OwaisAhmedKhan 朋友,我基本上想做 gif 中显示的内容,但以更优化的方式。我使用settimeouts
来实现它。但正如问题所说,我对如何将具有不透明度效果的元素从 1 转换为 0 但最后具有属性 display: none
很感兴趣。为什么?我想完全隐藏一个元素,但是使用opacity: 0
它仍然会占据空间,即使它不可见
我认为,更好的方法是在您的菜单上用animationend
事件替换setTimeout
@CedricCholley 谁能做到?
【参考方案1】:
您可以使用非常简单的基于 html 和 CSS 的动画菜单。看看这个来自你的stackblitz。
例如:
function closeMenu()
document.querySelector(".menuside_container").classList.add("hidemenu");
document.querySelector(".menuside_container").classList.remove("showmenu");
function showMenu()
document.querySelector(".menuside_container").classList.remove("hidemenu");
document.querySelector(".menuside_container").classList.add("showmenu");
body,
html
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
background: blue;
@keyframes menuOpen
from
opacity: 0.5;
transform: translateX(-500px);
display: none;
to
opacity: 1;
transform: translatX(0);
display: block;
background-color: rgba(0, 0, 0, 0.5);
@keyframes menuClose
from
opacity: 1;
transform: translateX(0);
display: block;
to
opacity: 0.5;
transform: translateX(-500px);
display: none;
z-index: -1;
background-color: transparent;
.menuside
position: absolute;
top: 0px;
width: 304px;
height: 100%;
background-color: #eaeaea;
.menuside_container
position: fixed;
top: 0px;
width: 100%;
height: 100%;
z-index: 999;
.showmenu,
.hidemenu
animation-duration: 0.4s;
animation-timing-function: linear;
animation-fill-mode: forwards;
.showmenu
animation-name: menuOpen;
.hidemenu
animation-name: menuClose;
.d-block
display: block;
<div class="menuside_container hidemenu" onclick="closeMenu()">
<div class="menuside">
<a class="menu-item d-block" style="height:46px">
option 1
</a>
<a class="menu-item d-block" style="height:46px">
option 2
</a>
<a class="menu-item d-block" style="height:46px">
option 3
</a>
<hr class="m-0">
</div>
</div>
<button onclick="showMenu()">show menu</button>
【讨论】:
当然你可以在Angular中使用jQuery,但你应该避免这样做 @Eliseo 它不需要 jQuery。在我的纯 HTML 示例中,我只是使用它来添加和删除类。将我的示例更新为仅包含香草 JS。此外,如果您查看 stackblitz 代码,它没有 jQuery 作为依赖项。 是的,抱歉,我看到document.querySelector
让我抓狂:) (无论如何,我认为这不是“Angular 方式”,-在 Angular 方式中,您可以使用 ViewChildren-)
@Eliseo 确定我没有在仅 html css 代码中使用角度。你有没有看过附加的 stablitz?
是的!,[ngClass]
是“Angular 方式”,我喜欢你在 stackblitz 中的解决方案 :) -对不起,我只看到了答案-【参考方案2】:
您实际上已经实现了您想要做的事情。如果你检查控制台,你会看到.menuside_container
在动画运行之前有display:none
,并在菜单关闭后恢复到这个。这是因为您正在对其应用 d-none
类,该类应用以下声明:display: none!important;
您还可以采取其他措施来改进您的代码。正如其他人指出的那样,Angular 确实有自己的动画系统,您可能想研究一下。此外,您可以使用translateX()
函数代替使用left
属性来制作动画,这被认为具有更高的性能。这是通过进行以下更改来实现的:
.showmenu
/* left: 0px; */
transform: translateX(0)
.hidemenu
/* left: -500px; */
transform: translateX(-500px)
【讨论】:
【参考方案3】:如果您希望display: none
阻止点击该元素,您可以使用pointer-events: none;
。
您还可以有一个类来显示菜单并假设正常状态是隐藏的。
所以我的建议是
.menuside
[...]
transition: transform 0.3s linear;
[...]
transform: translateX(-500px)
.menuside_container
[...]
pointer-events: none;
background-color: rgba(0, 0, 0, 0.5);
transition: opacity 0.3s linear;
opacity: 0;
.menuside.showmenu
transform: translateX(0)
.menuside_container.showmenu
pointer-events: auto;
opacity: 1;
.ts
中的函数只需设置showMenu
属性
fn_showSideMenu()
this.showMenu = true;
fn_hideSideMenu()
this.showMenu = false;
html
是:
<div class="menuside_container" (click)="fn_hideSideMenu()" [ngClass]="showmenu:showMenu">
<div class="menuside" [ngClass]="showmenu:showMenu">
<a class="menu-item d-block" style="height:46px">
option 1
</a>
<a class="menu-item d-block" style="height:46px">
option 2
</a>
<a class="menu-item d-block" style="height:46px">
option 3
</a>
<hr class="m-0">
</div>
</div>
<button (click)="fn_showSideMenu()">show menu</button>
你可以看看我在你的 Stackblitz 上制作的叉子
https://stackblitz.com/edit/angular-ng-bootstrap-rcwejo?file=app/app.component.css
【讨论】:
【参考方案4】:您可以通过使用javascript
Element.animate()
或使用CSS
创建相同的动画来做到这一点(您需要两个帮助类,例如关闭,打开)。使用translateX()
而不是left
制作动画。
只有在动画结束后,您才需要使用animationend
事件才能应用display: none
。
此效果不需要某些元素。例如,不需要.menuside_container
,只使用了一个简单的帮助类。
请检查以下示例的逻辑:
const menuside = document.querySelector('.menuside');
menuside.addEventListener('animationend', () =>
menuside.style.display = 'none';
);
menuside.addEventListener('click', () =>
menuside.animate([
// keyframes
transform: 'translateX(0)',
opacity: '1'
,
transform: 'translateX(-304px)',
opacity: '0'
],
// timing options
duration: 1000,
fill: 'forwards',
direction: 'normal',
iterations: 1
);
menuside.classList.add('closed');
);
document.querySelector('button').addEventListener('click', () =>
if (menuside.classList.contains('closed'))
menuside.style.display = 'block';
menuside.animate([
// keyframes
transform: 'translateX(0)',
opacity: '1'
,
transform: 'translateX(-304px)',
opacity: '0'
],
// timing options
duration: 1000,
fill: 'forwards',
direction: 'reverse',
iterations: 1
);
menuside.classList.remove('closed');
);
.menuside
position: fixed;
top: 0;
left: 0;
display: block;
width: 304px;
background-color: #eaeaea;
height: 100%;
body
width: 100%;
height: 100%;
background-color: red;
button
position: fixed;
top: 3rem;
right: 1rem;
<div class="menuside">
<a class="menu-item d-block" style="height:46px">
option 1
</a>
<a class="menu-item d-block" style="height:46px">
option 2
</a>
<a class="menu-item d-block" style="height:46px">
option 3
</a>
<hr class="m-0">
</div>
<button>show menu</button>
【讨论】:
【参考方案5】:这很好用,我得到了与你的 gif 中显示的相同的东西,但没有使用 setTimeout,但正如你所看到的,尽管在 @keyframes 中使用了等于 none 的显示属性,但它不会显示任何更改,因为显示属性是不可动画 .要查看动画属性的完整列表,请访问https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
var overlay=document.getElementById('overlay');
var menuside=document.getElementById('menuside');
function show_menu()
overlay.style.display="block";
overlay.style.animation="show_overlay 0.6s 1";
overlay.style.animationFillMode="forwards";
menuside.style.animation="show_menu_pane 0.6s 1";
menuside.style.animationFillMode="forwards";
function hide_menu()
menuside.style.animation="hide_menu_pane 0.6s 1";
menuside.style.animationFillMode="forwards";
overlay.style.animation="hide_overlay 0.6s 0.3s 1";
overlay.style.animationFillMode="forwards";
*
margin: 0px;
padding: 0px;
font-family: 'Arial';
body
background-color: blue;
.menuside
position: absolute;
top: 0px;
width: 304px;
transition: all 0.3s linear;
background-color: #eaeaea;
height: 100%;
z-index: 900;
transform: translateX(-304px);
.menuside li
padding: 10px;
.menuside li a
text-decoration: none;
font-size: 18px;
color:#707070;
transition: 0.4s;
.menuside li a:hover
margin-left: 20px;
.menuside_container
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index:-1;
.overlay
display:none;
position:absolute;
width:100%;
height:100%;
background-color: rgba(0, 0, 0, 0.5);
z-index:8;
transition:0.6s;
opacity: 1;
@keyframes hide_overlay
from
opacity: 1;
display: block;
z-index: 8;
to
opacity: 0;
display: none;
z-index: 0;
@keyframes show_overlay
from
opacity: 0;
z-index: 0;
to
opacity: 1;
z-index: 8;
@keyframes show_menu_pane
from
transform: translateX(-304px);
to
transform: translateX(0px);
@keyframes hide_menu_pane
from
transform: translateX(0px);
to
transform: translateX(-304px);
button
position: absolute;
z-index: 1;
padding: 10px;
border:1px solid black;
font-size: 18px;
outline: none;
<div class="menuside_container" >
<div class="overlay" id="overlay" onclick="hide_menu()"></div>
<div class="menuside" id="menuside">
<ul>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 1
</a>
</li>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 2
</a>
</li>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 3
</a>
</li>
<hr class="m-0">
</ul>
</div>
<button onclick="show_menu()">Show Menu</button>
</div>
2。 display:none 的另一种替代方法是将宽度和高度设为零,结果将与 gif 相同,但不透明度转换不起作用。
var overlay=document.getElementById('overlay');
var menuside=document.getElementById('menuside');
function show_menu()
overlay.style.display="block";
overlay.style.animation="show_overlay 0s 1";
overlay.style.animationFillMode="forwards";
menuside.style.animation="show_menu_pane 0.6s 1";
menuside.style.animationFillMode="forwards";
function hide_menu()
menuside.style.animation="hide_menu_pane 0.6s 1";
menuside.style.animationFillMode="forwards";
overlay.style.animation="hide_overlay 0s 0.6s 1";
overlay.style.animationFillMode="forwards";
*
margin: 0px;
padding: 0px;
font-family: 'Arial';
body
background-color: blue;
.menuside
position: absolute;
top: 0px;
width: 304px;
transition: all 0.3s linear;
background-color: #eaeaea;
height: 100%;
z-index: 900;
transform: translateX(-304px);
.menuside li
padding: 10px;
.menuside li a
font-size: 18px;
color:#707070;
text-decoration: none;
transition: 0.4s;
.menuside li a:hover
margin-left: 20px;
.menuside_container
position: absolute;
left: 0px;
top: 0px;
width: 304px;
height: 100%;
.overlay
display:none;
position:absolute;
width:100vw;
height:100vh;
background-color: rgba(0, 0, 0, 0.5);
z-index:14;
transition:0.6s;
@keyframes hide_overlay
from
width:100vw;
height:100vh;
to
width:0vw;
height:0vh;
@keyframes show_overlay
from
width:0vw;
height:0vh;
to
width:100vw;
height:100vh;
@keyframes show_menu_pane
from
transform: translateX(-304px);
to
transform: translateX(0px);
@keyframes hide_menu_pane
from
transform: translateX(0px);
to
transform: translateX(-304px);
button
position: absolute;
z-index: 13;
padding: 10px;
border:1px solid black;
font-size: 18px;
outline: none;
<div class="overlay" id="overlay" onclick="hide_menu()"></div>
<div class="menuside_container" >
<div class="menuside" id="menuside">
<ul>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 1
</a>
</li>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 2
</a>
</li>
<li>
<a href="#/" class="menu-item d-block" style="height:46px">
option 3
</a>
</li>
<hr class="m-0">
</ul>
</div>
</div>
<button onclick="show_menu()" id="button">Show Menu</button>
【讨论】:
【参考方案6】:如果你不仅想不显示,还想从 DOM 中移除,你可以使用 Angular 动画来实现。在你的组件中定义
@Component(
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"],
animations: [
trigger("menuOpenClose", [
transition(":enter", [
style( left: "-300px"), //state initial
animate("100ms", style( left: 0 )) //animate to a final state
]),
transition(":leave", [animate("100ms", style( left: "-300px" ))])
])
]
)
所以你只需声明一个变量
open=false;
还有一个类似的html
<div @menuOpenClose class="menuside" *ngIf="open">
<button (click)="open=false">close</button>
</div>
<button (click)="open=true">open</button>
见very ugly stackblitz
更新改进“菜单”
你声明了两个辅助变量
submenuOpen=false;
openFinished=false;
还有一个类似的.class
.fade
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
z-index: 999;
查看 .html - 您使用 open=true 和 (@menuOpenClose.done) 的地方-
<!--
if you want close when click in any place of "#menu" add
(click)="open=false"
if you want close ONLY y you click in "menu" (but not if click in a button inside "menu") e.g. you has a "submenu"
(click)="$event.target==menu && open=false"
-->
<div #menu @menuOpenClose (@menuOpenClose.done)="openFinished=!openFinished"
class="menuside" *ngIf="open"
(click)="$event.target==menu && open=false">
<button (click)="open=false">close</button>
<div>
<button (click)="submenuOpen=!submenuOpen" >menu</button>
</div>
<div *ngIf="submenuOpen" (click)="open=false">
<hr />
<button (click)="doIt('I\'m menu 1')">menu-1</button>
<button (click)="doIt('I\'m menu 2')">menu-2</button>
</div>
</div>
<button (click)="open=true">open</button>
<div class="fade" *ngIf="openFinished" (click)="open=false"></div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eius
【讨论】:
我觉得这个答案很简单,用最有效的方式解决问题【参考方案7】:display:none
不受转换速度的影响,因此不能由纯 CSS 完成。
你可以:
-
使用解决方法。 (例如,您可以使用
visibility:hidden;
或width:0;height:0;overflow:hidden;margin:0;
,它们会受到转换延迟的影响。
或
-
您可以使用 javascript,就像您在示例中所做的那样,
或
-
Angular 本身实际上具有内置动画支持,您可以将其设置为在
*ngIf
触发时触发。例如,这里:angular 2 ngIf and CSS transition/animation
【讨论】:
【参考方案8】:从此 repo 获取代码。你想要的东西是在响应模式下实现的。
代码:https://github.com/muhammadawaisshaikh/gamelist-ui-test/tree/master/header预览直播:https://muhammadawaisshaikh.github.io/gamelist-ui-test/header/
【讨论】:
谢谢,但我不知道如何做我需要的。以display: none
结束的过渡
请不要发布仅链接的答案。相反,请将解决方案包含在您的答案正文中。
您必须将显示属性转换为在您的情况下可以正常工作的可见性。【参考方案9】:
实际上你将不得不使用 translateX 来实现流畅的 60fps 动画。
您可以在本文 (https://medium.com/outsystems-experts/how-to-achieve-60-fps-animations-with-css3-db7b98610108) 中阅读其背后的理论,或者直接获取文章末尾的代码
【讨论】:
谢谢,但我不知道如何做我需要的。以display: none
结尾的过渡
您面临的问题是无法将显示属性从块切换到无。我分享的文章解释了它。如果您查看代码,您会发现它实现了相同的结果,但方式更高效、更流畅。如果您仍然需要以 display: none 结尾,那么我很抱歉,但我无法帮助您。以上是关于如何以显示结尾为不透明度 0 制作过渡效果:无?的主要内容,如果未能解决你的问题,请参考以下文章