简体   繁体   中英

How can I change svg color on click text tag

I have below tags inside a SVG:

<g>
    <use x="10" y="14" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" xlink:actuate="onRequest" id="PL-1-02" xlink:show="replace" xlink:href="#sfseat" />
</g>

    <rect x="43" y="18" width="25" style="fill:rgb(192,192,192); stroke:none;" rx="2" ry="2" height="30" />
<text x="18" y="35" style="stroke:rgb(0,0,0); stroke-width:0.5;">
    02
</text>

When I click on the text tag then I have to change the color of svg. Please suggest how can I get g element on click text tag in javascript.

Interestingly, this can be solved without any Javascript. SMIL animations have the ability to be triggered by events. You can use a simple <set fill="freeze"> tag as a child of the rectangle to change the value of an attribute or CSS property permanently. The element to be clicked needs to have an id attribute, and then you can add a begin="myId.click" to the <set> :

 <svg viewBox="0 15 100 50"> <rect x="43" y="18" width="25" rx="2" ry="2" height="30" style="fill:rgb(192,192,192); stroke:none;"> <set attributeName="fill" to="rgb(192,0,0)" begin="trigger02.click" fill="freeze" /> </rect> <text id="trigger02" x="18" y="35" style="stroke:rgb(0,0,0); stroke-width:0.5;cursor:pointer"> 02 </text> </svg>

As suggested in Radical Edward's answer you could edit the fill attribute of the SVG (or, probably better, the rect ) element – you'll probably get cleaner results and better portability by separating the styles though.

Use classnames for styling

Add a style element and define your styles separately:

<svg>
    <style>
        rect {
            stroke: none;
            fill: rgb(192,192,192);
        }

        rect.active {
            fill: rgb(255, 20, 20);
        }
    </style>
    <!-- The rest of your SVG -->
    <!-- The rect element with the inline style removed -->
    <rect
        x="43" 
        y="18" width="25" 
        rx="2" 
        ry="2" 
        height="30" 
    />
</svg>

Listen to click events on the text element

In order to indentify the text element and the rect, we'll give both of them a unique ID:

<rect 
    id="rect1" 
    x="43" 
    y="18" 
    width="25" 
    rx="2" 
    ry="2" 
    height="30" 
/>
<text 
    id="text1" 
    x="18" 
    y="35" 
    style="stroke:rgb(0,0,0); stroke-width:0.5;"
>

Then we'll add an event listener on the text element:

var textElement = document.querySelector('#text1');
var rect = document.querySelector('#rect1');

textElement.addEventListener('click', function() {
    rect.classList.add('active');
});

The above will work down to IE11, if you're targeting modern browsers only or using a transpiler like Babel you can use a more modern ES6+ syntax with const and arrow functions; for older browsers (IE10 and below) you'll need to polyfill or use other workarounds, see the chapter "Legacy Internet Explorer and attachEvent" on MDN .

Alternative: Modify the fill attribute's value

Instead of using a style element, you could also hard-code the rect's fill attribute and then modify it:

<rect fill="rgb(195,195,195)" ... />
textElement.addEventListener('click', function() {
    rect.setAttribute('fill', 'rgb(255,20,100)');
});

edit (as per OP's comments)

If you don't have access to the contents of the svg and mutliple SVGs you should at least wrap it in an identifiable container (ie with an ID or unique classname) to make sure you're working on the right one – if that's possible

<div class="clickable-svg-container">
 <svg .../>
</div>

You'll then have to find the elements you want to watch and/or modify by first selecting your containers (or all the svgs on the page) and then searching inside that:

var containers = document.querySelectorAll('.clickable-svg-container');

// Alternative: Pick all the SVG elements from the current document
// var svgs = document.querySelectorAll('svg');

// Now loop over your selected elements:
containers.forEach(function(container, index) {
  var rect = container.querySelector('rect');
  var text = container.querySelector('text');
  var group = container.querySelector('g');

  // now you can set up your event listener as seen above
  text.addEventListener(...);
});

Now you can use the rest of the above guide to react to click events. Note that you can still (a) declare the styles for the active class globally (eg in the HTML's <head /> and use the classname to style the modified element or (b) modify the fill attribute directly on each element.

Read more on the MDN Web Docs for:

        let totalUseTags=svg.getElementsByTagName('use');
        for(let i=0;i<totalUseTags.length;i++){
            let useParentElement=totalUseTags[i];
            let textElement=this.getSiblingTextElementOfUseTag(totalUseTags[i].parentElement.nextElementSibling);
            useParentElement.parentElement.appendChild(textElement)
        }
 
getSiblingTextElementOfUseTag(g){
        let i=1;
        while (g) {
            if(g.nodeName=='text'){  
                return g;
            }
            g = g.nextElementSibling;
            i++;
          }
    }

  1. first find out all the use tag elements.
  2. find their parent g tag element.
  3. find their next text tag sibling element.
  4. append that text element to the g tag.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM