rxjs学习笔记: swiper 简单的滚动图

利用 rxjs 实现一个简单的 swiper 效果,只展示原理
更新于: 2021-12-30 00:44:51

 HTML部分

<div id="main">
  <section id="wrapper">
    <div id="scroller">
      <ul>
        <li>
          <img src="https://jdc.jd.com/img/400x300" />
        </li>
        <li>
          <img
            src="https://pic.rmb.bdstatic.com/7f7a8d7b247d3aa430010f10a5765239.jpeg"
          />
        </li>
        <li>
          <img
            src="https://tva1.js.work/large/007S8ZIlgy1gexw87htqhj305k05k74o.jpg"
          />
        </li>
        <li>
          <img
            src="https://tiyu.baidu.com/static/tiyu/common/img/default-user-logo_70db74e.png"
          />
        </li>
      </ul>
    </div>
  </section>

  <nav id="ctrl">
    <label>
      Auto
      <input type="checkbox" id="chk" />
    </label>
    <button id="prev">prev</button>
    <button id="next">next</button>
  </nav>
</div>

CSS 部分

* {
  margin: 0;
  padding: 0;
  list-style: none;
  box-sizing: border-box;
}

#main {
  width: 400px;
  margin: 20px auto;
}

#wrapper {
  width: 400px;
  height: 300px;
  position: relative;
  overflow: hidden;
}

#scroller {
  position: absolute;
  transition: all 0.3s;
  left: 0;
  height: 300px;
  width: 20000px;
}

#scroller li {
  float: left;
}

#scroller img {
  width: 400px;
  height: 300px;
  object-fit: cover;
}

#ctrl {
  margin: 10px 0;
  text-align: center;
}

#ctrl * {
  margin-right: 5px;
}

Javascript 部分

import './style.css';

import { interval, fromEvent, merge } from 'rxjs';
import { scan, mapTo, map, withLatestFrom } from 'rxjs/operators';

// elements
const prev = document.getElementById('prev');
const next = document.getElementById('next');
const chk = document.getElementById('chk');
const scroller = document.getElementById('scroller');

// streams:
const inter$ = interval(3000);
const prev$ = fromEvent(prev, 'click').pipe(mapTo(-1));
const next$ = fromEvent(next, 'click').pipe(mapTo(1));
const chk$ = fromEvent(chk, 'change').pipe(map((e: any) => e.target.checked));

const idx = () => +scroller.getAttribute('data-index') || 0;
const goto = (index) => {
  scroller.style.cssText = `left: ${-index * 400}px;`;
  scroller.setAttribute('data-index', String(index));
};

merge(prev$, next$)
  .pipe(
    scan((cur, res) => {
      const sum = cur + res;
      if (sum > 3) return 3;
      if (sum < 0) return 0;
      return sum;
    }, idx())
  )
  .subscribe(goto);

inter$
  .pipe(
    withLatestFrom(chk$, (index, checked) => checked),
    map((v) => {
      const index = idx();
      return v ? (index + 1) % 4 : index;
    })
  )
  .subscribe(goto);

在线展示