What you need to know:

  • Display: None doesn’t apply the transition effect, and it even breaks it because when the browser renders the DOM, if one of the nodes is display: Display: None will not show up in the render tree, and display: None will cause backflow, changing the layout, and there will be no transition
  • Elements with the transition of opacity can still click the triggering event, hover effect and so on, only use opcityl to transition animations are not enough, some people say that can be combined with the visibility: visibile/hidden, but hidden in this element is a placeholder, This approach is also undesirable

So how do we add animations when we hide nodes?

Let’s take a look at the pros and cons of the following scenarios with a popup of hidden cases. [The following schemes are pseudo-code, only the implementation is discussed]

Solution 1: Use Vue transiton built-in animation with V-IF/V-show to control show and hide

Vue inserts or deletes DOM elements accordingly

Scheme 2: Opacity and scale3D are used to control the opacity of the popbox

// Animation transition.dialogMask{
	  transition: all .3sease-in; } // The popbox is hidden.hide{
	  opacity: 0;
	  transform: scale3d(1.1.0); } // The box is displayed.show{
	 opacity: 1;
	 transform: scale3d(1.1.1);
}
Copy the code

The scale z-axis turns to 0 when hidden to remove nodes inside dialogMask. This way there is only one external node when the popbox is hidden, reducing the initial rendering overhead

Wx :if=”{{show}}” if=”{{show}}”

This method works with native JS or applets

Scheme 3: Display and setTimeout

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Show hidden animation</title>
    <style>
        .model {
            width: 100px;
            height: 100px;
            background: # 787878;
            margin: 0 auto;
            transition: all .3s;
        }
    </style>
</head>

<body>
    <button onclick='dianji()'>Click on the</button>
    <div class="model">content</div>
    <script>
        let model = document.querySelector('.model')
        function dianji() {
            if (model.style.display === 'none') {
                model.style.display = 'block'
                // Macro task features
                setTimeout(() = > {
                    model.style.opacity = 1
                }, 0)}else {
                model.style.opacity = 0
                setTimeout(() = > {
                    model.style.display = 'none'
                }, 300); }}</script>
</body>
</html>
Copy the code

SetTimeout (()=>{},0)

SetTimeout needs to be set in the same way as the transition. Of course you can also listen for the transitionEnd/AnimationEnd end event and hide or remove elements when it ends

Option 4: Add animation when removing the DOM

<! DOCTYPEhtml>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Remove Adds animation when removing elements</title>
</head>
<style>
    #app {
        width: 100px;
        height: 100px;
        transition: all 300ms cubic-bezier(0.23.1.0.32.1);
        transform-origin: center top;
        border: 1px solid sienna;
        text-align: center;
        line-height: 100px;
        margin-top: 15px;
    }

    .show {
        opacity: 1;
        transform: scaleY(1);
    }

    .hide {
        opacity: 0;
        transform: scaleY(0);
    }
</style>

<body>
    <button id="btn">Click on the</button>
    <div id="app" class="show">content</div>
    <script>
        let element = document.getElementById("app");
        let btn = document.getElementById('btn')
        let copy = null
        function transition(ele, fn) {
            console.log(1)
            ele.addEventListener("transitionend".() = > {
                if (document.body.contains(ele)) {
                    document.body.removeChild(ele)
                    fn()
                }
            }, false);
        }
        btn.addEventListener('click'.() = > {
            if (!document.body.contains(element)) {
                let ele = document.body.appendChild(copy)
                setTimeout(() = > {
                    ele.classList.replace("hide"."show");
                    element = ele
                }, 0)}else {
                element.classList.replace("show"."hide");
                copy = element.cloneNode(true); / / deep cloning
                transition(element, () = > {
                    element = null})}})</script>
</body>

</html>
Copy the code

preview

Codepen. IO/wensiyuanse…

Option 5: Use animation library to process transition animation

    //startMove is a wrapped animation library
      let model = document.querySelector('.model')
       function dianji() {
           if (model.style.display === 'none') {
               model.style.display = 'block'
               startMove(model, {
                   opacity: 100})}else {
               startMove(model, {
                   opacity: 0
               }, () = > {
                   model.style.display = 'none'}}})Copy the code

movejs

function startMove(obj, json, fn) {
	clearInterval(obj.iTimer);
	var iCur = 0;
	var iSpeed = 0;

	obj.iTimer = setInterval(function () {

		var iBtn = true;

		for (var attr in json) {

			var iTarget = json[attr];

			if (attr == 'opacity') {
				iCur = Math.round(css(obj, 'opacity') * 100);
			} else {
				iCur = parseInt(css(obj, attr));
			}

			iSpeed = (iTarget - iCur) / 8;
			iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);

			if(iCur ! = iTarget) { iBtn =false;
				if (attr == 'opacity') {
					obj.style.opacity = (iCur + iSpeed) / 100;
					obj.style.filter = 'alpha(opacity=' + (iCur + iSpeed) + ') ';
				} else {
					obj.style[attr] = iCur + iSpeed + 'px'; }}}if (iBtn) {
			clearInterval(obj.iTimer); fn && fn.call(obj); }},30);
}

function css(obj, attr) {
	/ / compatible with ie
	if (obj.currentStyle) {
		return obj.currentStyle[attr];
	} else {
		// The second argument represents pseudo-classes such as :after, :before and so on
		return getComputedStyle(obj, false)[attr]; }}Copy the code

Reference article:

www.zhangxinxu.com/wordpress/2…

Segmentfault.com/a/119000001…