使用flexbox和svg(使用Sandbox)反应星级评分组件

问题描述 投票:2回答:2

我目前正在构建一个React组件,以便在我的应用中显示星级。

My star rating component

它目前正在运作。但不知何故,我只能通过将SVG元素包含在<span>标签中来实现它,这让我感到困扰。它为代码带来了另一个容器和维度,这使我在这种情况下更难以推理我的CSS维度。

我正在使用styled-components进行CSS。

以下是我渲染Stars组件的方法:

App.js

<Stars stars={3.4} />;

Stars.js

import React from "react";
import styled from "styled-components";
import IconStar from "./IconStar";

const S = {};

S.WrapperDiv = styled.div`
  display: flex;
  align-items: center;
`;

S.RatingSpan = styled.span`
  font-size: 1.8rem;
  font-weight: 700;
  padding-right: 5px;
  line-height: 1.8rem;
  font-family: Helvetica, Arial;
`;

S.BackStarsDiv = styled.div`
  display: flex;
  position: relative;
  color: #d3d3d3;
`;

S.FrontDiv = styled.div`
  display: flex;
  position: absolute;
  top: 0;
  overflow: hidden;
  width: ${props => props.rating};
  color: #ffbc0b;
`;

function Stars(props) {
  let rating = 0;

  /* This is to round the rating to closest .5 or .0 */
  if (props.stars) {
    rating =
      (((Math.round((props.stars * 10) / 5) * 5) / 10) * 20).toString() + "%";
  }

  return (
    <React.Fragment>
      <S.WrapperDiv>
        <S.RatingSpan>{props.stars || "N/A"}</S.RatingSpan>
        <S.BackStarsDiv>
          <IconStar />
          <IconStar />
          <IconStar />
          <IconStar />
          <IconStar />
          <S.FrontDiv rating={rating}>
            <IconStar />
            <IconStar />
            <IconStar />
            <IconStar />
            <IconStar />
          </S.FrontDiv>
        </S.BackStarsDiv>
      </S.WrapperDiv>
    </React.Fragment>
  );
}

export default Stars;

IconStar.js

import React from "react";
import styled from "styled-components";

const S = {};

S.span = styled.span`
  width: 1.8rem;
  height: 1.8rem;
`;

S.svg = styled.svg`
  /* display: inline-block;
  vertical-align: middle; */
`;

function IconStar(props) {
  return (
    <S.span>
      <S.svg
        viewBox="0 0 1000 1000"
        width="1.8rem"
        height="1.8rem"
        aria-hidden="true"
      >
        <path
          fill="currentColor"
          d="M10,394.5c0-14.8,10.9-23.9,32.7-27.4l295.4-42.2L471,56.9c7.7-16.2,17.2-24.3,28.5-24.3s21.1,8.1,29.5,24.3l131.9,267.9l295.4,42.2c22.5,3.5,33.8,12.7,33.8,27.4c0,8.4-5.3,17.9-15.8,28.5L760,630.8l50.6,294.3c0.7,2.8,1.1,7,1.1,12.7c0,7.7-2.1,14.4-6.3,20c-4.2,5.6-10.2,8.8-17.9,9.5c-7,0-14.8-2.5-23.2-7.4L499.5,820.7L235.7,959.9c-9.1,4.9-17.2,7.4-24.3,7.4c-7.7,0-13.7-3.2-17.9-9.5c-4.2-6.3-6.3-13-6.3-20c0-2.8,0.4-7,1.1-12.7l50.6-294.3L24.8,423C14.9,412.4,10,402.9,10,394.5L10,394.5z"
        />
      </S.svg>
    </S.span>
  );
}

export default IconStar;

有没有办法摆脱<span>IconStar.js元素,并使其直接与SVG元素一起使用?不知道为什么,但是当我删除它时,它会破坏我的CSS。

这是Code Sandbox与我目前工作的组件。

css reactjs styled-components
2个回答
2
投票

因为当你移除svg元素时,你的span正在缩小。为了防止这种情况,只需将flex-shrink: 0;添加到你的svg

https://codesandbox.io/s/rn14mq2ko


0
投票

我会删除<span>FrontDiv上的宽度。问题似乎是你在两个地方定义元素的宽度。当你在跨度上使用它时,它将覆盖父样式。

Code sandbox

© www.soinside.com 2019 - 2024. All rights reserved.