近期,笔试遇到一个题目,让我用纯css实现3/4圆环。虽然看过很多相关例题,但是到自己动手来写的时候,还是无法实现。此文将介绍一些实现圆环的方法。
一、圆环
要实现圆环,那么首先肯定要实现一个圆。最简单的方法就是通过设置border-radius: 50%
来实现。如下代码:
// html
<div class="circle"></div>
// css
.circle {
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #afb4db;
}
1.1 border 属性实现圆环
从某个角度来看,圆环就是圆的边框。那么想要实现圆环,就可以使用border
属性来实现。
<div class="circle"></div>
// css
.circle {
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #fff;
border: 10px solid #afb4db;
}
如上代码所示,background-color
设置的内容区和padding的颜色,而边框颜色是由border
属性设置,对边框和内部设置不同的颜色,一个圆环也就显现出来了。
由于设置了border
改变了盒子的实际大小,盒子所占空间需要重新计算,所以在进行布局的时候需要注意。如果不想border
改变盒子实际大小,可以设置box-sizing: border-box
。
1.2 两个圆嵌套实现
将圆环拆开来看,其实就是一个外圆和一个内圆嵌套组成,只要我们给外圆和内圆设置不同的背景色即可形成圆环。具体通过父子元素嵌套实现。
// html
<div class="outer-circle">
<div class="inner-circle"></div>
</div>
第一种方法,我们可以设置子元素宽高小于父元素宽高,然后通过定位position
使得子元素与父元素中心重合。
.outer-circle {
position: relative;
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #afb4db;
}
.inner-circle {
position: absolute;
top: 10px;
left: 10px;
width: 180px;
height: 180px;
border-radius: 50%;
background-color: #fff;
}
第二种方式,则是设置子元素宽高width: 100%, height: 100%
占满父元素内容区,然后设置父元素padding
即可。
.outer-circle {
width: 200px;
height: 200px;
padding: 10px;
border-radius: 50%;
background-color: #afb4db;
}
.inner-circle {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #fff;
}
两种代码中实现的圆环宽度相同,但是圆环的半径不同。第一种实现方式中圆环半径为100px - 10px = 90px
,而第二种方式圆环半径就是100px
。
1.3 伪元素实现
通过伪元素实现,其实思想与1.2中大致相同,即用一个元素遮挡另一个元素的中心部分。
// html
<div class="circle"></div>
// css
.circle {
width: 200px;
height: 200px;
border-radius: 50%;
background-color: #afb4db;
}
.circle::after {
content: '';
position: relative;
top: 10px;
left: 10px;
display: block;
width: 180px;
height: 180px;
border-radius: 50%;
background-color: #fff;
}
1.4 svg 实现
除了使用CSS的一些属性来实现圆环,我们也可以使用svg直接绘制一个圆环。
<div class="circle">
<svg width="200" height="200" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="90" stroke="#afb4db" fill="transparent" stroke-width="10"/>
</svg>
</div>
上述代码中相关属性介绍如下:
cx
:圆心 X 轴坐标cy
:圆心 Y 轴坐标r
:半径(内圆)stroke
:边界颜色fill
:填充色stroke-width
边界宽度
1.5 canvas 实现
svg能够实现,那么canvas也就一定能够实现,只不过canvas需要在JavaScript中绘制。
<div class="container">
<canvas id="circle" width="200px" height="200px"></canvas>
</div>
<script>
const canvas = document.getElementById('circle');
if (!canvas.getContext('2d')) {
console.log('浏览器不支持Canvas');
}
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#afb4db'; // 边界颜色
ctx.lineWidth = 10; // 边界宽度
ctx.beginPath(); // 路径开始
ctx.arc(100, 100, 90, 0, Math.PI * 2, true); // 绘制路径
ctx.stroke();
</script>
以上就是个人总结的几种实现圆环的方法,但实现圆环的方法不仅这些,当然还有很多,希望大家指出。
二、不完整的圆环
第一节中我们知道了几种实现圆环的方法,那么例如1/4圆环、3/4圆环这种不完整的圆环怎么实现呢?
2.1 border + transform 实现
如1.1所示,我们可以通过设置border
来实现圆环。但是我们不仅可以通过border
设置所有边界的属性,也可以通过border-top
、border-right
、border-bottom
、border-left
分别设置每个边界的样式。所以当我们设置某个边界的颜色与背景色相同时,那么也就实现了一个不完整的圆环。如下代码:
.circle {
width: 100px;
height: 100px;
margin-right: 20px;
border-radius: 50%;
background-color: #fff;
border: 10px solid #afb4db;
border-top: 10px solid #fff;
}
如上图所示,缺口的位置似乎并不满足我们的要求,那么可以通过transform: rotate(deg)
旋转一定角度来实现。代码如下:
// html
<div class="container">
<div class="circle"></div>
<div class="circle one-four"></div>
<div class="circle two-four"></div>
<div class="circle three-four"></div>
</div>
// css
.circle {
width: 100px;
height: 100px;
margin-right: 20px;
border-radius: 50%;
background-color: #fff;
border: 10px solid #afb4db;
float: left;
}
.one-four {
border-top: 10px solid #fff;
transform: rotate(45deg);
}
.two-four {
border-top: 10px solid #fff;
border-right: 10px solid #fff;
transform: rotate(45deg);
}
.three-four {
border-top: 10px solid #fff;
border-right: 10px solid #fff;
border-bottom: 10px solid #fff;
transform: rotate(45deg);
}
这种方法还是有很大限制的,它只能实现1/4,1/2,3/4 圆环,那如果我们需要实现一个80%的圆环这种方法就失效了。
2.2 clip-path 裁剪
看了很多资料,发现对于这种实现不完整圆或不完整圆环的需求,大部分都是通过 clip-path
属性来实现的。那么下面我们先简单介绍一下clip-path
属性。
(1)clip-path 属性
clip-path
属性使用裁剪方式创建元素的可显示区域
本文就以如下例子简单介绍一下几种常用的属性值:
// html
<div class="container">
<div class="clip"></div>
</div>
// css
.container {
width: 200px;
height: 200px;
background-color: #afb4db;
}
.clip {
width: 100%;
height: 100%;
background: url("./pupu.png") no-repeat;
background-size: 100% 100%;
}
inset
:矩形裁剪
定义一个 inset 矩形。
语法:
clip-path: inset(top left bottom right round border-radius);
- 前四个值代表了从参考框向内的上、右、下和左的偏移量,定义了嵌入矩形的边缘位置。
- 当设置为百分比时,上下偏移量对应高,左右偏移量对应宽
- 可选参数
border-radius
,定义了矩形的圆角弧度
如下代码:
clip-path: inset(40px 20% 10px 20px round 10px);
circle
:圆形裁剪
定义一个圆形(使用一个半径和一个圆心位置)
语法:
clip-path: circle(r at x y);
r
:圆形半径。其值可以为以下四种:- length:例如10px, 2rem等
- 百分比:(width * 百分比 + height * 百分比) / 2
closest-side
:宽高中较短者的一半farthest-side
:宽高中较长者的一半
x, y
:圆心坐标,默认为盒子中心位置。以左上角为原点。- length:例如 x = 10px, y = 10px,那么圆心就在(10px, 10px)处
- 百分比:x对应宽,y对应高
- x 还可以设置为
left
或right
,代表左右边界(对应百分比就是 0% 和 100%) - y 还可以设置为
top
或bottom
,代表上下边界(对应百分比就是 0% 和 100%) 如下代码:
clip-path: circle(50px at 100px 40%);
ellipse
裁剪
定义一个椭圆(使用两个半径和一个圆心位置)。
语法:
clip-path: ellipse(rx ry at x y);
rx
,ry
:长轴和短轴半径。其值可以为以下四种:- length:例如10px, 2rem等
- 百分比:rx对应宽, ry对应高
closest-side
:宽高中较短者的一半farthest-side
:宽高中较长者的一半
如下代码:
clip-path: ellipse(50px 30% at 100px 40%)
polygon
裁剪
定义一个多边形(使用一个 SVG 填充规则和一组顶点)。
具体语法可见 svg如何绘制多边形
如下代码:
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
path
裁剪
定义一个任意形状(使用一个可选的 SVG 填充规则和一个 SVG 路径定义)。
具体语法可见 svg路径
如下代码:
clip-path: path("M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80");
(2)clip-path 实现不完整圆环
通过如上的介绍,我们可以使用polygon
或者path
来裁剪,进而获得部分圆环。如下代码:
// html
<div class="circle"></div>
// css
.circle {
width: 100px;
height: 100px;
margin-right: 20px;
border-radius: 50%;
background-color: #fff;
border: 10px solid #afb4db;
clip-path: polygon(50% 50%, 100% 0, 50% 0);
}
//