JointJS change attributes in an SVG Image

Change fill attribute inside an SVG Image xlink:href

by Roman Bruckner

HTML

<html>

  <head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.5.5/joint.css" />
  </head>

  <body>
    <!-- content -->
    <button id="change-color">Change color</button>

    <div id="paper" />

    <!-- dependencies -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.5.5/joint.js"></script>

  </body>

</html>

CSS

#paper {
  border: 1px solid gray;
  float: left;
  position: relative;
  width: 500px;
  height: 300px;
  overflow: hidden;
}

JavaScript

const MyImage = joint.shapes.standard.Image.define('MyImage', {
  size: {
    width: 100,
    height: 100
  }
}, {

  dataURLPrefix: 'data:image/svg+xml;utf8,',

  initialize: function() {
    joint.shapes.standard.Image.prototype.initialize.apply(this, arguments);  
    this.on('change:color', this.setImageColor);
    this.setImageColor();
  },
  setImageColor: function() {
    var svg = this.get('svg') || '';
    var color = this.get('color') || 'black';
    // set modified SVG image with current color
    this.attr('image/xlink:href', this.dataURLPrefix + encodeURIComponent(svg.replace(/\$color/g, color)));
  }
});

const shapes = { ...joint.shapes, MyImage } 

var graph = new joint.dia.Graph({}, {
  cellNamespace: shapes
});

const paper = new joint.dia.Paper({
  el: document.getElementById('paper'),
  width: 800,
  height: 900,
  model: graph,
  cellViewNamespace: shapes,
  gridSize: 10,
  async: true,
  sorting: joint.dia.Paper.sorting.APPROX,
});

// SVG Image containing the $color placeholder
const imageDataUrl = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve" height="100px" width="100px" style="fill:$color;"><g><path d="M28.1,36.6c4.6,1.9,12.2,1.6,20.9,1.1c8.9-0.4,19-0.9,28.9,0.9c6.3,1.2,11.9,3.1,16.8,6c-1.5-12.2-7.9-23.7-18.6-31.3 c-4.9-0.2-9.9,0.3-14.8,1.4C47.8,17.9,36.2,25.6,28.1,36.6z"/><path d="M70.3,9.8C57.5,3.4,42.8,3.6,30.5,9.5c-3,6-8.4,19.6-5.3,24.9c8.6-11.7,20.9-19.8,35.2-23.1C63.7,10.5,67,10,70.3,9.8z"/><path d="M16.5,51.3c0.6-1.7,1.2-3.4,2-5.1c-3.8-3.4-7.5-7-11-10.8c-2.1,6.1-2.8,12.5-2.3,18.7C9.6,51.1,13.4,50.2,16.5,51.3z"/><path d="M9,31.6c3.5,3.9,7.2,7.6,11.1,11.1c0.8-1.6,1.7-3.1,2.6-4.6c0.1-0.2,0.3-0.4,0.4-0.6c-2.9-3.3-3.1-9.2-0.6-17.6   c0.8-2.7,1.8-5.3,2.7-7.4c-5.2,3.4-9.8,8-13.3,13.7C10.8,27.9,9.8,29.7,9,31.6z"/><path...