Vueプロジェクトでbetter-scrollを使用してマルチキャストマップを実現
7035 ワード
前言
better-scrollは非常に強力なサードパーティライブラリですモバイル側でこのライブラリを利用すると、原生のScrollViewに非常に似た効果を実現するだけでなく、輪番図の効果を実現することができます.ここでは、自分がこの効果を実現する過程を記録しておきましょう.
構想
1.まず、自分のHTML構造の基本構造がwrapperにcontentが含まれていることを確認します.
2.次に理解すべきページがスクロールできる原理は、コンテンツの高さが容器の高さを超えてこそスクロールを実現できるということであり、それを超えなければスクロールする必要はないので、第一に実現すべきことは、すべてのコンテンツの高さを取得することである.
ここでは、ページの横幅がビューポートの幅を超えている場合にもスクロールが実現されることが明らかである.上述したように、横幅の実現において最も重要な点は、幅であることが明らかである.
3.マルチキャスト図である以上、ユーザが同時に知るべきことは、現在再生されているのは、何枚目の図、すなわち一般的な「小白点」小白点の個数であり、ユーザに合計何枚かの図があることを示すために使用され、現在再生されている何枚目の図は、小白点にいくつかの特殊な様式の方法を加えてユーザに知らせることができる
4.マルチキャストマップには、ページレンダリング後の自動再生や再生間隔など、一般的なプロパティも必要です.もう1つは、マルチキャストがサポートされているかどうかです.
楽しいcoding
考えを整理してから仕事を始めることができます.HTML構造を改善するコードは非常に簡単です.つまり、2つのdivを作成し、ref参照を追加することで、ref属性を通じてコンテキストを簡単に取得できます."slider"
ref="slider">
"slider-content"
ref="sliderContent">
ここではvueで非常に一般的なslotスロットを使用します.このsliderコンポーネントを外部で呼び出すと、一部のサブコンポーネントが外部に容易に転送されます.
2.sliderを制御するいくつかの属性について述べたので、コンポーネントのpropsでこれらの属性を受け入れる必要があります.外部でこれらの属性を容易に制御することができます.props: {
//
loop: {
type: Boolean,
default: true
},
//
autoPlay: {
type: Boolean,
default: true
},
//
interval: {
type: Number,
default: 3000
}
}
3.いくつかの初期ステップの完了の差が少なくなった後、vueのライフサイクルフックmounted
、すなわち、ページレンダリングが完了した後に、マルチキャスト図の幅を取得し、マルチキャスト図のいくつかの設定を初期化する必要がある.mounted: function () {
setTimeout(() => {
this.setSliderWidth()
this.initSlider()
}, 20)
ここでは小さなtipsがあります.通常、ブラウザがdomをレンダリングする時間は17 msなので、ここでは遅延関数を使用して20 ms後にこれらの方法を呼び出します.つまり、ブラウザのdomが正しくレンダリングされ、いくつかの問題が発生しないようにします.
4.この方法を呼び出しただけで、これらの方法は実装されていません.まず、幅を設定する方法では、$refs.sliderContent
でコンテキストを取得し、$refs.slider.clientWidth
の方法で現在の画面幅を取得し、この容器を巡って容器内のすべてのコンテンツを取得し、取得したコンテンツ幅をこの画面の幅に設定し、最後にすべてのコンテンツの幅を加算することで、slider全体の幅を得ることができます.こんなにたくさん言っても迂回感があるのでコードを見てみましょう// slider
setSliderWidth: function (isResize) {
// slider
this.children = this.$refs.sliderContent.children
// console.log(this.children)
// = +
let width = 0
//
let sliderWidth = this.$refs.slider.clientWidth
for (let i = 0; i < this.children.length; i++) {
// children
let child = this.children[i]
child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if (this.loop) {
width += 2 * sliderWidth
}
this.$refs.sliderContent.style.width = width + 'px'
}
これにより、slider全体の幅を得ることができます.loopの場合、better-scrollはヘッダの最後に2部クローンされるので、幅は*2が必要です.次に、better-scrollの初期化を実現するためのいくつかの構成があります.具体的なパラメータの内容はbetter-scorllの公式サイトから調べることができます. // slider
initSlider: function () {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: {
loop: this.loop,
threshold: 0.3,
speed: 400
},
click: true
})
}
5.上記の2つの方法を実現すると、基本的にはページ上で見ることができるようになりますが、このように書き終わると、自動的に輪番することができず、現在表示されている数枚の図のスタイルが正しく表示されていないことがわかります.次に、この2つの方法を実現します.
6.dotsスタイルの正しいロードを実現vueでのスタイルのバインドに使用"dots">
"dot"
v-for="(item, index) of dots"
:class="{active:currentPageIndex === index}"
:key="index">
つまり、スタイルを下付きでバインドしながらbetter-scrollの'scrollEnd'イベントをリスニングし、スクロールが終了するとgetCurrentPage()
というメソッドを呼び出すと、戻り値pageX、すなわち、数ページ目に横にスクロールしてcurrentPageIndexにこの戻り値を割り当て、スタイルを正しく表示する目的を達成します.this.slider.on('scrollEnd', () => {
let page = this.slider.getCurrentPage().pageX
this.currentPageIndex = page
// ( )
if (this.autoPlay) {
clearTimeout(this.timer)
this.play()
}
})
7.自動再生機能を実現するbetter-scrollも1つのインターフェースgoToPage(x, y, time, easing)
を提供している.すなわち、対応するページに移動する.いくつかのパラメータはxを表す横方向ページyを表す縦方向ページtimeを表す.アニメーション実行時間easingは一般的にこのインターフェースを修正することを提案していない.そのインターフェースは簡単だ.methodsにPlayメソッドをもう1つ書くだけだ.具体的な考え方はcurrentPageIndex+=1を通じて次を得ることだ.再生するピクチャのインデックスを1枚作成し、インデックス値がピクチャ配列の長さに達したときにインデックスを0に再割り当てすればいいので、ページレンダリング後に呼び出せばいいです.play: function () {
let playPage = this.currentPageIndex + 1
if (playPage === this.children.length - 2) {
playPage = 0
}
setTimeout(() => {
this.slider.goToPage(playPage, 0, 400)
}, this.interval)
}
ここでも詳細については、このマルチキャストマップをループスクロールとして設定するとbetter-scrollが自動的にヘッダの最後に画像を1部ずつクローンするので、長さは2を減算する必要があります.これにより、マルチキャストマップの自動再生が実現されます.
###ここまで総括してbetter-scrollを通じて1つの輪播図の実現の具体的な過程を実現することに成功したのは実はそんなに難しくなくて、主に構想を整理すればいいのです!アヒルを突け!
転載先:https://juejin.im/post/5c04abfde51d452209013eb7
"slider"
ref="slider">
"slider-content"
ref="sliderContent">
props: {
//
loop: {
type: Boolean,
default: true
},
//
autoPlay: {
type: Boolean,
default: true
},
//
interval: {
type: Number,
default: 3000
}
}
mounted: function () {
setTimeout(() => {
this.setSliderWidth()
this.initSlider()
}, 20)
// slider
setSliderWidth: function (isResize) {
// slider
this.children = this.$refs.sliderContent.children
// console.log(this.children)
// = +
let width = 0
//
let sliderWidth = this.$refs.slider.clientWidth
for (let i = 0; i < this.children.length; i++) {
// children
let child = this.children[i]
child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if (this.loop) {
width += 2 * sliderWidth
}
this.$refs.sliderContent.style.width = width + 'px'
}
// slider
initSlider: function () {
this.slider = new BScroll(this.$refs.slider, {
scrollX: true,
scrollY: false,
momentum: false,
snap: {
loop: this.loop,
threshold: 0.3,
speed: 400
},
click: true
})
}
"dots">
"dot"
v-for="(item, index) of dots"
:class="{active:currentPageIndex === index}"
:key="index">
this.slider.on('scrollEnd', () => {
let page = this.slider.getCurrentPage().pageX
this.currentPageIndex = page
// ( )
if (this.autoPlay) {
clearTimeout(this.timer)
this.play()
}
})
play: function () {
let playPage = this.currentPageIndex + 1
if (playPage === this.children.length - 2) {
playPage = 0
}
setTimeout(() => {
this.slider.goToPage(playPage, 0, 400)
}, this.interval)
}