【CSS】762- 如何實(shí)現(xiàn)一個(gè)圓弧倒計(jì)時(shí)進(jìn)度條
一、前言
最近的項(xiàng)目中,需要實(shí)現(xiàn)一個(gè)圓弧形倒計(jì)時(shí)進(jìn)度條,對(duì)于本來(lái) css 知識(shí)薄弱的我當(dāng)場(chǎng)就懵逼,腦海里總是不斷思考如何實(shí)現(xiàn),不幸的是腦袋里沒(méi)能蹦出半個(gè)想法。然后立馬百度查看網(wǎng)上是否有相似的解決方案,百度下來(lái)初步知道如何來(lái)實(shí)現(xiàn)了,那我們就一步一步從 0 到有開(kāi)始這段旅程。
首先展示一下最終的成果,最終效果圖如下:

實(shí)現(xiàn)要點(diǎn):淺色圓弧需要分成左右兩邊,左右兩邊都需要用一個(gè)同心原來(lái)實(shí)現(xiàn),亮色圓弧也需要左右分開(kāi),各自用一個(gè)同心圓來(lái)實(shí)現(xiàn)。讓我們開(kāi)始吧!
二、實(shí)現(xiàn)步驟
添加容器
讓整個(gè)容器是 position: fixed 方便可以在整個(gè)頁(yè)面上隨意放置
html 代碼:
<div?class="task-container">div>
css 代碼:
.task-container?{
????position:?fixed;
????left:?0;
????right:?0;
????top:?0;
????bottom:?0;
????margin:?auto;
????width:?65px;
????height:?65px;
????display:?flex;
????justify-content:?center;
????align-items:?center;
}
畫(huà)底盤(pán)
加點(diǎn)陰影,讓它看起來(lái)有點(diǎn)立體的感覺(jué) html 代碼:
<div?class="task-container">
????<div?class="task-cicle">div>
div>
css 代碼:
.task-container?{
????position:?fixed;
????left:?0;
????right:?0;
????top:?0;
????bottom:?0;
????margin:?auto;
????width:?65px;
????height:?65px;
????display:?flex;
????justify-content:?center;
????align-items:?center;
?
????.task-cicle?{
????????display:?flex;
????????justify-content:?center;
????????align-items:?center;
????????width:?53px;
????????height:?53px;
????????border-radius:?50%;
????????background:?#FFFFFF;
????????box-shadow:?0px?0px?12px?0px?rgba(0,?0,?0,?0.05);
????}
}
效果:

重點(diǎn)來(lái)了,接下來(lái)實(shí)現(xiàn)圓弧
我們先畫(huà)右圓弧,我們用右半邊矩形來(lái)實(shí)現(xiàn),右半圓只設(shè)置上方和右邊的邊框顏色 html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????div>
????div>
div>
css 代碼:
.task-container?{
????position:?fixed;
????left:?0;
????right:?0;
????top:?0;
????bottom:?0;
????margin:?auto;
????width:?65px;
????height:?65px;
????display:?flex;
????justify-content:?center;
????align-items:?center;
????.task-cicle?{
????????display:?flex;
????????justify-content:?center;
????????align-items:?center;
????????width:?53px;
????????height:?53px;
????????border-radius:?50%;
????????background:?#FFFFFF;
????????box-shadow:?0px?0px?12px?0px?rgba(0,?0,?0,?0.05);
????}
????.task-inner?{
????????position:?relative;
????????width:?46px;
????????height:?46px;
????}
????.right-cicle?{
????????width:?23px;
????????height:?46px;
????????position:?absolute;
????????top:?0;
????????right:?0;
????????overflow:?hidden;
????}
????.cicle-progress?{
????????position:?absolute;
????????top:?0;
????????width:?46px;
????????height:?46px;
????????border:?3px?solid?transparent;
????????box-sizing:?border-box;
????????border-radius:?50%;
????}
????.cicle1-inner?{
????????left:?-23px;
????????border-right:?3px?solid?#e0e0e0;
????????border-top:?3px?solid?#e0e0e0;
????????transform:?rotate(-15deg);
????}
}
right-cicle 需要設(shè)置 overflow: hidden;對(duì)子元素超出的部分進(jìn)行裁剪。cicle1-inner 中的旋轉(zhuǎn)-15 度,其實(shí)可以根據(jù)設(shè)計(jì)稿來(lái)調(diào)整你需要展示的弧度 如果父節(jié)點(diǎn),沒(méi)有進(jìn)行裁剪,右半圓就會(huì)延伸到左邊

裁剪之后的效果

畫(huà)左邊的弧
接下來(lái)根據(jù)同樣的原理畫(huà)左邊的弧。左邊的圓,只設(shè)置上方和左邊的邊框顏色 html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle2-inner">div>
????????????div>
????????div>
????div>
div>
css 代碼:
.left-cicle?{
????width:?23px;
????height:?46px;
????position:?absolute;
????top:?0;
????left:?0;
????overflow:?hidden;
}
.cicle2-inner?{
????left:?0;
????border-left:?3px?solid?#e0e0e0;
????border-top:?3px?solid?#e0e0e0;
????transform:?rotate(15deg);
}
效果如下:

ok,圓弧的基本輪廓已經(jīng)完成,接下來(lái)實(shí)現(xiàn)亮色進(jìn)度條,進(jìn)度條也是分左右邊各自實(shí)現(xiàn)
畫(huà)右半邊進(jìn)度條
右半邊圓只設(shè)置上方和右邊的邊框顏色 html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle2-inner">div>
????????????div>
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle3-inner"?id="rightCicle">div>
????????????div>
????????div>
????div>
div>
css 代碼:
.cicle3-inner?{
????left:?-23px;
????border-right:?3px?solid?#feca02;
????border-top:?3px?solid?#feca02;
????transform:?rotate(-135deg);
}
效果如下:
為什么是旋轉(zhuǎn)-135 度?進(jìn)度條是從左邊蔓延到右邊的,讓亮色進(jìn)度條旋轉(zhuǎn)到左右兩邊的臨界點(diǎn),也就是初始角度是-135 度,隨著時(shí)間推移增加旋轉(zhuǎn)角度,進(jìn)度條就蔓延到右邊了
轉(zhuǎn)到哪個(gè)角度為止呢?轉(zhuǎn)到亮色邊框和右邊灰色邊框重合,也就是-15 度,那么右邊亮色進(jìn)度條的旋轉(zhuǎn)角度范圍就是-135 度到-15 度,共 120 度的。
右半邊進(jìn)度條已經(jīng)完成,初始角度是-135 度,隨著時(shí)間的推移,慢慢旋轉(zhuǎn)到-15 度的位置
畫(huà)左半邊的進(jìn)度條
左半圓只設(shè)置上方和左邊的邊框顏色 html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle2-inner">div>
????????????div>
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle3-inner"?id="rightCicle">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle4-inner"?id="leftCicle">div>
????????????div>
????????div>
????div>
div>
css 代碼:
.cicle4-inner?{
????left:?0;
????border-left:?3px?solid?#feca02;
????border-top:?3px?solid?#feca02;
????transform:?rotate(195deg);
}
效果如下(為了演示,父節(jié)點(diǎn)為設(shè)置了 overflow: inherit;不裁剪,能更清楚來(lái)龍去脈):

為什么要旋轉(zhuǎn) 195 度?進(jìn)度條是從左邊開(kāi)始由無(wú)到有的,我們讓亮色進(jìn)度條旋轉(zhuǎn)到左邊灰色圓弧起始點(diǎn)的臨界點(diǎn)位置,隨著時(shí)間的推移增加旋轉(zhuǎn)角度。左邊進(jìn)度條要轉(zhuǎn) 120 度,所以左邊進(jìn)度條旋轉(zhuǎn)角度范圍:195 到 315 度 我們把父節(jié)點(diǎn)的 overflow 設(shè)置回原來(lái)的 hidden,對(duì)子節(jié)點(diǎn)超出的部分進(jìn)行裁剪。

what?裁剪之后還露出了一個(gè)小尾巴,如何把這個(gè)小尾巴給掩蓋掉?這時(shí)候我們需要在左邊再畫(huà)一個(gè)同心圓來(lái)遮蓋掉它
畫(huà)遮蓋圓
注意:遮罩圓邊框?qū)挾纫茸筮吜辽M(jìn)度條圓的邊框?qū)挾纫?,不然?huì)遮蓋不完全,會(huì)出現(xiàn)金色余暉,且要和亮色進(jìn)度條是同心圓 html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle2-inner">div>
????????????div>
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle3-inner"?id="rightCicle">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle4-inner"?id="leftCicle">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="mask-inner">div>
????????????div>
????????div>
????div>
div>
css 代碼(為了展示遮罩圓是完全覆蓋的,我把父節(jié)點(diǎn)的 overflow: inherit;不裁剪,圓的邊框顏色設(shè)置為藍(lán)色):
.mask-inner?{
????position:?absolute;
????left:?0;
????top:?0;
????width:?39px;
????height:?39px;
????//?border:?4px?solid?transparent;
????border:?4px?solid?blue;
????border-radius:?50%;
????//?border-left:?4px?solid?#FFFFFF;
????//?border-top:?4px?solid?#FFFFFF;
????//?transform:?rotate(195deg);
}

看,我們的遮罩圓已經(jīng)完全遮罩了其他圓,遮蓋圓和左邊進(jìn)度條圓一樣,都是旋轉(zhuǎn) 195 度,只設(shè)置上方和左邊的邊框顏色,邊框顏色是和底盤(pán)顏色一樣,我們把父節(jié)點(diǎn) overflow 設(shè)置為 hidden 裁剪 css 代碼:
.mask-inner?{
????position:?absolute;
????left:?0;
????top:?0;
????width:?39px;
????height:?39px;
????border:?4px?solid?transparent;
????border-radius:?50%;
????border-left:?4px?solid?blue;
????border-top:?4px?solid?blue;
????transform:?rotate(197deg);
}

藍(lán)色部分就是我們的小尾巴的位置,我們用白色替換藍(lán)色邊框
.mask-inner?{
????position:?absolute;
????left:?0;
????top:?0;
????width:?39px;
????height:?39px;
????border:?4px?solid?transparent;
????border-radius:?50%;
????border-left:?4px?solid?#FFFFFF;
????border-top:?4px?solid?#FFFFFFl
????transform:?rotate(197deg);
}
效果:

哇,看看,小尾巴已經(jīng)不見(jiàn)了。如果遮蓋圓和左邊亮色進(jìn)度條設(shè)置一樣的邊框大小,會(huì)出現(xiàn)金色邊

好吧,樣式方面已經(jīng)基本完成,其他點(diǎn)綴的樣式就不在這里列出了,可以看看下面的源碼。要讓進(jìn)度條動(dòng)起來(lái),需要通過(guò) js 來(lái)操作,js 里的源碼我已經(jīng)寫(xiě)了比較清楚的注釋,方便理解。html 代碼:
<div?class="task-container">
????<div?class="task-cicle">
????????<div?class="task-inner">
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle1-inner">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle2-inner">div>
????????????div>
????????????<div?class="right-cicle">
????????????????<div?class="cicle-progress?cicle3-inner"?id="rightCicle">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="cicle-progress?cicle4-inner"?id="leftCicle">div>
????????????div>
????????????<div?class="left-cicle">
????????????????<div?class="mask-inner">div>
????????????div>
????????????<div?class="inner">
????????????????<img?src="https://img12.360buyimg.com/img/jfs/t1/150018/30/1001/2042/5eec2f8eEfd3c853a/e7982308423ce71a.png"?alt=""?srcset="">
????????????????<div?class="water-count">10div>
????????????div>
????????div>
????????<div?class="task-bottom">
????????????<div?class="task-btn"?id="time">div>
????????div>
????div>
div>
<script>
????const?rightCicle?=?document.getElementById('rightCicle');
????const?leftCicle?=?document.getElementById('leftCicle');
????const?timeDom?=?document.getElementById('time');
????let?isStop?=?false;
????let?timer;
????const?totalTime?=?10;?//?總時(shí)間
????const?halfTime?=?totalTime?/?2;?//?總時(shí)間的一半
????const?initRightDeg?=?-135;?//?右半邊進(jìn)度條初始角度
????const?initLeftDeg?=?195;?//?左半邊進(jìn)度條初始角度
????const?halfCicle?=?120;?//?左右連邊各要轉(zhuǎn)的總角度
????const?perDeg?=?120?/?halfTime;?//?每秒轉(zhuǎn)的角度
????let?inittime?=?10;
????let?begTime;?//?倒計(jì)時(shí)開(kāi)始時(shí)間戳
????let?stopTime;?//?倒計(jì)時(shí)停止時(shí)間戳
????function?run()?{
????????const?time?=?inittime;
????????let?animation;
????????if?(time?>?halfTime)?{
????????????//?左半邊還沒(méi)轉(zhuǎn)完
????????????//?左半邊:動(dòng)畫(huà)的初始角度=左半邊進(jìn)度條初始角度+已經(jīng)轉(zhuǎn)的角度,最終角度=初始角度+120?度,動(dòng)畫(huà)持續(xù)時(shí)間=左半邊還剩需要轉(zhuǎn)的時(shí)間
????????????//?右半邊:動(dòng)畫(huà)的初始角度=右半邊進(jìn)度條初始角度,最終角度=初始角度+120?度,動(dòng)畫(huà)持續(xù)時(shí)間=一半的時(shí)間,動(dòng)畫(huà)延遲=左半邊還剩需要轉(zhuǎn)的時(shí)間
????????????animation?=?`
????????????????@keyframes?task-left?{
????????????????????0%?{
????????????????????????transform:?rotate(${initLeftDeg?+?(totalTime?-?time)?*?perDeg}deg);
????????????????????}
????????????????????100%?{
????????????????????????transform:?rotate(${initLeftDeg?+?halfCicle}deg);
????????????????????}
????????????????}
????????????????.task-left?{
????????????????????animation-name:?task-left;
????????????????????animation-duration:?${time?-?halfTime}s;
????????????????????animation-timing-function:?linear;
????????????????????animation-delay:?0s;
????????????????????animation-fill-mode:?forwards;
????????????????????animation-direction:?normal;
????????????????????animation-iteration-count:?1;
????????????????}
????????????????@keyframes?task-right?{
????????????????????0%?{
????????????????????????transform:?rotate(${initRightDeg}deg);
????????????????????}
????????????????????100%?{
????????????????????????transform:?rotate(${initRightDeg?+?halfCicle}deg);
????????????????????}
????????????????}
????????????????.task-right?{
????????????????????animation-name:?task-right;
????????????????????animation-duration:?${halfTime}s;
????????????????????animation-timing-function:?linear;
????????????????????animation-delay:?${time?-?halfTime}s;
????????????????????animation-fill-mode:?forwards;
????????????????????animation-direction:?normal;
????????????????????animation-iteration-count:?1;
????????????????}
????????????`;
????????}?else?{
????????????//?左半邊已經(jīng)轉(zhuǎn)完
????????????//?左半邊動(dòng)畫(huà):起始幀和重點(diǎn)幀都=左半邊進(jìn)度條初始角度+120?度
????????????//?右半邊動(dòng)畫(huà):動(dòng)畫(huà)的初始角度=右半邊進(jìn)度條初始角度+右半邊已經(jīng)角度,最終角度=初始角度+120?度,動(dòng)畫(huà)持續(xù)時(shí)間=剩余時(shí)間
????????????animation?=?`
????????????????@keyframes?task-left?{
????????????????????0%?{
????????????????????????transform:?rotate(${initLeftDeg?+?halfCicle}deg);
????????????????????}
????????????????????100%?{
????????????????????????transform:?rotate(${initLeftDeg?+?halfCicle}deg);
????????????????????}
????????????????}
????????????????.task-left?{
????????????????????animation-name:?task-left;
????????????????????animation-duration:?0s;
????????????????????animation-timing-function:?linear;
????????????????????animation-delay:?0s;
????????????????????animation-fill-mode:?forwards;
????????????????????animation-direction:?normal;
????????????????????animation-iteration-count:?1;
????????????????}
????????????????@keyframes?task-right?{
????????????????????0%?{
????????????????????????transform:?rotate(${initRightDeg?+?(halfTime?-?time)?*?perDeg}deg);
????????????????????}
????????????????????100%?{
????????????????????????transform:?rotate(${initRightDeg?+?halfCicle}deg);
????????????????????}
????????????????}
????????????????.task-right?{
????????????????????animation-name:?task-right;
????????????????????animation-duration:?${time}s;
????????????????????animation-timing-function:?linear;
????????????????????animation-delay:?0s;
????????????????????animation-fill-mode:?forwards;
????????????????????animation-direction:?normal;
????????????????????animation-iteration-count:?1;
????????????????}
????????????`;
????????}
????????//?增加動(dòng)畫(huà)暫停和開(kāi)始類
????????animation?+=?`.stop?{animation-play-state:?paused;}?.run?{animation-play-state:?running;}`
????????const?styleDom?=?document.createElement('style');
????????styleDom.type?=?'text/css';
????????styleDom.innerHTML?=?animation;
????????document.getElementsByTagName('head').item(0).appendChild(styleDom);
????????leftCicle.classList.add('task-left');
????????rightCicle.classList.add('task-right');
????????begTime?=?Date.now();
????????countDown();
????}
????function?countDown()?{
????????if?(begTime?&&?stopTime)?{
????????????//?從?1?秒到?1.6?秒后暫停,動(dòng)畫(huà)一直在走,而倒計(jì)時(shí)因?yàn)槲吹?2?秒,定時(shí)器就清除了,下次還是會(huì)從?1?開(kāi)始計(jì)時(shí),
????????????//?這就會(huì)導(dǎo)致倒計(jì)時(shí)和動(dòng)畫(huà)的不同步,之類稍微校正一下,如果結(jié)束時(shí)間和開(kāi)始時(shí)間取余數(shù)大于?500,就把倒計(jì)時(shí)-1?秒
????????????const?runtime?=?stopTime?-?begTime;
????????????console.log(runtime?%?1000);
????????????if?(runtime?%?1000?>?500)?{
????????????????inittime?-=?1;
????????????}
????????}
????????begTime?=?Date.now();
????????timeDom.innerText?=?`${inittime}秒后獲得?`;
????????timer?=?setInterval(()?=>?{
????????????inittime?-=?1;
????????????timeDom.innerText?=?`${inittime}秒后獲得?`;
????????????if?(inittime?<=?0)?{
????????????????clearInterval(timer);
????????????}
????????},?1000);
????}
????//?點(diǎn)擊可暫停倒計(jì)時(shí)和動(dòng)畫(huà)
????timeDom.addEventListener('click',?()?=>?{
????????if?(isStop)?{
????????????isStop?=?false;
????????????countDown();
????????????leftCicle.classList.remove('stop');
????????????leftCicle.classList.add('run');
????????????rightCicle.classList.remove('stop');
????????????rightCicle.classList.add('run');
????????}?else?{
????????????stopTime?=?Date.now();
????????????isStop?=?true;
????????????clearInterval(timer);
????????????leftCicle.classList.remove('run');
????????????leftCicle.classList.add('stop');
????????????rightCicle.classList.remove('run');
????????????rightCicle.classList.add('stop');
????????}
????},?false);
????run();
script>
css 代碼:
.task-container?{
????position:?fixed;
????left:?0;
????right:?0;
????top:?0;
????bottom:?0;
????margin:?auto;
????width:?65px;
????height:?65px;
????display:?flex;
????justify-content:?center;
????align-items:?center;
????.task-cicle?{
????????display:?flex;
????????justify-content:?center;
????????align-items:?center;
????????width:?53px;
????????height:?53px;
????????border-radius:?50%;
????????background:?#FFFFFF;
????????box-shadow:?0px?0px?12px?0px?rgba(0,?0,?0,?0.05);
????}
????.task-inner?{
????????position:?relative;
????????width:?46px;
????????height:?46px;
????}
????.right-cicle?{
????????width:?23px;
????????height:?46px;
????????position:?absolute;
????????top:?0;
????????right:?0;
????????overflow:?hidden;
????}
????.cicle-progress?{
????????position:?absolute;
????????top:?0;
????????width:?46px;
????????height:?46px;
????????border:?3px?solid?transparent;
????????box-sizing:?border-box;
????????border-radius:?50%;
????}
????.cicle1-inner?{
????????left:?-23px;
????????border-right:?3px?solid?#e0e0e0;
????????border-top:?3px?solid?#e0e0e0;
????????transform:?rotate(-15deg);
????}
????.left-cicle?{
????????width:?23px;
????????height:?46px;
????????position:?absolute;
????????top:?0;
????????left:?0;
????????overflow:?hidden;
????}
????.cicle2-inner?{
????????left:?0;
????????border-left:?3px?solid?#e0e0e0;
????????border-top:?3px?solid?#e0e0e0;
????????transform:?rotate(15deg);
????}
????.cicle3-inner?{
????????left:?-23px;
????????border-right:?3px?solid?#feca02;
????????border-top:?3px?solid?#feca02;
????????transform:?rotate(-135deg);
????}
????.cicle4-inner?{
????????left:?0;
????????border-left:?3px?solid?#feca02;
????????border-top:?3px?solid?#feca02;
????????transform:?rotate(195deg);
????}
????.mask-inner?{
????????position:?absolute;
????????left:?0;
????????top:?0;
????????width:?39px;
????????height:?39px;
????????border:?4px?solid?transparent;
????????border-radius:?50%;
????????border-left:?4px?solid?#FFFFFF;
????????border-top:?4px?solid?#FFFFFF;
????????transform:?rotate(195deg);
????}
????.inner?{
????????position:?absolute;
????????left:?0;
????????top:?-2px;
????????right:?0;
????????bottom:?0;
????????width:?22px;
????????height:?26px;
????????margin:?auto;
????????img?{
????????????width:?100%;
????????????height:?100%;
????????}
????}
????.water-count?{
????????position:?absolute;
????????top:?8px;
????????left:?50%;
????????transform:?translateX(-50%);
????????font-family:?"JDZhengHei-01-Regular";
????????font-size:?12px;
????????color:?#FFFFFF;
????}
????.task-bottom?{
????????display:?flex;
????????justify-content:?center;
????????align-items:?center;
????????position:?absolute;
????????width:?60px;
????????height:?15px;
????????left:?50%;
????????transform:?translateX(-50%);
????????bottom:?2px;
????}
????.task-btn?{
????????display:?flex;
????????justify-content:?center;
????????align-items:?center;
????????height:?15px;
????????border-radius:?7px;
????????background-image:?linear-gradient(-45deg,?#FEB402?0%,?#FF8407?100%);
????????font-size:?8px;
????????color:?#FFFFFF;
????????line-height:?15px;
????????padding:?0?4px;
????}
}
三、總結(jié)
淺色圓弧和亮色進(jìn)度條的實(shí)現(xiàn)比較繞,一眼看過(guò)去不太好理解,我們可以把每一步拆分開(kāi)。4 個(gè)圓弧的實(shí)現(xiàn),父節(jié)點(diǎn)都進(jìn)行了裁剪,裁剪之后很難看出子元素原本的樣子,我們可以先把裁剪去掉,看看未裁剪時(shí),各個(gè)圓的表現(xiàn)。


