-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmarquee.js
225 lines (178 loc) · 6.58 KB
/
marquee.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
* Marquee by javascript
* @authors richard chen
* @date 2014-06-12
* @version 1.0
* @参数 opt{} 可选值
* elem:要滚动的元素
* step:每次滚动的步长(px),默认为0
* stepInterval:滚动效果执行时间(ms),默认为400
* interval:每次滚动间隔时间(ms), 默认为3000
* dir:滚动方向,up、down、left、right,默认为"left"
* autoPlay:是否自动滚动,默认为true
* hoverPause:是否在鼠标滑过时暂停滚动,默认为true
*/
var Marquee = function (opt) {
// 要滚动的元素
this.elem = null;
// 每次滚动的步长(px)
this.step = 0;
// 滚动效果执行时间(ms)
this.stepInterval = 400;
// 每次滚动间隔时间(ms)
this.interval = 3000;
// 滚动方向,up、down、left、right,默认为"left"
this.dir = "left";
// 是否自动滚动,默认为true
this.autoPlay = true;
// 是否在鼠标滑过时暂停滚动,默认为true
this.hoverPause = true;
// 保存暂停状态
this.pausing = false;
// 滚动计时器
this.timerStep = null;
// 滚动间隔计时器
this.timer = null;
this.init(opt);
};
Marquee.prototype = {
constructor: Marquee,
init: function (opt) {
this.extend(opt, this);
// 如果元素不存在则直接返回
if (!this.elem) return false;
// 复制滚动元素内容并填充
this.elem.innerHTML += this.elem.innerHTML;
this.loadStyle();
this.hoverPause && this.bindEvents();
this.autoPlay && this.startScroll();
},
// 初始化滚动元素的样式
loadStyle: function () {
var childrens = this.elem.children;
// 如果是左右滚动就给滚动元素加上宽度
if (this.dir == "left" || this.dir == "right") {
this.elem.style.width = childrens[0].offsetWidth * childrens.length + "px";
}
// 如果是向右滚动,初始时将滚动元素的left设置为负的自身宽度的一半
if (this.dir == "right" && this.elem.offsetLeft == 0) {
this.elem.style.left = -this.elem.offsetWidth / 2 + "px";
}
// 如果是向左滚动,初始时将滚动元素的left设置为0
if (this.dir == "left" && this.elem.offsetLeft == -this.elem.offsetWidth / 2) {
this.elem.style.left = 0;
}
// 如果是向下滚动,初始时将滚动元素的top设置为负的自向高度的一半
if (this.dir == "down" && this.elem.offsetTop == 0) {
this.elem.style.top = -this.elem.offsetHeight / 2 + "px";
}
// 如果是向上滚动,初始时将滚动元素的top设置为0
if (this.dir == "up" && this.elem.offsetTop == -this.elem.offsetHeight / 2) {
this.elem.style.top = 0;
}
},
// 绑定控制元素的事件
bindEvents: function () {
var _this = this;
// 鼠标移入父级元素时暂停
this.bind(this.elem.parentNode, "mouseover", function () {
_this.stop();
_this.pausing = true;
});
// 鼠标移出父级元素时重新开始滚动
this.bind(this.elem.parentNode, "mouseout", function () {
_this.pausing = false;
_this.autoPlay && _this.startScroll();
});
},
// 停止滚动
stop: function () {
clearInterval(this.timer);
},
// 执行滚动效果
doScroll: function () {
var _this = this,
style, offset, target, step, elemSize;
if (this.dir == "left" || this.dir == "right") {
// element.style[ "left" | "top" ]
style = "left";
offset = "offsetLeft";
elemSize = this.elem.offsetWidth / 2;
} else {
// element[ offset[Left|Top] ];
style = "top";
offset = "offsetTop";
elemSize = this.elem.offsetHeight / 2;
}
step = (this.dir == "left" || this.dir == "up") ? -this.step : this.step;
if (this.stepInterval == 0) {
// 滚动效果执行时间为0时,进入无缝滚动模式
if (elemSize - Math.abs(this.elem[offset]) < Math.abs(step)) {
step = step / Math.abs(step) * (elemSize - Math.abs(this.elem[offset]));
}
target = this.elem[offset] + step;
target = this.fixTarget(step, this.elem[offset] + step, elemSize);
this.elem.style[style] = target + "px";
} else {
if (this.timerStep != null) return;
//先停止掉this.timer,在滚动执行完过后再开启
this.stop();
// 将step按stepInterval分割
var seed = 30 / _this.stepInterval * step;
seed = seed < 0 ? Math.ceil(seed) : Math.floor(seed);
this.timerStep = setInterval(function () {
seed = seed > 0 ? Math.min(seed, step) : Math.max(seed, step);
target = _this.fixTarget(seed, _this.elem[offset] + seed, elemSize);
_this.elem.style[style] = target + "px";
step -= seed;
if (step == 0) {
clearInterval(_this.timerStep);
_this.timerStep = null;
if (_this.autoPlay && !_this.pausing) {
_this.startScroll();
}
}
}, 30);
}
},
// 修正超出边界的滚动
fixTarget: function (dir, target, max) {
// left or up, 当元素offset=最大滚动值时将offset变为0
if (dir < 0 && Math.abs(target) >= max) {
return 0;
}
// right or down,当元素offset=0时将offset变为最大滚动值
if (dir > 0 && target >= 0) {
return -max;
}
return target;
},
// 改变方向
changeDir: function (dir) {
this.dir = dir;
this.loadStyle();
this.doScroll();
},
// 开始滚动
startScroll: function () {
var _this = this;
this.timer = setInterval(function () {
_this.doScroll();
}, _this.interval);
},
extend: function (opt, target) {
for (name in opt) {
target[name] = opt[name];
}
},
//绑定事件方法
bind: function (element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = hanlder;
}
}
};