狀圖在網頁中的運用極為普遍,比如簡單的統計圖表、進度指示器、定時器等,通常人們會用圖像處理軟件來制作,那么今天我們一起學習下如何通過純CSS的方法來實現任意比率的餅狀圖。
知識點: CSS線性漸變:linear-gradient; CSS動畫:@keyframes規則和animation引用;
1、固定比率(<=50%)的餅狀圖
首先我們制作一個綠色背景的圓形
HTML <div class="pie></div> CSS .pie{ width: 500px; height: 500px; background: yellowgreen; border-radius: 50%; }
如果我們打算用棕色(#655)來表示比率的話,那么需要先把上面圓形的一半設置為棕色,只需要一個簡單的線性漸變即可實現:
background-image: linear-gradient(to right, transparent 50%, #655 0);
接著我們通過設置偽元素的樣式(背景顏色與圓形背景顏色相相同:yellowgreen)將棕色部分進行遮蓋,添加代碼如下:
.pie::before{ content: ''; display: block; margin-left: 50%; height: 100%; background: yellowgreen; }
然后去掉矩形突出圓形的多余部分,可以給 .pie 設置 overflow: hidden,或是給偽元素指定合適的border-radius屬性來把它變成一個半圓。
pie::before{ content: ''; display: block; margin-left: 50%; height:100%; background:yellowgreen; border-radius:0 100% 100% 0/50%; }
最后,我們可以通過rotate()旋轉屬性讓這個偽元素轉起來,當然我們希望它是繞著圓形的中心來旋轉的,對他自己來說,這個旋轉中心就是它左邊緣的中心點,因此,可以把它的 transform-origin 設置為:0 50%,或者干脆寫成left也可以。如果我們要顯示出30%的比率,就可以指定其旋轉值為108deg(30% × 360=108)。
pie::before{ .content: ''; display: block; margin-left: 50%; height: 100%; background:yellowgreen; border-radius:0 100% 100% 0/50%; transform-origin: left; transform: rotate(108deg);
2、固定比率(>=50%)的餅狀圖
如果不加修改直接用上面的方法來制作比率大于50%的餅狀圖,你會發現一個明顯的bug,如下圖顯示60%的比率時所出現的問題,本該顯露的部分不但沒有顯示出來已有的部分反而被覆蓋了一部分。
要解決這個問題很簡單,將覆蓋層即偽元素部分的背景顏色修改為棕色(#655),在旋轉時只需旋轉大于50%的部分,如:要顯示60%的比率時只需要旋轉10%的度數36°即可
.pie::before{ content: ''; display: block; margin-left: 50%; height: 100%; background: #655; border-radius:0 100% 100% 0/50%; transform-origin: left; transform: rotate(36deg); }
3、比率從0到100%動態顯示
通過上面兩種方法我們已經可以實現任意比率的餅狀圖了,那么結合CSS的動畫屬性便可以實現一個餅狀圖從0變化到100%的動畫(也可以看做是一個進度指示器)。
@keyframes scoll{ to{transform: rotate(180deg);} } @keyframes bg{ 50%{background: #655;} } .pie::before{ content: ''; display: block; margin-left: 50%; height: 100%; border-radius:0 100% 100 0/50%; background: yellowgreen; animation: scoll 3s linear infinite, bg 6s step-end infinite; }
4、通過負的動畫延時實現任意比率的靜態餅狀圖
既然我們已經可以動態顯示從0到100%比率的餅狀圖,在此基礎上如果可以讓動畫根據需要定格在某一時刻,那么就不用再像方法1和方法2那樣區別對待50%前后的兩種情況了。這里我們可以用負的動畫延時來直接眺至動畫中的任意時間點,并通過暫停屬性paused把它定格在那里。
假設動畫持續時間為100s,那么只需要把animation-delay設置為-30s,就可以顯示出30%的比率了(如果是-60s就表示60%比率)。
.說明:
推薦指數:★★★★
通俗易懂,小白一看就會,高手請飄過。
學python也是需要懂一點Html、Css、JavaScript的基礎知識的。
建議使用vscode編輯器。
2.效果圖1
3.代碼:保存為html,用瀏覽器打開即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>圓形百分比進度條效果</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
.bg{
width: 200px;
height: 200px;
border-radius: 100%;
background: #ccc;
position: relative;
margin: 20px auto;
}
.circle-right, .circle-left, .mask-right, .mask-left{
width: 200px;
height: 200px;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
}
.circle-right, .circle-left{
background: skyblue;
}
.mask-right, .mask-left{
background: #ccc;
}
.circle-right, .mask-right{
clip: rect(0,200px,200px,100px);
}
.circle-left, .mask-left{
clip: rect(0,100px,200px,0);
}
.text{
width: 160px;
height: 160px;
line-height: 160px;
text-align: center;
font-size: 34px;
color: deepskyblue;
border-radius: 100%;
background: #fff;
position: absolute;
top: 20px;
left: 20px;
}
</style>
</head>
<body>
<div class="bg">
<div class="circle-right"></div>
<!--100%是顯示百分數,動態顯示由0~100-->
<div class="text">100%</div>
</div>
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
//獲取百分比值
var num=parseInt($('.text').html());
//通過計時器來顯示過渡的百分比進度
var temp=0;
var timer=setInterval(function(){
calculate(temp);
//清除計時器結束該方法調用
if(temp==num){
clearInterval(timer);
}
temp++;
},30)
//改變頁面顯示百分比
function calculate(value){
//改變頁面顯示的值
$('.text').html(value + '%');
//清除上次調用該方法殘留的效果
$('.circle-left').remove();
$('.mask-right').remove();
//當百分比小于等于50
if(value <=50){
var html='';
html +='<div class="mask-right" style="transform:rotate('+ (value * 3.6) +'deg)"></div>';
//元素里添加子元素
$('.circle-right').append(html);
}else{
value -=50;
var html='';
html +='<div class="circle-left">';
html +='<div class="mask-left" style="transform:rotate('+ (value * 3.6) +'deg)"></div>';
html +='</div>';
//元素后添加元素
$('.circle-right').after(html);
}
}
})
</script>
</body>
</html>
4.拆分法:把一個含有css和js(JavaScript)的html,拆掉三個文件,一個叫cirbar1.html,另外的叫:cirbar1.css和cirbar1.js文件,放在同一個文件夾內。這是./的意思,也可以指定文件夾。
4.1 cirbar1.html的代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>圓形百分比進度條效果v2</title>
<!--如果是style type="text/css"這種直接在html中設置css,注意起始是*,不是點-->
<!--style type="text/css"-->
<link href="./cirbar1.css" rel="stylesheet" />
</head>
<body>
<div class="bg">
<div class="circle-right"></div>
<div class="text">100%</div>
</div>
<!--這個外部js文件=jquery.min.js,不能少,否則不能動了-->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"--></script>
<!--同樣的,把寫在html的js,新建一個cirbar1.js,復制下去,保存,這樣子簡潔很多-->
<!--script type="text/javascript"-->
<script src="./cirbar1.js"></script>
</body>
</html>
4.2 cirbar1.css的代碼:
*{
margin: 0;
padding: 0;
}
.bg{
width: 200px;
height: 200px;
border-radius: 100%;
background: #ccc;
position: relative;
margin: 20px auto;
}
.circle-right, .circle-left, .mask-right, .mask-left{
width: 200px;
height: 200px;
border-radius: 100%;
position: absolute;
top: 0;
left: 0;
}
.circle-right, .circle-left{
background: skyblue;
}
.mask-right, .mask-left{
background: #ccc;
}
.circle-right, .mask-right{
clip: rect(0,200px,200px,100px);
}
.circle-left, .mask-left{
clip: rect(0,100px,200px,0);
}
.text{
width: 160px;
height: 160px;
line-height: 160px;
text-align: center;
font-size: 34px;
color: deepskyblue;
border-radius: 100%;
background: #fff;
position: absolute;
top: 20px;
left: 20px;
}
4.3 cirbar1.js的代碼:
$(function(){
//獲取百分比值
var num=parseInt($('.text').html());
//通過計時器來顯示過渡的百分比進度
var temp=0;
var timer=setInterval(function(){
calculate(temp);
//清除計時器結束該方法調用
if(temp==num){
clearInterval(timer);
}
temp++;
},30)
//改變頁面顯示百分比
function calculate(value){
//改變頁面顯示的值
$('.text').html(value + '%');
//清除上次調用該方法殘留的效果
$('.circle-left').remove();
$('.mask-right').remove();
//當百分比小于等于50
if(value <=50){
var html='';
html +='<div class="mask-right" style="transform:rotate('+ (value * 3.6) +'deg)"></div>';
//元素里添加子元素
$('.circle-right').append(html);
}else{
value -=50;
var html='';
html +='<div class="circle-left">';
html +='<div class="mask-left" style="transform:rotate('+ (value * 3.6) +'deg)"></div>';
html +='</div>';
//元素后添加元素
$('.circle-right').after(html);
}
}
})
==============================
再來一個,不用外部js文件的圓形進度條
順帶回顧一下相關知識。
==============================
5.效果圖
6.三個文件,放在同一個文件夾中
6.1 cirbar.html代碼:
<!--第1步---聲明html5-->
<!DOCTYPE html>
<!--第2步---html大框架-->
<html lang="en">
<!--第2-1步---head部分-->
<head>
<!--第2-1-1步---meta部分:聲明字符編碼格式:utf-8-->
<!--注意與python的第一行聲明一樣:# -*- coding: utf-8 -*-->
<meta charset="utf-8" />
<!--第2-1-2步---標題名稱-->
<title>圓形進度條v1</title>
<!--注意:./代表同一個文件夾下,也就是css和js文件與本html文件放在同一個文件夾下-->
<!--第2-1-3步---導入css文件-->
<link href="./cirbar.css" rel="stylesheet" />
</head>
<!--第2-2步---body部分-->
<body>
<!--第2-2-1步---定義畫布部分,注意沒有逗號隔開,大小設置-->
<canvas class="canvas" id="canvas" width="400" height="400"></canvas>
<!--第2-2-2步---導入js文件部分-->
<script src="./cirbar.js"></script>
<!--注意收尾-->
</body>
<!--注意收尾-->
</html>
6.2 cirbar.css代碼:
.canvas {
/*畫布的背景顏色設置為:黑色*/
background:#303030;
}
6.3 cirbar.js代碼:
window.onload=function () {
var canvas=document.getElementById('canvas'), //獲取canvas元素
context=canvas.getContext('2d'), //獲取畫圖環境,指明為2d
centerX=canvas.width / 2, //Canvas中心點x軸坐標
centerY=canvas.height / 2, //Canvas中心點y軸坐標
rad=Math.PI * 2 / 100, //將360度分成100份,那么每一份就是rad度
speed=0.1; //加載的快慢就靠它了
//繪制紅色外圈
function blueCircle(n) {
context.save();
context.strokeStyle=" #1E90FF"; //隨百分數轉動的外圈的顏色為藍色
context.lineWidth=3; //設置線寬
context.beginPath(); //路徑開始
//注意-為順時針,+為逆時針
//用于繪制圓弧context.arc(x坐標,y坐標,半徑,起始角度,終止角度,順時針/逆時針)
//context.arc(centerX, centerY, 50, Math.PI / 2, Math.PI / 2 - n * rad, false);
context.arc(centerX, centerY, 50, -Math.PI / 2, -(Math.PI / 2 - n * rad), false);
context.stroke(); //繪制
context.closePath(); //路徑結束
context.restore();
}
//繪制白色外圈,初始的白色外圈
function whiteCircle() {
context.save();
context.beginPath();
// 下面百分數的字體顏色設置后上面的外圈的顏色竟然保持一樣
//context.strokeStyle="#F8F8FF";
context.arc(centerX, centerY, 50, 0, Math.PI * 2, false);
context.stroke();
context.closePath();
context.restore();
}
//百分比文字繪制
function text(n) {
context.save(); //save和restore可以保證樣式屬性只運用于該段canvas元素
context.strokeStyle="#7FFF00";//設置中間動態百分數的顏色
context.font="25px Arial"; //設置字體大小和字體
context.textAlign='center';//字體水平居中
context.textBaseline='middle';//字體垂直居中
//繪制字體,并且指定位置
context.strokeText(n.toFixed(0) + "%", centerX, centerY);
context.stroke(); //執行繪制
context.restore();
}
//循環獲取
(function drawFrame() {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
whiteCircle();
text(speed);
blueCircle(speed);
if (speed < 100) {
//1可從后臺獲取值,也是從0~100,step為1,代表速度
speed +=1;
}
}());
}
注意到6.3js文件與4.3js文件的區別了么?一個有:window.onload=,一個沒有,且只有$和小括號,因為外部的就是文件定義了一部分功能。
.說明:
推薦指數:★★★★
通過動畫太極的方法,增加學習興趣,對html的結構和css、JavaScript、div的認識和了解會逐步深入。
2.復習html的結構框架
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>html結構基本框架代碼</title>
</head>
<body>
</body>
</html>
3 div法
3.1 代碼:復制下面的代碼,命名為:div法.html,用瀏覽器打開即可。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>div法的旋轉的太極圖</title>
</head>
<!--單獨style,不在head和body,只是在body內有一個div容器-->
<style>
div{
width: 0;
/*這個高就是黑色圓形和白色圓形的直徑和*/
height: 200px;
/*黑色太極部分的圈帶動的黑色的陰影*/
border-left: 100px solid black;
/*白色太極部分的圈帶動的白色的陰影*/
border-right: 100px solid #fff;
box-shadow: 0 0 15px rgba(0,0,0,.5);
/*旋轉半徑100*/
border-radius: 100px;
/*旋轉速度定義,越小越快*/
-webkit-animation:rotation 2.5s linear infinite;
}
div:before{
content: "";
position: absolute;
height: 100px;
z-index: 1;
border-radius: 100px;
/*白色的小半圓*/
border-left: 50px solid #fff;
border-right: 50px solid #fff;
left: -50px;
/*黑色的小半圓,因為轉動拖動黑色陰影*/
box-shadow: 0 100px 0 black;
}
div:after{
content: "";
position: absolute;
/*height是太極里面小圓圈的高30,要和border-radius30一致,才畫出圓*/
height: 30px;
/*這個是顯示小圓圈的,0就是不顯示*/
z-index: 1;
border-radius: 30px;
border-left: 15px solid;
border-right: 15px solid;
/*top和left,決定小圓圈白色和黑色的位置*/
top: 40px;
left: -15px;
/*黑色太極部分里面的小白色圓圈*/
box-shadow: 0 100px 0 white;
}
/*旋轉角度函數定義*/
@-webkit-keyframes rotation {
0% {-webkit-transform:rotate(0deg);}
100% {-webkit-transform:rotate(-360deg);}
}
</style>
<body>
<div></div>
</body>
</html>
3.2 效果圖
4 css法
4.1 css法.html代碼
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>css法的旋轉的太極圖</title>
<!--css導入和js導入不一樣,請注意-->
<!--script-- src="./tj.css"></!--script-->
<link rel="stylesheet" type="text/css" href="./tj.css">
</head>
<body>
<div class="tj"></div>
</body>
</html>
4.2 tj.css代碼:注意與上面兩個文件放在同一個文件夾下
.tj{
width: 100px;
height: 200px;
border: solid black;
border-width: 2px 100px 2px 2px;
background-color: #fff;
border-radius: 50%;
position: absolute;
/*run是動起來的函數,在最后面設置和定義*/
animation: run 2s linear infinite;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.tj:before{
content: " ";
position: absolute;
width: 28px;
height: 28px;
background-color: black;
/*36=(100-28)/2得到的,是小白色圓圈的半徑*/
border: 36px #ffffff solid;
border-radius: 50%;
top: 0;
left: 50%;
}
.tj:after{
content: " ";
position: absolute;
width: 28px;
height: 28px;
background-color: #ffffff;
/*36=(100-28)/2得到的,是小黑色圓圈的半徑*/
border: 36px black solid;
border-radius: 50%;
top: 50%;
left: 50%;
}
/*run動起來的函數定義*/
@keyframes run{
0%{
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
4.3 效果圖
5 js法=就是JavaScript法
5.1 js法.html代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>js法的旋轉的太極圖</title>
<!--注意下面2鐘都可以,主要是瀏覽器都支持html5-->
<!--script-- src="script.js" type="text/javascript"></!--script-->
<script src="./script.js"></script>
<!--簡單的css內容就這樣寫在下面,如果css比較復雜,則需要外部導入-->
<style type="text/css">
canvas{
display: block;
margin: 20px auto;
}
</style>
</head>
<body onload="main()">
<!--畫布大小,畫布框的線顏色藍色設置,solid blue是指畫布外框的顏色為藍色-->
<canvas width="300" height="300" id="canvas"style="border:1px solid blue"></canvas>
</body>
</html>
5.2 script.js代碼:與上面html放在同一個文件夾下
//注意到沒有null=0,效果是一樣的
var angle=0;
//var canvas=null;
//var ctx=null;
var canvas=0;
var ctx=0;
function main()
{
window.setInterval(function()
{
canvas=document.getElementById("canvas");
ctx=canvas.getContext("2d");
// 畫布大小有關
ctx.clearRect(0, 0, 300, 300);
// 線條寬度0~10,均可
ctx.lineWidth=0;
ctx.save();
// 旋轉的中心點的坐標位置150,150
ctx.translate(150,150);
ctx.rotate(angle);
// 太極黑色部分
ctx.fillStyle="black";
ctx.beginPath();
// 注意幾個函數數值的關系,120,60,半徑和坐標的關系,如果要縮小半徑,那么坐標也需要調整
ctx.arc(0, 0, 120, 0, Math.PI, true);
ctx.fill();
ctx.closePath();
// 太極白色部分
ctx.fillStyle="white";
ctx.beginPath();
ctx.arc(0, 0, 120, 0, Math.PI, false);
ctx.fill();
ctx.closePath();
// 太極黑色部分
ctx.fillStyle="black";
ctx.beginPath();
ctx.arc(60, -0.6, 60, 0, Math.PI, false);
ctx.fill();
ctx.closePath();
// 太極白色部分
ctx.fillStyle="white";
ctx.lineWidth=0;
ctx.beginPath();
ctx.arc(-60, 0, 60, 0, Math.PI, true);
ctx.fill();
ctx.closePath();
// 白色太極部分里面的小黑色圓圈
ctx.fillStyle="black";
ctx.beginPath();
//畫圓的函數:-145,0是坐標,15是半徑,2*Math.PI是一個圓,一個π是半圓
ctx.arc(-60, 0, 15, 0, 2*Math.PI, false);
ctx.fill();
ctx.closePath();
// 黑色太極部分里面的小白色圓圈
ctx.fillStyle="white";
ctx.beginPath();
ctx.arc(60, 0, 15, 0, 2*Math.PI, false);
ctx.fill();
ctx.closePath();
// 旋轉角度一次增加多少
ctx.restore();
angle +=0.02;
// 50代表轉速,越大越慢,越小越快
},1);
}
5.3 效果圖
6 值得收藏,慢慢回味。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。