摘要:先上效果圖這種圖形大家應(yīng)該都見過,俗稱儀表盤,當(dāng)然,上圖只是個(gè)最基本的儀表盤架子,可能在實(shí)際場景中還會(huì)其他很多花里胡哨的點(diǎn)綴,那些暫且不管,不是關(guān)鍵,這東西經(jīng)常見到,但還沒親自上手在代碼層面實(shí)現(xiàn)過,最近做的一個(gè)需求恰好有這個(gè)場景,這里歸
先上效果圖:
這種圖形大家應(yīng)該都見過,俗稱儀表盤,當(dāng)然,上圖只是個(gè)最基本的儀表盤架子,可能在實(shí)際場景中還會(huì)其他很多花里胡哨的點(diǎn)綴,那些暫且不管,不是關(guān)鍵,這東西經(jīng)常見到,但還沒親自上手在代碼層面實(shí)現(xiàn)過,最近做的一個(gè)需求恰好有這個(gè)場景,這里歸納一下
canvas實(shí)現(xiàn)大部分情況下,對于這種偏可視化的元素,一般都選擇使用 canvas來進(jìn)行繪制,現(xiàn)在已經(jīng) 9120年了,線上使用 canvas完全沒問題
儀表盤整體是一個(gè)復(fù)雜圖形,而復(fù)雜圖形是由簡單圖形組合而成,只要把所有組成這個(gè)儀表盤的簡單圖形繪制出來,再進(jìn)行組合,整個(gè)儀表盤自然也就繪制出來了
所以,首先對儀表盤進(jìn)行分解,分解成 canvas能繪制出的基本圖形,其主體其實(shí)就兩個(gè)圓弧,一個(gè)是底部藍(lán)色的半圓軌道,一個(gè)是代表進(jìn)度的紅色圓弧,其實(shí)都是圓弧,canvas剛好有繪制圓弧的能力,即:
ctx.arc
至于動(dòng)態(tài)繪制,只需要配合 requestAnimationFrame即可
const trackW = 6
const rx = 500
const ry = 500
const radius = 400
const innerLineW = 20
const canvas = document.getElementById(canvas)
const ctx = canvas.getContext(2d)
function draw (toAngle, currentAngle = Math.PI) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
// 半圓軌道
ctx.beginPath()
ctx.strokeStyle = #ad80fc
ctx.lineWidth = trackW
ctx.arc(rx, ry, radius, Math.PI, 0, false)
ctx.stroke()
// 圓弧
ctx.beginPath()
ctx.lineCap = round
ctx.strokeStyle = #fe4d55
ctx.lineWidth = innerLineW
ctx.arc(rx, ry, radius, Math.PI, currentAngle, false)
ctx.stroke()
if (currentAngle < toAngle) {
currentAngle += 0.02
if (currentAngle > toAngle) currentAngle = toAngle
requestAnimationFrame(() => {
draw(toAngle, currentAngle)
})
}
}
draw(1.5 * Math.PI)
加上變量定義,花括號(hào)等幾十行代碼即可完成,由此可見,canvas繪圖還是很方便的,所以在可視化領(lǐng)域,例如一些庫或者UI組件基本上都是以canvas進(jìn)行構(gòu)建
css繪制canvas實(shí)質(zhì)上就是借助 js操縱瀏覽器 API進(jìn)行渲染,然而 UI渲染這種事情本應(yīng)該交給 CSS來做才是,感覺用 js直接畫多影響性能啊(實(shí)際上并不),哪有 css來的流暢,實(shí)際上,css完全可以做到
從 css的角度對儀表盤進(jìn)行分解,同樣還是兩個(gè)圓弧,通過設(shè)置 border-radius屬性即可讓元素呈現(xiàn)整圓效果,然后再用一個(gè)矩形元素進(jìn)行遮罩,決定展現(xiàn)出來的部分,即為圓弧,通過控制遮罩的面積來呈現(xiàn)動(dòng)態(tài)繪制的效果
<div class="arc-wrapper">
<p class="track-arc">p>
<div class="round-box">
<p class="round">p>
div>
div>
:root {
--arcRadius: 200px;
--rectWidth: calc(var(--arcRadius) * 2);
--trackWidth: 4px;
--roundWidth: 10px;
}
.arc-wrapper {
position: relative;
margin: 0 auto;
width: var(--rectWidth);
height: var(--arcRadius);
overflow: hidden;
background-color: pink;
}
.track-arc {
width: 100%;
height: var(--rectWidth);
box-sizing: border-box;
border-radius: 50%;
border: var(--trackWidth) solid #ad80fc;
}
.round-box {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: hidden;
transform-origin: 50% 100%;
transform: rotate(-45deg);
z-index: 20;
}
.round {
width: 100%;
height: var(--rectWidth);
box-sizing: border-box;
border-radius: 50%;
border: var(--roundWidth) solid #fe4d55;
}
其實(shí)沒多少代碼,也沒什么難以理解的,只不過效果似乎微調(diào):
由于圓弧的線是存在寬度的,并不是數(shù)學(xué)意義上的可以忽略,canvas繪制圓弧,是根據(jù)圓心坐標(biāo)和半徑進(jìn)行繪制的,繪制出來的圓弧會(huì)自動(dòng)根據(jù)圓弧 line的寬度進(jìn)行調(diào)整,即圓弧的半徑是圓弧線的中心位置與圓心坐標(biāo)距離
而通過 css繪制的圓弧,此圓弧的半徑則是圓弧最外層邊線與圓心的坐標(biāo)距離:
知道了問題其實(shí)就好解決了,只要縮減軌道半圓的半徑,并對其進(jìn)行一定的偏移即可:
.track-arc {
--trackArcSize: calc(var(--rectWidth) - var(--roundWidth) + var(--trackWidth));
/* 尺寸改變 */
width: var(--trackArcSize);
height: var(--trackArcSize);
box-sizing: border-box;
border-radius: 50%;
border: var(--trackWidth) solid #ad80fc;
/* 位置偏移 */
transform: translate(calc(var(--roundWidth) / 2 - var(--trackWidth) / 2), calc(var(--roundWidth) / 2 - var(--trackWidth) / 2));
}
然后就順眼多了:
然而,還有個(gè)問題,一般為了呈現(xiàn)更加圓潤的效果,設(shè)計(jì)稿上圓弧的斷點(diǎn)處一般都是圓頭:
而上述呈現(xiàn)出來的效果是直接截?cái)嗟模?/p>
一般人之所以不使用 css來繪制儀表盤,基本都是因?yàn)檫@個(gè)原因,canvas簡簡單單通過設(shè)置一個(gè) ctx.lineCap = round就能解決的問題。似乎 css無解了
乍一看好像確實(shí)沒什么好辦法,但稍微思考下,這不就是一個(gè)圓角嗎,完全在css能力范圍內(nèi)啊,只不過實(shí)現(xiàn)的方式不太那么直接罷了
方法很簡單,就是使用一個(gè)圓角矩形覆蓋在圓弧的頂端,將圓弧本身的矩形頂端覆蓋住,圓角矩形當(dāng)做是圓弧的頂端,這樣視覺上看起來不就是圓頭了嗎
<div class="round-box">
<p class="round">p>
<p class="dot-r-box">
<span class="dot-r">span>
p>
div>
.dot-r-box {
position: absolute;
right: 0;
bottom: 0;
width: var(--roundWidth);
height: var(--dotHeight);
background-color: var(--backColor);
}
.dot-r {
display: inline-block;
width: 100%;
height: 100%;
/* 這里的100px只是為了呈現(xiàn)出最大限度的圓角 */
border-bottom-left-radius: 100px;
border-bottom-right-radius: 100px;
background-color: var(--roundColor);
}
效果如下:
圓角頂端 get
同樣的,圓弧左邊的頂端也可以這么做
不過左邊這個(gè)頂端有個(gè)稍微需要注意的地方,因?yàn)槠浯嬖诘哪康氖菫榱水?dāng)做圓弧的左斷點(diǎn),但是當(dāng)進(jìn)度為 0的時(shí)候,圓弧應(yīng)該是完全不展現(xiàn)的,或者當(dāng)進(jìn)度很小的時(shí)候,圓弧應(yīng)該展現(xiàn)的長度還沒有 dot-l的高度大,這樣就露餡了:
不過呢轉(zhuǎn)而又一想,一般實(shí)際場景中,就算進(jìn)度為 0,我們其實(shí)為了看起來更符合常識(shí)直覺,也會(huì)讓圓弧展現(xiàn)一點(diǎn)點(diǎn)出來,只要 dot-l的高度不是太大,或者說只要圓弧的寬度不要太寬,其實(shí)預(yù)留的這點(diǎn)圓弧完全就可以 cover住了,不至于露餡
小結(jié)css的新特性 var 和 calc還挺好用的嘛
本文示例的 Live Demo已經(jīng)上傳,感興趣的可以親自試下
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/7088.html
摘要:先上效果圖這種圖形大家應(yīng)該都見過,俗稱儀表盤,當(dāng)然,上圖只是個(gè)最基本的儀表盤架子,可能在實(shí)際場景中還會(huì)其他很多花里胡哨的點(diǎn)綴,那些暫且不管,不是關(guān)鍵,這東西經(jīng)常見到,但還沒親自上手在代碼層面實(shí)現(xiàn)過,最近做的一個(gè)需求恰好有這個(gè)場景,這里歸先上效果圖: showImg(https://user-gold-cdn.xitu.io/2019/5/23/16ae28a94cb51d3e); 這種圖形大...
小編寫這篇文章的主要目的,主要還是去進(jìn)行講解一些關(guān)于Python pyecharts繪制儀表盤的一些講解,具體怎么去進(jìn)行操作呢?下面就給大家詳細(xì)解答下。 儀表盤 儀表盤的效果我只能說炫酷而已,如果想要運(yùn)用在實(shí)際的場景中,我其實(shí)也不清楚那個(gè)場景比較適合,但是pyecharts畢竟是炫酷可視化的利器,炫酷自然也就有它了。 小汽車儀表盤是長這樣的,下面我們來看看pyecharts的儀表盤是怎么...
在vue項(xiàng)目中canvas實(shí)現(xiàn)截圖功能是常用的,下面是具體代碼: 實(shí)現(xiàn)效果: 在vue項(xiàng)目中做的一個(gè)截圖功能(只能夠截取圖片),只用鼠標(biāo)就可以在畫面中進(jìn)行框選截取。 實(shí)現(xiàn):做一個(gè)彈窗,打開彈窗的時(shí)候傳入要截的圖,接下來在這個(gè)窗口里面,點(diǎn)擊截圖按鈕,開始截圖;點(diǎn)擊取消按鈕,取消截圖。 窗口里面的html主要是三個(gè)部分,一個(gè)是可截圖區(qū)域,一個(gè)是截取圖片的回顯,一個(gè)是操作按鈕(截圖按鈕和取消...
訪問時(shí)間超過3S對于用戶就十分痛苦,為考慮到用戶訪問效果。為此我,首屏加載時(shí)間一頓操作,基本都在2s左右,這樣的首屏加載時(shí)間,對于用戶來說,算是可以接受的。 那我都哪些操作?下面就為大家展示 打包分析 在 package.json 中添加命令 "report":"vue-cli-servicebuild--report" 然后命令行執(zhí)行npm ...
上傳視頻要提供視頻封面(視頻封面必填),這是在開發(fā)中實(shí)際問題。封面可以用戶自己制作并上傳,但這樣脫離網(wǎng)站,體驗(yàn)不好,常見的處理方案就是用戶未選擇或上傳封面時(shí),自動(dòng)截取視頻第一幀作為封面,但這樣并不友好。因此考慮視頻上傳后,在播放中由人員自行截取畫面作為視頻封面。 簡單效果如圖: 前端代碼如下: <template> <div> <videosrc=&...
閱讀 713·2023-04-25 19:43
閱讀 3910·2021-11-30 14:52
閱讀 3784·2021-11-30 14:52
閱讀 3852·2021-11-29 11:00
閱讀 3783·2021-11-29 11:00
閱讀 3869·2021-11-29 11:00
閱讀 3557·2021-11-29 11:00
閱讀 6105·2021-11-29 11:00