In diesem Artikel wird hauptsächlich der Beispielcode der virtuellen Bildlaufleiste basierend auf vue.js 2.x vorgestellt. Jetzt teile ich ihn mit Ihnen und gebe ihn als Referenz.
Vorwort
Ich erinnere mich, dass ich zuvor zufällig ein Open-Source-CMS-Projekt durchgesehen habe und festgestellt habe, dass das linke Menü dieses Projekts die Breite der Fenster überschreitet. Ich war neugierig, warum. Es gibt keine Bildlaufleiste? Dann habe ich genauer hingesehen und auf der linken Seite ein kleines p gefunden. Dann habe ich versucht, es zu ziehen, und festgestellt, dass es mit der nativen Bildlaufleiste identisch ist! Als ich mir den Quellcode ansah, entdeckte ich, dass diese Bildlaufleiste „slimScroll“ heißt. Dann ging ich zu ihrem Github-Repository und schaute sie mir an. Nachdem ich den Quellcode studiert hatte, hatte ich das Gefühl, dass ich die gleiche Bildlaufleiste auch erstellen könnte. Erreicht durch Vue!
Design
Okay, jetzt beginnen wir mit den Schritten zum Entwerfen der Bildlaufleiste:
Dom der Bildlaufleiste entwerfen
Das erste, woran Sie denken müssen, ist: Wenn Sie den Inhalt scrollen möchten, den Sie scrollen möchten, muss der übergeordnete Dom zunächst eine feste Länge und Breite haben, dh der überschüssige Teil muss ausgeblendet sein. Das heißt, fügen Sie einen Stil hinzu: Overflow: Hidden. Daher fügen wir dem zu scrollenden Inhalt einen Wrapper hinzu, sodass seine Länge und Breite dem übergeordneten Dom entsprechen, und dann gibt es einen Stil namens: Overflow: Hidden und den Das umschlossene Element heißt scrollPanel
Zweitens: Wir wissen: Wir wollen es so leistungsstark machen wie die native Bildlaufleiste! Es ist notwendig, horizontale Bildlaufleisten und vertikale Bildlaufleisten zu entwerfen, die zur Beziehung zwischen Geschwisterknoten gehören, da das Vorhandensein der Bildlaufleiste den ursprünglichen Stil nicht beeinträchtigen kann und die Position oben und links steuert , also die Bildlaufleiste Die Position muss absolut sein. Nun, wir nennen die horizontale Bildlaufleiste: hBar und die vertikale Bildlaufleiste: vBar
Schließlich: Wir haben scrollPanel, vBar, hBar entworfen und brauchen ein übergeordnetes Element p, um sie einzuwickeln, und fügen Sie dann einen Stil hinzu: Position: relativ
Üben
Komponentenstruktur entwerfen
Zuerst Alles in allem bestehen unsere Plug-Ins aus 4 Komponenten, von denen 3 untergeordnete Komponenten und 1 eine übergeordnete Komponente sind, nämlich: vueScroll (übergeordnete Komponente), scrollPanel (Unterkomponente, die Inhalte umschließt, die gescrollt werden müssen), vBar (vertikale Bildlaufleiste) , hBar (horizontale Bildlaufleiste)
Zweitens entwerfen wir die Funktionen, für die jede Komponente verantwortlich ist. Die Komponenten sind hier in Komponenten der Steuerungsschicht und Komponenten der Anzeige unterteilt (Studenten, die mit React vertraut sind, sollten dies wissen. Die Komponenten der Anzeigeebene vervollständigen nur die Anzeigefunktion: vBar, hBar, scrollPanel Die Komponenten der Steuerungsebene ähneln in gewisser Weise der CPU und können steuern Unterkomponenten. Verschiedene Zustände, wie Breite, Höhe, Farbe, Transparenz, Position usw. Die Steuerungsschichtkomponente ist: vueScroll.
Spezifische Implementierung
hBar/vBar
hBar/vBar Diese beiden sind horizontale Bildlaufleiste bzw. vertikale Bildlaufleiste. Die implementierten Funktionen sind ungefähr gleich, daher werden die alten zusammen erwähnt. Hier nehmen wir vBar als Beispiel.
props empfängt die von der übergeordneten Komponente übergebenen Eigenschaften, insbesondere:
{ height: vm.state.height + 'px', //滚动条的高度 width: vm.ops.width, // 滚动条的宽度 position: 'absolute', background: vm.ops.background, // 滚动条背景色 top: vm.state.top + 'px', // 滚动条的高度 transition: 'opacity .5s', // 消失/显示 所用的时间 cursor: 'pointer', // opacity: vm.state.opacity, // 透明度 userSelect: 'none' }
2-Ereignis, das hauptsächlich die Bildlaufleiste anzeigt, wenn sich die Maus bewegt.
... render(_c){ return _c( // ... { mouseenter: function(e) { vm.$emit('showVBar'); // 触发父组件事件,显示滚动条 } } // ... ) }
Dabei stellt state den Zustand dar, der zur Laufzeit geändert werden kann, und ops ist der Konfigurationsparameter, der vom Benutzer übergeben wird.
scrollPanel
ist eine Komponente, die scrollende Inhalte umschließt. Der Stil muss auf „overflow: versteckt“ eingestellt sein.
1. Stil
var style = vm.scrollContentStyle; style.overflow = 'hidden'; // ... { style: style } // ...
2. Ereignis
// ... render(_c) { // ... on: { mouseenter: function() { vm.$emit('showBar'); }, mouseleave: function() { vm.$emit('hideBar'); } } // ... } // ...
vuescroll
Steuerungskomponente. Steuern Sie den von Unterkomponenten angezeigten Status, fügen Sie verschiedene Abhörereignisse hinzu usw.
1. Rufen Sie das Dom-Element der Unterkomponente ab, um Echtzeitinformationen über den Dom zu erhalten.
// ... initEl() { this.scrollPanel.el = this.$refs['vueScrollPanel'] && this.$refs['vueScrollPanel'].$el; this.vScrollBar.el = this.$refs['vScrollBar'] && this.$refs['vScrollBar'].$el; this.hScrollBar.el = this.$refs['hScrollBar'] && this.$refs['hScrollBar'].$el; } // ...
2. Bildlaufleiste anzeigen
Anzeige der horizontalen Bildlaufleiste und Anzeige der vertikalen Bildlaufleiste als Beispiel:
// ... var temp; var deltaY = { deltaY: this.vScrollBar.ops.deltaY // 获取用户配置的deltaY }; if(!this.isMouseLeavePanel || this.vScrollBar.ops.keepShow){ if ((this.vScrollBar.state.height = temp = this.getVBarHeight(deltaY))) { // 判断条件 // 重新设置滚动条的状态 this.vScrollBar.state.top = this.resizeVBarTop(temp); this.vScrollBar.state.height = temp.height; this.vScrollBar.state.opacity = this.vScrollBar.ops.opacity; } } // ...
3 , Ermitteln Sie die Höhe der Bildlaufleiste
Da die Höhe des Dom-Elements nicht festgelegt ist, müssen Sie die tatsächliche Höhe des Doms in Echtzeit ermitteln. Die Berechnungsformel für die Höhe des Bildlaufs Die Leiste lautet wie folgt:
var height = Math.max( scrollPanelHeight / (scrollPanelScrollHeight / scrollPanelHeight), this.vScrollBar.minBarHeight );
Das heißt: scroll Bar height: scrollPanel height == scrollPanel height: dom element height
4. resizeVBarTop, um Fehler zu vermeiden und die Höhe ermitteln zu können der Bildlaufleiste vom übergeordneten Element.
resizeVBarTop({height, scrollPanelHeight, scrollPanelScrollHeight, deltaY}) { // cacl the last height first var lastHeight = scrollPanelScrollHeight - scrollPanelHeight - this.scrollPanel.el.scrollTop; if(lastHeight < this.accuracy) { lastHeight = 0; } var time = Math.abs(Math.ceil(lastHeight / deltaY)); var top = scrollPanelHeight - (height + (time * this.vScrollBar.innerDeltaY)); return top; }
5. Achten Sie auf Scroll-Ereignisse.
// ... on: { wheel: vm.wheel } // ... wheel(e) { var vm = this; vm.showVBar(); vm.scrollVBar(e.deltaY > 0 ? 1 : -1, 1); e.stopPropagation(); } // ...
6. Achten Sie auf Ziehereignisse in der Bildlaufleiste
listenVBarDrag: function() { var vm = this; var y; var _y; function move(e) { _y = e.pageY; var _delta = _y - y; vm.scrollVBar(_delta > 0 ? 1 : -1, Math.abs(_delta / vm.vScrollBar.innerDeltaY)); y = _y; } function t(e) { var deltaY = { deltaY: vm.vScrollBar.ops.deltaY }; if(!vm.getVBarHeight(deltaY)) { return; } vm.mousedown = true; y = e.pageY; // 记录初始的Y的位置 vm.showVBar(); document.addEventListener('mousemove', move); document.addEventListener('mouseup', function(e) { vm.mousedown = false; vm.hideVBar(); document.removeEventListener('mousemove', move); }); } this.listeners.push({ dom: vm.vScrollBar.el, event: t, type: "mousedown" }); vm.vScrollBar.el.addEventListener('mousedown', t); // 把事件放到数组里面,等销毁之前移除掉注册的时间。 }
7. Das Prinzip ähnelt dem von Drag-Ereignissen, außer dass es eine zusätzliche Beurteilung gibt, um zu bestimmen, ob die aktuelle Richtung x oder y ist.
listenPanelTouch: function() { var vm = this; var pannel = this.scrollPanel.el; var x, y; var _x, _y; function move(e) { if(e.touches.length) { var touch = e.touches[0]; _x = touch.pageX; _y = touch.pageY; var _delta = void 0; var _deltaX = _x - x; var _deltaY = _y - y; if(Math.abs(_deltaX) > Math.abs(_deltaY)) { _delta = _deltaX; vm.scrollHBar(_delta > 0 ? -1 : 1, Math.abs(_delta / vm.hScrollBar.innerDeltaX)); } else if(Math.abs(_deltaX) < Math.abs(_deltaY)){ _delta = _deltaY; vm.scrollVBar(_delta > 0 ? -1 : 1, Math.abs(_delta / vm.vScrollBar.innerDeltaY)); } x = _x; y = _y; } } function t(e) { var deltaY = { deltaY: vm.vScrollBar.ops.deltaY }; var deltaX = { deltaX: vm.hScrollBar.ops.deltaX }; if(!vm.getHBarWidth(deltaX) && !vm.getVBarHeight(deltaY)) { return; } if(e.touches.length) { e.stopPropagation(); var touch = e.touches[0]; vm.mousedown = true; x = touch.pageX; y = touch.pageY; vm.showBar(); pannel.addEventListener('touchmove', move); pannel.addEventListener('touchend', function(e) { vm.mousedown = false; vm.hideBar(); pannel.removeEventListener('touchmove', move); }); } } pannel.addEventListener('touchstart', t); this.listeners.push({ dom: pannel, event: t, type: "touchstart" }); }
8. Scrollen von Inhalten
Das Prinzip des Scrollens von Inhalten ist nichts anderes als das Ändern von scrollTop/scrollLeft des scrollPanels, um den Inhalt so zu steuern, dass er sich nach oben, unten, links und rechts bewegt.
scrollVBar: function(pos, time) { // >0 scroll to down <0 scroll to up var top = this.vScrollBar.state.top; var scrollPanelHeight = getComputed(this.scrollPanel.el, 'height').replace('px', ""); var scrollPanelScrollHeight = this.scrollPanel.el.scrollHeight; var scrollPanelScrollTop = this.scrollPanel.el.scrollTop; var height = this.vScrollBar.state.height; var innerdeltaY = this.vScrollBar.innerDeltaY; var deltaY = this.vScrollBar.ops.deltaY; if (!((pos < 0 && top <= 0) || (scrollPanelHeight <= top + height && pos > 0) || (Math.abs(scrollPanelScrollHeight - scrollPanelHeight) < this.accuracy))) { var Top = top + pos * innerdeltaY * time; var ScrollTop = scrollPanelScrollTop + pos * deltaY * time; if (pos < 0) { // scroll ip this.vScrollBar.state.top = Math.max(0, Top); this.scrollPanel.el.scrollTop = Math.max(0, ScrollTop); } else if (pos > 0) { // scroll down this.vScrollBar.state.top = Math.min(scrollPanelHeight - height, Top); this.scrollPanel.el.scrollTop = Math.min(scrollPanelScrollHeight - scrollPanelHeight, ScrollTop); } } // 这些是传递给父组件的监听滚动的函数的。 var content = {}; var bar = {}; var process = ""; content.residual = (scrollPanelScrollHeight - scrollPanelScrollTop - scrollPanelHeight); content.scrolled = scrollPanelScrollTop; bar.scrolled = this.vScrollBar.state.top; bar.residual = (scrollPanelHeight - this.vScrollBar.state.top - this.vScrollBar.state.height); bar.height = this.vScrollBar.state.height; process = bar.scrolled/(scrollPanelHeight - bar.height); bar.name = "vBar"; content.name = "content"; this.$emit('vscroll', bar, content, process); },
9. Zerstöre registrierte Ereignisse.
Gerade haben wir die registrierten Ereignisse in das Listeners-Array eingefügt und können sie im beforedestroy-Hook zerstören.
// remove the registryed event. this.listeners.forEach(function(item) { item.dom.removeEventListener(item.event, item.type); });
Bedienungs-Screenshot
Der PC-seitige Betriebs-Screenshot ist wie unten dargestellt:
Nach der Registrierung des Hörereignisses sieht er wie abgebildet aus unten:
Führen Sie den Screenshot auf Ihrem Telefon aus:
Es ist ersichtlich, dass der Leistungseffekt mit der nativen Bildlaufleiste übereinstimmt.
Fazit & Reflexion
Das Obige ist im Grunde das Design der Bildlaufleiste, die ich entworfen habe. Zunächst einmal bin ich den Nuggets sehr dankbar, dass sie mir so etwas gegeben haben Sharing-Plattform, und dann möchte ich mich bei slimScroll bedanken. Der Autor hat mich auf eine solche Idee gebracht. Nachdem ich dieses Plug-in fertiggestellt habe, weiß ich mehr über scrollWidth, scrollHeigh, scrollTop und scrollLeft von DOM-Elementen.
Das Obige habe ich für alle zusammengestellt. Ich hoffe, dass es in Zukunft für alle hilfreich sein wird.
Verwandte Artikel:
3 Grundmodi von Vue-Routing-Parametern (ausführliches Tutorial)
Verwandte Tricks in JavaScript
Dynamisches Importieren von Dateien im Webpack implementieren
Das obige ist der detaillierte Inhalt vonVirtuelle Bildlaufleisten etwa 2.x in vue.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!