score:2

Accepted answer

D3 code is almost fine, but suffers from a hierarchy of SVG elements. It seems that it should be in this order:

<a>ID here for a specific picture display task is not required

let personCircles = svg.selectAll("a")
            .data(data)
            .enter()
            .append("a")
            .attr("id", function(d) {
                console.log(d["Person Name"]);
                if (d && d.length !== 0) {
                    return d["Person Name"].replace(/ |,|\./g, '_');
                }
            })
            .style("opacity", 1)
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));

then defs

<defs>
//Define defs 
        let defs =  personCircles.append("defs");

then first container goes in which the picture will be placed

<rect id = "RECT" / > // ID is required

defs.append('rect')
                    .attr('id', 'rect-ggg')
                    .attr('x', function(d){
                        return markerCirclesScale(name)
                    })
                     .attr('y', function(d){
                        return fullSVGHeight / 2;
                    })
                    .attr('width', 60)
                    .attr('height', 60)
                    .attr('rx', 40)
                    .style('fill', 'red')

the container attached a clip to create a mask

<clipPath id = "the CLIP"> // and here, too, ID is required

defs.append("clipPath")
                .attr('id', 'clip-ggg')

bind the mask to the container

<use the href = "# a RECT"> </use> // a reference to the container

.append("use")
                    .attr('href', function(d){
                        return  "#rect-ggg";

                    })

<use> this needs, as I understand it, to add a container to the page, as DEFS contents itself is not rendered by the browser

<use href = "# RECT" > </ use> // a reference to the container

personCircles
                .append("use")
                .attr('href', function(d){
                return  "#rect-ggg";

            })

finally add the photo

<image href clip-path = " url (#CLIP)" /> // with reference to the mask

personCircles.append('image')
                .attr('href', function(d){
                    return 'https://vignette.wikia.nocookie.net/ideas/images/8/82/Donald_Trump.png/revision/latest/scale-to-width-down/640?cb=20170512015233'})


                .attr("clip-path", function(d){ 
                    return "url(#clip-ggg)";
                })
                .attr("width", 60)
                .attr("height", 60)
                .attr('x', function(d){
                    return markerCirclesScale(name)
                })
                .attr('y', function(d){
                   return fullSVGHeight / 2 + 8;
                })

circle // this circle is not required, I used it in my layout to add stroke

//Define SVG width and height
let fullSVGHeight = 700;
let fullSVGWidth = 900;

//Define margins 
// let margins = {
//     top: 10,
//     right: 50,
//     bottom: 10,
//     left: 10
// }

//Define chart width, height, x/y scale
// let chartHeight = fullSVGHeight - margins.top - margins.bottom;
// let chartWidth = fullSVGWidth - margins.left - margins.right;

//Define marker circles scale
let markerCirclesScale = d3.scalePoint()
    .range([0, fullSVGWidth])


//Fetch data
d3.json("https://api.myjson.com/bins/7gjbe").then(data => {

    //   data.forEach(function(d){
    //     console.log("This is initial d.Period: ", +d.Period)
    //         return data.filter(function() {
    //             if (+d["Period"] === 0){
    //                 return d["Period"] = 1;
    //             } else {
    //             return d.Period = Math.floor(+d["Period"]);
    //         }
    // })});

    console.log(data);

    markerCirclesScale
        .domain(data.map(function(d) {
            return d["Person Name"];
        }))


    let svg = d3.select("body")
        .append("svg")
        .attr("width", fullSVGWidth)
        .attr("height", fullSVGHeight)
        .append("g")
        .attr("transform", "translate(" + 0 + "," + 0 + ")");

    data.forEach(function(d) {
        return render(d["Person Name"])
    });


    function render(name) {
        let markerCircles = svg.selectAll("circle")
            .data([1, 2, 3, 4, 5])
            .enter()
            .append("circle")
            .style("fill", "none")
            .attr("stroke", "#ff97c4")
            .style("stroke-width", "1.5px")
            .attr("cy", fullSVGHeight / 2)
            .attr("cx", markerCirclesScale(name) + 330)
            .attr("r", 0)

        markerCircles
            .transition()
            .duration(1000)
            .attr("r", function(d) {
                return d * 65;
            });

        let personCircles = svg.selectAll("a")
            .data(data)
            .enter()
            .append("a")
            .attr("id", function(d) {
                console.log(d["Person Name"]);
                if (d && d.length !== 0) {
                    return d["Person Name"].replace(/ |,|\./g, '_');
                }
            })
            .style("opacity", 1)
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));




        //Define defs 
        let defs =  personCircles.append("defs");
       
         defs.append('rect')
                .attr('id', 'rect-ggg')
                .attr('x', function(d){
                    return markerCirclesScale(name)
                })
                 .attr('y', function(d){
                    return fullSVGHeight / 2;
                })
                .attr('width', 60)
                .attr('height', 60)
                .attr('rx', 40)
                .style('fill', 'red')
               

         defs.append("clipPath")
            .attr('id', 'clip-ggg')
            .append("use")
            .attr('href', function(d){
                return  "#rect-ggg";
                
            })

            
        let simulation = d3.forceSimulation(data)
            .force("charge", d3.forceCollide().radius(3))
            .force('center', d3.forceCenter(fullSVGWidth / 2, fullSVGHeight / 2))
            .force("radius", d3.forceRadial(function(d) {
                return +d["Period"] * 60
            }, fullSVGWidth / 2, fullSVGHeight / 2).strength(0.3))
            .on("tick", ticked)
            .velocityDecay(0.07)
            .stop();



        function ticked() {
            personCircles
                .attr("cx", function(d) { return d.x - 100; })
                .attr("cy", function(d) { return d.y; });
        }


        d3.timeout(function() {
            personCircles
                .append("use")
                 .attr('href', function(d){
                return  "#rect-ggg";
                
            })
            personCircles.append('image')
                .attr('href', function(d){
                    return 'https://vignette.wikia.nocookie.net/ideas/images/8/82/Donald_Trump.png/revision/latest/scale-to-width-down/640?cb=20170512015233'})
                .attr("clip-path", function(d){ 
                    return "url(#clip-ggg)";
                })
                .attr("width", 60)
                .attr("height", 60)
                .attr('x', function(d){
                    return markerCirclesScale(name)
                })
                 .attr('y', function(d){
                    return fullSVGHeight / 2 + 8;
                })
            
            simulation.restart().on("tick", ticked);

        }, 2000)

        function dragstarted(d) {
            d.dragged = true;
            simulation.alphaTarget(0.8).restart();
            d.fx = d.x;
            d.fy = d.y;
        }

        function dragged(d) {
            d.fx = d3.event.x;
            d.fy = d3.event.y;
        }

        function dragended(d) {
            simulation.alphaTarget(0);
            d.fx = null;
            d.fy = null;
            d3.timeout(function() {
                d.dragged = false;
            }, 1000)
        }

    }

}).catch(error => console.log(error));
body, body *{
            top:0;
            padding: 0;
            margin: 0;
            background-color: #80d6c7;
            overflow: hidden;
            font-family: Lucida Console, Monaco, monospace;

        }

        a {
            background-color: transparent;
            color: #679fa5;
            text-decoration: none;
        }

        svg {
            margin-top: 2% ;
            margin-left: 29%;
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>


Related Query

More Query from same tag