前端程式碼實現圖形的幾種方式:CSS、SVG、Canvas(主要是JavaScript編碼)
CSS也是可以畫圖的,需要藉助於高寬、邊框border
、clip-path
裁剪、漸變色背景等屬性來模擬實現各種圖形,當然只能實現一些簡單的圖形。
border:用四條邊框樣式屬性的各種組合變換,實現一些簡單的圖形。網上也有畫一些稍微複雜的圖形,如哆啦A夢,但程式碼量稍多,可讀性不好,並不推薦。
<div class="gcss">
<p class="border">border</p>
<p class="rborder">圓角按鈕</p>
<p class="radio"></p>radio
<p class="triangle1"></p>三角形
<p class="triangle2"></p>三角形
</div>
<style>
.gcss p {
display: inline-block;
text-align: center; vertical-align: middle;
}
.border {
border: 30px solid;
border-color: aqua tan violet peru;
border-radius: 20px;
}
.rborder {
background-color: #b1ccf3;
width: 100px; height: 40px; line-height: 40px;
border-radius: 20px;
}
.radio {
width: 40px; height: 40px;
border-radius: 50%;
border: 10px solid;
}
.triangle1 {
border: 50px solid #0001;
border-left-color: red;
}
.triangle2 {
border-left: 50px solid #0001;
border-right: 50px solid #0001;
border-bottom: 50px solid red;
}
</style>
< svg>可縮放向量圖形(Scalable Vector Graphics,SVG),是一種基於 XML(數學)描述的二維的向量圖形,內容可以直接插入網頁,成為DOM的一部分,然後用 JavaScript 和 CSS 進行操作。SVG 內容也可以寫在一個獨立檔案中,然後用CSS(background-url)、<img>
、<object>
、<embed>
、<iframe>
來參照。
大多數現代瀏覽器都支援SVG 圖形,越來越多的專案在使用SVG圖形,簡單的像圖示,複雜的一些圖表Chart也有不少是基於SVG實現的。相比於點陣圖,體積更小,可無線縮放而不失真。
比較 | 向量圖形 | 點陣圖 |
---|---|---|
儲存的資料 | 儲存元素、演演算法資料 | 儲存畫素資料 |
儲存大小 | 小 | 大 |
縮放效果 | 無線縮放,不失真 | 固定大小,放大會失真 |
可維護性 | 很容易修改 | 修改麻煩 |
擴充套件性 | 支援CSS、JS | 不支援 |
檔案格式 | .svg ,直接嵌入資料到頁面 |
.bmp /.png /.jpg /.gif ,< img>可嵌入svg檔案 |
支援的元素 | <svg> 、<img> 、<iframe> 、<object> |
<img> 、<iframe> |
相容性 | IE9開始支援 | 較好 |
渲染效能 | 複雜的SVG會佔用很多時間 | 穩定 |
網路傳輸效能 | 和頁面資料一起,體積小,速度快 | 需單獨請求圖片資源 |
快取 | 隨網頁內容一起,不可單獨快取 | 圖片可單獨快取 |
<svg>
內部支援多種圖形演演算法,基礎的如線line
、圓形<circle>
、矩形rect
、文字text
,複雜的有折線polyline
、多邊形polygon
、路徑資料path
等。這些圖形都以子元素的形式組合,因此也就都支援CSS、JS的操作了。iconfont-阿里巴巴向量圖示庫上有非常豐富的< svg>向量圖形。
元素/屬性 | 描述 | 值/範例 |
---|---|---|
< svg > |
向量圖形元素 | |
viewBox | SVG 畫布顯示區域,這裡 1 單位等同於 1 螢幕單位,SVG裡的座標、尺寸都是基於此畫布區域 | viewBox="0 0 300 200" |
width、height | 寬度、高度 | width="300" height="200" |
xmlns | xml標籤的名稱空間,為了區分html、svg,可以省略 | |
< line> | 線段 | |
x1、y1 | 起點x、y座標 | <line x1="0" y1="100" /> |
x2、y2 | 終點x、y座標 | x2="300" y2="100" |
< rect> | 矩形:<rect x="5" y="50" height="100" width="290"/> |
|
x、y | 起點座標 | |
width、height | 矩形的寬、高 | |
rx、ry | x、y方向的圓角半徑。r=radius 半徑 | rx="50" ry="50" |
<circle/ellipse> | 圓和橢圓:<circle cx="150" cy="100" r="80"/> |
|
cx、cy | 圓心的x、y座標 | |
r | 圓的半徑長度 | |
rx、ry | 橢圓的x、y半徑 | |
<polyline/polygon> | 折線、多邊形,兩者資料結構相似,多邊形是自動首尾連線封閉成一個區域(Polygon /ˈpɒlɪɡən/ 多邊形) | |
points | x、y座標的集合,多個座標逗號, 分割 |
points="0 0, 20 40, 70 80/> |
< path> | 路徑,很常用、很強大的圖形繪製,資料在屬性d 中 |
|
< d> | 路徑資料,< path> 最重要的屬性,由多組命令+ 座標點組成 |
d="M 50 5 H250 V195 H50 Z" |
M x y | 移動畫筆到座標點x、y | M50 5 |
L x y | 劃線到座標x、y | L 250 0 |
H x | 繪製水平線,到座標x;小寫h 的座標為相對位置 |
H 250 |
V y | 繪製垂直線,到座標y;小寫v 的座標為相對位置 |
V195 |
Z | 閉合路徑(closepath),放到最後用於閉合路徑 | |
C* | 繪製曲線,包括貝塞爾曲線、圓弧。 | |
<text> | 文字標籤,支援CSS樣式中的文字樣式 | |
x、y | 文字開始位置 | |
font-size | 字型大小 | |
< textPath> | 文字繪製的路徑,這個就比較有趣了 | <textPath xlink:href="#path1"> |
公共屬性 | 部分屬性可以用CSS設定,支援hover偽類 | |
stroke | 筆畫顏色(stroke /stroʊk/ 筆畫) ,包括線段、形狀線條。 | stroke="red" |
stroke-width | 畫筆線寬 | stroke-width="10" |
fill | 填充顏色,填充一個區域(矩形、圓形等) | fill="#0001" |
❗小提示:注意伺服器新增對svg的支援,及gzip壓縮。
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="150" cy="100" r="80" fill="green" />
<circle cx="150" cy="100" r="70" fill="#fff" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="orange">SVG</text>
<line x1="0" y1="100" x2="300" y2="100" stroke="white" stroke-width="8"/>
</svg>
<svg class="icon" height="200" viewBox="0 0 300 200" version="1.1">
<rect x="5" y="50" rx="50" ry="50" height="100" width="290" fill="white" stroke="blue" stroke-width="10"/>
<path d="M 50 5 H250 V195 H50 Z" stroke="red" stroke-width="10" fill="#00000001" />
<text x="145" y="125" font-size="60" text-anchor="middle" fill="#fab">Path</text>
</svg>
<style>
svg:hover{
background-color: aliceblue;
stroke: red;
stroke-width: 1px;
fill: red;
}
</style>
SVG 本身就是一個HTML元素,因此動畫可以用CSS的動畫來實現(參考 CSS動畫),SVG中也有專門用於實現動畫的<animate>
子元素。這裡範例採用JavaScript+transform
變換實現旋轉效果。
<svg version="1.1" baseProfile="full" width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<circle cx="150" cy="100" r="80" fill="green" />
<circle cx="150" cy="100" r="70" fill="#fff" />
<text class="svgc" x="150" y="125" font-size="60" text-anchor="middle" fill="orange" >SVG</text>
<line class="svgc" x1="0" y1="100" x2="300" y2="100" stroke="white" stroke-width="8" />
</svg>
<script>
let svgcs = document.querySelectorAll(".svgc");
//設定中心點
svgcs.forEach(element => {
element.setAttribute("transform-origin", '150 100');
});
let deg = 0;
setInterval(() => {
deg = deg > 360 ? 0 : deg+4;
svgcs.forEach(element => {
element.setAttribute("transform", `rotate(${deg})`);
});
}, 100);
</script>
<!-- 用CSS動畫實現的版本 -->
<style>
.svgc {
transform-origin: 150px 100px;
animation: svgc-routate 2s linear 1s infinite;
}
@keyframes svgc-routate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>