1、完整代码及样式示例
1.1. 渐变色 圆角/倒角 效果图
圆角
倒角
1.2. 渐变色 圆角/倒角 完整示例代码
渐变色色值:linear-gradient(270deg,rgba(34,117,211,1) 0%,rgba(14,244,243,1) 49%,rgba(34,117,211,1) 100%)
边宽:5px
宽:300px
高:150px
圆角值: 左上25px 右上30px 右下35px 左下40px
类型:圆角(若想要查看倒角样式,将borderType设置为chamfer即可)
2、前景提要
圆角
渐变色边框不支持圆角
1.fillet-gradient-color-box {
2 display: flex;
3 justify-content: center;
4 align-items: center;
5 width: 400px;
6 height: 200px;
7
8 border: 1px solid transparent;
9 border-image: linear-gradient(270deg,rgba(34,117,211,1) 0%,rgba(14,244,243,1) 49%,rgba(34,117,211,1) 100%) 1;
10 border-image-slice: 1;
11}
圆角
纯色边框不支持渐变色
1.fillet-pure-color-box {
2 border: 1px solid #9ba2b0;
3 border-radius: 20;
4}
所以当我们需要满足既要**支持圆角**
,又要**支持渐变色**
的时候,就没有直接可以使用的css样式可以实现
圆角
背景色设置渐变,after切割出圆角效果
【注】这种效果的缺陷是背景颜色不能有透明度,不然被叠加遮盖住的_background-image_
颜色就会显示出来
1.border-radius-demo {
2 width: 400px;
3 height: 400px;
4
5 position: relative;
6 display: flex;
7 justify-content: center;
8 align-items: center;
9
10 background-image: linear-gradient(270deg,rgba(34,117,211,1) 0%,rgba(14,244,243,1) 49%,rgba(34,117,211,1) 100%);
11 border-radius: 25px 30px 35px 40px;
12}
13.border-radius-demo:after {
14 content: "";
15 position: absolute;
16 left: 5px;
17 top: 5px;
18 z-index: 10;
19 width: calc(100% - 10px);
20 height: calc(100% - 10px);
21 border-radius: 25px 30px 35px 40px;
22 background-color: red;
23}
倒角
结合边框配置单纯切割图形实现的倒角,会出现切割部分没有边的问题
【注】一下这种矩形裁切方式,会将四个角裁去的部分中边框的部分同样裁去,最终并不是想要实现的效果
1.chamfer-gradient-color-box {
2 width: 400px;
3 height: 200px;
4
5 border: 3px solid transparent;
6 border-image: linear-gradient(270deg,rgba(34,117,211,1) 0%,rgba(14,244,243,1) 49%,rgba(34,117,211,1) 100%) 1;
7 border-image-slice: 1;
8 background-color: rgb(103, 235, 63);
9 clip-path: polygon(15px 0, calc(100% - 15px) 0, 100% 15px, 100% calc(100% - 5px), calc(100% - 15px) 100%,15px 100%, 0 calc(100% - 15px), 0 15px);
10}
11.chamfer-pure-color-box {
12 width: 400px;
13 height: 200px;
14
15 border: 3px solid #9ba2b0;
16 border-radius: 20;
17 background-color: rgb(127, 255, 212);
18 clip-path: polygon(15px 0, calc(100% - 15px) 0, 100% 15px, 100% calc(100% - 15px), calc(100% - 15px) 100%,15px 100%, 0 calc(100% - 15px), 0 15px);
19}
3、实现方法及逻辑
通过CSS样式中的clip-path样式,结合dom元素的after进行叠加遮盖,实现 渐变色 圆角/倒角 边框 的效果
3.1. 内圆 圆角值计算逻辑图解
3.2. CSS绘制逻辑图解
3.3. 绘制外圈圆角矩形路径(按照逆时针方向绘制)
1const createOuterRoundedRectPath = (params) => {
2 const { x, y, width, height, borderRadius } = params;
3 return (
4 "M " +
5 x +
6 "," +
7 (y + height / 2 + (height / 2 - borderRadius.leftBottom)) +
8 " a " +
9 borderRadius.leftBottom +
10 "," +
11 borderRadius.leftBottom +
12 " 0 0 0 " +
13 borderRadius.leftBottom +
14 "," +
15 borderRadius.leftBottom +
16 " h " +
17 (width - (borderRadius.rightBottom + borderRadius.leftBottom)) +
18 " a " +
19 borderRadius.rightBottom +
20 "," +
21 borderRadius.rightBottom +
22 " 0 0 0 " +
23 borderRadius.rightBottom +
24 "," +
25 borderRadius.rightBottom * -1 +
26 " v " +
27 (height - (borderRadius.rightBottom + borderRadius.rightTop)) * -1 +
28 " a " +
29 borderRadius.rightTop +
30 "," +
31 borderRadius.rightTop +
32 " 0 0 0 " +
33 borderRadius.rightTop * -1 +
34 "," +
35 borderRadius.rightTop * -1 +
36 " h " +
37 (width - (borderRadius.rightTop + borderRadius.leftTop)) * -1 +
38 " a " +
39 borderRadius.leftTop +
40 "," +
41 borderRadius.leftTop +
42 " 0 0 0 " +
43 borderRadius.leftTop * -1 +
44 "," +
45 borderRadius.leftTop +
46 " z"
47 );
48};
3.4. 绘制内圈圆角矩形路径(按照顺时针方向绘制)
1const createInnerRoundedRectPath = (params) => {
2 const { x, y, width, height, borderRadius } = params;
3 return (
4 "M " +
5 (x + borderRadius.leftTop) +
6 "," +
7 y +
8 " h " +
9 (width - (borderRadius.rightTop + borderRadius.leftTop)) +
10 " a " +
11 borderRadius.rightTop +
12 "," +
13 borderRadius.rightTop +
14 " 0 0 1 " +
15 borderRadius.rightTop +
16 "," +
17 borderRadius.rightTop +
18 " v " +
19 (height - (borderRadius.rightBottom + borderRadius.rightTop)) +
20 " a " +
21 borderRadius.rightBottom +
22 "," +
23 borderRadius.rightBottom +
24 " 0 0 1 " +
25 borderRadius.rightBottom * -1 +
26 "," +
27 borderRadius.rightBottom +
28 " h " +
29 (width - (borderRadius.leftBottom + borderRadius.rightBottom)) * -1 +
30 " a " +
31 borderRadius.leftBottom +
32 "," +
33 borderRadius.leftBottom +
34 " 0 0 1 " +
35 borderRadius.leftBottom * -1 +
36 "," +
37 borderRadius.leftBottom * -1 +
38 " v " +
39 (height - (borderRadius.leftBottom + borderRadius.leftTop)) * -1 +
40 " a " +
41 borderRadius.leftTop +
42 "," +
43 borderRadius.leftTop +
44 " 0 0 1 " +
45 borderRadius.leftTop +
46 "," +
47 borderRadius.leftTop * -1 +
48 " z"
49 );
50};
3.5. 绘制外圈倒角矩形路径(按照逆时针方向绘制)
1const createOuterAngleRectPath = (params) => {
2 const { x, y, width, height, borderRadius } = params;
3 return (
4 "M " +
5 x +
6 "," +
7 (y + height / 2 + (height / 2 - borderRadius.leftBottom)) +
8 " l " +
9 borderRadius.leftBottom +
10 "," +
11 borderRadius.leftBottom +
12 " h " +
13 (width - (borderRadius.rightBottom + borderRadius.leftBottom)) +
14 " l " +
15 borderRadius.rightBottom +
16 "," +
17 borderRadius.rightBottom * -1 +
18 " v -" +
19 (height - (borderRadius.rightBottom + borderRadius.rightTop)) +
20 " l " +
21 borderRadius.rightTop * -1 +
22 "," +
23 borderRadius.rightTop * -1 +
24 " h -" +
25 (width - (borderRadius.rightTop + borderRadius.leftTop)) +
26 " l " +
27 borderRadius.leftTop * -1 +
28 "," +
29 borderRadius.leftTop +
30 " z"
31 );
32};
3.6. 绘制内圈倒角矩形路径(按照顺时针方向绘制)
1const createInnerAngleRectPath = (params) => {
2 const { x, y, width, height, borderRadius } = params;
3 return (
4 "M " +
5 (x + borderRadius.leftTop) +
6 "," +
7 y +
8 " h " +
9 (width - borderRadius.rightTop - borderRadius.leftTop) +
10 " l " +
11 borderRadius.rightTop +
12 "," +
13 borderRadius.rightTop +
14 " v " +
15 (height - borderRadius.rightBottom - borderRadius.rightTop) +
16 " l " +
17 borderRadius.rightBottom * -1 +
18 "," +
19 borderRadius.rightBottom +
20 " h " +
21 -1 * (width - borderRadius.leftBottom - borderRadius.rightBottom) +
22 " l " +
23 borderRadius.leftBottom * -1 +
24 "," +
25 borderRadius.leftBottom * -1 +
26 " v " +
27 -1 * (height - borderRadius.leftTop - borderRadius.leftBottom) +
28 " l " +
29 borderRadius.leftTop * -1 +
30 "," +
31 borderRadius.leftTop +
32 " z"
33 );
34};
3.7. 结合内圈&外圈return的路径,返回clip-path样式path的路径数据
【注】这里传递参数时,需要对圆角大小进行限制,不能超过宽高最小值的一半
1const getAssemblePath = (outerParams, innerParams, type) => {
2
3 const outerRoundPath =
4 type === "fillet"
5 ? createOuterRoundedRectPath(outerParams)
6 : createOuterAngleRectPath(outerParams);
7
8 const innerRoundPath =
9 type === "fillet"
10 ? createInnerRoundedRectPath(innerParams)
11 : createInnerAngleRectPath(innerParams);
12 return {
13 borderPath: `${outerRoundPath} ${innerRoundPath}`,
14 bgPath: `${outerRoundPath}`,
15 };
16};
17
18const handleCalculatePath = (
19 borderRadius,
20 type,
21 strokeWidth,
22 { boxWidth, boxHeight }
23) => {
24
25 let newBorderRadius = {
26 leftTop: Math.min(borderRadius.leftTop, Math.min(boxWidth, boxHeight) / 2),
27 rightTop: Math.min(
28 borderRadius.rightTop,
29 Math.min(boxWidth, boxHeight) / 2
30 ),
31 rightBottom: Math.min(
32 borderRadius.rightBottom,
33 Math.min(boxWidth, boxHeight) / 2
34 ),
35 leftBottom: Math.min(
36 borderRadius.leftBottom,
37 Math.min(boxWidth, boxHeight) / 2
38 ),
39 };
40 const outerParams = {
41 x: 0,
42 y: 0,
43 width: boxWidth,
44 height: boxHeight,
45 borderRadius: newBorderRadius,
46 };
47 const innerParams = {
48 x: strokeWidth,
49 y: strokeWidth,
50 width: boxWidth - strokeWidth * 2,
51 height: boxHeight - strokeWidth * 2,
52 borderRadius: {
53 leftTop: newBorderRadius.leftTop + (Math.sqrt(2) - 2) * strokeWidth,
54 rightTop: newBorderRadius.rightTop + (Math.sqrt(2) - 2) * strokeWidth,
55 rightBottom:
56 newBorderRadius.rightBottom + (Math.sqrt(2) - 2) * strokeWidth,
57 leftBottom: newBorderRadius.leftBottom + (Math.sqrt(2) - 2) * strokeWidth,
58 },
59 };
60 const path = getAssemblePath(outerParams, innerParams, type).borderPath;
61 const bgPath = getAssemblePath(outerParams, innerParams, type).bgPath;
62
63 return { path, bgPath };
64};
3.8. 生成CSS样式
1const handleDrawGraph = (
2 borderRdius,
3 type,
4 borderWidth,
5 boxWidth,
6 boxHeight,
7 borderColor
8) => {
9 const { path, bgPath } = handleCalculatePath(
10 borderRadius,
11 type,
12 borderWidth,
13 {
14 boxWidth,
15 boxHeight
16 }
17 );
18 return {
19 "--custom-box-clip-path": `path('${path}')`,
20 "--custom-box-clip-path-bg-path": `path('${bgPath}')`,
21 "--custom-box-clip-path-bg-color": borderColor
22 }
23}
1.custom-box {
2 position: relative;
3 width: 100%;
4 height: 100%;
5 clip-path: var(--custom-box-clip-path-bg-path);
6 &::after {
7 position: absolute;
8 left: 0;
9 top: 0;
10 z-index: -1;
11 width: 100%;
12 height: 100%;
13 background: var(--custom-box-clip-path-bg-color);
14 clip-path: var(--custom-box-clip-path);
15 }
16}
通过以上设置就可以实现 渐变色/纯色+圆角/倒角 的样式效果
个人笔记记录 2021 ~ 2025