xjinza
5/25/2018 - 8:05 AM

marquee 跑马灯 无线循环 # js #angularjs

marquee 跑马灯 无线循环 # js #angularjs

注意:容器的高度必须小于等于内容的高度。否则scrollTop滚动到一定的高度,就不再滚动,因为没有内容可以滚动了,已经滚动到了底部。
angularjs 的marquee实现
~~~html
<div marquee data="users" class="winner-list" id="winner-list" ng-if="users.length">
                <div class="winner-item" ng-repeat="item in users track by $index">
                    <span class="NO">{{item.no}}</span>
                    <img ng-src="{{item.userPic}}" alt="" width="64" height="64">
                    <p>{{item.nickName}}</p>
                    <p>20% OFF Bonus</p>
                </div>
            </div>
~~~
~~~javascript
appModule.directive('marquee', function() {
		return {
			restrict: 'A',
			scope: {
				data: '='
			},
			priority: 0,
			link: function(scope, element, attrs, controllers) {

				var arr = scope.data;
				var len = arr.length;
				var liHeight = 120;
				if (len < 4) return;
				scope.data = arr.concat(arr);
				element.css('height', len * liHeight-50);
				var area = element[0];
				/*无法找到ng-repeat的元素,因为ng-repeat会在compile阶段把这个节点摘除掉,单独compile一次,
				然后在发生数据绑定的时候对每个实例单独进行link。
				用$timeout是可以的,不过不建议,因为这样就变成单次绑定了。
				可以在子元素上再写个指令。
				*/

				// var liHeight = element.find('.winner-item').height();
				// setTimeout(function() {
				// 	console.log(liHeight,45)
				// },0);

				area.scrollTop = 0;
				var delay = 1200;
				var speed = 50;
				var interval;
				var timeout;

				function starMove() {
					area.scrollTop++;
					interval = $interval(scrollUp, speed);
				}

				function scrollUp() {
					if (area.scrollTop % liHeight == 0) {
						$interval.cancel(interval);
						timeout=$timeout(starMove, delay);
					} else {
						area.scrollTop++;
						if (area.scrollTop >= liHeight * len) {
							area.scrollTop = 0;
						}
					}

				}

				timeout=$timeout(starMove, delay);

				element.on('$destroy', function() {
					$interval.cancel(interval);
					$timeout.cancel(timeout);
				});
			}
		};
	});
~~~
指令中可能会用到require,^^myTabs从父级查找controller,^myTabs则从父级或本元素查找controller,不加前缀myTabs则从本元素查找。
The myPane directive has a require option with value ^^myTabs. When a directive uses this option, $compile will throw an error unless the specified controller is found. The ^^ prefix means that this directive searches for the controller on its parents. (A ^ prefix would make the directive look for the controller on its own element or its parents; without any prefix, the directive would look on its own element only.)

指令操作dom往往通过link函数,它会在模板被复制后执行。
Directives that want to modify the DOM typically use the link option to register DOM listeners as well as update the DOM. It is executed after the template has been cloned and is where directive logic will be put.

link takes a function with the following signature, function link(scope, element, attrs, controller, transcludeFn) { ... }
~~~javascript
angular.module('docsTabsExample', [])
.directive('myPane', function() {
  return {
    require: ['^^myTabs', 'ngModel'], //查找父级的myTabs controller和本元素的ngModelController.
    restrict: 'E',
    transclude: true,
    scope: {
      title: '@'
    },
    link: function(scope, element, attrs, controllers) {
      var tabsCtrl = controllers[0],
          modelCtrl = controllers[1];

      tabsCtrl.addPane(scope);
    },
    templateUrl: 'my-pane.html'
  };
});
~~~

原生js实现:
~~~html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>www.jb51.net - 间歇循环滚动</title>
    <style>
        #box{
            height:48px;
            width:300px;
            margin:0 auto;
            border:1px solid #0066FF;
            overflow:hidden;
        }
        #box li{
            color:#333;
            height:24px;
        }
        #box ul{
            margin:0;
            padding:0;
        }
    </style>
</head>
<body>
<div id="box">
    <ul id="con1">
        <li>脚本之家1</li>
        <li>脚本之家2</li>

    </ul>
</div>
<script>
	var area=document.getElementById("box");
	area.innerHTML+=area.innerHTML;
	var liHeight=document.getElementById("con1").getElementsByTagName('li')[0].offsetHeight;
	area.scrollTop=0;
	var delay=2000;
	var speed=50;
	var time;
	alert(liHeight)
	// alert(area.offsetHeight)
	// alert(area.clientHeight)
	// alert(area.getBoundingClientRect().height)
	function starMove(){
		area.scrollTop++;
		time=setInterval(scrollUp,speed);
	}
	function scrollUp(){
		if(area.scrollTop%liHeight==0){
			clearInterval(time);
			setTimeout(starMove,delay);
		}else{
			area.scrollTop++;
			if(area.scrollTop>=area.clientHeight){
				area.scrollTop=0;
			}
		}
	}
	setTimeout(starMove,delay);
</script>
</body>
</html>
~~~