React-Native 中边框半径图像的自定义形状

Custom shape for border radius image in React-Native

我想在我的组件(边框底部)中重现该样式。 我基本上是加载一个矩形图像,然后我想在底部把它弄圆。

我考虑:

有没有办法使用 React-Native 以适当的方式做到这一点?

谢谢!

是的。 clip-path 属性!

只需添加: clip-path:圆形(69.3% 在 50% 30%)

到你的class,它会起作用。

如果你想自己创建,这里有一个生成器: https://bennettfeely.com/clippy/

我假设您想要保持笔直的左边缘和右边缘,只有底部边缘是弯曲的。 Here's one way 与 CSS 和两个堆叠 divs

您必须根据自己的喜好调整半径的 CSS 和图像大小。它最适用于大于 divs 的图像,使用 background-position:background-repeat: no-repeat 进行调整。您还可以使用 border-leftborder-right 使顶部 div 没有顶部或底部框架。

.imagediv {
width: 400px;
height: 300px;
border-radius: 0 0 50% 50%;
background-image: url("https://www.scriptbarrel.com/images/swim.png");
background-position: 50% 20%;
background-repeat: no-repeat;
position: relative;
box-shadow: 0px 5px 4px #999;
z-index: 0;
margin: 0 auto;
}

.topdiv {
margin: 0 auto;
left: -10px;
width: 340px;
height: 300px;
border-top: 15px solid white;
border-left: 40px solid white;
border-right: 40px solid white;
position: absolute;
z-index: 1;
}
 
<html><head>
<title>CSS fun</title>
</head>
<body>
<div class = "imagediv">
<div class = "topdiv"></div>
</div>

</body>
</html>

这是可能的,但有点棘手。这个想法是你需要创建一个可以应用形状的 "mask" 种类。这样做之后,您可以将图像作为遮罩元素的子元素,以便它基本上遮住您想要的区域。可能可以使用动态大小来完成,但我没有花时间想出那个解决方案,我会把它留给你;)

但愿这会让您朝着正确的方向前进。

首先让我们设置应用程序结构

class App extends Component {
  render() {
    return (
      <View style={styles.app}>
        <Mask />
      </View>
    );
  }
}

非常简单,只是一个带有遮罩组件的基本应用程序。我把它变成了一个组件,这样你以后就可以将道具传递给它(例如图像 uri)。

然后是遮罩组件

const logoUri = `http://66.media.tumblr.com/86b941b3445b80a518ea51208f48ab35/tumblr_ntpi99a6Pl1uounv1o1_500.png`;
const Mask = (props) => (
  <View style={styles.maskContainer}>
    <View style={styles.mask}>
      <Image
        source={{ uri: logoUri }}
        style={styles.img}
      />
    </View>
  </View>
)

maskContainer 是一个帮助图像居中的定位元素。
mask 使用 oval style approach 但要使边缘不像边界半径那样圆润,我们必须将其缩放 2x
img 样式需要反转缩放,这样图像本身就不会变形 :)

const styles = StyleSheet.create({
  app: {
    marginHorizontal: "auto",
    maxWidth: 500,
    backgroundColor: "#e0e0e0",
    width: 700,
    height: 700
  },
  mask: {
    width: 200,
    height: 470,
    borderBottomLeftRadius: 100,
    borderBottomRightRadius: 100,
    overflow: "hidden",
    transform: [{ scaleX: 2 }]
  },
  img: {
    height: 470,
    width: 299,
    left: 25,
    position: "absolute",
    transform: [{ scaleX: 0.5 }, { translate: "-50%" }]
  },
  maskContainer: {
    position: "absolute",
    left: "50%",
    transform: [{ translate: "-50%" }]
  }
});

See it working on this fiddle!

@John Ruddell 的回答很有帮助。 我可以通过创建蒙版并通过 SVG 路径应用来设计它。所以,你需要安装2个库。

  1. react-native-svg (expo install react-native-svg)
  2. react-native-masked-view (npm install --save @react-native-community/masked-view)

以下代码尊重图像的纵横比。因此,您需要设置图像的纵横比并调整 curveAdjustment 的值,以达到您想要的曲线锐度。

      import React from "react";
      import {
        Image,
        View,
        StyleSheet,
        Text,
        useWindowDimensions,
      } from "react-native";

      import MaskedView from "@react-native-community/masked-view";
      import Svg, { Path } from "react-native-svg";

      const logoUri = `http://66.media.tumblr.com/86b941b3445b80a518ea51208f48ab35/tumblr_ntpi99a6Pl1uounv1o1_500.png`;

      function SplashScreen(props) {
        const windowWidth = useWindowDimensions().width;

        const imageAspectWidth = 375;
        const imageAspectHeight = 332;

        const curveAdjustment = 40;
        const maskHeight = (imageAspectHeight / imageAspectWidth) * windowWidth;

        const scaleFactor = imageAspectWidth / imageAspectHeight;
        const scaledHeight = scaleFactor * maskHeight;

        const controlPointX = windowWidth / 2.0;
        const controlPointY = scaledHeight + curveAdjustment;

        const curveCenterPointY = (controlPointY - maskHeight) / 2;

        return (
          <View style={styles.main}>
            <MaskedView
              style={[
                styles.mask,
                {
                  height: controlPointY - curveCenterPointY,
                },
              ]}
              maskElement={
                <Svg height="100%" width="100%">
                  <Path
                    d={`M0 0 L${windowWidth} 0 L${windowWidth} ${maskHeight} Q${controlPointX} ${controlPointY} 0 ${maskHeight} Z`}
                    fill={"#fff"}
                  />
                </Svg>
              }
            >
              <Image source={{ uri: logoUri }} style={styles.image} />
            </MaskedView>
            <Text>{"Tag line"}</Text>
          </View>
        );
      }

      const styles = StyleSheet.create({
        image: {
          flex: 1,
          resizeMode: "stretch",
        },
        main: {
          flex: 1,
        },
        mask: {
          backgroundColor: "orange",
          width: "100%",
        },
      });

      export default SplashScreen;

最终结果