D3: combine circles and images

后端 未结 1 1363
Happy的楠姐
Happy的楠姐 2021-01-24 08:15

I have function to generate circle and images

        node.append(\"circle\")
        .attr(\"r\", function(d) { return d.weight * 2+ 12; })
        .attr(\"clas         


        
1条回答
  •  野性不改
    2021-01-24 09:08

    You can use clip-path property to implement this as suggested by Brad.

    node.append("circle")
      .attr("r", function(d) {
        d.radius = d.weight * 2 + 12;
        return d.radius;
      })
      .attr("class", "logo")  
      .style("fill", "transparent")
      .style("stroke", "black")
      .style("stroke-width", 0.25)
      .on("mouseover", function() {
        d3.select(this)
          .style("fill", "url(#/images/fake/FakeTree/100331934)");
      })
      .on("mouseout", function() {
        d3.select(this)
          .style("fill", "transparent");
      });
    
    node.append("clipPath")
      .attr('id', function(d, i) {
        return "clip" + i
      })
      .append("circle")
      .attr("class", "clip-path")
      .attr("r", function(d) {
        return d.radius;
      })
      .style("fill", function(d) {
        return color(1 / d.rating);
      });
    
    node.append("svg:image")
      .attr("class", "circle")
      .attr("xlink:href", d => d.url)
      .attr("clip-path", function(d, i) {
        return "url(#clip" + i + ")"
      })
      .attr("x", function(d) {
        return -d.radius;
      })
      .attr("y", function(d) {
        return -d.radius;
      })
      .attr("width", function(d) {
        return d.radius * 2;
      })
      .attr("height", function(d) {
        return d.radius * 2;
      });
    

    var graph = {
      "nodes": [{
          "name": "1",
          "rating": 90,
          "id": 2951,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.pngo"
        }, {
          "name": "2",
          "rating": 80,
          "id": 654654,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "3",
          "rating": 80,
          "id": 6546544,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.pngo"
        }, {
          "name": "4",
          "rating": 1,
          "id": 68987978,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "5",
          "rating": 1,
          "id": 9878933,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "6",
          "rating": 1,
          "id": 6161,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "7",
          "rating": 1,
          "id": 64654,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "8",
          "rating": 20,
          "id": 354654,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "9",
          "rating": 50,
          "id": 8494,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "10",
          "rating": 1,
          "id": 6846874,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "11",
          "rating": 1,
          "id": 5487,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "12",
          "rating": 80,
          "id": "parfum_kenzo",
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "13",
          "rating": 1,
          "id": 65465465,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "14",
          "rating": 90,
          "id": "jungle_de_kenzo",
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "15",
          "rating": 20,
          "id": 313514,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "16",
          "rating": 40,
          "id": 36543614,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "17",
          "rating": 100,
          "id": "Yann_YA645",
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "18",
          "rating": 1,
          "id": 97413,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.png"
        }, {
          "name": "19",
          "rating": 1,
          "id": 97414,
          "url": "http://a4.mzstatic.com/us/r30/Purple71/v4/67/24/35/672435a3-3f19-4a13-21e6-057a8e5a3ca7/icon175x175.pngg"
        },
    
    
    
      ],
      "links": [{
          "source": 6,
          "target": 5,
          "value": 6,
          "label": "publishedOn"
        }, {
          "source": 8,
          "target": 5,
          "value": 6,
          "label": "publishedOn"
        }, {
          "source": 7,
          "target": 1,
          "value": 4,
          "label": "containsKeyword"
        }, {
          "source": 8,
          "target": 10,
          "value": 3,
          "label": "containsKeyword"
        }, {
          "source": 7,
          "target": 14,
          "value": 4,
          "label": "publishedBy"
        }, {
          "source": 8,
          "target": 15,
          "value": 6,
          "label": "publishedBy"
        }, {
          "source": 9,
          "target": 1,
          "value": 6,
          "label": "depicts"
        }, {
          "source": 10,
          "target": 1,
          "value": 6,
          "label": "depicts"
        }, {
          "source": 16,
          "target": 1,
          "value": 6,
          "label": "manageWebsite"
        }, {
          "source": 16,
          "target": 2,
          "value": 5,
          "label": "manageWebsite"
        }, {
          "source": 16,
          "target": 3,
          "value": 6,
          "label": "manageWebsite"
        },
    
    
      ]
    }
    
    //seting size and position
    var margin = {
      top: -5,
      right: -5,
      bottom: -5,
      left: -5
    };
    var width = 1000 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;
    
    //give out random color for circle (currently disable)
    var color = d3.scale.category20();
    
    //the Link porperty
    var force = d3.layout.force()
      .charge(-200)
      .linkDistance(150)
      .size([width + margin.left + margin.right, height + margin.top + margin.bottom]);
    
    //interactive
    var zoom = d3.behavior.zoom()
      .scaleExtent([1, 10])
      .on("zoom", zoomed);
    
    var drag = d3.behavior.drag()
      .origin(function(d) {
        return d;
      })
      .on("dragstart", dragstarted)
      .on("drag", dragged)
      .on("dragend", dragended);
    
    //the main body
    var svg = d3.select("#map").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
      .call(zoom)
    
    var rect = svg.append("rect")
      .attr("width", width)
      .attr("height", height)
      .style("fill", "none")
      .style("pointer-events", "all");
    
    
    //fake data - should have some score and the peoplo s name1
    var x = {
      name: 'test',
      Id: '9999',
      score: '100'
    };
    
    //var z = ""+x.Id+""""+x.name+""""+x.score+"";
    
    var tooltip = d3.select("body")
      .append("div")
      .attr("class", "tooltip")
      .style("position", "absolute")
      .style("z-index", "9999")
      .style("visibility", "hidden")
      //.html(API); should get data from api
      .html("Name : " + x.name + "" + "

    Id :" + x.Id + "

    " + "

    Score :" + x.score + "

    "); //.html(function(d) { return d.name}); var container = svg.append("g"); //d3.json('http://blt909.free.fr/wd/map2.json', function(error, graph) { force .nodes(graph.nodes) .links(graph.links) .start(); var link = container.append("g") .attr("class", "links") .selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function(d) { return Math.sqrt(d.value); }); var node = container.append("g") .attr("class", "nodes") .selectAll(".node") .data(graph.nodes) .enter().append("g") .attr("class", "node") .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }) .call(drag); node.append("circle") .attr("r", function(d) { d.radius = d.weight * 2 + 12; return d.radius; }) .attr("class", "logo") .style("fill", "transparent") .style("stroke", "black") .style("stroke-width", 0.25); node.append("clipPath") .attr('id', function(d, i) { return "clip" + i }) .append("circle") .attr("class", "clip-path") .attr("r", function(d) { return d.radius; }) .style("fill", function(d) { return color(1 / d.rating); }); node.append("svg:image") .attr("class", "circle") .attr("xlink:href", d => d.url) .attr("clip-path", function(d, i) { return "url(#clip" + i + ")" }) .attr("x", function(d) { return -d.radius; }) .attr("y", function(d) { return -d.radius; }) .attr("width", function(d) { return d.radius * 2; }) .attr("height", function(d) { return d.radius * 2; }); node.append("text") .attr("x", function(d) { return d.weight * 2 - 35; }) .attr("y", height / 15 - 38) .style("opacity", "1") .html(function(d) { return d.name }); force.on("tick", function() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); }); var linkedByIndex = {}; graph.links.forEach(function(d) { linkedByIndex[d.source.index + "," + d.target.index] = 1; }); function isConnected(a, b) { return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index]; } //Show tooltip box node.on("mouseover", function(d) { node.classed("node-active", function(o) { thisOpacity = isConnected(d, o) ? true : false; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); link.classed("link-active", function(o) { return o.source === d || o.target === d ? true : false; }); d3.select(this).classed("node-active", true); tooltip.style("visibility", "visible") tooltip.style("diplay", "block") .style('top', d3.event.pageY - 6 + 'px') .style('left', d3.event.pageX + 10 + 'px') }) //hide tooltip box .on("mouseout", function(d) { node.classed("node-active", false); link.classed("link-active", false); tooltip.style("visibility", "hidden") }); // On Click, we want to add data to the array and chart svg.on("click", function() { var coords = d3.mouse(this); // Normally we go from data to pixels, but here we're doing pixels to data var newData = { x: Math.round(xScale.invert(coords[0])), // Takes the pixel number to convert to number y: Math.round(yScale.invert(coords[1])) }; dataset.push(newData); // Push data to our array svg.selectAll("circle") // For new circle, go through the update process .data(dataset) .enter() .append("circle") .attr(circleAttrs) // Get attributes from circleAttrs var .on("mouseover", handleMouseOver) .on("mouseout", handleMouseOut); }) function dottype(d) { d.x = +d.x; d.y = +d.y; return d; } function zoomed() { container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); } function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); d3.select(this).classed("dragging", true); force.start(); } function dragged(d) { d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y); } function dragended(d) { d3.select(this).classed("dragging", false); }
    .node {
      font: 10px sans-serif;
    }
    .node-active {
      stroke: #555;
      stroke-width: 1.5px;
    }
    .link {
      stroke: #555;
      stroke-opacity: .3;
    }
    .link-active {
      stroke-opacity: 1;
    }
    .overlay {
      fill: none;
      pointer-events: all;
    }
    #map {
      border: 2px #555;
      width: 1100px;
      height: 400px;
    }
    div.tooltip {
      position: absolute;
      padding: 2px;
      background: white;
      border-radius: 25px;
      padding: 20px;
      border: 2px solid steelblue;
      opacity: 1 !important;
    }
    .MakeItround {
      border-radius: 50%;
    }
    
    
      

    0 讨论(0)
提交回复
热议问题