使用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编写,可直接在调试工具中查看代码)

你可能感兴趣的:(前端开发)