Step by step刹前!css3泳赋、svg 畫圓形漸變圓角進(jìn)度條

css3

首先擺上那個(gè)灰色的圈



然后蓋上一個(gè)藍(lán)色的半圈(由一半的藍(lán)色和一半的透明border組成)



讓它轉(zhuǎn)起來
這就像進(jìn)度為百分之五十的時(shí)候的樣子

把右邊給他遮住,這樣他還沒到百分之五十的時(shí)候喇喉,右邊不會(huì)出現(xiàn)這個(gè)半圓的一個(gè)部分



動(dòng)起來是這樣的


左邊.gif

然后右邊我們?nèi)绶ㄅ谥埔粋€(gè)祖今,這樣整個(gè)圓就實(shí)現(xiàn)了
完整效果
<template>
    <div class="processCircle">
            <div class="grayCircle center">
                <p>{{ percent }}%</p>
            </div>
            <section class="half left">
                <div class="blueCircle"></div>
            </section>
            <section class="half right">
                <div class="blueCircle"></div>
            </section>
    </div>
</template>
<script>
export default {
    name: 'processCircle',
    data() {
        return {
            percent: 1,
            timeLimit: 5000
        };
    },
    created() {
        let gap = this.timeLimit / 100;
        let clock = setInterval(() => {
            if (this.percent < 99) {
                let res = Math.floor(this.percent + 4);
                this.percent = res >= 99 ? 99 : res;
                if (this.percent > 40) {
                    gap = 0.5;
                }
            } else {
                clearInterval(clock);
            }
        }, 100);
    }
};
</script>
<style lang="scss">
.processCircle {
    $maxl: 110px;
    position: relative;
    width: $maxl;
    height: $maxl;
    display: flex;
    align-items: flex-end;
    .half {
        width: 51%;
        height: 100%;
        overflow: hidden;
        position: absolute;
        top: 0;
    }
    .center {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        display: flex;
        p {
            text-align: center;
            margin: auto;
            color: #384369;
            font-size: 18px;
            font-family: fzlt_bold;
        }
    }
    @mixin circle($w) {
        width: $w;
        height: $w;
        $wh: $w / 2;
        border-radius: $wh;
    }
    .grayCircle {
        @include circle(106px);
        border: 0;
        border: 6px solid #f4f4f4;
    }
    .blueCircle {
        // border-image: linear-gradient(to right, #90b2ff, #6d91ff) 1 10;
        @include circle($maxl);
        border: 10px solid transparent;
    }
    .left {
        left: 0;
        .blueCircle {
            border-top: 10px solid #6d91ff;
            border-left: 10px solid #6d91ff;
            transform: rotate(135deg);
            animation: load_left 2s ease-in;
            animation-fill-mode: forwards;
        }
    }
    .right {
        right: 0;
        .blueCircle {
            transform: rotate(135deg);
            position: relative;
            left: -$maxl / 2;
            animation: load_right 3s ease-in;
            animation-fill-mode: forwards;
        }
    }

    @-webkit-keyframes load_left {
        0% {
            border-top: 10px solid #6d91ff;
            border-left: 10px solid #6d91ff;
            transform: rotate(150deg);
        }
        50% {
            border-top: 10px solid #6d91ff;
            border-left: 10px solid #6d91ff;
            transform: rotate(315deg);
        }
        100% {
            border-top: 10px solid #6d91ff;
            border-left: 10px solid #6d91ff;
            transform: rotate(315deg);
        }
    }
    @-webkit-keyframes load_right {
        0% {
            transform: rotate(135deg);
        }
        50% {
            border-bottom: 10px solid #90b2ff;
            border-right: 10px solid #90b2ff;
            transform: rotate(135deg);
        }
        100% {
            border-bottom: 10px solid #6d91ff;
            border-right: 10px solid #6d91ff;
            transform: rotate(312deg);
        }
    }
    .success {
        width: 90px;
        height: 90px;
        position: relative;
        margin: 0 auto;
        img {
            width: 100%;
            height: auto;
        }
    }
}
</style>

最終

!!
但是這個(gè)效果和最終設(shè)想的差別有比較大的距離。如果使用這個(gè)方案是做不出漸變色和圓角的效果的拣技。

svg


只要去學(xué)習(xí)一下svg的圓和漸變千诬,就能很容易地做出來這個(gè)效果。
所以在這里簡單說一下動(dòng)畫的原理膏斤。
circle標(biāo)簽上支持兩個(gè)屬性大渤,stroke-dashoffsetstroke-dasharray

stroke-dashoffset 屬性指定了dash模式到路徑開始的距離
如果使用了一個(gè) <百分比> 值掸绞, 那么這個(gè)值就代表了當(dāng)前viewport的一個(gè)百分比泵三。
屬性stroke-dasharray可控制用來描邊的點(diǎn)劃線的圖案范式。
作為一個(gè)外觀屬性衔掸,它也可以直接用作一個(gè)CSS樣式表內(nèi)部的屬性烫幕。

噫,老實(shí)說沒看懂這兩個(gè)參數(shù)到底是干啥的敞映。動(dòng)手試一下這兩個(gè)屬性较曼。

控制變量法:
  1. 我的圓周長大約為314。
    此時(shí)設(shè)置
    stroke-dashoffset: 0;
    stroke-dasharray: 314;

則圓為這樣


  1. 設(shè)置
    stroke-dashoffset: 0;
    stroke-dasharray: 298;

合理地猜測振愿,stroke-dasharray的改變可以變更軌跡的樣子捷犹。
其實(shí)如果把這個(gè)值變小弛饭,這個(gè)外圍就是虛線,所以僅僅靠變更這個(gè)值去實(shí)現(xiàn)連續(xù)的藍(lán)色弧線是行不通的萍歉。


  1. 變更stroke-dashoffset
    stroke-dashoffset: 314;
    stroke-dasharray: 314;

如果這兩值相等侣颂,則藍(lán)色的部分就消失了。

    stroke-dashoffset: 100;
    stroke-dasharray: 314;


終上所述枪孩,設(shè)置 stroke-dasharray為圓周長憔晒,讓stroke-dashoffset從大到小變化,則動(dòng)畫就會(huì)從缺到完整那么去動(dòng)蔑舞。

我這里設(shè)置了最終為有缺口的99%狀態(tài)拒担,效果及源碼如下:


最終效果

完整代碼如下

// progressBar.vue
<template>
    <div class="loadingContainer">
        <svg
            :width="progressBarParams.boxWidth"
            :height="progressBarParams.boxHeight"
            :VIEWBOX="
                '0 0 ' +
                    progressBarParams.boxWidth +
                    ' ' +
                    progressBarParams.boxHeight
            "
            id="svg"
        >
            <defs>
                <linearGradient id="cirGradient">
                    <stop
                        offset="0%"
                        :stop-color="progressBarParams.frontColor"
                    />
                    <stop
                        offset="100%"
                        :stop-color="progressBarParams.endColor"
                    />
                </linearGradient>
            </defs>
            <circle
                :cx="progressBarParams.boxWidth / 2"
                :cy="progressBarParams.boxHeight / 2"
                :r="progressBarParams.raduis"
                :stroke="progressBarParams.innerClcColor"
                :stroke-width="progressBarParams.innerClcWidth"
                fill="none"
                stroke-linecap="round"
            />
            <circle
                id="clc"
                class="loadingProcess"
                :cx="progressBarParams.boxWidth / 2"
                :cy="progressBarParams.boxHeight / 2"
                :r="progressBarParams.raduis"
                stroke="url(#cirGradient)"
                :stroke-width="progressBarParams.outerClcWidth"
                fill="none"
                stroke-linecap="round"
            />
        </svg>
        <div id="loadingPercent">
            <span>{{ percent }}</span
            ><span style="font-size:14px;">%</span>
        </div>
    </div>
</template>
<script>
export default {
    props: {
        progressBarParams: Object
    },
    data() {
        return {
            offset: 0,
            percent: 0,
            strokeDasharray: 0
        };
    },
    created() {
        let gap = 3;
        let clock = setInterval(() => {
            if (this.percent < 99) {
                let res = Math.floor(this.percent + gap);
                this.percent = res >= 99 ? 99 : res;
                if (this.percent > 50) {
                    gap = 2;
                }
                if (this.percent > 80) {
                    gap = 1.5;
                }
            } else {
                clearInterval(clock);
            }
        }, 100);
    },
    methods: {}
};
</script>

<style lang="scss" scoped>
.loadingContainer {
    position: relative;
    width: 100%;
    height: 110px;
    font-size: 12px;
    display: flex;
}
.loadingContainer span {
    font-size: 18px;
    font-weight: bold;
}
.loadingContainer > svg {
    margin: 0 auto;
}
#loadingPercent {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    font-family: fzlt_bold;
    font-size: 18px;
    color: #384369;
    margin-left: 3px;
    margin-top: 1px;
}
$perimter: 314;
$percent: 1;
.loadingProcess {
    transform-origin: center;
    animation: task 5s ease-in;
    animation-fill-mode: forwards;
    // stroke-dashoffset: ((100 - $percent) / 100) * $perimter;
    // stroke-dasharray: $perimter;
    transform: rotate(95deg);
}
@-webkit-keyframes task {
    0% {
        $percent: 2;
        stroke-dashoffset: ((100 - $percent) / 100) * $perimter;
        stroke-dasharray: $perimter;
    }
    20% {
        $percent: 30;
        stroke-dashoffset: ((100 - $percent) / 100) * $perimter;
        stroke-dasharray: $perimter;
    }
    50% {
        $percent: 60;
        stroke-dashoffset: ((100 - $percent) / 100) * $perimter;
        stroke-dasharray: $perimter;
    }
    90% {
        $percent: 80;
        stroke-dashoffset: ((100 - $percent) / 100) * $perimter;
        stroke-dasharray: $perimter;
    }
    100% {
        // $percent: 93;
        stroke-dashoffset: 32;
        stroke-dasharray: 329;
    }
}
</style>

// 使用
<progress-bar
            v-if="status === 'loading'"
            v-bind:progressBarParams="progressBarParams"
        ></progress-bar>
<script>
import progressBar from './progressBar';

export default {
    name: 'processCircle',
    components: {
        progressBar
    },
    props: {
        status: {
            type: String,
            default: 'loading'
        }
    },
    data() {
        return {
            percent: 1,
            timeLimit: 5000,
            progressBarParams: {
                boxWidth: '110',
                boxHeight: '110',
                raduis: '50',
                innerClcWidth: '6',
                outerClcWidth: '10',
                frontColor: '#90B2FF',
                endColor: '#6D91FF',
                innerClcColor: '#F4F4F4',
                fastDurTime: 100,
                slowDurTime: 1000
            }
        };
    },
}
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市攻询,隨后出現(xiàn)的幾起案子从撼,更是在濱河造成了極大的恐慌,老刑警劉巖钧栖,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件低零,死亡現(xiàn)場離奇詭異,居然都是意外死亡桐经,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門浙滤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阴挣,“玉大人,你說我怎么就攤上這事纺腊∨线郑” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵揖膜,是天一觀的道長誓沸。 經(jīng)常有香客問我,道長壹粟,這世上最難降的妖魔是什么拜隧? 我笑而不...
    開封第一講書人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮趁仙,結(jié)果婚禮上洪添,老公的妹妹穿的比我還像新娘。我一直安慰自己雀费,他們只是感情好干奢,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盏袄,像睡著了一般忿峻。 火紅的嫁衣襯著肌膚如雪薄啥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評(píng)論 1 312
  • 那天逛尚,我揣著相機(jī)與錄音垄惧,去河邊找鬼。 笑死黑低,一個(gè)胖子當(dāng)著我的面吹牛赘艳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播克握,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蕾管,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了菩暗?” 一聲冷哼從身側(cè)響起掰曾,我...
    開封第一講書人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎停团,沒想到半個(gè)月后旷坦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佑稠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年秒梅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舌胶。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡捆蜀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幔嫂,到底是詐尸還是另有隱情辆它,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布履恩,位于F島的核電站锰茉,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏切心。R本人自食惡果不足惜飒筑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绽昏。 院中可真熱鬧扬霜,春花似錦、人聲如沸而涉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啼县。三九已至材原,卻和暖如春沸久,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背余蟹。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來泰國打工卷胯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人威酒。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓窑睁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親葵孤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子担钮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361