simonyouth / Blog

Record techniques like javascript
0 stars 0 forks source link

Swiper loop not working correctly with canvas element #12

Open simonyouth opened 4 years ago

simonyouth commented 4 years ago
export default ({
  className,
  list,
  xData,
}) => {
  const swiperRef = useRef(null);
  useEffect(() => {
    swiperRef.current = new Swiper('.h-s', {
      speed: 400,
      autoplay: {
        delay: 5000,
       disableOnInteraction: false,
     },
      loop: true,
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    });
  }, []);

  const chart = useCallback(({ xAxis, data }) => {
    return <LineBasicEchart
      option={setOption(xAxis)}
      seriesData={[{
        ...data,
        label: {
          show: true,
          color: '#fff',
          formatter: '{c}%'
        },
        symbolSize: 6,
        symbol: 'circle'
      }]}
      isArea={false}
    />;
  }, []);

  const swiperChart = useMemo(() => {
    return list.map(v => (
      <div className="swiper-slide" key={v.name}>
        <span className={styles.name}>{v.name}</span>
        {chart({ ...v, xAxis: xData })}
      </div>
    ));
  }, [xData, list, chart]);

  return (
    <div className={classNames(className, 'swiper-container', 'h-s', styles.chart)}>
      <div className="swiper-wrapper" ref={wrapperRef}>
        {swiperChart}
      </div>
      <div className="swiper-button-prev"></div>
      <div className="swiper-button-next"></div>
    </div>
  );
};

使用swiper的loop自动循环轮播,每个slide是一个span+canvas,会出现span有但是canvas内容没有的情况。花了半天时间找原因和解决方法。 最终。。。 swiper loop原理是在第一个slide之前添加最后一个slide的复制,最后一个slide后加第一个slide的复制。但是HTML的copy canvas并不会重新渲染,所以出现空白页。 解决

  useEffect(() => {
    if (list.length) {
      const first = wrapperRef.current.querySelector('.swiper-slide.swiper-slide-duplicate.swiper-slide-prev');
      const last = wrapperRef.current.querySelector('.swiper-slide.swiper-slide-duplicate.swiper-slide-duplicate-active');
      // 手动生成复制的第一个元素和最后一个元素
     try {
        ReactDom.unmountComponentAtNode(first);
        ReactDom.unmountComponentAtNode(last);
        ReactDom.render(chart(list[list.length - 1]), first);
        ReactDom.render(chart(list[0]), last);
      } catch(e) {}
    }
  }, [chart, list]);