block by timelyportfolio 131fcfc39acef1050794

experimental add image to node with DiagrammeR grViz

Full Screen

experimental: add image to node with grViz

with no d3

# devtools::install_github("timelyportfolio/DiagrammeR@feature/grViz-tasks")

library(DiagrammeR)
library(pipeR)
library(htmltools)

gv <-  grViz('
  digraph {
    saltedcaramel [shape="doublecircle" id = "saltedcaramel2"]
    chocolatechip [shape="doublecircle" id = "chocolatechip"]
  }
')

gv$x$tasks <- htmlwidgets::JS('function(){

var imageLinks = {
  saltedcaramel2 : "http://ec12.cdn.cincopa.com/SaltedCaramel2.jpg?o=1&res=76&cdn=ec&p=y&pid=231720&ph3=b2d1timslim1sat2p2lxtiganpc1chim&d=AMWAjFwULOAANQJsAMnyJRB&as=mp3",
  chocolatechip : "http://ec12.cdn.cincopa.com/ChocolateChip.jpg?o=1&res=15&cdn=ec&p=y&pid=231720&ph3=b4crlpi4unglrfh2tdvemjskr24gidgq&d=AMWAjFwULOAANQJsAMnyJRB&as=mp3"
}

var nodes = this.getElementsByClassName("node")

var svgns = "http://www.w3.org/2000/svg"
var defs = document.createElementNS(svgns,"defs")
this.getElementsByTagName("svg")[0].appendChild(defs)

for(i = 0; i < nodes.length; i ++){
  var pattern = document.createElementNS(svgns,"pattern")
  var image = document.createElementNS(svgns,"image")

  pattern.setAttribute("id","pattern" + i)
  pattern.setAttribute("patternContentUnits","objectBoundingBox")
  pattern.setAttribute("width",1)
  pattern.setAttribute("height",1)
  image.setAttributeNS(
    "http://www.w3.org/1999/xlink", // xlink NS URI
    "href",
    imageLinks[nodes[i].id]
  )
  image.setAttribute("x",0)
  image.setAttribute("y",0)
  image.setAttribute("width",1)
  image.setAttribute("height",1)

  pattern.appendChild(image)
  defs.appendChild(pattern)

  nodes[i].getElementsByTagName("ellipse")[0].style.fill="url(#pattern" + i + ")"
}

}
'    
)

gv

… or with d3 if you have it

# devtools::install_github("timelyportfolio/DiagrammeR@feature/grViz-tasks")

library(DiagrammeR)
library(pipeR)
library(htmltools)

gv <-  grViz('digraph {A [shape="doublecircle"]}')
gv$x$tasks <- htmlwidgets::JS('function(){
d3.select(this).select("svg")
  .append("defs")
  .append("pattern")
    .attr("id","patternOne")
    .attr("patternContentUnits","objectBoundingBox")
    .attr("width",1)
    .attr("height",1)
  .append("image")
    .attr("xlink:href", "http://ec12.cdn.cincopa.com/SaltedCaramel2.jpg?o=1&res=76&cdn=ec&p=y&pid=231720&ph3=b2d1timslim1sat2p2lxtiganpc1chim&d=AMWAjFwULOAANQJsAMnyJRB")
    .attr("x",0)
    .attr("y",0)
    .attr("width",1)
    .attr("height",1)

d3.select(this).select("ellipse")
  .style("fill","url(#patternOne)")
}
'    
  )

tagList(gv) %>>%
  attachDependencies(
    htmlDependency(
      name = "d3"
      ,version = "3.4"
      ,src = c(href = "http://d3js.org")
      ,script = "d3.v3.min.js"
    )
  ) %>>%
  html_print

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="htmlwidgets.js"></script>
<script src="viz-0.3/viz.js"></script>
<link href="styles.css" rel="stylesheet" />
<script src="grViz.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>

</head>
<body style="background-color:white;">
<div id="htmlwidget-7211" style="width:960px;height:500px;" class="grViz"></div>
<script type="application/json" data-for="htmlwidget-7211">{ "x": {
 "diagram": "\n  digraph {\n    saltedcaramel [shape=\"doublecircle\" id = \"saltedcaramel2\"]\n    chocolatechip [shape=\"doublecircle\" id = \"chocolatechip\"]\n  }\n",
"config": {
 "engine": "dot",
"options": null 
},
"tasks": "function(){\n\nvar imageLinks = {\n  saltedcaramel2 : \"//ec12.cdn.cincopa.com/SaltedCaramel2.jpg?o=1&res=76&cdn=ec&p=y&pid=231720&ph3=b2d1timslim1sat2p2lxtiganpc1chim&d=AMWAjFwULOAANQJsAMnyJRB&as=mp3\",\n  chocolatechip : \"//ec12.cdn.cincopa.com/ChocolateChip.jpg?o=1&res=15&cdn=ec&p=y&pid=231720&ph3=b4crlpi4unglrfh2tdvemjskr24gidgq&d=AMWAjFwULOAANQJsAMnyJRB&as=mp3\"\n}\n\nvar nodes = this.getElementsByClassName(\"node\")\n\nvar svgns = \"//www.w3.org/2000/svg\"\nvar defs = document.createElementNS(svgns,\"defs\")\nthis.getElementsByTagName(\"svg\")[0].appendChild(defs)\n\nfor(i = 0; i < nodes.length; i ++){\n  var pattern = document.createElementNS(svgns,\"pattern\")\n  var image = document.createElementNS(svgns,\"image\")\n  \n  pattern.setAttribute(\"id\",\"pattern\" + i)\n  pattern.setAttribute(\"patternContentUnits\",\"objectBoundingBox\")\n  pattern.setAttribute(\"width\",1)\n  pattern.setAttribute(\"height\",1)\n  image.setAttributeNS(\n    \"//www.w3.org/1999/xlink\", // xlink NS URI\n    \"href\",\n    imageLinks[nodes[i].id]\n  )\n  image.setAttribute(\"x\",0)\n  image.setAttribute(\"y\",0)\n  image.setAttribute(\"width\",1)\n  image.setAttribute(\"height\",1)\n  \n  pattern.appendChild(image)\n  defs.appendChild(pattern)\n\n  nodes[i].getElementsByTagName(\"ellipse\")[0].style.fill=\"url(#pattern\" + i + \")\"\n}\n\n}\n" 
},"evals": [ "tasks" ] }</script>
</body>
</html>

grViz.js

HTMLWidgets.widget({

  name: 'grViz',

  type: 'output',

  initialize: function(el, width, height) {
        
    return {
      // TODO: add instance fields as required
    }

  },

  renderValue: function(el, x, instance) {
    // use this to sort of make our diagram responsive
    //  or at a minimum fit within the bounds set by htmlwidgets
    //  for the parent container
    function makeResponsive(el){
       var svg = el.getElementsByTagName("svg")[0];
       if(svg){
        if(svg.width) {svg.removeAttribute("width")};
        if(svg.height) {svg.removeAttribute("height")};
        svg.style.width = "100%";
        svg.style.height = "100%";
       }
    };
    
    if ( x.diagram != "" ) {
      
      if ( typeof x.config === "undefined" ){
        x.config = {};
        x.config.engine = "dot";
        x.config.options = {};
      }
      
      try {
        el.innerHTML = Viz( x.diagram, format="svg", engine=x.config.engine, options=x.config.options );
        
        makeResponsive(el);
        
        // set up a container for tasks to perform after completion
        //  one example would be add callbacks for event handling
        //  styling
        if (!(typeof x.tasks === "undefined") ){
          if ( (typeof x.tasks.length === "undefined") ||
           (typeof x.tasks === "function" ) ) {
             // handle a function not enclosed in array
             // should be able to remove once using jsonlite
             x.tasks = [x.tasks];
          }
          x.tasks.map(function(t){
            // for each tasks add it to the mermaid.tasks with el
            t.call(el);
          })
        }        
      } catch(e){
        var p = document.createElement("pre")
        p.innerText = e;
        el.appendChild(p);
      }
    }
    
  },

  resize: function(el, width, height, instance) {
    
  }
  

});

styles.css

.DiagrammeR,.grViz pre {
  white-space: pre-wrap;       /* CSS 3 */
  white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
  white-space: -pre-wrap;      /* Opera 4-6 */
  white-space: -o-pre-wrap;    /* Opera 7 */
  word-wrap: break-word;       /* Internet Explorer 5.5+ */
}

.DiagrammeR g .label {
  color: black;
}