SVG

From Fundamental Ramen
Jump to navigation Jump to search

Compatibility of Browsers

Chrome Edge Firefox Safari
<text alignment-baseline="..."> O ? X ?
<use href="..."> O ? O X
<use xlink:href="...."> O O O O

https://stackoverflow.com/questions/43961807/svg-use-not-working-in-safari

Better approach to trigger an event

<template lang="pug">
<svg>
  <g @click="onClickShape">
    <!-- shape to receive click event -->
  </g>
</svg>
</template>

<script>
export default {
  methods: {
    onClickShape (e) {
      // TODO: Do something ...
    }
  }
}
</script>

常用換算

TODO Code
Get width of <text> element.
Math.max.apply(null, d3.selectAll("text").nodes().map((e) => { return e.getBBox().width; }))

常用濾鏡

濾鏡效果 濾鏡 code
陰影特效
<filter id="dropShadow">
   <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
   <feOffset dx="4" dy="4" />
   <feBlend in="SourceGraphic" />
</filter>

常用座標轉換

轉換效果 轉換 code
相對定位
<g transform="translate(X Y)"></g>
以 (X, Y) 為原點,轉換笛卡兒座標系
<g transform="translate(X Y) scale(1 -1)"></g>
在笛卡兒座標系中的指定位置顯示文字
(用 x, y 屬性會上下顛倒)
<!-- 方法 1 -->
<text transform="translate(X Y) scale(1 -1)">fuck</text>
<!-- 方法 2 -->
<text transform="scale(1 -1) translate(X -Y)">fuck</text>
<!-- 方法 3: 適用於多組文字 -->
<g transform="scale(1 -1)">
  <text transform="translate(X1 -Y1)">fuck 1</text>
  <text transform="translate(X2 -Y2)">fuck 2</text>
</g>

扇形繪圖法

<path d="m 160 160 l 0 -150 a 150 150 0 0 1 150 150 z" />
<path d="m 160 160 l 0 -150 a 150 150 0 1 0 150 150 z" />

這個畫法從圓心出發,畫直線到第一個點,再順時針畫弧線,最後畫一直線回圓心,其中 a 指令的部分比較難

a 150 150 0 0 1 150 150
a 150 150 0 1 0 150 150
弧線指令
(相對座標)
半徑X 半徑Y X軸旋轉角度 0 小弧線
1 大弧線
0 逆時針
1 順時針
X 偏移 Y 偏移

以 d3.js 畫任意角度扇形

參數說明 File:ArcPathDemo.png
start 起點角度
end 終點角度
r 半徑 (圓心 ~ 0度角長度)
ratio 半徑寬高比
// 畫扇形
var r     = 120;
var ratio = 2;
var start = -90;
var end   = 180;
var rx    = r;
var ry    = Math.floor(r / ratio);
var dtpl  = "m 160 160 l {X1} {Y1} a {RX} {RY} 0 {LA} 1 {X2} {Y2} z";
var deg   = Math.PI/180;
var x1    = Math.floor(rx * Math.cos(start * deg));
var y1    = Math.floor(ry * Math.sin(start * deg));
var x2    = Math.floor(rx * Math.cos(end * deg)) - x1;
var y2    = Math.floor(ry * Math.sin(end * deg)) - y1;
var la    = (end-start)>180 ? "1" : "0";

dtpl = dtpl
	.replace("{X1}", x1).replace("{Y1}", y1)
	.replace("{X2}", x2).replace("{Y2}", y2)
	.replace("{LA}", la)
	.replace("{RX}", rx).replace("{RY}", ry);

rsvg.append("path").attr({
	"d": dtpl,
	"style": "stroke:#ffffff; stroke-width:2; fill: #000077"
});

立體扇形製圖技巧

除了扇形本身以外,需要畫些立體面,製圖邏輯如下:

立體元素 可見範圍 先後次序
起點矩形 90 < 起點角 < 270 1
終點矩形 -90 < 終點角 < 90 1
曲面 0 < 起點角 < 180 or 0 < 終點角 < 180 2

畫圓餅圖時,多個立體扇形間需要輻射性拆散,圓心要稍作修正: TODO

注意事項

  • 設定優先權 CSS Attribute > Tag Attribute
  • <g> 無法繼承 x, y, cx, cy, r, x1, x2, y1, y2 等屬性
  • SVG Animation 有部分瀏覽器不支援
  • 目前主流的瀏覽器支援到 SVG 1.1
  • Firefox 透過 d3 觸發 mousemove 事件時,子圖的座標不是相對座標
  • 外部 SVG 有五種載入方式,其中 <embed> 與 <object> 比較理想 Embedding SVG Examples