09_(掌握)项目-全部-RoomItem的轮播图实现效果 antd组件库

107 阅读1分钟

效果:

image.png React\airbib\src\assets\svg\icon-arrow-left.jsx svg 左图标

import React, { memo } from 'react'
import styleStrToObj from './utils'

const IconArrowLeft = memo((props) => {
	const {width=12,height=12} = props
  return (
    <svg viewBox="0 0 18 18" role="img" aria-hidden="false" aria-label="previous" focusable="false" style={styleStrToObj(`height: ${height}px; width: ${width}px; display: block; fill: currentcolor;`)}><path d="m13.7 16.29a1 1 0 1 1 -1.42 1.41l-8-8a1 1 0 0 1 0-1.41l8-8a1 1 0 1 1 1.42 1.41l-7.29 7.29z" fillRule="evenodd"></path></svg>
  )
})

export default IconArrowLeft

svg 右图标

import React, { memo } from 'react'
import styleStrToObj from './utils'

const IconArrowRight = memo((props) => {
	const {width=12,height=12} = props
  return (
    <svg viewBox="0 0 18 18" role="img" aria-hidden="false" aria-label="next" focusable="false" style={styleStrToObj(`height: ${height}px; width: ${width}px; display: block; fill: currentcolor;`)}><path d="m4.29 1.71a1 1 0 1 1 1.42-1.41l8 8a1 1 0 0 1 0 1.41l-8 8a1 1 0 1 1 -1.42-1.41l7.29-7.29z" fillRule="evenodd"></path></svg>
  )
})

export default IconArrowRight

React\airbib\src\components\room-item\index.jsx

import IconArrowLeft from '@/assets/svg/icon-arrow-left';
import IconArrowRight from '@/assets/svg/icon-arrow-right';
import Rating from '@material-ui/lab/Rating'; // 只能用 4.0版本
import { Carousel } from 'antd';

// import { Rating } from '@mui/material'
import PropTypes from 'prop-types'
import React, { memo, useRef } from 'react'
import {ItemWrapper} from './style'



const RoomItem = memo((props) => {
	const {itemData,itemWidth="25%"} = props
	const sliderRef = useRef()
	function controlClickHandle(isRight = true) {
		isRight ? sliderRef.current.next() : sliderRef.current.prev()
	}
	return (
		<ItemWrapper 
			verifyColor={itemData?.verify_info.text_colo || "#39576a"}
			itemWidth={itemWidth}
		>
			<div className='inner'>
						{/* <div className='cover'>
					<img src={itemData.picture_url} alt="" />
				</div> */}
				{/* 轮播图 */}
				<div className='slider'>
					<div className='control'>
						<div className='btn left' onClick={e=>controlClickHandle(false)}>
							<IconArrowLeft width='30' height='30'/>
						</div>
						<div className='btn right' onClick={e=>controlClickHandle(true)}>
							<IconArrowRight width='30' height='30'/>
						</div>
					</div>
					<Carousel dots={false} ref={sliderRef}>
						{
							itemData?.picture_urls?.map(item =>{
								return (
									<div className='cover' key="item">
										<img src={item} alt="" />
									</div>
								)
							})
						}
					</Carousel>
				</div>
				<div className='desc'>
					{itemData.verify_info.messages.join(' · ')}
				</div>
				<div className='name'>{itemData.name}</div>
				<div className='price'>¥{itemData.price}/晚</div>
				<div className='bottom'>
					
				{/* <Rating value={2.5} precision={0.2} readOnly sx={{fontSize:"12px",color:"#00848a", marginRight:"-1px"}}/> */}
				<Rating value={2.5} precision={0.2} readOnly size="small" />
				<span className='count'>{itemData.reviews_count}</span>
				{
					itemData.bottom_info && <span className='extra'>·{itemData.bottom_info?.content}</span>
				}
				</div>
			</div>
		</ItemWrapper>
	)
})

RoomItem.propTypes = {
	itemData:PropTypes.object,
	itemWidth:PropTypes.string
}

export default RoomItem

React\airbib\src\components\room-item\style.js

import styled from "styled-components";

export const ItemWrapper = styled.div`
	flex-shrink: 0;
	box-sizing: border-box;
	width: ${props => props.itemWidth};
	padding: 8px;
	
	.inner {
    width: 100%;
  }
	.cover {
    position: relative;
    box-sizing: border-box;
    padding: 66.66% 8px 0;
    border-radius: 3px;
    overflow: hidden;

    img {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
			object-fit: cover;
    }
  }
	
	// 轮播图样式
	.slider{
		position: relative;
		cursor: pointer;
		
		&:hover{
			.control{
				display: flex;
			}
		}
		.control{
			position: absolute;
			z-index: 1;
			left: 0;
			right: 0;
			top: 0;
			bottom: 0;
			display: none;
			justify-content: space-between;
			color: #fff;
			.btn{
				display: flex;
				justify-content: center;
				align-items: center;
				width: 83px;
				height: 100%;
				background: linear-gradient(to left, transparent 0%, rgba(0,0,0,.25) 100%);
				&.right{
					background: linear-gradient(to right,transparent 0%, rgba(0,0,0,.25) 100%);
				}
			}
		}
	}
	.desc {
    margin: 10px 0 5px;
    font-size: 12px;
    font-weight: 700;
    color: ${props => props.verifyColor};
  }

  .name {
    font-size: 16px;
    font-weight: 700;

    overflow: hidden;  
    text-overflow: ellipsis; 
    display: -webkit-box; 
    -webkit-line-clamp: 2; 
    -webkit-box-orient: vertical;
  }

  .price {
    margin: 8px 0;
  }

  .bottom {
    display: flex;
    align-items: center;
    font-size: 12px;
    font-weight: 600;
    color: ${props => props.theme.text.primaryColor};

    .count {
      margin: 0 2px 0 4px;
    }

    .MuiRating-decimal {
      margin-right: -2px;
    }
  }
`