SVG - SVG 引入(SVG 概述、SVG 基本使用、SVG 使用 CSS、SVG 使用 JavaScript、SVG 实例实操)

一、SVG 概述

  • 官方文档:https://developer.mozilla.org/zh-CN/docs/Web/SVG
  1. SVG 全称 Scalable Vector Graphics,即可缩放矢量图形

  2. SVG 基于 XML 标记语言,用于描述二维的矢量图形

  3. SVG 格式提供的是矢量图,这意味着它的图像能够被无限放大而不失真或降低质量,并且可以方便地修改内容,无需图形编辑器


二、SVG 基本使用

1、准备阶段
  • 准备一个宽 400 像素、高 300 像素的灰色边框的空白 SVG 画布
html 复制代码
<svg id="mySvg" width="400" height="300" xmlns="http://www.w3.org/2000/svg">

    ...

</svg>
css 复制代码
svg {
    border: 1px solid #ccc;
}
2、基础图形绘制
  1. 矩形:x, y 是左上角坐标;fill 是填充色;stroke 是描边色;stroke-width 是描边粗细
html 复制代码
<rect x="50" y="50" width="100" height="60" fill="steelblue" stroke="darkblue" stroke-width="3" />
  1. 圆形:cx, cy 是圆心坐标;r 是半径;fill 是填充色;opacity 控制透明度(0 ~ 1)
html 复制代码
<circle cx="250" cy="100" r="40" fill="coral" opacity="0.8"/>
  1. 直线:x1, y1 是起点坐标,x2, y2 是终点坐标。stroke 是线条颜色,stroke-width 是线条粗细
html 复制代码
<line x1="50" y1="200" x2="150" y2="250" stroke="green" stroke-width="5"/>
  1. 多边形:points 属性定义了一系列用空格分隔的 x,y 坐标对,它会自动连接首尾点形成封闭图形
html 复制代码
<polygon points="300,200 350,250 250,250" fill="lavender" stroke="purple" />
  1. 路径:d 属性包含绘制命令,上例中,M(移动到)、L(画线到)、Z(闭合路径)
html 复制代码
<path d="M 100,150 L 200,150 L 150,100 Z" fill="lightyellow" stroke="orange" />

三、SVG 使用 CSS

  • SVG 的 fill、stroke、opacity 等属性可以使用 CSS控制,这有助于统一风格与交互效果
html 复制代码
<svg id="mySvg" width="400" height="300" xmlns="http://www.w3.org/2000/svg">
    <rect class="shape" x="50" y="50" width="100" height="60" />
    <circle class="shape" cx="250" cy="100" r="40" />
</svg>
css 复制代码
svg {
    border: 1px solid #ccc;
}

.shape {
    stroke-width: 2;
    stroke-opacity: 0.7;
    stroke: blue;
    fill: gray;
    transition: fill 0.3s ease;
}

.shape:hover {
    fill: gold;
}

四、SVG 使用 JavaScript

html 复制代码
<svg id="mySvg" width="400" height="300" xmlns="http://www.w3.org/2000/svg">
    <rect id="myRect" class="shape" x="50" y="50" width="100" height="60" />
</svg>
css 复制代码
svg {
    border: 1px solid #ccc;
}

.shape {
    stroke-width: 3;
    stroke-opacity: 0.7;
    stroke: blue;
}
js 复制代码
const mySvg = document.getElementById("mySvg");
const myRect = document.getElementById("myRect");

// 生成一个随机颜色,改变矩形的填充色
myRect.addEventListener("click", function () {
    const randomColor = "#" + Math.floor(Math.random() * 16777215).toString(16);
    console.log(randomColor);

    this.setAttribute("fill", randomColor);
});

// 在 SVG 内部点击时添加圆形
mySvg.addEventListener("click", function (event) {
    const point = mySvg.createSVGPoint();
    point.x = event.clientX;
    point.y = event.clientY;
    const svgPoint = point.matrixTransform(mySvg.getScreenCTM().inverse());

    const newCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    newCircle.setAttribute("cx", svgPoint.x);
    newCircle.setAttribute("cy", svgPoint.y);
    newCircle.setAttribute("r", "15");
    newCircle.setAttribute("fill", "lightcoral");
    newCircle.classList.add("shape");

    mySvg.appendChild(newCircle);
});

五、SVG 实例实操(房屋绘制)

html 复制代码
<svg width="400" height="400" viewBox="0 0 400 400">
    <!-- 房屋主体 -->
    <rect class="house-body" x="100" y="200" width="200" height="150" rx="5" />

    <!-- 屋顶 -->
    <polygon class="roof" points="70,200 330,200 200,100" />

    <!-- 烟囱 -->
    <rect class="chimney" x="260" y="120" width="30" height="60" />
    <rect class="chimney" x="255" y="115" width="40" height="10" />

    <!-- 烟囱烟 -->
    <path d="M275,90 Q280,70 290,65 Q300,60 310,55" fill="none" stroke="#aaa" stroke-width="3" stroke-linecap="round" />
    <path d="M280,80 Q285,60 295,55 Q305,50 315,45" fill="none" stroke="#aaa" stroke-width="3" stroke-linecap="round" />

    <!-- 窗户 -->
    <rect class="window" x="120" y="220" width="40" height="40" rx="3" />
    <rect class="window" x="240" y="220" width="40" height="40" rx="3" />

    <!-- 窗户十字架 -->
    <line x1="140" y1="220" x2="140" y2="260" stroke="#3366cc" stroke-width="1" />
    <line x1="120" y1="240" x2="160" y2="240" stroke="#3366cc" stroke-width="1" />
    <line x1="260" y1="220" x2="260" y2="260" stroke="#3366cc" stroke-width="1" />
    <line x1="240" y1="240" x2="280" y2="240" stroke="#3366cc" stroke-width="1" />

    <!-- 门 -->
    <rect class="door" x="180" y="280" width="40" height="70" rx="3" />

    <!-- 门把手 -->
    <circle cx="210" cy="315" r="3" fill="gold" />

    <!-- 台阶 -->
    <rect x="170" y="350" width="60" height="10" fill="#888" rx="2" />

    <!-- 文字 -->
    <text x="200" y="390" text-anchor="middle" font-size="14" fill="#666">SVG 房屋绘制</text>
</svg>

<div style="text-align: center; margin: 20px">
    <button onclick="addSun()">添加太阳</button>
    <button onclick="changeColor()">改变颜色</button>
    <button onclick="reset()">重置</button>
</div>
css 复制代码
svg {
    border: 1px solid #ddd;
    background-color: #f8f9fa;
    display: block;
    margin: 20px auto;
}

.house-body {
    fill: #ffcc99;
    stroke: #cc9966;
    stroke-width: 2;
}

.roof {
    fill: #cc3333;
    stroke: #993333;
    stroke-width: 2;
}

.window {
    fill: #99ccff;
    stroke: #3366cc;
    stroke-width: 1;
}

.window:hover {
    fill: #66aaff;
}

.door {
    fill: #996633;
    stroke: #663300;
    stroke-width: 2;
}

.door:hover {
    fill: #cc9966;
}

.chimney {
    fill: #cccccc;
    stroke: #999999;
    stroke-width: 2;
}
js 复制代码
function addSun() {
    const svg = document.querySelector("svg");
    const sun = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    sun.setAttribute("cx", "350");
    sun.setAttribute("cy", "50");
    sun.setAttribute("r", "30");
    sun.setAttribute("fill", "gold");
    sun.setAttribute("opacity", "0.8");
    svg.appendChild(sun);

    // 阳光光线
    for (let i = 0; i < 12; i++) {
        const ray = document.createElementNS("http://www.w3.org/2000/svg", "line");
        const angle = (i * 30 * Math.PI) / 180;
        const x1 = 350 + Math.cos(angle) * 30;
        const y1 = 50 + Math.sin(angle) * 30;
        const x2 = 350 + Math.cos(angle) * 45;
        const y2 = 50 + Math.sin(angle) * 45;

        ray.setAttribute("x1", x1);
        ray.setAttribute("y1", y1);
        ray.setAttribute("x2", x2);
        ray.setAttribute("y2", y2);
        ray.setAttribute("stroke", "gold");
        ray.setAttribute("stroke-width", "3");
        svg.appendChild(ray);
    }
}

function changeColor() {
    const colors = ["#ff9999", "#99ff99", "#9999ff", "#ffff99", "#ff99ff"];
    const houseBody = document.querySelector(".house-body");
    const randomColor = colors[Math.floor(Math.random() * colors.length)];
    houseBody.style.fill = randomColor;
}

function reset() {
    location.reload();
}
相关推荐
charlie1145141912 分钟前
现代嵌入式C++教程:if constexpr——把编译期分支写得像写注释 —— 工程味实战指南
开发语言·c++·笔记·学习·嵌入式·现代c++
冰暮流星4 分钟前
javascript如何转换为字符串与布尔型
java·开发语言·javascript
LIZhang20165 分钟前
c++ 转化句柄,解决多线程安全释放问题
开发语言·c++
2501_9481226313 分钟前
React Native for OpenHarmony 实战:Steam 资讯 App 个人中心页面
javascript·react native·react.js·游戏·ecmascript·harmonyos
Younglina14 分钟前
想提升专注力?我做了一个web端的训练工具
前端·vue.js·游戏
youqingyike15 分钟前
Qt 中 QWidget 调用setLayout 后不显示
开发语言·c++·qt
xiaoxiaoxiaolll19 分钟前
《自然·通讯》:纳米TiC复合粉末如何赋予3D打印CoCrNi合金超常低温韧性?
学习
2301_7973122622 分钟前
学习Java38天
学习
_OP_CHEN24 分钟前
【从零开始的Qt开发指南】(二十二)Qt 音视频开发宝典:从音频播放到视频播放器的实战全攻略
开发语言·c++·qt·音视频·前端开发·客户端开发·gui开发
FAFU_kyp24 分钟前
Rust 字符串与切片
开发语言·后端·rust