实现弧形效果

371 阅读3分钟

今天我们来聊一聊,怎么实现下面的弧形效果👇

效果.png

图像引入

首先,我们想到的就是直接引入透明的图片 .png

当然,这个是可行的。

但是,它存在下面的问题:

  • 需要进行多一次的请求
  • 不可以随便更改图像的样式,比如尺寸,颜色等

使用纯 CSS

需求上的效果,我们是可以通过 CSS 来实现的👇

<div id="container"></div>
#container {
  width: 100px;
  height: 100px;
  background-color: red;
  margin: 0 auto;
  margin-top: 100px;
  position: relative;
  &::after {
    content: "";
    display: block;
    width: 100px;
    height: 100px;
    background-color: white;
    position: absolute;
    top: 0;
    left: 0;
    border-bottom-left-radius: 100px;
  }
}

我们使用了一个伪元素,然后然后设定其左下角的圆角为宽度的尺寸,之后设定一个背景颜色和上级的背景颜色为同颜色,比如这里的 white 白色。

这样的编写比较简单,但是有个问题?

如果背景颜色是透明或者其他颜色的话,那就不建议使用该方式👇

background-confict.png

嗯~ 我们采用另外一种方式来实现 - 采用裁剪

<div id="demo"></div>
#demo {
  width: 100px;
  height: 100px;
  background-color: red;
  margin: 0 auto;
  margin-top: 60px;
  clip-path: path('M 0 0 A 100,100,0,0,0,100,100 L 100 100 L 0 100 Z');
}

我们使用 clip-path 来按照路径来裁剪。

clip-path.png

我们来解析下 path 的参数👇

此时的 100 * 100 的红色框的二维坐标系如下图

cooridinate_axes.png

  • M 0 0

    • M 表示移动到一个新的位置
    • 0 0 表示移动到坐标原点 (0, 0)
  • A 100,100 0,0,0,100,100

    • A 表示绘制一个椭圆弧 Arc
    • 100,100 表示椭圆的半轴长度
    • 0 表示椭圆的旋转角度
    • 0 表示大弧标志(0 表示小弧, 1 表示大弧)
    • 0 表示扫过角度标志(0 表示正向,1 表示逆向)
    • 100,100 表示弧的终点坐标
  • L 100 100

    • L 表示绘制一条直线 Line
    • 100 100 表示直线的终点坐标
  • Z

    • Z 表示关闭路径,即从当前点绘制一条直线回到路径的起点,这里是 (0, 0)

在英文中,z 表示 closepath

嗯~ 我们能够成功实现效果。

但是我们看了下兼容性,通过 can i use 查看

兼容性.png

其兼容性很是不错。但是笔者在内嵌的 app 设备中,却发现效果无效。

于是,我们换一种思路。

使用 svg

我们在 css 中直接使用 svg。更改下上面的代码如下👇

<div id="demo"></div>
#demo {
    width: 100px;
    height: 100px;
    background: red;
    mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 0 0 A 100,100,0,0,0,100,100 L 100 100 L 0 100 Z" fill="white"/></svg>');
    margin: 0 auto;
    margin-top: 60px;
}

我们使用了 svg ,实现了同样的效果。

clip-path.png

为了更好管理 svg 文件,我们将其提取出来,统一管理。

我们拿 react 项目来举例。现在有个文件 src/assets/close.svg 的文件:

<svg width="108" height="108" viewBox="0 0 108 108" fill="none" xmlns="http://www.w3.org/2000/svg">
    <circle cx="54" cy="54" r="52" stroke="currentColor" stroke-width="4" />
    <path
        d="M70.4036 37.6016L37.6079 70.3973"
        stroke="currentColor"
        stroke-width="6"
        stroke-linecap="round"
        stroke-linejoin="round"
    />
    <path
        d="M37.6079 37.6016L70.4036 70.3973"
        stroke="currentColor"
        stroke-width="6"
        stroke-linecap="round"
        stroke-linejoin="round"
    />
</svg>

然后我们在 webpack.config.js 上配置:

{ 
  test: /\.svg$/, 
  loader: "svg-sprite-loader", 
  include: paths.appSrc, 
  options: { 
    symbolId: "jimmy-icon-[name]", 
  }, 
}

配置详情解析

  • options: { symbolId: "jimmy-icon-[name]" }
    • options 属性用于传递配置选项给 svg-sprite-loader

    • symbolId: "jimmy-icon-[name]" 是一个选项,用于指定生成的符号(symbol)DOM 元素的 ID。

      • jimmy-icon- 是 ID 的前缀。
      • [name] 是一个占位符,会被替换为 SVG 文件的名称(不包括扩展名)。

然后我们在需要引入的地方使用👇

<svg width="1em" height="1em" fill="currentColor">
    <use xlinkHref="#jimmy-icon-close"></use>
</svg>

使用 svg 我们可以确保 icon 图像的清晰度,不失真,可以灵活更改其样式,比如颜色等。

本文【完✅】,谢谢阅读🌹