同步發布:https://blog.jijian.link/2020-04-14/svg-arc/
由於功能受限,此處不能放 iframe 嵌入鏈接,如需看到實時效果,請移步 https://blog.jijian.link/2020-04-14/svg-arc/
解析
<path> 標簽應該算是 SVG 中最為強大的標簽了,各種圖形都可以用他繪制。
本文使用 path 標簽的貝塞爾曲線 Q 指令繪制弧線。
用法
<path d="M30 90 Q115 139 200 90"></path>
<path> 標簽常用指令:
- M = moveto
- L = lineto
- H = horizontal lineto
- V = vertical lineto
- C = curveto
- S = smooth curveto
- Q = quadratic Belzier curve
- T = smooth quadratic Belzier curveto
- A = elliptical Arc
- Z = closepath
注釋:以上所有命令均允許小寫字母。大寫表示絕對定位,小寫表示相對定位。
繪制線條
常見效果:繪制實線、繪制虛線、繪制弧線、繪制漸變線條、繪制箭頭線條。
源碼:
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg"> <defs> <!-- 箭頭 --> <marker id="arrow" markerUnits="strokeWidth" markerWidth="12" markerHeight="12" viewBox="0 0 12 12" refX="6" refY="6" orient="auto"> <path d="M2,2 L10,6 L2,10 L6,6 L2,2" style="fill: #000000;"/> </marker> <linearGradient id="line-gradient" x1="0" y1="0" x2="1" y2="0"> <stop offset="0" stop-color="#990000" stop-opacity="0" /> <stop offset="1" stop-color="#990000" stop-opacity="1" /> </linearGradient> </defs> <!-- 實線 --> <path class="line" d="M30 30 L200 30"></path> <!-- 虛線 --> <path class="line" d="M30 60 L200 60" style="stroke-dasharray: 5;"></path> <!-- 弧線 --> <path class="line" d="M30 90 Q115 139 200 90"></path> <!-- 漸變線條 --> <path class="line" d="M30 120 Q115 169 200 120" style="stroke: url(#line-gradient)"></path> <!-- 箭頭線條 --> <path class="line" d="M30 150 Q115 199 200 150" style="marker-end:url(#arrow)"></path> <!-- 無瀏覽器潤色的線條,有鋸齒像素 --> <path class="line" d="M30 180 Q115 229 200 180" style="shape-rendering: optimizeSpeed;"></path> </svg>
實際應用
實際應用場景不一定會有詳細坐標點,需要我們根據已有條件去計算。
比如:已有開始左邊和結束坐標,根據這兩個坐標繪制一條弧線。
SVG 繪制弧線:
<path d="M30 90 Q115 139 200 90"></path>
M30 90 :表示開始點 x:30 y:90
Q115 139 :表示控制點在 x:115 y:139
200 90 :表示結束點 x:200 y:90
計算控制點圖解:
換算為 JS 算法:
const pos = getPosition ({left: 30, top: 90}, {left: 200, top: 90}, 30); console.log(pos); // [{"x":115,"y":139},{"x":115,"y":41}] function getPosition (dot1, dot2, angle) { var x1 = dot1.left; var y1 = dot1.top; var x2 = dot2.left; var y2 = dot2.top; var PI = Math.PI; // 兩點間的x軸夾角弧度 var xAngle=Math.atan2((y2-y1), (x2-x1)); // 轉為角度 xAngle = 360*xAngle/(2*PI); // 兩點間的長度 var L=Math.sqrt((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1)); // 計算等腰三角形斜邊長度 var L2 = L/2 / Math.cos(angle* 2*PI/360); // 求第一個頂點坐標,位於下邊 var val1={}; // 求第二個頂點坐標,位於上邊 var val2={}; val1['x']=x1+Math.round(L2 * Math.cos((xAngle+angle)* 2*PI/360)); val1['y']=y1+Math.round(L2 * Math.sin((xAngle+angle)* 2*PI/360)); val2['x']=x1+Math.round(L2 * Math.cos((xAngle-angle)* 2*PI/360)); val2['y']=y1+Math.round(L2 * Math.sin((xAngle-angle)* 2*PI/360)); return [val1,val2]; }
應用場景:
總結:path 運用遠不止此,比如常見的字體圖標,SVG 圖標等,都可見 path 標簽運用,一些炫酷的動畫效果也可以使用 path 標簽實現。