首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找一种更好的方法在AngularJS中一次遍历和显示一个元素

寻找一种更好的方法在AngularJS中一次遍历和显示一个元素
EN

Stack Overflow用户
提问于 2013-07-06 14:40:56
回答 1查看 894关注 0票数 1

我正在构建一个有动画的应用程序,我需要它更好地工作。我希望能够在指定的动画间隔内完成一系列的div,并一次显示一个。我希望每个系列都有自己的速度和电视。

,这是我到目前为止所拥有的(也复制到下面):http://jsfiddle.net/ollerac/shkq7/

基本上,我在寻找一种将setInterval放在animatedBox属性上的方法,这样我就可以用自定义属性创建一个新的animatedBox。但每次我试着这样做,它都会破裂。

代码语言:javascript
复制
<div ng-app ng-controller="BoxController">

    <div class="layer" ng-repeat="layer in animatedBox.layers" ng-style="{ 'backgroundColor': layer.color}" ng-show="layer == animatedBox.selectedLayer"></div>

</div>

JAVASCRIPT

代码语言:javascript
复制
function buildBox () {
    return {
        color: '#' + (Math.random() * 0xFFFFFF << 0).toString(16)
    }
}

function BoxController ($scope) {
    $scope.animatedBox = {
        layers: [],
        selectedLayer: null
    };

    for (var i = 0; i < 5; i++) {
        $scope.animatedBox.layers.push(buildBox());
    }

    var i = -1;
    setInterval(function () {
        $scope.$apply(function() {
            i++;

            if (i < $scope.animatedBox.layers.length) {
                $scope.animatedBox.displayThisLayer = $scope.animatedBox.layers[i];
            } else {
              i = 0;
              $scope.animatedBox.selectedLayer = $scope.animatedBox.layers[i];
            }
        });
    }, 500);
}

CSS

代码语言:javascript
复制
.layer {
    width: 30px;
    height: 30px;
    position: absolute;
}

*更新*

下面是我想做的更多事情:

更新的jsFiddle:http://jsfiddle.net/ollerac/shkq7/2/

代码语言:javascript
复制
function buildBox () {
    return {
        color: '#' + (Math.random() * 0xFFFFFF << 0).toString(16)
    }
}

function BoxController ($scope) {
    $scope.animatedBox = {
        layers: [],
        selectedLayer: null,
        selectedLayerIndex: -1,
        updateSelectedLayer: function () {
            var self = this;

            if (self.layers.length) {
                $scope.$apply(function() {
                    self.selectedLayerIndex++;

                    if (self.selectedLayerIndex < self.layers.length) {
                        self.selectedLayer = self.layers[self.selectedLayerIndex];
                    } else {
                        self.selectedLayerIndex = 0;
                        self.selectedLayer = self.layers[self.selectedLayerIndex];
                    }
                });
            }
        }
    };

    for (var i = 0; i < 5; i++) {
        $scope.animatedBox.layers.push(buildBox());
    }

    setInterval(function () {
        $scope.animatedBox.updateSelectedLayer();
    }, 500);    
}

因此,现在对象更新自己的selectedLayer属性。,但是,我仍然需要调用单独调用更新的setInterval,以便让它更新。但我希望这个对象能够自我更新,并且完全独立。你能想出个好办法吗因为我真的很困惑.

我想这更像是一个普通的javascript问题,但我认为可能有一种有角度的方法来处理这种情况,比如可能使用指令或其他什么是合适的。

如有任何建议,将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-07-06 17:25:39

你是对的,我相信指令是正确的解决办法。(顺便说一句,这是一个很有趣的工作。:)

当遇到这样的问题时,我通常从编写HTML和控制器开始,如果一切都正常的话,我希望可以编写它们。对于这个例子,下面是我最后得出的结论。

代码语言:javascript
复制
<div ng-controller="BoxController">
  <div animated-boxes="colors"></div>
</div>
代码语言:javascript
复制
app.value('randomColor', function() {
  var red   = Math.floor(Math.random() * 255);
  var green = Math.floor(Math.random() * 255);
  var blue  = Math.floor(Math.random() * 255);
  return "rgb(" + red + "," + green + "," + blue + ")";
});

app.controller('BoxController', function($scope, randomColor) {
  $scope.colors = [ randomColor(), randomColor() ];
});

在这里,控制器只负责设置作用域上的一些基本数据--一个颜色数组;DOM非常简单,只将该数组传递给一个名为animated-boxes的数组。randomColor已被移动到服务中,因此可以更容易地重用和测试。(我也对它做了一些修改,这样就不会产生坏的十六进制值。)

现在,唯一不起作用的部分是这个叫做animated-boxes的东西。当您想要与DOM交互或在使用HTML属性时触发某些行为时,我们将转到一个指令。

我们将定义我们的指令,注入$timeout服务,因为我们知道我们想做基于计时器的事情。指令的结果将只是一个对象。

代码语言:javascript
复制
app.directive('animatedBoxes', function($timeout) {
  return {
  };
});

由于我们希望指令是独立的,并且不想搞乱它包含的外部作用域,所以我们将给它一个隔离作用域(请参阅指令文档获取更多信息,但基本上这意味着除了通过我们指定的变量之外,我们没有附加到指令所在的作用域)。

因为我们希望通过HTML属性访问传递给指令的值,所以我们将在该值上设置一个双向作用域绑定;我们将称之为colors

代码语言:javascript
复制
app.directive('animatedBoxes', function($timeout) {
  return {
    scope: {
      colors: '=animatedBoxes'
    }
  };
});

我们将给它一个简单的模板,它在colors上循环,每种颜色输出一个div。我们的ng-show指出,只有当作用域值selected等于$index时才能显示div$indexng-repeat循环当前迭代的数组索引。

代码语言:javascript
复制
app.directive('animatedBoxes', function($timeout) {
  return {
    scope: {
      colors: '=animatedBoxes'
    },
    template: "<div><div class='layer' ng-repeat='color in colors' " +
      "ng-style='{backgroundColor: color}' ng-show='selected == $index'>" +
      "</div></div>"
  };
});

现在是链接函数--处理指令逻辑的函数。首先,我们希望跟踪显示的框;在我们的ng-show中,我们使用了selected。我们还想跟踪我们有多少个盒子;我们将在指令的范围内使用$watch来跟上这个过程。

代码语言:javascript
复制
link: function(scope, elem, attrs) {
  scope.selected = 0;
  var count = 0;

  scope.$watch('colors', function(value) {
    // whenever the value of `colors`, which is the array
    // of colors passed into the directive, changes, update
    // our internal count of colors
    if (value) count = value.length;
    else count = 0; // if `colors` is falsy, set count to 0
  }, true); // `true` ensures we watch the values in the array,
            // not just the object reference
}

最后,我们需要经常通过每一个盒子。我们将用$timeout来实现这一点,这是setTimeout的一个版本,其中包含了一个范围$apply调用(它做了一些其他的事情,但我们现在并不关心这个问题)。

代码语言:javascript
复制
var nextBox = function() {
  if (scope.selected >= count - 1) scope.selected = 0;
  else scope.selected++;
  // recursively use `$timeout` instead of `setInterval`
  $timeout(nextBox, 500);
};

// kick off the directive by launching the first `nextBox`
nextBox();

如果将整个指令放在一起,您将得到以下代码(注释已删除):

代码语言:javascript
复制
app.directive('animatedBoxes', function($timeout) {
  return {
    scope: {
      colors: '=animatedBoxes'
    },
    template: "<div><div class='layer' ng-repeat='color in colors' " +
      "ng-style='{backgroundColor: color}' ng-show='selected == $index'>" +
      "</div></div>",
    link: function(scope, elem, attrs) {
      scope.selected = 0;
      var count = 0;

      scope.$watch('colors', function(value) {
        if (value) count = value.length;
        else count = 0;
      }, true);

      var nextBox = function() {
        if (scope.selected >= count - 1) scope.selected = 0;
        else scope.selected++;
        $timeout(nextBox, 500);
      };

      nextBox();
    }
  };
});

一个完整的工作示例,包括注释和一个小的调试区域,您可以在这里看到colors的值并与其交互(因此您可以看到指令如何响应控制器中的更改),可以在这里找到:http://jsfiddle.net/BinaryMuse/g6A6Y/

现在您已经具备了这个功能,请考虑应用这些知识,通过DOM传递指令,使其具有可变的速度,就像我们在colors中所做的那样。这是我的结果:http://jsfiddle.net/BinaryMuse/cHHKn/

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17503975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档