如何将图案图像动态添加到 svg?

Posted

技术标签:

【中文标题】如何将图案图像动态添加到 svg?【英文标题】:How can I dynamically add a pattern image to a svg? 【发布时间】:2017-02-20 13:02:27 【问题描述】:

我是使用 SVG 图像的新手。我正在使用它们为夹克涂上几次不同颜色的颜色,而无需为每种颜色制作图像。这是使用 jQuery 完成的。

那是“简单”的部分。我通过将fill: #color; CSS 规则应用于<path> 内的<svg> 来解决它。

困难的部分是尝试用图像填充 svg 路径时。这真的很奇怪。我的代码在<svg> 内的 html 中打印得很好,但根本不起作用。当我在 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"  ></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 开发工具中,如果我删除 &lt;defs&gt; 元素并再次粘贴它,它会起作用,我尝试了这个并且起作用了:

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

【问题讨论】:

将 $clone.prepend($('')... 替换为 DOM 创建 defs 和 pattern 元素,就像对图像元素所做的那样。 感谢您的回答。没有什么变化。在我“刷新” html 之前,它不会生效 我可以看看你所做的更改吗? 我建议使用 D3.js;它与svg 配合得非常好,并且'svg` 中的所有动态任务在D3 中都是轻而易举的。 @RobertLongson 我现在已经更改了完整的代码。太大了,这里没法贴。无论如何,刷新 html 工作正常。它真的很奇怪,但它有效。 【参考方案1】:

你的问题在这里:

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

您不能使用 jQuery 来创建这样的 SVG 元素。当您创建 &lt;image&gt; 元素时,您正在以正确的方式(使用 createElementNS())进行操作。但是在创建&lt;defs&gt; 和 pattern> 元素时也需要使用相同的方法。

【讨论】:

感谢您的回答,但仍然无法正常工作。正如您在编辑中看到的那样,错误已通过“刷新”&lt;svg&gt; 内部 html 得到修复。

以上是关于如何将图案图像动态添加到 svg?的主要内容,如果未能解决你的问题,请参考以下文章

如何将边框图像添加到动态创建的图像?

如何使用图像组件将图像动态添加到 Gatsby 中的页面?

如何将图像从相机/UIImagePickerController 动态添加到 iPhone 中的 iCarousel

使用 Javascript 动态添加时,SVG 元素无法正确缩放

将 svg 拟合到 angular.js 中的背景图像 div

在映像URL中动态添加资产前缀 - Ember-CLI