天天看點

使用SVG畫一個羅盤

效果

使用SVG畫一個羅盤

示範位址:羅盤

項目位址:svg繪制羅盤-github

解析

工具庫: svg.js

中心太極:

  1. 使用 circle 畫一個黑色大圓背景
  2. 使用 path 畫一個白色半圓移動到左/右側
  3. 使用 circle 畫一個半徑為大圓半徑一半的黑色圓移動到上/下方
  4. 使用 circle 畫一個半徑為大圓半徑一半的白色圓移動到下/上方
  5. 使用 circle 畫一個半徑為大圓半徑3/10的黑圓移動4畫的白色圓中心
  6. 使用 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)
           

一圈圓:

  1. 使用path畫一段圓弧
    1. 設外圈半徑為

      radiusOut

      ,弧寬為

      arcWidth

      ,則内圈半徑為

      radiusIn = radiusOut - arcWidth

    2. 設圓分為n段圓弧,則每段圓弧占圓角度

      angle = Math.PI * 2 / n

    3. 設内圈起點

      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 }

    4. 則 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 }

    5. 以 path 可以繪制出一段圓弧
  2. 以 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編寫,可直接在調試工具中檢視代碼)