UNPKG

3.05 kBPlain TextView Raw
1<template>
2 <div id="vscroll-root-element" :style="{height:height+'px', opacity}">
3 <div class="child" id="vscroll-e1">
4 <slot></slot>
5 </div>
6 <div class="child" id="vscroll-e2">
7 <slot></slot>
8 </div>
9 </div>
10</template>
11<script>
12import createEventHub from "ynw/createEventHub";
13const byId = name => document.getElementById(name);
14const hub = createEventHub();
15const IS_BOTTOM = "IS_BOTTOM";
16/**
17 * ----------------------------------------
18 * @param {Element} el - 运动元素
19 * @param {Element} root - 元素容器
20 * @param {Boolean} start - 开始运行
21 * ----------------------------------------
22 */
23const move = ({ el, speed = 3, root, start = false, elHeight, rootHeight }) => {
24 const bottom = rootHeight - elHeight;
25 const maxTop = 0 - elHeight;
26 const setpos = v => {
27 el.style.transform = `translateY(${v}px)`;
28 curpos = v;
29 };
30 let curpos = rootHeight;
31 let run = start;
32 let hover = false;
33 setpos(rootHeight);
34
35 root.addEventListener("mouseenter", () => (hover = true));
36 root.addEventListener("mouseleave", () => (hover = false));
37
38 hub.on(IS_BOTTOM, notify => {
39 if (notify !== el) {
40 run = true;
41 }
42 });
43
44 animate();
45 function animate() {
46 requestAnimationFrame(() => {
47 if (run && hover === false) {
48 // IS_OUT
49 if (curpos <= maxTop) {
50 run = false;
51 setpos(rootHeight);
52 return animate();
53 }
54 // IS_BOTTOM
55 if (curpos <= bottom) {
56 hub.emit(IS_BOTTOM, el);
57 }
58 setpos(curpos - speed);
59 }
60
61 animate();
62 });
63 }
64};
65/**
66 * ----------------------------------------
67 * 垂直方向跑马灯
68 * @param {Number} start - 开始滚动(依赖DOM元素的高度::数据渲染完成后再开始)
69 * @param {Number} [speed=0.5] - 速度(px)
70 * @param {Number} [height=150] - 样式 - 控制ROOT高度
71 * ----------------------------------------
72 */
73export default {
74 props: {
75 speed: {
76 type: Number,
77 default: 0.5
78 },
79 start: {
80 type: Boolean,
81 default: false
82 },
83 height: {
84 type: Number,
85 default: 150
86 }
87 },
88 data() {
89 return {
90 opacity: 0
91 };
92 },
93 watch: {
94 start(v) {
95 if (!v) return;
96 setTimeout(() => {
97 const root = byId("vscroll-root-element");
98 const e1 = byId("vscroll-e1");
99 const e2 = byId("vscroll-e2");
100 const elHeight = e1.getBoundingClientRect().height;
101 const rootHeight = root.getBoundingClientRect().height;
102 const speed = this.speed;
103
104 // 小于容器的高度不滚动
105 if (elHeight < rootHeight) {
106 this.opacity = 1;
107 return;
108 }
109 move({ el: e1, root, start: true, speed, elHeight, rootHeight });
110 move({ el: e2, root, speed, elHeight, rootHeight });
111 this.opacity = 1;
112 }, 200);
113 }
114 }
115};
116</script>
117<style scoped lang='scss'>
118#vscroll-root-element {
119 overflow: hidden;
120 position: relative;
121}
122.child {
123 width: 100%;
124 position: absolute;
125 left: 0;
126 top: 0;
127}
128</style>
\No newline at end of file