如何添加延迟以在 angularjs 中悬停元素?

Posted

技术标签:

【中文标题】如何添加延迟以在 angularjs 中悬停元素?【英文标题】:How do I add a delay for hovering an element in angularjs? 【发布时间】:2014-09-10 05:27:35 【问题描述】:

我有一个元素:

    <span ng-mouseenter="showIt()" ng-mouseleave="hideIt()">Hover Me</span>
    <div class="outerDiv" ng-show="hovering">
        <p>Some content</p>
        <div class="innerDiv">
            <p>More Content</p>
        </div>
    </div>

这里是 JS:

// mouseenter event
$scope.showIt = function () 
    $scope.hovering = true;
;

// mouseleave event
$scope.hideIt = function () 
    $scope.hovering = false;
;

我希望能够为悬停事件设置 500 毫秒的延迟。

我已经有了这个问题的答案,但我不能再发布 8 小时。我会回来的!

【问题讨论】:

【参考方案1】:

就像这里大多数人已经提到的那样,我在 mouseenter 事件中添加了一个计时器。

// create the timer variable
var timer;

// mouseenter event
$scope.showIt = function () 
    timer = $timeout(function () 
        $scope.hovering = true;
    , 500);
;

我遇到的问题是,如果我滚动过该项目并且鼠标光标击中它,那么半秒后仍然会出现弹出窗口。我希望能够滚动过去一个项目而不会意外发生弹出窗口。

将超时设置在变量中允许我取消超时。我在鼠标离开事件中执行此操作以确保用户不会意外触发弹出窗口。

// mouseleave event
$scope.hideIt = function () 
    $timeout.cancel(timer);
    $scope.hovering = false;
;

这是一个小提琴,以防有人想看到它的实际效果: jsfiddle

【讨论】:

【参考方案2】:

我建议使用 CSS 过渡和 angular-animate:

JS

var app = angular.module('app', ['ngAnimate']);

CSS

.outerDiv.ng-hide-remove 
    -webkit-transition: 0.5s linear all; 
    transition: 0.5s linear all;
    transition-delay: 0.5s;
    opacity: 0;

.outerDiv.ng-hide-remove.ng-hide-remove-active 
    opacity: 1;

HTML

<span ng-mouseenter="hovering=true" ng-mouseleave="hovering=false">Hover Me</span>
<div class="outerDiv" ng-show="hovering">
    <p>Some content</p>
    <div class="innerDiv">
        <p>More Content</p>
    </div>
</div>

Demo Plunker

【讨论】:

【参考方案3】:

使用$timeout:

$scope.showIt = function () 
    $timeout(function()
        $scope.hovering = true;
    , 500);
;

不要忘记将其添加为依赖项。

如果您想多玩一些,您可以创建自己的指令,例如 delayedMouseEnter,其中包含延迟并改用它。

【讨论】:

【参考方案4】:

window.setTimeout在指定延迟后调用函数或执行代码sn-p。

$scope.hideIt = function () 
    window.setTimeout(function() 
        $scope.hovering = false;
        $scope.$apply();
    , 500);  // 500ms delay        
;

或 Angular $timeout 服务:

$scope.hideIt = function () 
    $timeout(function() 
        $scope.hovering = false;
    , 500);  // 500ms delay        
;

【讨论】:

推荐使用$timeout 服务而不是setTimeout,因为它允许测试并自动调用$scope.$apply(),这在此代码中是缺失的。 因为他回答说我还不能发布我使用 $timeout 然后在 mouseleave 上取消它。 link【参考方案5】:

我为此写了一个简单的指令。

(function () 
    'use strict';
    angular
        .module('app')
        .directive('scHover', scHoverDirective);

    function scHoverDirective($timeout) 
        return 
            link: function(scope, element, attrs, modelCtrl) 
                    var inTimeout = false;
                    var hoverDelay = parseInt(attrs.scHoverDelay, 10) | 1000;

                    element.on('mouseover', function () 
                      inTimeout = true;
                      $timeout(function () 
                        if (inTimeout) 
                          scope.$eval(attrs.scHover);
                          inTimeout = false;
                        
                      , hoverDelay);
                    );

                    element.on('mouseleave', function () 
                      inTimeout = false;
                      scope.$apply(function () 
                        scope.$eval(attrs.scHoverEnd);
                      );
                    );
            
        
    
)();

使用示例(sc-hover-delay 是可选的):

<div sc-hover='vm.title="Hovered..."' sc-hover-end='vm.title=""' sc-hover-delay="800">Hover me!   vm.title </div>

这里是一个笨蛋:http://plnkr.co/edit/iuv604Mk0ii8yklpp6yR?p=preview

【讨论】:

【参考方案6】:

感谢您提出这个问题,因为这个示例帮助我理解 $timeout 的工作原理比 AngularJS 的文档做得更好。不过,我确实在正确答案上稍微改进了操作,想在这里分享一下。

您永远不必创建一个名为 timer 的空变量。事实上,这样做会耗尽你不必这样做的内存。你有一个变量和两个函数来处理实际上是一个单一的操作。

所以,我所做的是创建一个名为“toggleHover”的函数,它接受一个名为“bool”的布尔参数。然后一个 if/else 语句确定您需要运行哪个 $timeout 函数。

AngularJS 在控制器中

$scope.hovering = false; //Sets the initial state of hover

$scope.toggleHover = function (bool) 
    if (bool === true) 
        $timeout(function () 
            $scope.hovering = !$scope.hovering;
        , 500);
     else 
        $timeout(function() 
            $scope.hovering = !$scope.hovering;
        , 500);
    ;

html/视图

<span ng-mouseenter="toggleHover(true)" ng-mouseleave="toggleHover(false)">Hover Me</span>

示例

http://jsfiddle.net/89RTg/12/

【讨论】:

对不起,如果我没有得到这个 .. 查看您的代码,您甚至不需要布尔值,除非您想更改进入与离开的时间。但是如果你这样做,并且离开比进入更快,你需要清除进入的超时时间(或者它可能会在你离开后触发)。这就是为什么你需要这个变量。 为什么还需要 if else ?两者都在做同样的事情吗?【参考方案7】:

你好,上面的答案很好 只是想添加,如果需要,当您将鼠标悬停并且它仍然没有触发或您销毁指令时,请不要忘记取消您的计时器

 $timeout.cancel( timer );
 $scope.$on("$destroy",
                    function( event ) 

                        $timeout.cancel( timer );

                    
                );

【讨论】:

以上是关于如何添加延迟以在 angularjs 中悬停元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何添加淡入淡出功能以在悬停功能上播放?

使用 CSS 或 AngularJS 的 SVG 路径元素悬停缩放

半秒后使用 AngularJS 在鼠标悬停时显示子菜单

css:悬停在chrome中无法延迟动态添加的类

如何在angularjs中悬停显示文本?

是否可以升级 angularjs 属性指令以在 Angular 4 中使用?