JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://d3js.org/d3.v3.min.js"></script>
<div class="container">
<div class="background-image">
<div class="shell"></div>
<div class="maskmaker" data-role="maskmaker" data-displace-left="800" data-displace-top="400" data-bubble-value="150" data-label-name="Label test" data-color="#12353e" data-opacity="1" data-width="200" data-height="175"></div>
<img src="http://i.istockimg.com/file_thumbview_approve/83190789/6/stock-photo-83190789-couple-in-love-drinking-coffee-in-coffee-shop.jpg">
</div>
</div>
<script src="https://d3js.org/d3.v4.js"></script>
CSS
.background-image {
position: absolute;
bottom: 0;
top: 0;
left: 0;
right: 0;
overflow: hidden;
z-index: 0;
}
.container {
overflow: hidden;
width: 1100px;
height: 460px;
position: relative;
}
img {
width: 100%;
height: auto;
}
.mask {
position: absolute;
}
.pointer {
stroke: #ffffff;
}
.labels text {
fill: #ffffff;
font-size: 25px;
}
.centrallabel text {
fill: #ffffff;
font-size: 60px;
}
JavaScript
$(document).ready(function() {
function maskMaker(el) {
var backcolor = $(el).data("color");
var backopacity = $(el).data("opacity");
var height = $(el).data("height");
var width = $(el).data("width");
var width = 1120;
var height = 500;
var labelName = $(el).data("label-name");
var bubbleValue = $(el).data("bubble-value");
var displaceLeft = $(el).data("displace-left");
var displaceTop = $(el).data("displace-top");
var data = [{
"label": labelName,
"x": displaceLeft,
"y": displaceTop,
"value": bubbleValue
}];
console.log("MASK data", data);
// Set the main elements for the series chart
var svgroot = d3.select($(el)[0])
.append("svg")
.attr("viewBox", "0 0 " + width + " " + height)
/*
.attr("width", "100%")
.attr("height", "100%")*/
.attr("width", width)
.attr("height", height)
.attr("preserveAspectRatio", "xMidYMid meet");
// filters go in defs element
var defs = svgroot.append("defs");
var mask = defs.append("mask")
.attr("id", "myMask");
mask.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", "100%")
.attr("height", "100%")
.style("fill", "white")
.style("opacity", backopacity);
var invisiblebubble = mask.append("circle")
.data(data);
//create a fixed bubble first
invisiblebubble
.attr("cx", "50%")
.attr("cy", "50%")
.attr("r", function(d) {
return d.value - 20;
});
//now mask the fixed circle
var masker = defs.append(function() {
return mask.node().cloneNode(true)
})
.attr("id", "myMaskForPointer")
.select("rect")
.style("opacity", 0.8);
invisiblebubble
.attr("r", 10);
//animate this circle
invisiblebubble
.attr("cx", "50%")
.attr("cy", "50%")
.transition()
...