在timeOut之后无法删除新添加的HTML元素

时间:2015-03-05 10:17:03

标签: javascript css3 dom

我尝试制作Google材料"涟漪"效果,没有任何库。为此,我使用了Sitepoint's script for capturing CSS3 Animation和一个脚本来模拟" jQuery的偏移方法:

function offset(elt) {
    var rect = elt.getBoundingClientRect(), bodyElt = document.body;
    return {
        top: rect.top + bodyElt.scrollTop,
        left: rect.left + bodyElt.scrollLeft
    }
}

我从Hai Nguyen react touch-ripple file获取动画的例子但是我甚至不知道反应的基础知识,所以我做了类似他的代码主要用于动画。我的问题是,为了效果,我添加了一个新的<span>,在完成所有修改并在1秒延迟后移除旧的,只需点击一下它就能正常工作,但如果我点击几次新的<span>元素仍在此处。我远不是一个JS大师。因此,如果您发现一个重大错误,请告诉我,我将改进我的代码。 HTML,SCSS和JS的所有代码都可见here。 我的HTML:

<button>
    <span class="ripples">
        <span class="ripples-circle"></span>
    </span>Test
</button>
<button>
    <span class="ripples">
        <span class="ripples-circle"></span>
    </span>Test
</button>
<button>
    <span class="ripples">
        <span class="ripples-circle"></span>
  </span>Test
</button>
<button>
    <span class="ripples">
    <span class="ripples-circle"></span>
  </span>Test
</button>
<button class="round">
    <span class="ripples">
        <span class="ripples-circle"></span>
    </span>Test
</button>

我的SCSS(我使用Autoprefixer):

body { /*just for remove inline-block lateral margins*/
    font-size: 0;
}

button {
    font-size: 12px;
    height: 4em;
    width: 25%;
    background-color: gray;
    border-style:solid;
    color: #fff;
    cursor: pointer;
    position: relative;
    display: inline-block;
    overflow: hidden;
    padding: 12px 24px;
    margin-top: 0;
    margin-bottom: 0;
    vertical-align: middle;
    transition: all 250ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;

&.round {
    border-radius: 50%;
    height: 100px;
    width: 100px;
}
&:focus {
    outline: 0;
}

&:hover {
    background-color: darken(gray, 5%);
}
}

.ripples {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;

    background-color: transparent;
    opacity: 0.7;
    transition: opacity 1s cubic-bezier(0.23, 1, 0.32, 1) 0ms;

    &.is-active {
        opacity: 1;
        .ripples-circle {
              -webkit-transform: scale(1);
              transform: scale(1);
        }
    }

    .ripples-circle {
        background-color: rgba(255,255,255,.5);
        position: absolute;
        left: 0;
        right: 0;
        height: 100%;
        width: 100%;
        border-radius: 50%;
        -webkit-transform: scale(0);
        transform: scale(0);
        transition: -webkit-transform 1s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
        transition: transform 1s cubic-bezier(0.23, 1, 0.32, 1) 0ms;
    }
}

JavaScript的:

;(function(window, document, undefined){
    'use strict';
    //http://www.debray-jerome.fr/js-performance-la-fonction-offset-de-jquery-vs-vanilla-javascript-23.html -- french
    function offset(elt) {
        var rect = elt.getBoundingClientRect(), bodyElt = document.body;
        return {
            top: rect.top + bodyElt.scrollTop,
            left: rect.left + bodyElt.scrollLeft
        }
    }

    //http://www.sitepoint.com/css3-animation-javascript-event-handlers/

    var pfx = ["webkit", "moz", "MS", "o", ""];
    function prefixedEvent(element, type, callback) {
        for (var p = 0; p < pfx.length; p++) {
            if (!pfx[p]) type = type.toLowerCase();
            element.addEventListener(pfx[p]+type, callback, false);
    }
}

function calcDiag(a, b) {
    return Math.sqrt((a * a) + (b * b));
}

    var buttons = document.querySelectorAll('button');
    for(var i=0; i < buttons.length;i++ ){
        buttons[i].addEventListener('click', function(e){

        var rippleThis = this;
        var parentOffset = offset(rippleThis);
        var elHeight = rippleThis.offsetHeight;
        var elWidth = rippleThis.offsetWidth;
        var pageX = e.pageX == undefined ? e.nativeEvent.pageX : e.pageX;
        var pageY = e.pageY == undefined ? e.nativeEvent.pageY : e.pageY;
        var x = pageX - parentOffset.left;
        var y = pageY - parentOffset.top;

        var topLeftDiag = calcDiag(x, y);
        var topRightDiag = calcDiag(elWidth - x, y);
        var botRightDiag = calcDiag(elWidth - x, elHeight - y);
        var botLeftDiag = calcDiag(x, elHeight - y);
        var rippleRadius = Math.max(topLeftDiag, topRightDiag, botRightDiag, botLeftDiag);
        var rippleSize = rippleRadius * 2;

        var j;
        var childrenLength = rippleThis.childNodes.length;
        var targetParent;
        var targetChild;

        for(j = 0; j < childrenLength; j++){
          if(rippleThis.childNodes[j].className == 'ripples') {
            targetParent = rippleThis.childNodes[j];
            targetParent.style.top = (y - rippleRadius) + 'px';
            targetParent.style.left = (x -rippleRadius) + 'px';
            targetParent.style.height = rippleSize +'px';
            targetParent.style.width = rippleSize +'px';
            targetParent.className = 'ripples is-active';
          }
        }

       //New span element
       var rippleSpan = document.createElement('span');
       var rippleCircleSpan = document.createElement('span');
       rippleSpan.className = "ripples";
       rippleCircleSpan.className = "ripples-circle";
       //Add new span
       rippleSpan.appendChild(rippleCircleSpan);
       rippleThis.insertBefore(rippleSpan, rippleThis.childNodes[0]);
    }, false);
    buttons[i].addEventListener('mouseup', function(e){
      prefixedEvent(e.currentTarget, "TransitionEnd", function(e){
      var button = e.currentTarget;
        for(var j = 0; j < button.childNodes.length; j++){
          if(button.childNodes[j].className == 'ripples is-active') {
            var targetParent = button.childNodes[j];
            targetParent.style.opacity = 0;
            setTimeout(function(){
              if(targetParent.parentNode){ targetParent.parentNode.removeChild(targetParent);             
              }
            }, 1000);

          }
        }
    });
    }, false);
}
})(window, document);

我想要的最终效果是here

2 个答案:

答案 0 :(得分:4)

我已经为我的问题找到了解决方案。工作脚本可见here。 我在代码中将我的前缀事件置于最高位置,之后它是eventListener mouseup事件的单独span,更重要的是我在父button元素上调用它之前setTimeOut元素1}}本身,这就是事件不起作用的原因。我又为if(targetParent.parentNode){ 条件增加了一个条件:

if(targetParent && targetParent.parentNode){

span

现在我的代码正常运行,DOM从{{1}}

消失

答案 1 :(得分:2)

从链接网站上我可以看出,视觉效果非常好,问题是你的剩余跨度。我相信你的问题实际上是closure并且与反应没有任何关系。我最近有一个类似的问题(在完全不同的环境中,但基本相同),我通过删除超时并使用检查超时条件的间隔来解决它。这几乎是它的工作原理:

有一个javascript变量,用于保存所有活动元素的数组及其创建时间。每1秒循环所有元素,看看他们的计时器是否已经过期。如果是这样,请删除它们。

这显然不是最有效的解决方案,因为它需要(几乎)不断检查元素,但它肯定会起作用。如果在性能密集型环境中未实现此功能,则应该可以很好地执行此操作。

另外,如果您找到另一种解决方案,我很高兴看到我是否也可以实施。