【问题标题】:Select SVG group's elements inside an <object> tag在 <object> 标记内选择 SVG 组的元素
【发布时间】:2020-04-11 19:35:28
【问题描述】:

我有一个 SVG 外部文件,它在 &lt;object&gt; 标记中调用。

 <object data="Img/PumpStation/Interfata.svg" type="image/svg+xml" id="p1"></object>

SVG 包含两个组。

 <svg>
   <g id="g1">
      <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="93.75" x2="30.2922" y2="93.75" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4F4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <path fill="url(#SVGID_2_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,3.266V37.5h23.423v-0.45V3.266l-1.577-2.703L27.59,0   h-0.676h-1.239H10.248L7.545,1.577L6.982,2.703L6.869,3.266" />

    <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="78.1523" x2="30.2922" y2="78.1523" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4D4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <path fill="url(#SVGID_3_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,34.347h23.423" />

    <linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="105.8555" x2="30.2922" y2="105.8555" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4D4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <path fill="url(#SVGID_4_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,6.645h23.423" />
   </g>
   <g id="g2">
     <linearGradient id="linearColors" x1="0" y1="0" x2="1" y2="1">
       <stop offset="5%" stop-color="#01E400"></stop>
       <stop offset="25%" stop-color="#FEFF01"></stop>
       <stop offset="40%" stop-color="#FF7E00"></stop>
       <stop offset="60%" stop-color="#FB0300"></stop>
       <stop offset="80%" stop-color="#9B004A"></stop>
       <stop offset="100%" stop-color="#7D0022"></stop>
    </linearGradient>
   <circle r="120" cx="150" cy="150" class="external-circle" stroke-width="4" fill="none" stroke="url(#linearColors)"></circle>
   </g>
 </svg>

还有一个按钮:

<asp:Button ID="StartP1" class="startP btn btn-light" runat="server" Text="Start P1" Style="width: 100%" />

我知道如何在点击操作中替换 stop 标记中的所有 stop-color。我通过使用这个 jQuery 函数来做到这一点:

    jQuery('.startP').on('click', function () {            
        $("object").contents().find('stop').each(function () {
            var color = jQuery(this).css('stop-color');
            if (color === 'rgb(77, 77, 77)') {
                jQuery(this).css('stop-color', '#00ff00');
            }
        });
    });

我的问题是我如何才能只为具有id="g1" 的组而不是我的 SVG 的两个组实现 jQuery 函数?

【问题讨论】:

    标签: jquery svg colors


    【解决方案1】:

    代码需要引用要转换的对象。您需要记住Jquery 中的how that works$("object") 选择任何object$(".object") 选择任何具有object 类的元素,$("#object") 选择任何具有object id 的元素。当您说$("object").contents().find('stop') 时,您选择object 元素内的任何stop 元素。如果您只想在 #g1 元素中引用 stop,您可以通过多种方式进行,例如:

    • $("object").contents().find('#g1').contents().find('stop')

    • $("object #g1 stop")

    我准备了一个codepen link,您的功能已通过多种方式进行了调整。您有四个按钮来更改两个对象的颜色(我必须更改第二个对象的渐变末端以与第一个对象具有相同的颜色),只有第一个,只有第二个或重置为默认值。

    评论后编辑

    现在问题更笼统了。问题不仅在于如何选择一个特定的对象。问题:

    • 您的 svg 文件需要一个 xmlns 链接。

    • 您需要确保在设置事件之前加载了object 内容(例如,使用$(window).load()

    • Jquery 并不总是能很好地处理对象的内容(例如this)。

    所以这是一个混合解决方案(不是唯一可能的):

    HTML:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta charset="utf-8">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script>
    
    
    
    $(window).load(function(){
    
    var svg = document.getElementById("p1").contentDocument.documentElement;
    
    
      $('.startP').on('click', function () {            
            $(svg).contents().find("stop").each(function () {
                var color = jQuery(this).css('stop-color');
                if (color === 'rgb(77, 77, 77)') {
                    jQuery(this).css('stop-color', '#00ff00');
                }
            });
        });
    
      $('.startOne').on('click', function () {            
            $(svg).contents().find("#SVGID_2_ stop,#SVGID_3_ stop,#SVGID_4_ stop").each(function () {
                var color = jQuery(this).css('stop-color');
                if (color === 'rgb(77, 77, 77)') {
                    jQuery(this).css('stop-color', '#00ff00');
                }
            });
        });
    
      $('.startTwo').on('click', function () {   
            $(svg).contents().find("#linearColors stop").each(function () {
                var color = jQuery(this).css('stop-color');
                if (color === 'rgb(77, 77, 77)') {
                    jQuery(this).css('stop-color', '#00ff00');
                }
            });
        });
    
    $('.restart').on('click', function () {            
            $(svg).contents().find('stop').each(function () {
                var color = jQuery(this).css('stop-color');
    
                if (color === 'rgb(0, 255, 0)') {
                    jQuery(this).css('stop-color', '#4D4D4D');
                }
            });
        });
    });
    
    </script>
    </head>
    <body>
    <button class="startP">both</button> 
    <button class="startOne">one</button> 
    <button class="startTwo">two</button> 
    <button class="restart">restart</button> 
    <div></div>
    <object data="delme.svg" type="image/svg+xml" id="p1"><img src="tfs860830.jpg" /></object>
    
    
    
    </body>
    </html>
    

    SVG:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    
    <svg width="300" height="300" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" id="objsvg">
    <defs>
    <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="93.75" x2="30.2922" y2="93.75" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4F4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="78.1523" x2="30.2922" y2="78.1523" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4D4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="6.8694" y1="105.8555" x2="30.2922" y2="105.8555" gradientTransform="matrix(1 0 0 -1 0 112.5)">
      <stop offset="0.01" style="stop-color:#4D4D4D" />
      <stop offset="0.51" style="stop-color:#F5F5F5" />
      <stop offset="1" style="stop-color:#4D4D4D" />
    </linearGradient>
    <linearGradient id="linearColors" x1="0" y1="0" x2="1" y2="1">
       <stop offset="5%" stop-color="#01E400"></stop>
       <stop offset="25%" stop-color="#FEFF01"></stop>
       <stop offset="40%" stop-color="#FF7E00"></stop>
       <stop offset="60%" stop-color="#FB0300"></stop>
       <stop offset="80%" stop-color="#4D4D4D"></stop>
       <stop offset="100%" stop-color="#7D0022"></stop>
    </linearGradient>
    </defs>
       <g id="g1">
        <path fill="url(#SVGID_2_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,3.266V37.5h23.423v-0.45V3.266l-1.577-2.703L27.59,0   h-0.676h-1.239H10.248L7.545,1.577L6.982,2.703L6.869,3.266" />
    
        <path fill="url(#SVGID_3_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,34.347h23.423" />
        <path fill="url(#SVGID_4_)" stroke="#4C4C4C" stroke-width="0.25" d="M6.869,6.645h23.423" />
       </g>
       <g id="g2">
       <circle r="120" cx="150" cy="150" class="external-circle" stroke-width="4" fill="none" stroke="url(#linearColors)"></circle>
       </g>
     </svg>
    

    我还将linearGradient 元素移至defs 部分。现在代码直接引用它们,而不是#g1#g2

    编辑 2

    我已经设法通过示例设置了plunker。请注意,我调用了 svg delme.svg

    编辑 3

    如果您无法修改svg,我会使用 Jquery 获取 svg 代码,然后将其内联插入 DOM。这样,您就不需要xlmns(如果需要,您可以添加它)。我已经用新代码分叉了 plunker (link)。现在 svg 文件没有 xmlns 属性。请注意接受object id 的makeInline 函数,然后在div 内创建内联svg,并修改id。之后,您可以使用新的id(或您添加的类)来识别新创建的元素。该函数还会删除原始对象以避免混乱。

    【讨论】:

    • 当我按下按钮时,如果我使用您提供的两种方式中的任何一种,那么任何 svg 组的颜色都不会改变。您来自 codepen 链接的代码可以按我的意愿工作,但您直接在 SVG 代码上工作。在 标记中调用 svg,该代码不起作用。
    • 感谢您的回复!更改 SVG 外部文件的代码对我来说不是解决方案。我不允许这样做。我尝试使用 $(window).load() 然后像这样调用对象: var svg = document.getElementById("p1").contentDocument.documentElement;但没有成功。我认为 jQuery 的问题不适用于我,因为我可以使用 data 属性中提供的 svg 访问 的文档内容。在我看来,您在编辑答案之前给我的解决方案是合乎逻辑的。我无法弄清楚为什么不适用于外部 SVG。
    • 有了这个限制,我会选择不同的东西。请查看更新的答案。
    • 使用我的问题中的 svg 代码以及您在编辑 2 中提供的示例,我设法更改了一个对象的颜色。我确实像这样通过 id 识别每个 linearGradient: ($(svg).contents().find("#SVGID_2_ stop, #SVGID_3_ stop, #SVGID_4_").each(function ())。这不是最简单和优雅的解决方案(如果我有一个包含许多 linearGradient 元素的 svg,这个解决方案很难实现)。这就是为什么我坚持使用组 应该包含我想要更改的 linearGradients。但我看到并不是那么简单我认为应该是这样的。
    • 在我看来,最好写下你需要的每个linearGradient,然后设置和更改每个对象的fill 属性。这样您就无需循环浏览stops,而且您拥有更大的灵活性。
    猜你喜欢
    • 2016-01-27
    • 2020-04-05
    • 2021-02-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 1970-01-01
    • 2018-03-17
    • 2022-01-19
    相关资源
    最近更新 更多