Как я могу динамически добавлять изображение шаблона в svg?

#javascript #jquery #html #css #svg

#javascript #jquery #HTML #css #svg

Вопрос:

Я новичок в работе с изображениями SVG. Я использую их, чтобы нарисовать куртку несколько раз разными цветами без необходимости иметь изображение для каждого цвета. Это делается с помощью jQuery.

Это была «легкая» часть. Я решил это, применив fill: #color; правило CSS к <path> inside <svg> .

Сложная часть заключается в попытке заполнить путь svg изображением. Это действительно странно. Мой код отлично печатается в html внутри <svg> , но вообще не работает. И когда в инструментах разработчика Chrome я вырезаю <defs> элемент и вставляю его снова точно туда, где он был, он внезапно работает! Это сводит меня с ума: (.

Мой код:

 var items = [
            {
                title: 'Africa',
                // color: '#776254'
            },
            {
                title: 'Aguamarina',
                // color: '#9cd3be'
            },
            {
                title: 'Aluminio',
                // color: '#9b9b9b'
            },
            {
                title: 'Amarillo Jamaica',
                // color: '#ffcd01'
            },
            {
                title: 'Amatista',
                // color: '#4d4169'
            },
            {
                title: 'Ambar Brillante',
                // color: '#eb6608'
            },
            {
                title: 'Arándano',
                // color: '#604483'
            }
        ];

        $(function () {
            var PrendaShow = {
                $mac_wrapper: $('#prendas-mac-slider-wrapper .mac-slider'),
                $fullprints_wrapper: $('#fullprints-gallery'),
                img: {
                    src: 'image.svg',
                    width: 350,
                    height: 188
                },
                init: function () {
                    this.makeItems();
                    this.bindEvents();
                },
                bindEvents: function () {
                    // events
                },
                makeItems: function() {
                    var self = this,
                        $model = $('<div/>', { class: 'mac-item' });
                    $model.append($('<div/>', { class: 'item-img' }));
                    $.each(items, function() {
                         var $item = $model.clone();
                        self.$mac_wrapper.append($item);
                    });
                    this.svgDraw();
                },
                svgDraw: function () {
                    var self = this;
                    $.get(this.img.src, function(data) {
                        var $svg = self.normalizeSvg(data);
                        self.appendImgs($svg);
                    });
                },
                normalizeSvg: function (data) {
                    var $svg = $(data).find('svg');
                    $svg = $svg.removeAttr('xmlns:a');
                    $svg.width(this.img.width).height(this.img.height);
                    return $svg;
                },
                appendImgs: function ($svg) {
                    var items = this.$mac_wrapper.find('.mac-item');
                    $.each(items, function() {
                        var $clone = $svg.clone(),
                            color = $(this).data('color');
                        $clone.find('path').css('fill', 'url(#img1)');
                        var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
                        img.setAttributeNS(null,'height','536');
                        img.setAttributeNS(null,'width','536');
                        img.setAttributeNS('http://www.w3.org/1999/xlink','href','http://www.boogdesign.com/examples/svg/daisy-grass-repeating-background.jpg');
                        img.setAttributeNS(null,'x','10');
                        img.setAttributeNS(null,'y','10');
                        img.setAttributeNS(null, 'visibility', 'visible')
                        $clone.prepend($('<defs/>').html('<pattern id="img1" patternUnits="userSpaceOnUse" width="100" height="100"></pattern>'));
                        $clone.find('pattern').append(img)
                        $(this).find('.item-img').append($clone);
                    });
                }
            };
            PrendaShow.init();
        });  
 #prendas-mac-slider-wrapper {
  margin-top: 80px;
}
.mac-slider {
  display: flex;
  font-size: 0;
  padding: 0 100px;
}
.mac-item {
  width: 100%;
  height: 160px;
  min-width: 0;
  position: relative;
  display: inline-block;
  text-align: center;
  cursor: pointer;
}
.item-img {
  background: url('https://ae01.alicdn.com/kf/HTB1Cqi6KXXXXXbpXVXXq6xXFXXXy/Classic-font-b-White-b-font-font-b-Jacket-b-font-font-b-Men-b-font.jpg') center center no-repeat;
  background-size: contain;
  pointer-events: none;
  position: absolute;
  top: 0;
  left: -9999px;
  right: -9999px;
  margin: auto;
}
svg {
  mix-blend-mode: multiply;
}  
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hero">
        <div class="container-fluid">
            <div id="prendas-mac-slider-wrapper" class="row">
                <div class="mac-slider">
                </div>
            </div>
        </div>
    </div>  

Я не могу привести свой точный пример из-за загрузки изображений. Я действительно надеюсь, что вы понимаете, что я пытаюсь здесь сделать, и что происходит не так.


РЕДАКТИРОВАТЬ: Не уверен, заслуживает ли это быть в ответе, но я предпочел написать это здесь, так как я не думаю, что это правильный способ сделать это.

Поскольку я знал, что из chrome dev tools, если я удалил <defs> элемент и вставил его снова, это сработало, я попробовал это и сработало:

 var svg_html = $svg.html();
$svg.html('');
$svg.html(svg_html);
  

Комментарии:

1. Замените $clone.prepend($(‘<defs/>’) … с помощью DOM создаются defs и элементы шаблона, как вы делаете для элемента изображения.

2. Спасибо за ответ. Ничего не меняется. Пока я не «обновлю» HTML-код <svg>, он не вступит в силу

3. Могу ли я увидеть внесенные вами изменения?

4. Я бы предложил использовать D3.js ; он очень хорошо работает с svg , и все динамические задачи в ‘svg` легко решаются в D3.

5. @RobertLongson Теперь я полностью изменил код. Он слишком большой, его невозможно вставить сюда. В любом случае, обновление html работало нормально. Это действительно странно, но это работает.

Ответ №1:

Ваша проблема здесь:

 $clone.prepend($('<defs/>').html('<pattern ...
  

Вы не можете использовать jQuery для создания подобных элементов SVG. Вы делаете это правильно (с createElementNS() помощью) при создании <image> элемента. Но вам также необходимо использовать тот же метод при создании элементов <defs> и < pattern> .

Комментарии:

1. Спасибо за ответ, но он все еще не работает. Как вы можете видеть в РЕДАКТИРОВАНИИ, ошибка была исправлена путем «обновления» <svg> внутреннего html.