An API to create "stickers" from DOM elements that can then be repasted and manipulated.
This example shows how you can dynamically create and remove icons using the d3.sticker API
For more data driven examples see:
And a video tutorial:
http://www.youtube.com/watch?v=fDqfoICbz7E
xxxxxxxxxx
<meta charset="utf-8">
<head>
<link rel="stylesheet" href="style.css">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="sticker.js"></script>
</head>
<body>
<div id="toolbar">
<div id="sticker1" class="sticker">
<svg width=80 height=80 viewbox="0 0 100 100">
<g id="heart" opacity=0.2>
<path d="M90,16.667V5.556H55.556v11.111H44.444V5.556H10v11.111H7.641H0V50h7.641H10v12.223h11.111v10h11.111v12.222h11.111v10
h13.333v-10h11.11V72.223h0.994h10.117v-10H90V50h2.283H100V16.667 M24.444,29.016v12.096H11.111V29.016V17.778h13.333V29.016z"></path>
</g>
</svg>
</div>
<div id="sticker2" class="sticker">
<svg width=80 height=80 viewbox="0 0 100 100">
<g id="postit" opacity = 0.2>
<path d="M99.276,61.623C86.663,47.747,86.507,3.225,86.507,2.778C86.507,1.244,85.263,0,83.729,0H13.572 c-0.71,0-1.358,0.267-1.85,0.705c-0.002,0-0.002,0.001-0.002,0.003c-0.039,0.034-0.076,0.069-0.112,0.106L0.814,11.607 C0.293,12.128,0,12.835,0,13.571V74.28c0,0.015,0,0.029,0,0.044c0,0.002,0,0.002,0,0.002c0,0.001,0,0.001,0,0.003 c0.006,0.359,0.08,0.702,0.21,1.016c0.135,0.329,0.337,0.638,0.604,0.904c0.264,0.265,0.568,0.464,0.893,0.6 c0.33,0.139,0.691,0.215,1.071,0.215h80.555c1.534,0,2.777-1.244,2.777-2.778v-8.016h0.317h10.794c1.101,0,2.096-0.648,2.541-1.655 C100.207,63.609,100.018,62.436,99.276,61.623z M16.35,47.618c1.394,4.868,3.148,9.375,5.329,13.096H16.35V47.618z M5.556,14.722 l5.238-5.238v52.857l-5.238,5.237V14.722z M80.556,71.507H9.484l5.237-5.238h12.341h53.493V71.507z M86.428,60.713H28.344 C18.263,48.113,16.654,15.318,16.397,5.556h64.592c0.215,9.346,1.622,39.436,10.825,55.158H86.428z"></path>
</g>
</svg>
</div>
<div id="sticker3" class="sticker">
<svg width=80 height=80 viewbox="0 0 100 100">
<g id="marker" opacity=0.2>
<path d="M99.375,96.315c0-0.485-0.112-0.942-0.314-1.35l-2.013-6.036c-0.149-0.445-0.399-0.852-0.732-1.184l-4.945-4.947 l-2.982-6.961c-0.151-0.354-0.37-0.677-0.643-0.949L69.234,56.377c0.268-1.009,0.018-2.124-0.773-2.916L18.106,3.107 C16.103,1.104,13.44,0,10.606,0s-5.497,1.104-7.5,3.107C1.103,5.11,0,7.773,0,10.606c0,2.833,1.103,5.496,3.107,7.499L53.462,68.46 c0.568,0.568,1.339,0.888,2.143,0.888c0.265,0,0.522-0.047,0.774-0.114l18.51,18.513c0.272,0.271,0.595,0.491,0.948,0.642 l6.967,2.986l2.565,2.565H10.606c-1.674,0-3.03,1.356-3.03,3.03s1.356,3.03,3.03,3.03h84.848c0.873,0,1.654-0.376,2.208-0.966 C98.674,98.543,99.375,97.516,99.375,96.315z M7.392,13.819c-0.858-0.858-1.331-1.999-1.331-3.213c0-1.214,0.473-2.355,1.332-3.214 c0.858-0.859,2-1.332,3.214-1.332c1.214,0,2.355,0.473,3.214,1.332l48.212,48.211l-6.428,6.429L7.392,13.819z M60.961,65.246 l4.285-4.286l17.802,17.802l2.176,5.078l-0.256,0.254l-1.129,1.129l-5.078-2.175L60.961,65.246z"></path>
</g>
</svg>
</div>
</div>
<svg id="surface">
</svg>
<script>
//this is nice to have
d3.selection.prototype.moveToFront = function() {
return this.each(function() {
this.parentNode.appendChild(this);
});
};
</script>
<script>
//active sticker is kept in this variable
var sticker;
var bbox;
var toolbar = d3.select("#toolbar");
var stickers = toolbar.selectAll(".sticker");
function stickerPicker(d,i) {
var el = d3.select(this).select("svg g").node();
sticker = d3.sticker(el);
console.log("sticker!", sticker);
console.log("el", el)
bbox = el.getBBox();
stickers.classed("selected", false);
d3.select(this).classed("selected", true);
}
stickers.on("click", stickerPicker);
//pick first sticker by default
stickerPicker.call(stickers.node(), null, 0);
var svg = d3.select("#surface");
svg.on("click", function() {
var mouse = d3.mouse(this);
mouse[0] -= bbox.width/2 + bbox.x;
mouse[1] -= bbox.height/2 + bbox.y;
//place the sticker centered
sticker(svg)
.attr("transform", "translate(" + mouse + ")");
//we want our ghost to be on top all the time
ghost.moveToFront();
})
var ghost;
var mousedown = false;
svg.on("mousedown", function() {
mousedown = true;
})
svg.on("mouseup", function() {
mousedown = false;
})
svg.on("mouseenter", function() {
ghost = sticker(svg);
ghost.style({
opacity: 0.4,
stroke: "#000",
"stroke-width": 2,
"stroke-dasharray": "2 2"
});
})
svg.on("mouseleave", function() {
mousedown = false;
ghost.remove();
})
svg.on("mousemove", function() {
var mouse = d3.mouse(this);
mouse[0] -= bbox.width/2 + bbox.x;
mouse[1] -= bbox.height/2 + bbox.y;
ghost
.attr("transform", "translate(" + mouse + ")");
//continuously paste if mouse is held down
if(mousedown) {
sticker(svg)
.attr("transform", "translate(" + mouse + ")");
ghost.moveToFront()
}
})
</script>
</body>
Modified http://d3js.org/d3.v3.min.js to a secure url
https://d3js.org/d3.v3.min.js