摘要:先上效果圖這種圖形大家應該都見過,俗稱儀表盤,當然,上圖只是個最基本的儀表盤架子,可能在實際場景中還會其他很多花里胡哨的點綴,那些暫且不管,不是關鍵,這東西經常見到,但還沒親自上手在代碼層面實現過,最近做的一個需求恰好有這個場景,這里歸
先上效果圖:
這種圖形大家應該都見過,俗稱儀表盤,當然,上圖只是個最基本的儀表盤架子,可能在實際場景中還會其他很多花里胡哨的點綴,那些暫且不管,不是關鍵,這東西經常見到,但還沒親自上手在代碼層面實現過,最近做的一個需求恰好有這個場景,這里歸納一下
canvas實現大部分情況下,對于這種偏可視化的元素,一般都選擇使用 canvas來進行繪制,現在已經 9120年了,線上使用 canvas完全沒問題
儀表盤整體是一個復雜圖形,而復雜圖形是由簡單圖形組合而成,只要把所有組成這個儀表盤的簡單圖形繪制出來,再進行組合,整個儀表盤自然也就繪制出來了
所以,首先對儀表盤進行分解,分解成 canvas能繪制出的基本圖形,其主體其實就兩個圓弧,一個是底部藍色的半圓軌道,一個是代表進度的紅色圓弧,其實都是圓弧,canvas剛好有繪制圓弧的能力,即:
ctx.arc
至于動態繪制,只需要配合 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)
加上變量定義,花括號等幾十行代碼即可完成,由此可見,canvas繪圖還是很方便的,所以在可視化領域,例如一些庫或者UI組件基本上都是以canvas進行構建
css繪制canvas實質上就是借助 js操縱瀏覽器 API進行渲染,然而 UI渲染這種事情本應該交給 CSS來做才是,感覺用 js直接畫多影響性能啊(實際上并不),哪有 css來的流暢,實際上,css完全可以做到
從 css的角度對儀表盤進行分解,同樣還是兩個圓弧,通過設置 border-radius屬性即可讓元素呈現整圓效果,然后再用一個矩形元素進行遮罩,決定展現出來的部分,即為圓弧,通過控制遮罩的面積來呈現動態繪制的效果
<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;
}
其實沒多少代碼,也沒什么難以理解的,只不過效果似乎微調:
由于圓弧的線是存在寬度的,并不是數學意義上的可以忽略,canvas繪制圓弧,是根據圓心坐標和半徑進行繪制的,繪制出來的圓弧會自動根據圓弧 line的寬度進行調整,即圓弧的半徑是圓弧線的中心位置與圓心坐標距離
而通過 css繪制的圓弧,此圓弧的半徑則是圓弧最外層邊線與圓心的坐標距離:
知道了問題其實就好解決了,只要縮減軌道半圓的半徑,并對其進行一定的偏移即可:
.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));
}
然后就順眼多了:
然而,還有個問題,一般為了呈現更加圓潤的效果,設計稿上圓弧的斷點處一般都是圓頭:
而上述呈現出來的效果是直接截斷的:
一般人之所以不使用 css來繪制儀表盤,基本都是因為這個原因,canvas簡簡單單通過設置一個 ctx.lineCap = "round"就能解決的問題。似乎 css無解了
乍一看好像確實沒什么好辦法,但稍微思考下,這不就是一個圓角嗎,完全在css能力范圍內啊,只不過實現的方式不太那么直接罷了
方法很簡單,就是使用一個圓角矩形覆蓋在圓弧的頂端,將圓弧本身的矩形頂端覆蓋住,圓角矩形當做是圓弧的頂端,這樣視覺上看起來不就是圓頭了嗎
<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只是為了呈現出最大限度的圓角 */
border-bottom-left-radius: 100px;
border-bottom-right-radius: 100px;
background-color: var(--roundColor);
}
效果如下:
圓角頂端 get
同樣的,圓弧左邊的頂端也可以這么做
不過左邊這個頂端有個稍微需要注意的地方,因為其存在的目的是為了當做圓弧的左斷點,但是當進度為 0的時候,圓弧應該是完全不展現的,或者當進度很小的時候,圓弧應該展現的長度還沒有 dot-l的高度大,這樣就露餡了:
不過呢轉而又一想,一般實際場景中,就算進度為 0,我們其實為了看起來更符合常識直覺,也會讓圓弧展現一點點出來,只要 dot-l的高度不是太大,或者說只要圓弧的寬度不要太寬,其實預留的這點圓弧完全就可以 cover住了,不至于露餡
小結css的新特性 var 和 calc還挺好用的嘛
本文示例的 Live Demo已經上傳,感興趣的可以親自試下
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7023.html
摘要:先上效果圖這種圖形大家應該都見過,俗稱儀表盤,當然,上圖只是個最基本的儀表盤架子,可能在實際場景中還會其他很多花里胡哨的點綴,那些暫且不管,不是關鍵,這東西經常見到,但還沒親自上手在代碼層面實現過,最近做的一個需求恰好有這個場景,這里歸先上效果圖: showImg(https://user-gold-cdn.xitu.io/2019/5/23/16ae28a94cb51d3e); 這種圖形大...
小編寫這篇文章的主要目的,主要還是去進行講解一些關于Python pyecharts繪制儀表盤的一些講解,具體怎么去進行操作呢?下面就給大家詳細解答下。 儀表盤 儀表盤的效果我只能說炫酷而已,如果想要運用在實際的場景中,我其實也不清楚那個場景比較適合,但是pyecharts畢竟是炫酷可視化的利器,炫酷自然也就有它了。 小汽車儀表盤是長這樣的,下面我們來看看pyecharts的儀表盤是怎么...
在vue項目中canvas實現截圖功能是常用的,下面是具體代碼: 實現效果: 在vue項目中做的一個截圖功能(只能夠截取圖片),只用鼠標就可以在畫面中進行框選截取。 實現:做一個彈窗,打開彈窗的時候傳入要截的圖,接下來在這個窗口里面,點擊截圖按鈕,開始截圖;點擊取消按鈕,取消截圖。 窗口里面的html主要是三個部分,一個是可截圖區域,一個是截取圖片的回顯,一個是操作按鈕(截圖按鈕和取消...
訪問時間超過3S對于用戶就十分痛苦,為考慮到用戶訪問效果。為此我,首屏加載時間一頓操作,基本都在2s左右,這樣的首屏加載時間,對于用戶來說,算是可以接受的。 那我都哪些操作?下面就為大家展示 打包分析 在 package.json 中添加命令 "report":"vue-cli-servicebuild--report" 然后命令行執行npm ...
上傳視頻要提供視頻封面(視頻封面必填),這是在開發中實際問題。封面可以用戶自己制作并上傳,但這樣脫離網站,體驗不好,常見的處理方案就是用戶未選擇或上傳封面時,自動截取視頻第一幀作為封面,但這樣并不友好。因此考慮視頻上傳后,在播放中由人員自行截取畫面作為視頻封面。 簡單效果如圖: 前端代碼如下: <template> <div> <videosrc=&...
閱讀 1106·2021-11-23 10:05
閱讀 1785·2021-11-12 10:36
閱讀 1853·2019-08-30 15:56
閱讀 1684·2019-08-29 12:32
閱讀 3043·2019-08-28 18:04
閱讀 3428·2019-08-26 12:17
閱讀 2502·2019-08-26 11:35
閱讀 1240·2019-08-23 15:11