效果
示範位址:羅盤
項目位址:svg繪制羅盤-github
解析
工具庫: svg.js
中心太極:
- 使用 circle 畫一個黑色大圓背景
- 使用 path 畫一個白色半圓移動到左/右側
- 使用 circle 畫一個半徑為大圓半徑一半的黑色圓移動到上/下方
- 使用 circle 畫一個半徑為大圓半徑一半的白色圓移動到下/上方
- 使用 circle 畫一個半徑為大圓半徑3/10的黑圓移動4畫的白色圓中心
- 使用 circle 畫一個半徑為大圓半徑3/10的白圓移動3畫的黑色圓中心
// 代碼示例(使用svg.js)
const draw = SVG('drawing').size(100, 100)
const radius = 100
const background = draw.circle(radius * 2).fill('#000').move(-radius, -radius)
const white = draw.path(`M0 ${ radius } A${ radius } ${ radius } 0 0 0 0 ${ -radius }Z`).fill('#fff')
const topWhiteCircle = draw.circle(radius).fill('#fff').move(-radius / 2, -radius)
const bottomBlackCircle = draw.circle(radius).fill('#000').move(-radius / 2, 0)
const topBlackCircle = draw.circle(radius / 2.5).fill('#000').move(-radius / 4, -radius / 1.5)
const bottomWhiteCircle = draw.circle(radius / 2.5).fill('#fff').move(-radius / 4, radius / 4)
一圈圓:
- 使用path畫一段圓弧
- 設外圈半徑為
,弧寬為radiusOut
,則内圈半徑為arcWidth
。radiusIn = radiusOut - arcWidth
- 設圓分為n段圓弧,則每段圓弧占圓角度
angle = Math.PI * 2 / n
- 設内圈起點
,外圈起點startIn = { x: 0, y: radiusIn }
,則内圈終點為{ x: 0, y: radiusOut }
,外圈終點為{ x: Math.sin(angle) * radiusIn, y: Math.cos(angle) * radiusIn }
{ x: Math.sin(angle) * radiusOut, y: Math.cos(angle) * radiusOut }
- 則 path 為
M${ startIn.x } ${ startIn.y } L${ startOut.x } ${ startOut.y } A${ radiusOut } ${ radiusOut } 0 ${ Number(angle > Math.PI) } 0 ${ endOut.x - 0.01 } ${ endOut.y } L${ endIn.x - 0.01 } ${ endIn.y } A${ radiusIn } ${ radiusIn } 0 ${ Number(angle > Math.PI) } 1 ${ startIn.x } ${ startIn.y }
- 以 path 可以繪制出一段圓弧
- 設外圈半徑為
- 以 path 繪制其餘圓弧,并計算需要旋轉的角度(建議逆時針:
)進行旋轉,即可拼接為一個完整圈-(angle * index) * 180 / Math.PI
// 關鍵代碼(需要引入svg.js)
const draw = SVG('drawing').size(100, 100)
const radiusOut = 100 // 外圈半徑
const arcWidth = 40 // 圓弧寬度
const radiusIn = radiusOut - arcWidth // 内圈半徑
const n = 8 // 圓弧數量
const angle = Math.PI * 2 / n
const startIn = { x: 0, y: radiusIn }
const startOut = { x: 0, y: radiusOut }
const endIn = { x: Math.sin(angle) * radiusIn, y: Math.cos(angle) * radiusIn }
const endOut = { x: Math.sin(angle) * radiusOut, y: Math.cos(angle) * radiusOut }
const path = `M${ startIn.x } ${ startIn.y } L${ startOut.x } ${ startOut.y }
A${ radiusOut } ${ radiusOut } 0 ${ Number(angle > Math.PI) } 0 ${ endOut.x - 0.01 } ${ endOut.y }
L${ endIn.x - 0.01 } ${ endIn.y }
A${ radiusIn } ${ radiusIn } 0 ${ Number(angle > Math.PI) } 1 ${ startIn.x } ${ startIn.y }`
for (let index = 0; index < n; index++) {
const rotateAngle = -(angle * index) * 180 / Math.PI
draw.path(path).rotate(rotateAngle, 0, 0)
}
羅盤圓弧間沒有間隔,且弧長相等,計算坐标較為簡單,略微複雜的弧間有間隔且弧長不等的例子:
示範位址:https://xiaoleng123.github.io/arc-by-svg/
項目位址:https://github.com/Xiaoleng123/Xiaoleng123.github.io/tree/master/arc-by-svg
更多詳情可直接檢視源碼(示範代碼使用普通html編寫,可直接在調試工具中檢視代碼)