Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏

20.7. SVG 图形库

20.7.1. SVG 标签

20.7.1.1. 符号定义

symbol元素用来定义一个图形模板对象,它可以用一个use元素实例化。symbol元素对图形的作用是在同一文档中多次使用,添加结构和语义。结构丰富的文档可以更生动地呈现出来,类似讲演稿或盲文,从而提升了无障碍。注意,一个symbol元素本身是不呈现的。只有symbol元素的实例(亦即,一个引用了symbol的 use元素)才能呈现。

			
<svg>
  <!-- symbol definition  NEVER draw -->
  <symbol id="sym01" viewBox="0 0 150 110">
    <circle cx="50" cy="50" r="40" stroke-width="8" stroke="red" fill="red" />
    <circle
      cx="90"
      cy="60"
      r="40"
      stroke-width="8"
      stroke="green"
      fill="white" />
  </symbol>

  <!-- actual drawing by "use" element -->
  <use xlink:href="#sym01" x="0" y="0" width="100" height="50" />
  <use xlink:href="#sym01" x="0" y="50" width="75" height="38" />
  <use xlink:href="#sym01" x="0" y="100" width="50" height="25" />
</svg>			
			
			

20.7.1.2. 矩形

绘制圆角矩形

			
<svg width="300px" height="300px" viewBox="0 0 200 200">
  <!-- rx 和 ry 相等, 逐渐增大 -->
  <rect x="10" y="10" width="20" height="40" rx="2" ry="2"
    style="stroke: black; fill: none;"/>

  <rect x="40" y="10" width="20" height="40" rx="5"
    style="stroke: black; fill: none;"/>

  <rect x="70" y="10" width="20" height="40" ry="10"
    style="stroke: black; fill: none;"/>

  <!-- rx 和 ry 不相等 -->
  <rect x="10" y="60" width="20" height="40" rx="10" ry="5"
    style="stroke: black; fill: none;"/>

  <rect x="40" y="60" width="20" height="40" rx="5" ry="10"
    style="stroke: black; fill: none;"/>
</svg>
			
			

20.7.1.3. 圆形

			
<circle
  cx="x-coordinate"      <!-- 圆心的 x 坐标 -->
  cy="y-coordinate"      <!-- 圆心的 y 坐标 -->
  r="radius"             <!-- 圆的半径 -->
  fill="fill-color"      <!-- 圆的填充颜色 -->
  stroke="stroke-color"  <!-- 圆的描边颜色 -->
  stroke-width="width"   <!-- 圆的描边宽度 -->
/>
			
			

20.7.1.4. 路径

贝塞尔曲线
两次贝塞尔曲线

拥有两个控制点的贝塞尔曲线

				
<path d="M{x},{y} C{cx1},{cy1} {cx2},{cy2} {x1},{y1}" id="路径" stroke="blue" stroke-width="2"></path>

起点:M{x},{y}
起点控制点:C{cx1},{cy1}
终点控制点:{cx2},{cy2}
终点:{x1},{y1}
				
					

下面代码生成类似 mindmap 思维导图的连接线

				
            <path d="M0,200 C200,200 200,0 400,0" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,50 400,50" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,100 400,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,150 400,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,200 400,200" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M0,200 C200,200 200,250 400,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,300 400,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,350 400,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,400 400,400" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C200,200 200,450 400,450" id="路径" stroke="#FFA500" stroke-width="2"></path>				
				
					

进一步增加复杂度,生成二级子集,同时在起点处增加两个圆圈点缀。

				
            <path d="M0,200 C150,200 200,0 300,0" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,50 300,50" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,100 300,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,150 300,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,200 300,200" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M0,200 C150,200 200,250 300,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,300 300,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,350 300,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,400 300,400" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M0,200 C150,200 200,450 300,450" id="路径" stroke="#FFA500" stroke-width="2"></path>

            <path d="M300,200 C400,200 500,100 600,100" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,150 600,150" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,200 600,200" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,250 600,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,250 600,250" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,300 600,300" id="路径" stroke="#FFA500" stroke-width="2"></path>
            <path d="M300,200 C400,200 500,350 600,350" id="路径" stroke="#FFA500" stroke-width="2"></path>
            
            <circle cx="0" cy="200" r="5" fill="white" stroke="blue" stroke-width="2"/>
            <circle cx="300" cy="200" r="5" fill="white" stroke="green" stroke-width="2"/>				
				
					

两端延伸出一段横线,横线上增加文字

				
            <text text-anchor="middle" x="50" y="120" fill="purple" stroke="none">咖啡豆分类</text>

            <text text-anchor="middle" x="350" y="45" fill="red" stroke="none">阿拉比卡咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,50 300,50 L 400,50" id="路径" stroke="red" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="95" fill="green" stroke="none">罗布斯塔咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,100 300,100 L 400,100" id="路径" stroke="green" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="145" fill="orange" stroke="none">利比里亚咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,150 300,150 L 400,150" id="路径" stroke="orange" stroke-width="2"></path>

            <text text-anchor="middle" x="350" y="195" fill="blue" stroke="none">埃克萨斯咖啡豆</text>
            <path d="M0,125 L100,125 C200,125 200,200 300,200 L 400,200" id="路径" stroke="blue" stroke-width="2"></path>
            <circle cx="100" cy="125" r="5" fill="white" stroke="blue" stroke-width="2"/>				
				
					

20.7.1.5. script

绘制三角形
				
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300" width="400" height="300">
  <!-- 样式定义 -->
  <style>
    .triangle { fill: #4a90e2; fill-opacity: 0.7; stroke: #333; stroke-width: 2; }
    .angle-label { font-family: Arial; font-size: 14px; font-weight: bold; }
    .angle-arc { stroke: #666; stroke-width: 1.5; fill: none; }
    .side-label { font-family: Arial; font-size: 12px; }
    .info { font-family: Arial; font-size: 12px; fill: #333; }
  </style>
  
  <!-- 背景和说明文字 -->
  <rect width="100%" height="100%" fill="#f9f9f9" />
  <text x="200" y="20" text-anchor="middle" class="info">指定内角的三角形 (30°, 60°, 90°)</text>
  
  <!-- 计算参数:三个内角之和必须为180° -->
  <defs>
    <data id="angles" value="30,60,90" /> <!-- 可修改此处的角度值 -->
    <data id="sideLength" value="150" /> <!-- 基准边长 -->
  </defs>
  
  <!-- 三角形绘制:通过JavaScript计算坐标 -->
  <script type="text/javascript"><![CDATA[
    // 获取参数
    const anglesStr = document.getElementById('angles').getAttribute('value');
    const [A, B, C] = anglesStr.split(',').map(Number);
    const a = parseFloat(document.getElementById('sideLength').getAttribute('value'));
    
    // 验证角度和为180°
    if (A + B + C !== 180) {
      alert(`角度和必须为180°,当前总和为${A+B+C}°`);
    }
    
    // 转换角度为弧度
    const radA = A * Math.PI / 180;
    const radB = B * Math.PI / 180;
    const radC = C * Math.PI / 180;
    
    // 利用正弦定理计算其他两边长度: a/sinA = b/sinB = c/sinC
    const b = a * Math.sin(radB) / Math.sin(radA);
    const c = a * Math.sin(radC) / Math.sin(radA);
    
    // 计算三角形三个顶点坐标(以(100, 200)为第一个顶点)
    const x1 = 100, y1 = 200;
    const x2 = x1 + c, y2 = y1;
    const x3 = x1 + b * Math.cos(radA), y3 = y1 - b * Math.sin(radA);
    
    // 创建三角形路径
    const triangle = document.createElementNS("http://www.w3.org/2000/svg", "path");
    triangle.setAttribute('d', `M ${x1},${y1} L ${x2},${y2} L ${x3},${y3} Z`);
    triangle.setAttribute('class', 'triangle');
    document.querySelector('svg').appendChild(triangle);
    
    // 绘制角度标记
    function drawAngleMarker(x, y, angleRad, radius, label, isInside) {
      const startAngle = isInside ? Math.PI : 0;
      const endAngle = isInside ? Math.PI - angleRad : angleRad;
      
      // 计算弧线
      const arc = document.createElementNS("http://www.w3.org/2000/svg", "path");
      const startX = x + radius * Math.cos(startAngle);
      const startY = y - radius * Math.sin(startAngle);
      const endX = x + radius * Math.cos(endAngle);
      const endY = y - radius * Math.sin(endAngle);
      const largeArcFlag = angleRad > Math.PI ? 1 : 0;
      
      arc.setAttribute('d', `M ${startX},${startY} A ${radius},${radius} 0 ${largeArcFlag},1 ${endX},${endY}`);
      arc.setAttribute('class', 'angle-arc');
      document.querySelector('svg').appendChild(arc);
      
      // 添加角度标签
      const labelAngle = isInside ? startAngle - angleRad / 2 : angleRad / 2;
      const labelX = x + (radius + 15) * Math.cos(labelAngle);
      const labelY = y - (radius + 15) * Math.sin(labelAngle);
      
      const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
      text.setAttribute('x', labelX);
      text.setAttribute('y', labelY);
      text.setAttribute('text-anchor', 'middle');
      text.setAttribute('class', 'angle-label');
      text.textContent = `${label}°`;
      document.querySelector('svg').appendChild(text);
    }
    
    // 绘制三个角的标记
    drawAngleMarker(x1, y1, radA, 30, A, true);
    drawAngleMarker(x2, y2, radB, 30, B, true);
    drawAngleMarker(x3, y3, radC, 30, C, true);
    
    // 添加边长标签
    function addSideLabel(x1, y1, x2, y2, label) {
      const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
      const midX = (x1 + x2) / 2;
      const midY = (y1 + y2) / 2;
      text.setAttribute('x', midX);
      text.setAttribute('y', midY - 5);
      text.setAttribute('text-anchor', 'middle');
      text.setAttribute('class', 'side-label');
      text.textContent = label;
      document.querySelector('svg').appendChild(text);
    }
    
    addSideLabel(x1, y1, x2, y2, `c = ${c.toFixed(1)}`);
    addSideLabel(x2, y2, x3, y3, `a = ${a}`);
    addSideLabel(x3, y3, x1, y1, `b = ${b.toFixed(1)}`);
  ] ] ></script>
</svg>
    				
				
				
绘制多边形
				
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400">
  <!-- 样式定义 -->
  <style>
    .polygon { fill: #4a90e2; fill-opacity: 0.7; stroke: #333; stroke-width: 2; }
    .control-panel { font-family: Arial; font-size: 14px; }
    .label { fill: #333; }
    .value-display { font-weight: bold; }
  </style>
  
  <!-- 背景 -->
  <rect width="100%" height="100%" fill="#f9f9f9" />
  
  <!-- 控制参数 -->
  <defs>
    <data id="sides" value="6" />      <!-- 多边形边数 -->
    <data id="radius" value="150" />   <!-- 多边形半径(中心点到顶点的距离) -->
    <data id="rotation" value="0" />   <!-- 旋转角度(度) -->
    <data id="centerX" value="200" />  <!-- 中心点X坐标 -->
    <data id="centerY" value="200" />  <!-- 中心点Y坐标 -->
  </defs>
  
  <!-- 说明文字 -->
  <text x="200" y="30" text-anchor="middle" class="label">正多边形绘制 (边数: <tspan id="sides-display" class="value-display">6</tspan>)</text>
  <text x="200" y="370" text-anchor="middle" class="label" font-size="12">可修改边数参数查看不同多边形</text>
  
  <!-- 多边形绘制逻辑 -->
  <script type="text/javascript"><![CDATA[
    // 获取参数
    const sides = parseInt(document.getElementById('sides').getAttribute('value'));
    const radius = parseFloat(document.getElementById('radius').getAttribute('value'));
    const rotation = parseFloat(document.getElementById('rotation').getAttribute('value'));
    const centerX = parseFloat(document.getElementById('centerX').getAttribute('value'));
    const centerY = parseFloat(document.getElementById('centerY').getAttribute('value'));
    
    // 验证边数(至少3条边)
    if (sides < 3) {
      alert("多边形边数必须至少为3");
    }
    
    // 更新显示的边数
    document.getElementById('sides-display').textContent = sides;
    
    // 计算每个顶点的坐标
    const points = [];
    const rotationRad = rotation * Math.PI / 180; // 转换旋转角度为弧度
    
    for (let i = 0; i < sides; i++) {
      // 计算每个顶点的角度(弧度)
      // 从顶部开始(-90度),加上旋转角度,再加上每个顶点的角度偏移
      const angle = rotationRad - Math.PI / 2 + (2 * Math.PI * i / sides);
      
      // 计算坐标
      const x = centerX + radius * Math.cos(angle);
      const y = centerY + radius * Math.sin(angle);
      
      points.push(`${x},${y}`);
    }
    
    // 创建多边形元素
    const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
    polygon.setAttribute('points', points.join(' '));
    polygon.setAttribute('class', 'polygon');
    document.querySelector('svg').appendChild(polygon);
    
    // 绘制中心点
    const center = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    center.setAttribute('cx', centerX);
    center.setAttribute('cy', centerY);
    center.setAttribute('r', 5);
    center.setAttribute('fill', '#ff6b6b');
    document.querySelector('svg').appendChild(center);
  ] ]> </script>
</svg>

				
				
				
基本参数设定:
边数(sides):决定多边形的形状,必须至少为 3
半径(radius):从中心到顶点的距离
中心点坐标(centerX, centerY):多边形在 SVG 中的位置
旋转角度(rotation):控制多边形的朝向

顶点坐标计算:
每个顶点之间的角度间隔 = 2π / 边数(弧度)
第 i 个顶点的角度 = 旋转角度 + 起始角度(-90 度,从顶部开始) + 角度间隔 × i

使用三角函数计算坐标:
x = 中心 x + 半径 × cos (角度)
y = 中心 y + 半径 × sin (角度)

绘制多边形:
将所有顶点坐标按顺序连接,形成闭合的多边形

修改 sides 值:
3:三角形
4:正方形
5:五边形
6:六边形
8:八边形等	
				
				
雷达图
				
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 500" width="600" height="500">
  <!-- 样式定义 -->
  <style>
    .axis-line { stroke: #ccc; stroke-width: 1; }
    .grid-line { stroke: #eee; stroke-width: 1; }
    .data-polygon-1 { fill: rgba(54, 162, 235, 0.2); stroke: rgba(54, 162, 235, 1); stroke-width: 2; }
    .data-polygon-2 { fill: rgba(75, 192, 192, 0.2); stroke: rgba(75, 192, 192, 1); stroke-width: 2; }
    .dimension-label { font-family: Arial; font-size: 14px; fill: #333; }
    .legend-item { font-family: Arial; font-size: 12px; fill: #333; }
    .title { font-family: Arial; font-size: 18px; font-weight: bold; fill: #333; }
    .center-circle { fill: #fff; }
  </style>
  
  <!-- 雷达图参数配置 -->
  <defs>
    <!-- 维度标签 -->
    <data id="dimensions" value="性能,易用性,稳定性,安全性,性价比,扩展性"></data>
    <!-- 数据值 (0-100),多组数据用|分隔 -->
    <data id="data" value="80,65,90,75,60,85|70,80,65,90,75,60"></data>
    <!-- 图例标签 -->
    <data id="legends" value="产品A,产品B"></data>
    <!-- 配置参数 -->
    <data id="centerX" value="300"></data>    <!-- 中心点X坐标 -->
    <data id="centerY" value="250"></data>    <!-- 中心点Y坐标 -->
    <data id="maxRadius" value="180"></data>  <!-- 最大半径 -->
    <data id="levels" value="5"></data>       <!-- 网格层数 -->
  </defs>
  
  <!-- 标题 -->
  <text x="300" y="30" text-anchor="middle" class="title">产品多维度评价雷达图</text>
  
  <!-- 雷达图绘制逻辑 -->
  <script type="text/javascript"><![CDATA[
    // 获取配置参数
    const dimensions = document.getElementById('dimensions').getAttribute('value').split(',');
    const dataGroups = document.getElementById('data').getAttribute('value').split('|').map(group => 
      group.split(',').map(Number)
    );
    const legends = document.getElementById('legends').getAttribute('value').split(',');
    const centerX = parseFloat(document.getElementById('centerX').getAttribute('value'));
    const centerY = parseFloat(document.getElementById('centerY').getAttribute('value'));
    const maxRadius = parseFloat(document.getElementById('maxRadius').getAttribute('value'));
    const levels = parseInt(document.getElementById('levels').getAttribute('value'));
    const numDimensions = dimensions.length;
    
    // 计算每个维度的角度(弧度)
    const getAngle = (index) => {
      // 从顶部开始(-90度),每个维度平均分配360度
      return (index * 2 * Math.PI / numDimensions) - Math.PI / 2;
    };
    
    // 计算坐标
    const getCoordinates = (index, value) => {
      const angle = getAngle(index);
      const radius = (value / 100) * maxRadius; // 数据值转换为半径比例
      return {
        x: centerX + radius * Math.cos(angle),
        y: centerY + radius * Math.sin(angle)
      };
    };
    
    // 绘制网格线和坐标轴
    for (let level = 1; level <= levels; level++) {
      const radius = (level / levels) * maxRadius;
      const points = [];
      
      // 绘制网格多边形
      for (let i = 0; i < numDimensions; i++) {
        const angle = getAngle(i);
        points.push(`${centerX + radius * Math.cos(angle)},${centerY + radius * Math.sin(angle)}`);
      }
      points.push(points[0]); // 闭合多边形
      
      const grid = document.createElementNS("http://www.w3.org/2000/svg", "polyline");
      grid.setAttribute('points', points.join(' '));
      grid.setAttribute('class', 'grid-line');
      document.querySelector('svg').appendChild(grid);
    }
    
    // 绘制轴线
    for (let i = 0; i < numDimensions; i++) {
      const angle = getAngle(i);
      const endX = centerX + maxRadius * Math.cos(angle);
      const endY = centerY + maxRadius * Math.sin(angle);
      
      const axis = document.createElementNS("http://www.w3.org/2000/svg", "line");
      axis.setAttribute('x1', centerX);
      axis.setAttribute('y1', centerY);
      axis.setAttribute('x2', endX);
      axis.setAttribute('y2', endY);
      axis.setAttribute('class', 'axis-line');
      document.querySelector('svg').appendChild(axis);
      
      // 绘制维度标签(位置略超出最大半径)
      const labelOffset = 20;
      const labelX = centerX + (maxRadius + labelOffset) * Math.cos(angle);
      const labelY = centerY + (maxRadius + labelOffset) * Math.sin(angle);
      
      const label = document.createElementNS("http://www.w3.org/2000/svg", "text");
      label.setAttribute('x', labelX);
      label.setAttribute('y', labelY);
      label.setAttribute('text-anchor', 'middle');
      label.setAttribute('dominant-baseline', 'middle');
      label.setAttribute('class', 'dimension-label');
      label.textContent = dimensions[i];
      document.querySelector('svg').appendChild(label);
    }
    
    // 绘制中心点
    const centerCircle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    centerCircle.setAttribute('cx', centerX);
    centerCircle.setAttribute('cy', centerY);
    centerCircle.setAttribute('r', 5);
    centerCircle.setAttribute('class', 'center-circle');
    document.querySelector('svg').appendChild(centerCircle);
    
    // 绘制数据多边形
    dataGroups.forEach((data, groupIndex) => {
      const points = [];
      for (let i = 0; i < numDimensions; i++) {
        const coords = getCoordinates(i, data[i]);
        points.push(`${coords.x},${coords.y}`);
      }
      points.push(points[0]); // 闭合多边形
      
      const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
      polygon.setAttribute('points', points.join(' '));
      polygon.setAttribute('class', `data-polygon-${groupIndex + 1}`);
      document.querySelector('svg').appendChild(polygon);
    });
    
    // 绘制图例
    legends.forEach((legend, index) => {
      const legendX = 450;
      const legendY = 100 + index * 30;
      
      // 图例颜色块
      const colorBox = document.createElementNS("http://www.w3.org/2000/svg", "rect");
      colorBox.setAttribute('x', legendX);
      colorBox.setAttribute('y', legendY - 10);
      colorBox.setAttribute('width', 15);
      colorBox.setAttribute('height', 15);
      colorBox.setAttribute('fill', index === 0 ? 'rgba(54, 162, 235, 0.2)' : 'rgba(75, 192, 192, 0.2)');
      colorBox.setAttribute('stroke', index === 0 ? 'rgba(54, 162, 235, 1)' : 'rgba(75, 192, 192, 1)');
      colorBox.setAttribute('stroke-width', 2);
      document.querySelector('svg').appendChild(colorBox);
      
      // 图例文本
      const legendText = document.createElementNS("http://www.w3.org/2000/svg", "text");
      legendText.setAttribute('x', legendX + 25);
      legendText.setAttribute('y', legendY + 3);
      legendText.setAttribute('class', 'legend-item');
      legendText.textContent = legend;
      document.querySelector('svg').appendChild(legendText);
    });
  ]] ></script>
</svg>
    				
				
				

20.7.2. drawsvg

20.7.2.1. 安装

		
pip3 install drawsvg -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install cairosvg -i https://pypi.tuna.tsinghua.edu.cn/simple
		
			

20.7.2.2. 绘制多边形

		
lines = draw.Lines(
    # 坐标
    5, 5,
    # 横线 
    200, 5,
    # 竖线 
    200, 40, 
    # 斜线
    200 - 10, 20,
    # 横线2
    5 + 10, 20,
    # 斜线
    5, 40,
    # 闭合竖线
    5,5,
    fill='none', stroke='black')		
		
			

20.7.2.3. SVG 事件

		
<!DOCTYPE html>  
<html>  
<body>  
<svg width="500" height="150">  

<rect x="10" y="10" width="100" height="40"  
   style="stroke: black; fill: silver; fill-opacity: .4;"  
   onmouseover="this.style.stroke = 'blue'; this.style['stroke-width'] = 5;"  
   onmouseout="this.style.stroke = 'green'; this.style['stroke-width'] = 1;"
   onclick="this.style['width'] = 300;" />  

</svg>  
</body>  
</html>		
		
			
		
<!DOCTYPE html>
<html>

<body>
   <input id="aa" type="text" value="200" onclick="svg.style['width']=this.value;" />
   <svg width="500" height="150">


      <rect id='svg' x="10" y="10" width="100" height="40" style="stroke: black; fill: silver; fill-opacity: .4;"
         onmouseover="this.style.stroke = 'blue'; this.style['stroke-width'] = 5;"
         onmouseout="this.style.stroke = 'green'; this.style['stroke-width'] = 1;"
         onclick="this.style['width'] = 300; aa.value='300'" />

   </svg>
</body>

</html>		
		
			

20.7.3. CairoSVG - SVG 转换为 PNG/PDF/PS

			
$ pip3 install cairosvg			
			
		
			
$ cairosvg image.svg -o image.png			
			
		
			
$ python3
>>> import cairosvg
>>> cairosvg.svg2pdf(url='image.svg', write_to='image.pdf')			
			
		

		
import os

import cairosvg

input_file = os.getcwd() + "/mindmap.svg"
output_file = os.getcwd() + "/mindmap.png"

cairosvg.svg2png(url=input_file, write_to=output_file)

# 设置背景色
cairosvg.svg2png(url=input_file, write_to=output_file, background_color="white")