Как применить динамический SVG градиент?

205
19 декабря 2017, 17:27

Делаю градиент с помощью jQuery, добавляю этот градиент в SVG указываю свойства fill, но ничего не происходит:

$(function(){
    jQuery('img.svg').each(function(){
        var $img = jQuery(this);
        var imgID = $img.attr('id');
        var imgClass = $img.attr('class');
        var imgURL = $img.attr('src');
        jQuery.get(imgURL, function(data) {
            // Get the SVG tag, ignore the rest
            var $svg = jQuery(data).find('svg');
            // Add replaced image's ID to the new SVG
            if(typeof imgID !== 'undefined') {
                $svg = $svg.attr('id', imgID);
            }
            // Add replaced image's classes to the new SVG
            if(typeof imgClass !== 'undefined') {
                $svg = $svg.attr('class', imgClass+' replaced-svg');
                if (imgClass.search(/gradient/) !== -1) {
                    var gradient = '<linearGradient id="gradient">' +
                      '<stop offset="0%" stop-color="#0086b3"/>' +
                    '<stop offset="51%" stop-color="#2aaad5"/>' +
                    '<stop offset="100%" stop-color="#0086b3"/>' +
                    '</linearGradient>';
                  $svg.prepend($.parseXML(gradient).documentElement);
                  $svg.find('path').each(function () {
                    $(this).removeAttr('style');
                    $(this).attr('fill', 'url(#gradient)');
                  });
                }
            }
            // Remove any invalid XML tags as per http://validator.w3.org
            $svg = $svg.removeAttr('xmlns:a');
            // Check if the viewport is set, else we gonna set it if we can.
            if(!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
                $svg.attr('viewBox', '0 0 ' + $svg.attr('height') + ' ' + $svg.attr('width'))
            }
            // Replace image with new SVG
            $img.replaceWith($svg);
        }, 'xml');
    });
});

Полный пример здесь: http://jsfiddle.net/mxww27bv/1/

Я так понимаю что градиент не применяется из-за того, что DOM самого SVG не знает про этот градиент, но как заставить применить его?

Answer 1

Решение кроется в элементарном понимании работы с SVG градиент корректно добавляется в SVG такой функцией:

var createGradient = function (svg, id, stops) {
    var svgNS = svg.namespaceURI;
    var grad = document.createElementNS(svgNS, 'linearGradient');
    grad.setAttribute('id', id);
    for (var i = 0; i < stops.length; i++) {
        var attrs = stops[i];
        var stop = document.createElementNS(svgNS, 'stop');
        for (var attr in attrs) {
            if (attrs.hasOwnProperty(attr))
                stop.setAttribute(attr, attrs[attr]);
        }
        grad.appendChild(stop);
    }
    var defs = svg.querySelector('defs') ||
        svg.insertBefore( document.createElementNS(svgNS,'defs'), svg.firstChild );
    return defs.appendChild(grad);
}

Вот реализованный пример: http://jsfiddle.net/mxww27bv/7/

Мой вопрос уже поднимался и решение тоже уже было: https://stackoverflow.com/a/10898304/1280133

Спасибо всем за помощь.

READ ALSO
Скролл до блока с учетом высоты фиксированного меню

Скролл до блока с учетом высоты фиксированного меню

Здравствуйте, этим кодом я реализую скролл до блока

212
HELP HELP HELP!!!! It&#39;s first work! [требует правки]

HELP HELP HELP!!!! It's first work! [требует правки]

Help me please!!! Finish please, I can not understand what is missing! thank you in advance!

213