【问题标题】:How to turn a <circle> (that's inside an svg) into a checkbox?如何将 <circle> (在 svg 中)变成一个复选框?
【发布时间】:2019-05-03 00:23:35
【问题描述】:

第 1 部分 - 所以我在 SVG 中有一堆 &lt;circle&gt;,我希望这些圆圈是复选框。之后我想:

第 2 部分 - 当圆圈 1(现在是一个复选框)被点击时,它被选中。但现在所有其他圈子都未选中。

这是我已经尝试过的:

第 1 部分 - 将 SVG 变成一个复选框:

<circle opacity="0.5" cx="842" cy="451.814" r="25.582" class="svg_spot" id="1" fill="#FFB60C" >
        <animate attributeName="r" values="25.582; 33; 25.582" keyTimes="0; 0.5; 1" begin="0s"  dur="1s" repeatCount="indefinite" calcMode="linear" />
        <input type="checkbox" id="spot1" name="spot" class="common_selector spot_id" value="spot1">   
</circle>

第 2 部分 -

$('input[name=spot]').click (function (){
        $(this).attr('checked', true);
        $('input[name=spot]').not(this).attr('checked', false);
});

感谢您的时间。非常感谢任何帮助!

【问题讨论】:

    标签: svg checkbox input


    【解决方案1】:

    无需任何 Javascript 即可实现此功能。

    这是如何工作的:

    • 将 SVG 放入输入的标签中。因此,单击 SVG(即标签)将激活该字段。
    • 使实际的&lt;input&gt; 字段不可见,以便您看到的只是标签。
    • 使用 :checked 伪选择器根据是否选择字段来设置 SVG 样式。

    // just here to prove that the form value is changing
    // prints value of spot field when inputs change
    document.querySelectorAll("#spot1, #spot2, #spot3")
            .forEach((elem) => elem.addEventListener("change", (evt) => console.log(document.myform.spot.value)));
    .common_selector {
      position: absolute;
      opacity: 0;
    }
    
    .common_selector + label svg {
      width: 50px;
      height: 50px;
      fill: red;
    }
    
    .common_selector:checked + label svg {
      fill: green;
    }
    <form name="myform">
    
    <input type="radio" id="spot1" name="spot" class="common_selector spot_id" value="spot1">
    <label for="spot1">
      <svg viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="50"/>
      </svg>
    </label>
    
    <input type="radio" id="spot2" name="spot" class="common_selector spot_id" value="spot2">
    <label for="spot2">
      <svg viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="50"/>
      </svg>
    </label>
    
    <input type="radio" id="spot3" name="spot" class="common_selector spot_id" value="spot3">
    <label for="spot3">
      <svg viewBox="0 0 100 100">
        <circle cx="50" cy="50" r="50"/>
      </svg>
    </label>
    
    </form>

    【讨论】:

      【解决方案2】:

      &lt;input&gt; 不是一个有效的 SVG 元素 - 它是一个 HTML 元素,所以这不起作用。您可以:

      1. 将输入元素包裹在&lt;foreignObject&gt; 元素中并这样做,或者
      2. 您可以使用定位将输入元素放置在圆上。但公平的警告 - 当表单元素定位在其他类型的元素之上时,它们并不总是能很好地发挥作用。或者
      3. 您可以手动绘制看起来像输入元素的 SVG,并使用 JavaScript 使其表现得像一个输入元素。或
      4. 既然您只需要一个圆,为什么不将输入元素包裹在一个具有适当边框半径的 Div 中,然后用这种方式制作一个圆。

      【讨论】:

        【解决方案3】:

        我希望我能理解你的问题。您不能将 svg 元素更改为输入,但您可以尝试模仿。

        // selects all the circles with a class of radio
        let inputs = document.querySelectorAll(".radio")
        // for every circle
        inputs.forEach(i =>{
          //when the circle is clicked
          i.addEventListener("click", ()=>{
           // remove the class checked from all the circles but the clicked one 
           inputs.forEach(j =>{if(i!==j)j.classList.remove("checked") })
           // toggle the class checked on the clicked one 
           i.classList.toggle("checked")
        })
        })
        svg{border:1px solid}
        .checked{fill:red}
        <svg id="theSVG" viewBox="800 410 300 85" width="300">
        <circle class="radio" opacity="0.5" cx="842" cy="451.814" r="25.582"  fill="#FFB60C"  stroke="#FFB60C" stroke-width="10" />   
        
          
        <circle class="radio"  opacity="0.5" cx="950" cy="451.814" r="25.582"  fill="#FFB60C"  stroke="#FFB60C" stroke-width="10" />   
          
        <circle class="radio"  opacity="0.5" cx="1050" cy="451.814" r="25.582"  fill="#FFB60C"  stroke="#FFB60C" stroke-width="10" /> 
        
        </svg>

        【讨论】:

          【解决方案4】:

          第 1 部分: 使用 &lt;foreignObect&gt; 在 SVG 中显示任何 HTML 元素:

          <foreignObject x="20" y="20" width="100" height="100">
             <input type="checkbox" id="spot1" name="spot" class="common_selector spot_id" 
             value="spot1">
          </foreignObject>
          

          然后您可以使用 css 隐藏此输入字段的默认样式并将您的圆圈放置在它上面。你可以在这里阅读:https://www.w3schools.com/howto/howto_css_custom_checkbox.asp

          第 2 部分: 使用单选按钮而不是复选框。复选框允许多个选择。单选按钮是您需要的。在这里阅读:https://www.w3schools.com/tags/att_input_type_radio.asp

          【讨论】:

            【解决方案5】:

            听起来您想将 SVG 用作一种“选择器”,例如颜色选择器,或者在我的情况下是行星选择器。在这里,我有一个代表太阳系的 SVG,用户点击一个行星来选择它。由于听起来您只想选择一个项目,因此单选按钮是更好的选择,但是下面的方法应该适用于任何一个。

            正如其他人所建议的那样,可以使用foreignObject 元素。如果没有专门为 svg 声明前缀命名空间并使用 .xhtml 扩展名保存文件,我无法让它工作。

            当然有很多方法可以用 javaScript 做类似的事情,但是使用底层单选按钮的一大优势是它可以处理所有逻辑并使验证更容易。

            我在圆圈上使用了一个空的div,作为单选按钮的label。由于单击label 会激活单选按钮,因此圆圈现在可以用作单选按钮!

            SVG 不显示在 sn-p 中,因此 div 为可见性添加了阴影。如果需要,可以隐藏实际的单选按钮。

            div{
            border: red solid 1px;
            background-color: black;
            opacity: 20%;
            }
            <html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg">
            
            <p>Select a planet</p>
            
            <form name="planetData">
            
                <input id="venus" name="planet" type="radio" value="venus" />
                <label for="venus">Venus</label>
            
                <input id="earth" name="planet" type="radio" value="earth" />
                <label for="venus">Earth</label>
            
                <input id="mars" name="planet" type="radio" value="mars" />
                <label for="venus">Mars</label>
            
            </form>
            
            <svg:svg height="100" width="100" viewbox="0 0 100 100">
            
                <svg:circle cx="0" cy="50" r="10" fill="yellow"/>
                <svg:circle cx="30" cy="75" r="10" fill="green"/>
                <svg:circle cx="60" cy="30" r="10" fill="blue"/>
                <svg:circle cx="90" cy="60" r="10" fill="red"/>
            
                <svg:foreignObject x="20px" y="65px" height="20px" width="20px">
                    <label for="venus">
                        <div style="height: 30px; width: 30px;">
                            
                        </div>
                    </label>
                </svg:foreignObject>
            
                <svg:foreignObject x="50" y="20" height="20" width="20">
                    <label for="earth">
                        <div style="height:20px; width: 20px;"></div>
                    </label>
                </svg:foreignObject>
            
                <svg:foreignObject x="80" y="50" height="20" width="20">
                    <label for="mars">
                        <div style="height:40px; width: 40px;"></div>
                    </label>
                </svg:foreignObject>
            
            </svg:svg>
            
            
            </html>

            【讨论】:

              猜你喜欢
              • 2016-04-27
              • 1970-01-01
              • 1970-01-01
              • 2018-02-01
              • 1970-01-01
              • 2021-09-10
              • 2019-02-17
              • 1970-01-01
              • 2013-07-24
              相关资源
              最近更新 更多