如何创建SVG径向线

时间:2018-09-10 11:46:41

标签: svg

Simple SVG gauge with radial lines and number range我正在尝试创建一个带有径向线和范围为0-100的数字的比例。 这是我的代码:

<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<head>
    <title>SVG Gauge</title>
</head>
<style>
    #wrapper {
        position: relative;  
        margin: auto;
    }

    #meter {
        width: 100%; 
        height: 100%;
        transform: rotateX(180deg);
    }

    .circle {
        fill: none;
    }

    #mask {
        stroke: #404040; 
        stroke-width: 60;
    }

    .blackie {
        fill:none;
        stroke: #000000;
        stroke-width: 30;
    }

    .range { 
        stroke-width: 60; 
    }

    .scale {
        stroke: #cccccc;
    }

    #slider, #lbl {
        position: absolute;
    }

    #slider {
        cursor: pointer;
        left: 0;
        margin: auto;
        right: 0;
        top: 58%;
        width: 94%;
    }

    #lbl {
        background-color: #4B4C51; 
        border-radius: 2px;
        color: white;   
        font-family: 'courier new';
        font-size: 15pt;
        font-weight: bold;
        padding: 4px 4px 2px 4px;
        right: -48px;
        top: 57%;
    }

    #meter_needle {
        height: 40%;
        left: 0;
        margin: auto;
        position: absolute;
        right: 0;
        top: 10%;
        transform-origin: bottom center;
        transform: rotate(270deg);
    }

</style>

<body>
    <div id="wrapper">
        <svg id="meter">
            <g class="scale">
                <defs>
                    <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
                        <stop offset="0%" style="stop-color:rgb(102, 102, 255);stop-opacity:1" />
                        <stop offset="100%" style="stop-color:rgb(204, 204, 255);stop-opacity:1" />
                    </linearGradient>
                </defs>
                <circle id="high" class="circle range" cx="50%" cy="50%" stroke="url(#grad)">
                </circle>
                <circle id="mask" class="circle" cx="50%" cy="50%">
                </circle>
                <circle id="low" class="blackie" cx="50%" cy="50%" r="360">
                </circle>
                <circle id="outline_ends" class="circle outline" cx="50%" cy="50%">
                </circle>
            </g>
        </svg>
        <img id="meter_needle" src="gauge-needle.svg" alt="">
        <input id="slider" type="range" min="0" max="100" value="0" />
        <label id="lbl" id="value" for="">0%</label>
    </div>
    <script>
        var r = 400;
        var circles = document.querySelectorAll('.circle');
        var total_circles = circles.length;
        for (var i = 0; i < total_circles; i++) {
            circles[i].setAttribute('r', r);
        }
        var meter_dimension = (r * 2) + 100;
        var wrapper = document.querySelector('#wrapper');
        wrapper.style.width = meter_dimension + 'px';
        wrapper.style.height = meter_dimension + 'px';

        var cf = 2 * Math.PI * r;
        var semi_cf = cf / 2;
        var z = 40 * Math.PI;

        document.querySelector('#outline_ends')
            .setAttribute('stroke-dasharray', 2 + ',' + (semi_cf - 2));
        document.querySelector('#high')
            .setAttribute('stroke-dasharray', semi_cf + ',' + cf);
        document.querySelector('#mask')
            .setAttribute('stroke-dasharray', semi_cf + ',' + cf);
        document.querySelector('#low')
            .setAttribute('stroke-dasharray', semi_cf - z + ',' + cf);

        var slider = document.querySelector('#slider');
        var lbl = document.querySelector("#lbl");
        var svg = document.querySelector('#meter');
        var high = document.querySelector('#high');
        var mask = document.querySelector('#mask');
        var low = document.querySelector('#low');
        var meter_needle = document.querySelector('#meter_needle');

        function range_change_event() {
            var percent = slider.value;
            var meter_value = semi_cf - ((percent * semi_cf) / 100);
            mask.setAttribute('stroke-dasharray', meter_value + ',' + cf);
            meter_needle.style.transform = 'rotate(' + (270 + ((percent * 180) / 100)) + 'deg)';
            lbl.textContent = percent + '%';
        }
        slider.addEventListener('input', range_change_event);
    </script>
</body>

</html>

我在网络上发现了很多关于HTML canvas和D3js的很好的示例,但没有基于SVG的示例。 我正在考虑创建一个元素“线”并将其添加到黑色弧上。 创建数字刻度的最简单方法是什么?

2 个答案:

答案 0 :(得分:1)

  

创建数字刻度的最简单方法是什么?

设置svg圆缩放比例最简单的方法是为其半径设置动画

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
    width="400" height="400" viewBox="0 0 400 400" >  

<circle cx="200" cy="200"  r="10" fill="none" stroke-width="2" stroke="purple" >
<animate attributeName="r" values="1;100;1" dur="4s" repeatCount="indefinite" />
</circle> 
</svg>	 

答案 1 :(得分:1)

您在这里:

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="-250 -250 500 500" width="500" height="500" id="svg">
      <defs>
        <style>
            line {
                stroke: black;
                stroke-width: 1px;
            }

            text {
                fill: red;
                text-anchor: middle;
                font-size: 16px;
                font-family: sans-serif;
            }

            rect {
                fill: transparent;
            }

            #id {
                display: none;
            }

            .origin {
                fill: green;
            }

            .outer {
                fill: none;
                stroke: black;
            }
        </style>
      </defs>

        <circle r="5" cx="0" cy="0" class="origin"/>
        <path d="M-180,0 a1,1 0 0,1 360,0" class="outer"/>

        <g id="gauge" transform="rotate(-90)">
            <g id="noon">
                <rect x="-10" y="-220" width="20" height="100"/>
                <line x1="0" y1="-190" x2="0" y2="-180"/>
                <text x="0" y="-200"></text>
            </g>
        </g>

    </svg>

    <script>
        for (i=0; i<=180; i = i + 18) {
            var new_tick = noon.cloneNode(true);
            new_tick.getElementsByTagName('text')[0].textContent = i/180 * 100;
            new_tick.removeAttribute("id");
            new_tick.setAttribute("transform", "rotate(" + i + " 0 0)");
            gauge.appendChild(new_tick);
        }
    </script>

我认为这是不言而喻的。 (例如,RECT只是一个指南,如果您想更好地可视化每个G内部的内容,可以通过更改填充来打开它。)

如果您有任何后续问题,请告诉我。

如果有帮助,这里是一个Codepen:https://codepen.io/MSCAU/pen/OoQMdV