svg基本标签

学习站点:

SVG 路径 | 菜鸟教程

https://www.w3school.com.cn/svg

https://svgjs.dev/docs/ svg编辑常用方法

1.text 文字标签

 x 右起点 
 y 下起点
 text-anchor 文字左右居中
dominant-baseline="central" 上下居中
x,y要选中心点坐标

<text x="200" y="0" style="font-size:24px; writing-mode: tb;">垂直文字</text>

<text class="title" x="20" y="27.5" dx="-14 -14 -14 -14 -14 -14" dy="0 15 15 15 15 15">
    响应率︵%︶
</text>
text{
    font-size: 14px;
    fill: rgb(232, 239, 244);
    text-anchor: middle;
  }

默认<text>从起始位置(x,y)开始展示
fill的默认为black,stroke默认为none
text-anchor="middle"
start|middle|end(起始坐标|中轴坐标|结束坐标)

tspan 文本分行
<text x="240" y="120"> 
    <tspan>SVG</tspan>
    <tspan>SVG</tspan>
</text>

文字排列沿线
<defs>
    <path id="MyPath"
          d="M 100 200 
             C 200 100 300   0 400 100
             C 500 200 600 300 700 200
             C 800 100 900 100 900 100" />
  </defs>
  <use xlink:href="#MyPath" fill="none" stroke="red"  />
 <text font-family="Verdana" font-size="42.5">
    <textPath xlink:href="#MyPath">
      We go up, then we go down, then up again
    </textPath>
  </text>

2. image 图片标签

x y width height
xlink:href 图片位置

3.circle 圆标签

cx cy r
fill stroke stroke-width transparent

4.rect 柱形标签

width height x y

5.line 线标签

x1 y1 x2 y2
stroke-opacity 透明度

6.marker 箭头标签

<svg> 
<defs>
<marker id="arrow" 
		markerUnits="strokeWidth" 
		markerWidth="4" 
		markerHeight="4" 
		viewBox="0 0 10 4" 
		refX="0" 
		refY="3" 
		orient="auto">
        <path d="M0,0 L9,3 L0,6 Z" style="fill: #00ff00;" />
</marker>
</defs>
 
<!-- 实箭头的使用-->
<polyline
  points="0,15 50,15"
  fill="none"
  stroke="#00ff00"
  stroke-width="10"
  marker-end="url(#arrow)"
></polyline>
</svg>

双向箭头
 <svg class="page-map">
        <defs>
            <marker id="mar-success"
                    markerUnits="strokeWidth"
                    markerWidth="5"
                    markerHeight="5"
                    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: grey;" />
            </marker>
            <marker id="mar1-success"
                    markerUnits="strokeWidth"
                    markerWidth="5"
                    markerHeight="5"
                    viewBox="0 0 12 12"
                    refX="6"
                    refY="6"
                    orient="auto">
                <path d="M10,2 L2,6 L10,10 L6,6 L10,2" style="fill: grey;" />
            </marker>
        </defs>
        <line x1="50" y1="50" x2="100" y2="50" id="montoser" stroke="grey" stroke-width="8" marker-start="url(#mar1-success)" marker-end="url(#mar-success)" />
    </svg>

7.linearGradient 线性渐变

树的阴影效果
<svg width="400" height="600">
        <defs>
            <pattern id="grap" patternUnits="userSpaceOnUse" x="0" y="0" width="100" height="67" viewBox="0 0 102 76">
                <image x="0" y="0" width="102" height="76" xlink:href="http://pic27.nipic.com/20130324/9148618_153134223000_2.jpg"></image>
            </pattern>
            <linearGradient id="TrunkGrad">
                <stop offset="0%" stop-color="#663300"></stop>
                <stop offset="40%" stop-color="#996600"></stop>
                <stop offset="100%" stop-color="#552200"></stop>
            </linearGradient>
            <rect x="-5" y="-50" width="10" height="50" id="Trunk"></rect>
            <path d="M-25,-50L-10,-80L-20,-80L-5,-110L-15,-110L0,-140L15,-110L5,-110L20,-80L10,-80L25,-50Z" fill="#f00" id="can">
            </path>
            <linearGradient id="shadow" x=0 y=0 x2=0 y2=100%>
                <stop offset="0%" stop-color="#000" stop-opacity=".5"></stop>
                <stop offset="20%" stop-color="#996600" stop-opacity="0"></stop>
            </linearGradient>
            <g id="tree">
                <use xlink:href="#Trunk" fill="url(#TrunkGrad)"/>
                <use xlink:href="#Trunk" fill="url(#shadow)"/>
                <use xlink:href="#can" fill="none" stroke="#663300" stroke-linejoin="round" stroke-width="4px" />
                <use xlink:href="#can" fill="#339900" stroke="none"/>
            </g>
            <g id="treeShadow">
                <use xlink:href="#Trunk" fill="#000"/>
                <use xlink:href="#can" fill="#000" stroke="none"/>
            </g>
        </defs>
        <text y=60 x=200 font-family="Arial" font-size="60px" fill="#996600" text-anchor="middle">tree</text>
        <text y=90 x=200 font-family="Arial" font-size="20px" fill="#996600" text-anchor="middle" id="treeCounter"></text>
        <text y=550 x=20 font-family="Arial" font-size="20px" fill="#996600" text-anchor="left">
            <tspan>点击一颗树或树的影子</tspan>
            <tspan>并移除掉它。。。</tspan>
        </text>
        <g transform="translate(-10,350)" stroke-width="20" stroke="url(#grap)" stroke-linejoin="round">
            <path d="M0,0Q170,-50 260,-190Q310,-250 410,-250" fill="none">
            </path>
        </g>
        <!--skewX() x轴方向向右扭曲25像素-->
        <use xlink:href="#treeShadow" transform="translate(130,250) scale(1,.6) skewX(-25)" opacity="0.4" />
        <use xlink:href="#tree" transform="translate(130,250)" />
        <use xlink:href="#treeShadow" transform="translate(260,500) scale(2,1.2) skewX(-25)" opacity="0.4" />
        <use xlink:href="#tree" transform="translate(260,500) scale(2)" />
    </svg>

8.g 组合标签

可将字体、颜色、边框等样式等放到g上使用,组合后可结合 defs可多处使用

9.path 标签

画拆线时用line效果可能不好,结合处放大可能会有断开处

M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Bézier curve
T = smooth quadratic Bézier curveto
A = elliptical Arc
Z = closepath

注意:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。


1.直线命令
<svg width="100px" height="100px" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path d="M10 10 H 90 V 90 H 10 L 10 10"/> 
    <!-- Points -->
    <circle cx="10" cy="10" r="2" fill="red"/>
    <circle cx="90" cy="90" r="2" fill="red"/>
    <circle cx="90" cy="10" r="2" fill="red"/>
    <circle cx="10" cy="90" r="2" fill="red"/>
</svg>

2.曲线命令
<!--三次贝塞尔曲线-->
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="transparent"/>
    <circle cx="130" cy="110" r="2" fill="red"/>
    <circle cx="120" cy="140" r="2" fill="red"/>
    <line x1="130" y1="110" x2="120" y2="140" style="stroke:rgb(255,0,0);stroke-width:2"/>
    <circle cx="180" cy="140" r="2" fill="red"/>
    <circle cx="170" cy="110" r="2" fill="red"/>
    <line x1="180" y1="140" x2="170" y2="110" style="stroke:rgb(255,0,0);stroke-width:2"/>
</svg>

<!--三次贝塞尔曲线简写-->
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/>
    <circle cx="10" cy="80" r="2" fill="red"/>
    <circle cx="40" cy="10" r="2" fill="red"/>
    <line x1="10" y1="80" x2="40" y2="10" style="stroke:rgb(255,0,0);stroke-width:1"/>

    <circle cx="65" cy="10" r="2" fill="red"/>
    <circle cx="95" cy="80" r="2" fill="red"/>
    <line x1="65" y1="10" x2="95" y2="80" style="stroke:rgb(255,0,0);stroke-width:1"/>

    <circle cx="125" cy="150" r="2" fill="blue"/>
    <circle cx="180" cy="80" r="2" fill="red"/>
    <circle cx="150" cy="150" r="2" fill="red"/>
    <line x1="95" y1="80" x2="125" y2="150" style="stroke:blue;stroke-width:1"/>
    <line x1="180" y1="80" x2="150" y2="150" style="stroke:rgb(255,0,0);stroke-width:1"/>
</svg>

<!--二次贝塞尔曲线-->
<svg width="190px" height="160px" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/>
     <!--Points-->
    <circle cx="10" cy="80" r="2" fill="red"/>
    <circle cx="95" cy="10" r="2" fill="red"/>
    <circle cx="180" cy="80" r="2" fill="red"/>
    <line x1="10" y1="80" x2="95" y2="10" style="stroke:rgb(255,0,0);stroke-width:1"/>
    <line x1="95" y1="10" x2="180" y2="80" style="stroke:rgb(255,0,0);stroke-width:1"/>
</svg>  

10.js编辑svg元素属性

两种方式:
1)style样式只能这样修改才会生效
document.getElementById("mycircle").style.fill='red';
2)其他属性修改
document.getElementById("mycircle").setAttribute("r",r);

11.围绕中心转动


<style>
svg {
  border:1px solid blue;
  margin:100px;
}
</style>

<svg width="500" height="250" >
  <rect
        x="50" y="50"
        width="50" height="50"
        fill="red">
    <animateTransform
                      attributeName="transform"
                      attributeType="XML"
                      type="rotate"
                      from="0 75 75"
                      to="360 75 75"
                      begin="0"
                      dur="2"
                      repeatCount="indefinite" />
  </rect>
</svg>          

12.文字沿着指定的曲线运动

<svg width="100%" height="100%" viewBox="0 0 1000 300"
     xmlns="http://www.w3.org/2000/svg" 
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <path id="MyPath"
          d="M 100 200 
             C 200 100 300   0 400 100
             C 500 200 600 300 700 200
             C 800 100 900 100 900 100" />
  </defs>

  <use xlink:href="#MyPath" fill="none" stroke="red"  />

  <text font-family="Verdana" font-size="42.5">
    <textPath xlink:href="#MyPath">
      CSDN-叶常落
             <animate attributeName="startOffset" from="0" to ="830" begin="0s" dur="10s" repeatCount="indefinite"/>

    </textPath>
  </text>

  <!-- Show outline of the viewport using 'rect' element -->
  
</svg>

13.js制作的小圆柱


 <div id="main" style="width: 100%; height: 800px"></div>

 <script>
     var svgNS = "http://www.w3.org/2000/svg";
        var toolTip;

        function initSvg(myDiv, array) {
            document.getElementById(myDiv).innerHTML = '';            

            var oParent = document.getElementById(myDiv);

            var oWidth = oParent.clientWidth;
            var oHight = oParent.clientHeight;
            var count = array.length;
            var avg = (oWidth - 100) / (array.length + 1);

            var maxCapacity = 0;
            for (var i = 0; i < count; i++) {
                var item = array[i];
                maxCapacity = Math.max(maxCapacity, item.capacity);
            }

            for (var i = 0; i < count; i++) {
                var item = array[i];
                var oSvg = createSvg(avg, oHight, maxCapacity, item);
                oParent.appendChild(oSvg);
            }

        }

        function createSvg(oWidth, oHight, maxCapacity, item) {
            var oSvg = createTag('svg', {'xmlns': svgNS, 'width': oWidth, 'height': oHight, x: 0});
            var btmY = oHight * 0.7;
            var leftX = oWidth * 0.1;
            var rightX = oWidth * 0.9;
            var rx = (leftX + rightX) / 2;
            var ry = rx / 5;

            var topY = 20 + ry + (btmY - 20 - ry) * (1 - (item.capacity / maxCapacity));
            var costPencent = (item.remain / item.capacity) > 1 ? 1 : (item.remain / item.capacity);
            var midY = topY + (btmY - topY) * (1 - costPencent);

            var textY = (btmY + 25);

            var oG = createTag('g', {'style': 'cursor:pointer; padding:0px 10px;'});

            var iName = item.name;
            if (item.name && item.name.length > 12) {
                iName = item.name.substring(0, 12) + "...";
            }
            var oText = createTag('text', {
                'x': rx,
                'y': textY,
                width: oWidth,
                'text-anchor': 'middle',
                'fill': '#0dc59f',
            }, iName);
            var emptyPath = createTag('path', {
                'd': 'M' + leftX + ',' + topY + ' A' + rx + ',' + ry + ' 0 0,0 ' + rightX + ',' + topY + ' A' + rx + ',' + ry + ' 0 0,0 ' + leftX + ',' + topY + ' L' + leftX + ',' + midY + ' A' + rx + ',' + ry + ',0 0,0 ' + rightX + ',' + midY + ' L' + rightX + ',' + topY,
                'style': 'stroke:#660000; fill: #fff',
            });
            var remainPath = createTag('path', {
                'd': 'M' + leftX + ',' + midY + ' A' + rx + ',' + ry + ' 0 0,0 ' + rightX + ',' + midY + ' A' + rx + ',' + ry + ' 0 0,0 ' + leftX + ',' + midY + ' L' + leftX + ',' + btmY + ' A' + rx + ',' + ry + ',0 0,0 ' + rightX + ',' + btmY + ' L' + rightX + ',' + midY,
                'style': 'stroke:#660000; fill: #c23531',
            });
            var remainAni = createTag('animate', {
                attributeName: 'd',
                dur: '0.5',
                from: 'M' + leftX + ',' + topY + ' A' + rx + ',' + ry + ' 0 0,0 ' + rightX + ',' + topY + ' A' + rx + ',' + ry + ' 0 0,0 ' + leftX + ',' + topY + ' L' + leftX + ',' + btmY + ' A' + rx + ',' + ry + ',0 0,0 ' + rightX + ',' + btmY + ' L' + rightX + ',' + topY,
                to: 'M' + leftX + ',' + midY + ' A' + rx + ',' + ry + ' 0 0,0 ' + rightX + ',' + midY + ' A' + rx + ',' + ry + ' 0 0,0 ' + leftX + ',' + midY + ' L' + leftX + ',' + btmY + ' A' + rx + ',' + ry + ',0 0,0 ' + rightX + ',' + btmY + ' L' + rightX + ',' + midY
            });
            oSvg.appendChild(oG);
            oG.appendChild(emptyPath);
            remainPath.appendChild(remainAni);
            oG.appendChild(remainPath);
            oG.appendChild(oText);

            oG.onmousemove = function (ev) {
                if (toolTip) {
                    toolTip.remove();
                }

                var ev = ev || window.event;
                toolTip = document.createElement("div");
                toolTip.setAttribute("style", "position: absolute; border-style: solid; white-space: nowrap; z-index: 9999999; transition: left 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s, top 0.4s cubic-bezier(0.23, 1, 0.32, 1) 0s; background-color: rgba(50, 50, 50, 0.7); border-width: 0px; border-color: rgb(51, 51, 51); border-radius: 4px; color: rgb(255, 255, 255); font: 14px / 21px &quot;Microsoft YaHei&quot;; padding: 5px; left: 694px; top: 392px; pointer-events: none;");
                toolTip.style.left = (ev.clientX + 25) + 'px';
                toolTip.style.top = (ev.clientY + 25) + 'px';

                var rPencent = item.remain / item.capacity * 100;
                rPencent = rPencent.toFixed(2) + "%";

                var iHtml = item.name + "<br><span style=\"display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:#c23531;\"></span>总容量:" + item.capacity
                    + "<br><span style=\"display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:#2f4554;\"></span>剩余量:" + item.remain + " (" + rPencent + ")";
                toolTip.innerHTML = iHtml;

                document.body.appendChild(toolTip);
            };
            oG.onmouseleave = function (ev) {
                if (toolTip) {
                    toolTip.remove();
                }
            }
            return oSvg;
        }

        function createTag(tag, params, innerHtml) {
            var oTag = document.createElementNS(svgNS, tag);
            for (var attr in params) {
                oTag.setAttribute(attr, params[attr]);
            }
            if (innerHtml) {
                oTag.innerHTML = innerHtml;
            }
            return oTag;
        }

        function initData() {
           initSvg('main', data.data);
        }

        var data = {
            "code": 200,
            "msg": null,
            "count": "0",
            "data": [{
                "name": "柱子1",
                "capacity": 20000.00,
                "total": 466.00,
                "cost": 0,
                "remain": 466.00
            }, {
                "name": "柱子2",
                "capacity": 10200.00,
                "total": 11041.00,
                "cost": 0,
                "remain": 11041.00
            }, {
                "name": "柱子3",
                "capacity": 16300.00,
                "total": 0,
                "cost": 0,
                "remain": 0
            }, {
                "name": "柱子4",
                "capacity": 12400.00,
                "total": 971.00,
                "cost": 0,
                "remain": 971.00
            }, {
                "name": "柱子5",
                "capacity": 12000.00,
                "total": 3000.00,
                "cost": 0,
                "remain": 3000.00
            }, {
                "name": "柱子6",
                "capacity": 10400.00,
                "total": 485.00,
                "cost": 0,
                "remain": 485.00
            }, {
                "name": "柱子7",
                "capacity": 12000.00,
                "total": 0,
                "cost": 0,
                "remain": 0
            }, {
                "name": "柱子8",
                "capacity": 10000.00,
                "total": 0,
                "cost": 0,
                "remain": 0
            }, {
                "name": "柱子9",
                "capacity": 10000.00,
                "total": 548.00,
                "cost": 0,
                "remain": 548.00
            }, {
                "name": "柱子10",
                "capacity": 10000.00,
                "total": 0,
                "cost": 0,
                "remain": 0
            }]
        }
        
        window.onload = function() {
            initData();
        }
 </script>

14、 svg.js使用

<!DOCTYPE html>
<html>

<head>
    <title>SVG.js画图Demo</title>
    <link rel="stylesheet" href="svg/svg.select.css" media="all">
    <script src="svg/svg.js"></script>
    <script src="svg/svg.draggable.js"></script>
    <script src="svg/svg.select.js"></script>
    <script src="svg/svg.resize.js"></script>
    <script src="svg/svg.panzoom.js"></script>
    <script src="svg/jquery-1.10.2.js"></script>
</head>

<body>

    <div class="layui-fluid">
        <div class="left" style="width: 210px">
            <div class="buttons">
                <img id="imgYard" nodeType="yard" class="controls" src="image/yard.svg" />
            </div>
            <div class="buttons">
                <img id="imgFactory" nodeType="factory" class="controls" src="image/factory.svg" />
            </div>
            <div class="buttons">
                <img id="imgSource" nodeType="source" class="controls" src="image/source.svg" />
            </div>
            <div class="buttons">
                <img id="imgPoint" nodeType="point" class="controls" src="image/point.svg" />
            </div>
        </div>
        <div class="main" style="width: calc(100% - 30px);border-left: none;">
            <svg id="mSvg" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
                <defs>
                    <image id="yard" xlink:href="image/yard.svg"></image>
                    <image id="factory" xlink:href="image/factory.svg"></image>
                    <image id="source" xlink:href="image/source.svg"></image>
                    <image id="point" xlink:href="image/point.svg"></image>
                </defs>
            </svg>
        </div>
        <div class="right"></div>
    </div>

    <style>
        .layui-fluid {
            padding: 10px 15px;
            /* height: calc(100% - 24px); */
            height: calc(100vh - 36px);
            display: flex;
        }

        .left,
        .main {
            box-shadow: rgb(13 197 159 / 10%) 0px 0px 40px 0px inset;
            border-width: 1px;
            border-style: solid;
            border-color: rgba(13, 197, 159, 0.4);
            border-image: initial;
            height: 100%;
        }

        .main {
            cursor: url("image/openhand.cur"), default;
        }

        .drag {
            cursor: url("image/closedhand.cur"), default;
        }

        .controls {
            width: 170px;
            height: 85px;
            cursor: pointer;
        }

        .buttons {
            margin: auto;
            line-height: 90px;
            text-align: center;
        }
    </style>

    <script>
        var joinLines = [];
        const lineMap = {
            "yard": "factory",
            "factory": "point",
            "source": "point",
        }

        const draw = SVG('mSvg').size('100%', '100%').panZoom({ zoomMin: 0.5, zoomMax: 2 });
        const rootGroup = draw.group().id('rootGroup');

        // draw.defs().pattern(10, 10, function (add) {
        //     add.path('M 10 0 L 0 0 0 10').fill('none').stroke({color: '#eee', width: 0.5})
        //     add.pattern(10, 10, function (add) {
        //         add.rect().attr({width: 10, height: 10, fill: 'url(#smallGrid)'})
        //         add.path('M 100 0 L 0 0 0 100').fill('none').stroke({color: '#eee', width: 1})
        //     }).attr({'id': 'grid'})
        // }).attr({'id': 'smallGrid'})
        // const gridRect = rootGroup.rect().size('100%', '100%').fill('url(#grid)').id('gridrect') // 网格
        // rootGroup.add(gridRect)

        $('.controls').off('mousedown').on('mousedown', function () {
            console.log($(this).attr('nodeType'))
            let nodeType = $(this).attr('nodeType')
            draw.remember('addNode', nodeType);
        })

        function addNewNode(nodeType) {
            let selectNode = rootGroup.use(nodeType).attr('nodeType', nodeType);
            draw.remember('selectNode', selectNode)
            selectNode.on('selectNode mousedown', function (e) {
                console.log('selectNode mousedown')
                let startNode = draw.remember('startNode');
                if (startNode && this !== startNode) {
                    startNode.selectize(false).resize(false).draggable(false);
                }
                this.selectize().resize().draggable();
                addJoinLine(this);
                draw.remember('startNode', this);
                e.stopPropagation();
            })
            selectNode.on('dragend', function (e) {
                console.log('dragend')
                updateJoinLine(this);
                // e.stopPropagation();
            });
            selectNode.on('resizing', function (e) {
                console.log('resizing')
                updateJoinLine(this);
                // e.stopPropagation();
            });
            return selectNode;
        }

        $('.main').on('mouseover', function (e) {
            // console.log('mouseover', e)
            let addNode = draw.remember('addNode');
            if (addNode) {
                let selectNode = draw.remember('selectNode');
                if (!selectNode) {
                    selectNode = addNewNode(addNode);
                }
                let rbox = selectNode.rbox();
                let point = draw.point(e.pageX - rbox.width / 2, e.pageY - rbox.height / 2);
                selectNode.move(point.x, point.y);
                selectNode.on('mouseup', function (e) {
                    // console.log('mouseup', e)
                    //鼠标左键保留
                    if (e.which === 1) {
                        console.log('save')
                        draw.forget('addNode');
                        draw.forget('selectNode');
                    }
                    this.off('mouseup');
                })
            }
        }).on('mousedown', function (e) {
            console.log('main.mousedown', e)
            $('.main').addClass('drag');
            let startNode = draw.remember('startNode');
            if (startNode) {
                let rbox = startNode.rbox();
                if (rbox.x <= e.pageX && rbox.x + rbox.width >= e.pageX && rbox.y <= e.pageY && rbox.y + rbox.height >= e.pageY) {
                    console.log('inner')
                    draw.forget('startDrag');
                } else {
                    console.log('outer')
                    draw.remember('startDrag', e);
                    draw.forget('startNode');
                    startNode.selectize(false).resize(false).draggable(false);
                }
            } else {
                draw.remember('startDrag', e);
            }
        }).on('mouseup', function (e) {
            console.log('main.mouseup', e)
            let selectNode = draw.remember('selectNode');
            if (selectNode) {
                console.log('delete')
                draw.forget('addNode');
                draw.forget('selectNode');                
                selectNode.remove();
                e.stopPropagation();
            }
            let startNode = draw.remember('startNode');
            if (startNode) {
                draw.forget('startNode'); 
                startNode.selectize(false).resize(false).draggable(false);            
                startNode.remove();
            }
            $('.main').removeClass('drag');
        })

        $(document).on('keydown', function (e) {
            let startNode = draw.remember('startNode');
            console.log('document.keydown', e, startNode)
            if (startNode) {
                if (e.key == 'Delete') {
                    deleteSelectNode(startNode);
                } else if (e.key == 'ArrowLeft') {
                    let x = startNode.x();
                    x -= 3;
                    startNode.x(x);
                    updateJoinLine(startNode);
                } else if (e.key == 'ArrowRight') {
                    let x = startNode.x();
                    x += 3;
                    startNode.x(x);
                    updateJoinLine(startNode);
                } else if (e.key == 'ArrowUp') {
                    let y = startNode.y();
                    y -= 3;
                    startNode.y(y);
                    updateJoinLine(startNode);
                } else if (e.key == 'ArrowDown') {
                    let y = startNode.y();
                    y += 3;
                    startNode.y(y);
                    updateJoinLine(startNode);
                }
            }
        }).on('contextmenu', function(){
            return false;
        })

        function deleteSelectNode(node) {
            console.log('deleteNode', node.attr('nodeId'))
            if (node.attr('nodeId')) {
                top.layer.confirm('确定删除吗?', function (index) {
                    deleteNode(node);
                    top.layer.close(index);
                });
            } else {
                deleteNode(node);
            }
        }

        function deleteNode(node) {
            //删除连接线
            joinLines.forEach((joinLine, index) => {
                if (node === joinLine.startNode || node === joinLine.endNode) {
                    joinLine.path.remove();
                    joinLines.splice(index, 1);
                }
            });
            node.selectize(false).resize(false).draggable(false);
            node.remove();
            draw.forget('startNode')
        }

        //两个节点间添加连接线
        function addJoinLine(endNode) {
            let startNode = draw.remember('startNode');
            if (!startNode) return;
            if (startNode === endNode) {
                // console.log('节点之间才相互连线');
                return;
            }
            let repeat = false;
            joinLines.forEach(joinLine => {
                if (startNode === joinLine.startNode && endNode === joinLine.endNode) {
                    // console.log('不允许重复添加连线');
                    repeat = true;
                    return;
                }
            })
            let startNodeType = startNode.attr('nodeType');
            let endNodeType = endNode.attr('nodeType');
            if (endNodeType !== lineMap[startNodeType]) {
                console.log('不允许添加连线', startNodeType, endNodeType);
                return;
            }

            if (!repeat) {
                let path = drawLine(startNode, endNode);

                let joinLine = { path, startNode, endNode };
                joinLines.push(joinLine);

                draw.remember('startNode', endNode);
            }
        }

        //更新连接线位置
        function updateJoinLine(node) {
            joinLines.forEach(joinLine => {
                if (node === joinLine.startNode || node === joinLine.endNode) {
                    let path = drawLine(joinLine.startNode, joinLine.endNode, joinLine.path);
                    joinLine.path = path;
                }
            })
        }

        function drawLine(startNode, endNode, path) {
            let srb = startNode.rbox();
            let erb = endNode.rbox();
            let start;
            let end;

            //x轴距离较长,取左右边缘中点
            if (Math.abs(srb.cx - erb.cx) > Math.abs(srb.cy - erb.cy)) {
                if (srb.cx < erb.x) {
                    start = startNode.point(srb.x + srb.width, srb.y + srb.height / 2);
                    end = endNode.point(erb.x, erb.y + erb.height / 2);
                } else {
                    start = startNode.point(srb.x, srb.y + srb.height / 2);
                    end = endNode.point(erb.x + erb.width, erb.y + erb.height / 2);
                }
            } else { //y轴距离较远,取上下边缘中点
                if (srb.cy < erb.y) {
                    start = startNode.point(srb.x + srb.width / 2, srb.y + srb.height);
                    end = endNode.point(erb.x + erb.width / 2, erb.y);
                } else {
                    start = startNode.point(srb.x + srb.width / 2, srb.y);
                    end = endNode.point(erb.x + erb.width / 2, erb.y + erb.height);
                }
            }

            let mid = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };

            let pathArray = new SVG.PathArray([
                ['M', start.x, start.y]
                , ['L', mid.x, mid.y]
                , ['L', end.x, end.y]
            ]);
            // console.log(pathArray);

            if (path) {
                path.reference('marker-mid').remove();
                path.remove();
            }
            let nodeTypes = [startNode.attr('nodeType'), endNode.attr('nodeType')]
            path = draw.path(pathArray).attr('nodeType', nodeTypes.join('-'));
            rootGroup.add(path);
            path.marker('mid', 12, 12, function (add) {
                add.path('M2,2 L2,11 L10,6 L2,2').fill('#0dc59f')
            }).stroke({ width: 3, color: '#0dc59f' }).fill('none').back();

            path.on('click', function (e) {
                console.log('path.click')
                let startNode = draw.remember('startNode');
                if (startNode && this !== startNode) {
                    startNode.selectize(false).resize(false).draggable(false);
                }
                this.selectize().resize().draggable();
                draw.remember('startNode', this);
                // e.stopPropagation();
            })

            return path;
        }

        window.onresize = function () {
            heightAdaptive();
        }
        heightAdaptive()

        function heightAdaptive() {
            $(document).trigger('mouseup');
        }
    </script>
</body>

</html>

15.流动的铁路线

<!DOCTYPE html>
<html>
<body>
	<style style="text/css">
		 .svgLineDL{		 
		  animation:move2 1s infinite;
		}
		 @keyframes move2{
		   0%{
			stroke-dashoffset: 100;
		  }
		  100%{
			stroke-dashoffset: 0;
		  }
		} 
	</style>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <defs>
<symbol id="sym">
<polyline points="100 100 250 90 400 80 500 90 550 100 600 110"/>
</symbol>
</defs>
<g >
<use xlink:href="#sym" style="fill:none;stroke:black;stroke-width:20"/>
<use xlink:href="#sym" style="fill:none;stroke:rgb(128,128,128);stroke-width:18;
    stroke-dasharray:50 50;stroke-dashoffset :50" class="svgLineDL"/>
</g>
	
</svg>
 
</body>
</html>

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SVG-icon标签是一种用于在网页中显示可缩放矢量图形(Scalable Vector Graphics)的HTML标签。它允许开发者使用SVG格式的图像作为图标,并具有以下特点: 1. 可缩放性:SVG图像是基于矢量的,因此可以在不失真的情况下缩放到任意大小。 2. 矢量性:SVG图像使用数学描述来定义形状和路径,而不是像素网格,因此图像可以无损地缩放。 3. 可编辑性:SVG图像可以使用文本编辑器进行编辑,可以修改形状、颜色、大小等属性。 4. 支持透明度和滤镜效果:SVG图像可以应用透明度和各种滤镜效果,使得图标具有更多的样式和效果。 使用SVG-icon标签,你可以将SVG图像嵌入到HTML文件中,并通过CSS样式来控制其显示和行为。通常,你需要在HTML文件中使用`<svg>`标签来定义SVG图像,然后使用`<use>`标签来引用并显示特定的图标。 例如,假设你有一个名为"icon.svg"的SVG图像文件,其中包含一个id为"icon-heart"的图标。你可以在HTML文件中使用以下代码来显示该图标: ```html <svg class="icon"> <use xlink:href="icon.svg#icon-heart"></use> </svg> ``` 上述代码中,`<svg>`标签定义了一个具有"class"属性的SVG容器,用于包含图标。`<use>`标签通过"xlink:href"属性引用了SVG图像文件中的"id"为"icon-heart"的图标。 使用CSS样式,你可以进一步调整图标的大小、颜色等属性。例如: ```css .icon { width: 24px; height: 24px; fill: red; } ``` 上述代码将图标的宽度和高度设置为24像素,并将填充颜色设置为红色。 这就是使用SVG-icon标签在网页中显示可缩放矢量图形的基本方法。希望能对你有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值