zl程序教程

您现在的位置是:首页 >  Python

当前栏目

swiper + 网易云api 实现音乐卡片[2]

2023-02-25 18:16:13 时间

上一篇文章已经把Swiper卡片加入到我们的项目中了,今天这篇文章我们结合一下网易云音乐Api,来实现一个音乐卡片。先看一下实现的效果

网易云api

获取每日推荐歌曲

接口地址 : /recommend/songs

说明: 这个接口需要先登录才能访问,并且拿到登录后返回的token和cookie值。

然后我们这里展示用到的值有

  • 歌曲名称: al.name
  • 歌曲封面: al.picUrl
  • 歌手名: ar.name
  • 歌曲id: privilege.id 这是后面为了播放用的id,这里不展示。

手机登录

接口地址 : /login/cellphone

说明: 需要传两个参数:password 和 phone。这个账号密码需要是网易云的账号密码。

登录成功后返回值如下,我们需要cookie 和 token供/recommend/songs使用。

渲染卡片

处理数据

如下返回的数据是一个有30项的数组。我想要把它拆分成这种结构: [[{},{}...],[{},{}],[{},{}],[{},{}]]。渲染出如下图的四组卡片,每组下又有7张卡片

 // 这是自己封装请求数据的hook
 const [response] = useFetch(recommendSongs(), {});
  const data = response?.data.dailySongs;
  let cards = [];
  // 进行了一个 七个一分组的处理
  for (let i = 0; i < data?.length; i += 7) {
    if (i < 28) {
      cards.push(data?.slice(i, i + 7));
    }
  }

渲染卡片

  • 这是Swiper的使用,两层循环:第一层是对 [[],[],[],[]]的渲染,渲染出四个卡片组<Swiper>,第二次渲染每个卡片组的卡片<SwiperSlide>
  • <IconDoubleChevronLeft />和<IconDoubleChevronRight />是两个图标。用的是字节的图标库 字节图标可以复制为React代码
 <div className={style.container}>
      {cards?.map((item, index) => (
        <Swiper
          effect={'cards'}
          grabCursor={true}
          style={{ overflow: 'visible' }}
          modules={[EffectCards]}
          className={style.swiper}
        >
          {item.map((song: any, no: number) => (
            <SwiperSlide
              onClick={
                () => setCurrentPlaying(() => ({ id: song?.privilege?.id }))
              }
            >
              <div style={{ width: '100%', position: 'relative' }}>
                <div style={{ position: 'absolute', left: 10, top: 5 }}>
                  {no + 1}.
                </div>
                <img src={song?.al?.picUrl} width="100%" height="100px" />
              </div>
              <div style={{ width: '100%', paddingLeft: '10px' }}>
                <Title heading={6} style={{ margin: '8px 0' }}>
                  {song?.al?.name}
                </Title>
              </div>
              <div style={{ width: '100%', paddingLeft: '10px' }}>
                <p style={{ fontSize: '12px' }}>{song?.ar[0]?.name}</p>
              </div>
              <div
                style={{
                  display: 'flex',
                  justifyContent: 'space-evenly',
                  position: 'absolute',
                  bottom: '10px',
                  width: '100%',
                }}
              >
                <IconDoubleChevronLeft />
                <IconDoubleChevronRight style={{ marginRight: '10px' }} />
              </div>
            </SwiperSlide>
          ))}
        </Swiper>
      ))}
    </div>

完整代码

import { Avatar, Dropdown, Layout, Nav, Typography } from '@douyinfe/semi-ui';
import {
  Route,
  Routes,
  NavLink,
  BrowserRouter,
  Link,
  useNavigate,
} from 'react-router-dom';
import * as React from 'react';
import useFetch from '../../../../utils/useFetch';
import { recommendSongs } from '../../../apis/api';
import { Swiper, SwiperSlide } from 'swiper/react';
import { EffectCards } from 'swiper';
import style from './index.module.scss';
import 'swiper/css/effect-cards';
import 'swiper/css/bundle';

// Import Swiper styles
import 'swiper/css';
import {
  IconDoubleChevronLeft,
  IconDoubleChevronRight,
} from '@douyinfe/semi-icons';
import { useRecoilState } from 'recoil';
import { palying } from '../../../../store/atom';
const { useState } = React;
const { Title } = Typography;
const Songs: React.FC = () => {
  const navigate = useNavigate();
  const [currentPlaying, setCurrentPlaying] = useRecoilState(palying);
  // const [data, setDtata] = useState();
  const [response] = useFetch(recommendSongs(), {});
  console.log(response?.data.dailySongs, '?');
  const data = response?.data.dailySongs;
  let cards = [];
  for (let i = 0; i < data?.length; i += 7) {
    if (i < 28) {
      cards.push(data?.slice(i, i + 7));
    }
  }
  console.log(cards, 'sss');
  return (
    <div className={style.container}>
      {cards?.map((item, index) => (
        <Swiper
          effect={'cards'}
          grabCursor={true}
          style={{ overflow: 'visible' }}
          modules={[EffectCards]}
          className={style.swiper}
        >
          {item.map((song: any, no: number) => (
            <SwiperSlide
              onClick={
                () => setCurrentPlaying(() => ({ id: song?.privilege?.id }))
              }
            >
              <div style={{ width: '100%', position: 'relative' }}>
                <div style={{ position: 'absolute', left: 10, top: 5 }}>
                  {no + 1}.
                </div>
                <img src={song?.al?.picUrl} width="100%" height="100px" />
              </div>
              <div style={{ width: '100%', paddingLeft: '10px' }}>
                <Title heading={6} style={{ margin: '8px 0' }}>
                  {song?.al?.name}
                </Title>
              </div>
              <div style={{ width: '100%', paddingLeft: '10px' }}>
                <p style={{ fontSize: '12px' }}>{song?.ar[0]?.name}</p>
              </div>
              <div
                style={{
                  display: 'flex',
                  justifyContent: 'space-evenly',
                  position: 'absolute',
                  bottom: '10px',
                  width: '100%',
                }}
              >
                <IconDoubleChevronLeft />
                <IconDoubleChevronRight style={{ marginRight: '10px' }} />
              </div>
            </SwiperSlide>
          ))}
        </Swiper>
      ))}
    </div>
  );
};
export default Songs;