图像作为圆形背景(d3.js svg)

image as circle background (d3.js svg)

已更新 我使用 D3.js 制作了一个力导向图。 每个节点对应一个公司,每个link根据link颜色对应它们之间的关系。 我想要实现的是使用“节点”数据中的图像 URL 并为每个气泡显示不同的图像。 目前我可以为我所有的气泡设置一个固定的 static/identical 图像。 我试图将模式连接到我的“节点”数据,但没有成功,最终陷入无限循环。

简单 HTML canvas 用于我的 svg 和两个用于通过单击放大和缩小的按钮。

    <div class="main-map-container" style="overflow: hidden">
        <div class="canvas">
            <div>
                <button id="zoom_in">+</button>
                <button id="zoom_out">-</button>
            </div>
        </div>
    </div> 

我的数据集(links 和节点),注意节点上的图像属性。它指的是我希望设置为节点背景的图像


    const links = [
        {src:"Amazon",target:"Aurora",link:"Investment",market:"Semi_Truck",tags:"AD_L3-4|AD_Driverless",technology:"",aces:"Automated",amount:"",region:"EU| US",date:"2019-02-01",description:"Amazon Investing in Aurora in an 0 million Financing Round",source:"https://drive.google.com/open?id=1aLuuUqXKSQcGzivH21CSuO7204pdyP7K",years:"2019"},
        {src:"Amazon",target:"Aurora",link:"Investment",market:"Robotaxi | Semi_Truck",tags:"AD_Driverless",technology:"",aces:"Automated",amount:"0",region:"EU| US",date:"2019-02-01",description:"Aurora announced that they have secured over 0 million in Series B financing led by Sequoia. This funding and partnership will accelerate their mission of delivering the benefits of self-driving technology safely, quickly, and broadly.\r\n\r\nIn addition to Sequoia, Amazon, and funds and accounts advised by T. Rowe Price Associates, Inc. are making significant investments in Aurora. Amazon’s unique expertise, capabilities, and perspectives will be valuable for us as we drive towards our mission.",source:"https://drive.google.com/open?id=1aLuuUqXKSQcGzivH21CSuO7204pdyP7K",years:"2019"},
        {src:"Amazon",target:"Zoox",link:"Acquisition",market:"Robotaxi",tags:"AD_Driverless",technology:"",aces:"Automated",amount:",200",region:"US",date:"2020-06-01",description:"Amazon acquires Zoox to help bring their vision of autonomous ride-hailing to reality. [The Financial Times reports that Amazon spends .2bn on the acquisition.]",source:"https://drive.google.com/open?id=18-zXDSHy9_o0OrIwYFfb5FdyMxMzgtHH",years:"2020"},
        {src:"Amazon",target:"Rivian",link:"Investment",market:"Light_CV",tags:"Other",technology:"",aces:"Automated",amount:"",region:"US",date:"2020-10-01",description:"Amazon unveils its new electric delivery vans built by Rivian\nThe delivery giant aims to have 10,000 vehicles on the road by 2022, 100,000 vehicles expected by 2030.",source:"https://www.theverge.com/2020/10/8/21507495/amazon-electric-delivery-van-rivian-date-specs",years:"2020"},
        {src:"Amazon",target:"Torc",link:"Partnership",market:"Semi_Truck",tags:"AD_L3-4| Edge/Cloud_computing",technology:"",aces:"Automated| Connected",amount:"",region:"US",date:"2021-02-17",description:"Torc selects AWS as preferred cloud provider for self-driving truck fleet",source:"https://drive.google.com/open?id=1QDHZIyUHpAY4oKEqmeM9cngPIWZWV2doE0r1emQZuNY",years:"2021"},
        {src:"Amazon",target:"Intel",link:"Partnership",market:"PoV",tags:"Edge/Cloud_computing",technology:"",aces:"Connected",amount:"",region:"EU| US| China| Korea| Japan| Others",date:"2021-03-01",description:"Intel Achieves AWS High Performance Computing Competency Status",source:"https://drive.google.com/open?id=1MvhLikyzwbu-Mz_OuXUvytAuqXNEnUjHdSxMGXcKLok",years:"2021"},
        {src:"Aurora",target:"Blackmore",link:"Acquisition",market:"Semi_Truck | Robotaxi",tags:"AD_Driverless",technology:"LiDAR",aces:"Automated",amount:"",region:"US",date:"2019-01-09",description:"Yesterday announce that they plan to acquire the industry-leading lidar company Blackmore, located in Bozeman, Montana.\r\n\r\nThe Bozeman, Montana–based outfit, which started up a decade ago to do work for the defense industry, uses a “frequency modulated continuous wave” system, also known as a Doppler lidar. When the infrared light hits an object and bounces back, the system determines both how far away it is and its velocity. Knowing where something is headed and how fast is prized data. Blackmore has at least one Doppler lidar competitor in Aeva, founded in early 2017 by a pair of former Apple engineers. [...]",source:"https://drive.google.com/open?id=1UkF-sxgA1AgpgWoRCd2qgWjovLQULoAP",years:"2019"},
        {src:"Aurora",target:"Uber ATG",link:"Acquisition",market:"Robotaxi | Semi_Truck",tags:"AD_Driverless",technology:"",aces:"Automated",amount:",000",region:"US",date:"2020-12-01",description:"Aurora is acquiring Uber's self-driving unit, ATG, accelerating the first Aurora Driver applications for heavy-duty trucks while allowing us to continue and accelerate our work on light-vehicle products. \"Simply put, Aurora will be the company best positioned to deliver the self-driving products necessary to make transportation and logistics safer, more accessible, and less expensive,\" said Chris Urmson, co-founder and CEO of Aurora.",source:"https://drive.google.com/open?id=1rc-_3VLlITe2bdxBgws3Bvb2rPvCluMfsMkFXiwbg98",years:"2020"},
        {src:"Aurora",target:"Paccar",link:"Partnership",market:"Semi_Truck",tags:"AD_L3-4",technology:"",aces:"Automated",amount:"",region:"US",date:"2021-01-19",description:"Aurora teams up with PACCAR to build and deploy self-driving trucks",source:"https://drive.google.com/open?id=1TfA9U81CbyNwQc4Xfg2iJ9wqmka7RLqVEIsES2-62Ww",years:"2021"},
        {src:"Aurora",target:"Denso",link:"Partnership",market:"Robotaxi",tags:"AD_Driverless",technology:"",aces:"Automated",amount:"",region:"EU| US| China| Korea| Japan| Others",date:"2021-02-09",description:"Aurora enters into long-term, global, and strategic collaboration with Toyota and Denso",source:"https://drive.google.com/open?id=1QnlNnMMxbcPdnbi4AcBo36_UWM9TuMrNqItZHfPDUos",years:"2021"},
        {src:"Aurora",target:"Toyota",link:"Partnership",market:"Robotaxi",tags:"AD_Driverless",technology:"",aces:"Automated",amount:"",region:"EU| US| China| Korea| Japan| Others",date:"2021-02-09",description:"Aurora enters into long-term, global, and strategic collaboration with Toyota and Denso",source:"https://drive.google.com/open?id=1QnlNnMMxbcPdnbi4AcBo36_UWM9TuMrNqItZHfPDUos",years:"2021"},
        {src:"Aurora",target:"OURS-Tech",link:"Acquisition",market:"Semi_Truck| Robotaxi",tags:"",technology:"LiDAR",aces:"Automated",amount:"",region:"US",date:"2021-02-26",description:"Aurora acquires OURS lidar (FMCW), unlocking the commercialization of its Aurora Driver",source:"https://drive.google.com/open?id=1TWEII1c0jQk26DcCC2WXw3plT0XTnfDzmD-e551VWSQ",years:"2021"},
        {src:"Zoox",target:"ZadarLabs",link:"Investment",market:"PoV| Robotaxi",tags:"AD_L3-4| AD_Driverless",technology:"Radar",aces:"Automated",amount:"",region:"US",date:"2021-01-26",description:"Zadar Labs, Developing Next Generation Imaging Radar, Closes .6M in Seed Funding",source:"https://drive.google.com/open?id=1fz3MhS4P_Cmq2VmT9crQztUBd9W5Pj-IWEL9ABq3ySg",years:"2021"},
        {src:"Intel",target:"Mobileye",link:"Acquisition",market:"PoV",tags:"AD_L3-4",technology:"",aces:"Automated",amount:",000",region:"Worldwide",date:"2017-01-14",description:"Instead of Mobileye being integrated into Intel, Intel’s AD Group (ADG) will be integrated into Mobileye.",source:"https://www.engadget.com/2017-08-08-intel-acquisition-Mobileye-complete.html",years:"<2017"},
        {src:"Intel",target:"Infineon",link:"Acquisition",market:"",tags:"",technology:"",aces:"Automated|Experience",amount:"1400",region:"US|EU",date:"2010-01-01",description:"Intel to Acquire Infineon’s Wireless Solutions Business",source:"https://www.infineon.com/cms/en/about-infineon/press/press-releases/2010/INFXX201008-069.html",years:"<2017"},
    ]

    const nodes = [
        {id:"Amazon",type:"Tech",tags:"",technology:"",market:"Droid_Goods|Robotaxi",valuation:"",description:"Amazon is an international e-commerce website for consumers, sellers, and content creators.",country:"US",region:"North America",image:"https://images-eu.ssl-images-amazon.com/images/G/02/gc/designs/livepreview/a_generic_10_uk_noto_email_v2016_uk-main._CB485921599_.png"},
        {id:"Aurora",type:"Tier1",tags:"AD_Driverless",technology:"",market:"Robotaxi|Semi_Truck",valuation:"1100",description:"Aurora is delivering the benefits of self-driving technology safely, quickly, and broadly.",country:"US",region:"North America",image:"https://res-3.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/oeagjbu7wau6o16zdhb1"},
        {id:"Zoox",type:"Tier1",tags:"AD_Driverless",technology:"",market:"Robotaxi",valuation:"",description:"Zoox is an AI robotics company that provides mobility as-a-service and self-driving car services.",country:"US",region:"North America",image:"https://res-4.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/kpc7mmk886nbbipbeqau"},
        {id:"Rivian",type:"OEM",tags:"",technology:"",market:"PoV",valuation:"8200",description:"Rivian is an electric vehicle manufacturer that develops products and services to advance the shift to sustainable mobility.",country:"US",region:"North America",image:"https://res-4.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/sdz7aspakybuxp7oojvh"},
        {id:"Torc",type:"Tier1",tags:"AD_Driverless|AD_L3-4",technology:"",market:"Semi_Truck|Mining",valuation:"",description:"Torc provides L4 end-to-end self-driving software for mobility, trucking, mining, and defense markets through strategic partnerships",country:"US",region:"North America",image:"https://res-2.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/smfgyxvfot1dwq4vqvo7"},
        {id:"Intel",type:"Tech",tags:"",technology:"",market:"PoV | Robotaxi",valuation:"",description:"Intel designs, manufactures, and sells integrated digital technology platforms worldwide.",country:"US",region:"North America",image:"https://res-3.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1505768454/wrhwa2ogipbd1o6tgggi.png"},
        {id:"Blackmore",type:"Tier2",tags:"",technology:"LiDAR",market:"PoV|Other",valuation:"21.5",description:"Blackmore Sensors and Analytics develops frequency-modulated continuous wave lidar imaging and its supporting analytic tools software.",country:"US",region:"North America",image:"https://res-2.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1497015437/tqor2yimyfapcsn5uyaj.png"},
        {id:"Uber ATG",type:"Tier1",tags:"AD_Driverless",technology:"",market:"Robotaxi",valuation:"1000",description:"Uber Advanced Technologies Group focuses on autonomous vehicles and the self-driving car business.",country:"US",region:"North America",image:"https://res-5.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/dlzugstswtlgq9wejmfi"},
        {id:"Paccar",type:"OEM",tags:"",technology:"",market:"Semi_Truck",valuation:"",description:"Global technology leader in the design, manufacture and customer support of high-quality premium trucks.",country:"US",region:"North America",image:"https://res-2.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1404996232/nmvcucjqpgpnhrolbnnk.png"},
        {id:"Denso",type:"Tier1",tags:"",technology:"",market:"PoV",valuation:"",description:"Supplier of advanced automotive technology",country:"Japan",region:"Japan",image:"https://res-5.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1398234958/fnjwkbbov8sivhs79wta.png"},
        {id:"Toyota",type:"OEM",tags:"",technology:"",market:"PoV",valuation:"",description:"Toyota is a Japanese automotive company that manufactures and markets vehicles to over 170 countries and regions.",country:"Japan",region:"Japan",image:"https://res-3.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1425366959/cleoo1wmofcfxxspobul.jpg"},
        {id:"OURS-Tech",type:"Tier2",tags:"",technology:"LiDAR",market:"Semi_Truck| Robotaxi",valuation:"",description:"Enabling mass-production 5D LiDAR for the autonomous future",country:"US",region:"North America",image:"https://static.wixstatic.com/media/c668c3_f1f58317e99d41deac4152d212fcdbc2~mv2.gif"},
        {id:"ZadarLabs",type:"Tier2",tags:"",technology:"Radar",market:"PoV| Robotaxi",valuation:"",description:"Zadar Labs brings radar intelligence to autonomous systems",country:"US",region:"North America",image:"https://res-1.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/g3kgj9vsfjzlpbichdml"},
        {id:"Mobileye",type:"Tech",tags:"AS_NCAP|ADAS_uptoL2+|AD_Driverless",technology:"ECU_ADAS",market:"PoV|Robotaxi|Semi_Truck",valuation:"515",description:"Mobileye is a technology company developing vision-based advanced driver assistance systems that help prevent and mitigate collisions.",country:"Israel",region:"Others",image:"https://res-3.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/bcuhhoflftvvdbpeaarx"},
        {id:"Infineon",type:"Tier2",tags:"Interior_cocoon",technology:"",market:"PoV",valuation:"",description:"Infineon Technologies offers semiconductor solutions, microcontrollers, LED drivers, sensors and Automotive & Power Management ICs.",country:"Germany",region:"EU",image:"https://res-2.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/v1397183702/79bc5b009247cfd1a274f2a328ff17bf.png"},
    
    ]

至于我的 D3 javascript 代码,这里是最相关的部分:

    const svg = d3.create("svg")
        .attr("preserveAspectRatio", "xMinYMin meet")
        .attr("viewBox", [-width/2,-height/2, width,height])
        .classed("svg-content-responsive", true)

    const defs = svg.append('svg:defs');
    

    defs.append("svg:pattern")
    .attr("id", "grump_avatar")
    .attr("width", 1)
    .attr("height", 1)
    //.attr("patternUnits", "userSpaceOnUse")
    .append("svg:image")
    .attr("xlink:href", 'http://placekitten.com/g/48/48')
    .attr("width",40)
    .attr("height",40)
    .attr("x",0)
    .attr("y",0)

   
    const link = svg.append("g")
        .attr("stroke-opacity", 0.6)
        .attr("stroke-width",  7)
        .attr("stroke-linecap", "round")
        .selectAll("line")
        .data(links)
        .join("line")
        
    if (l) link.attr("stroke", ({index: i}) => setLinkColor(l[i])); // set conditional link color

    
    const node = svg.append("g")
        .attr("stroke", "teal")
        .attr("stroke-opacity", 1)
        .attr("stroke-width", 2)
        .selectAll("circle")
        .data(nodes)
        .join("circle")
        .style("fill", "#fff")
        .style("fill", "url(#grump_avatar)")
        .attr("r", 20)
        .call(drag(simulation))
        

我已经使用你的代码 assemble 一个小例子,你可以在下面看到它。

  1. svg > defs 中,为每个节点创建一个 pattern 并使用那个 pattern(带有公司 ID)来获取该公司的徽标;
  2. 使用您已有的信息为节点引用 pattern

关于您的代码的一些提示:

  1. 你已经使用了ES6逻辑,所以你也可以使用Array.prototype.map等功能。它们通常比 d3.map;
  2. 更具可读性(和 natively implemented!)
  3. 没有必要保留那么多值数组,通常数据的真实来源越少,代码就越容易在未来维护和更新;
  4. 使用清晰的变量名!当您了解上下文时,LS 和 LT 是合乎逻辑的,但是当您在 6 个月后重新访问此代码时,您可能不会立即知道您在编写代码时在说什么。

const nodes = [{
    id: "Amazon",
    image: "https://images-eu.ssl-images-amazon.com/images/G/02/gc/designs/livepreview/a_generic_10_uk_noto_email_v2016_uk-main._CB485921599_.png"
  },
  {
    id: "Aurora",
    image: "https://res-3.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/oeagjbu7wau6o16zdhb1"
  },
  {
    id: "Zoox",
    image: "https://res-4.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_170,w_170,f_auto,b_white,q_auto:eco/kpc7mmk886nbbipbeqau"
  }
];

const links = [{
    src: 'Amazon',
    target: 'Aurora'
  },
  {
    src: 'Amazon',
    target: 'Zoox'
  },
  {
    src: 'Aurora',
    target: 'Zoox'
  }
];

const width = 500,
  height = 500;

function ForceGraph({
  nodes, // an iterable of node objects (typically [{id}, …])
  links // an iterable of link objects (typically [{src, target}, …])
}, {
  nodeId = d => d.id, // given d in nodes, returns a unique identifier (string)
  nodeTitle, // given d in nodes, a title string
  nodeStroke = "teal", // node stroke color
  nodeStrokeWidth = 2, // node stroke width, in pixels
  nodeStrokeOpacity = 1, // node stroke opacity
  nodeRadius = 20, // node radius, in pixels
  nodeStrength = -750,
  linkDistance = 100,
  linkStrokeOpacity = 0.6, // link stroke opacity
  linkStrokeWidth = 7, // given d in links, returns a stroke width in pixels
  linkStrokeLinecap = "round", // link stroke linecap
  linkStrength,
  container
} = {}) {

  // Compute values.
  const N = d3.map(nodes, nodeId);

  // HERE: Don't replace the input nodes using this complex method,
  // just Object.assign({}, n) to essentially perform a deep copy of a node.

  // Replace the input nodes and links with mutable objects for the simulation.
  nodes = nodes.map(n => Object.assign({}, n));
  links = links.map(l => ({
    source: l.src,
    target: l.target
  }));

  const svg = d3.select('body')
    .append("svg")
    .attr("preserveAspectRatio", "xMinYMin meet")
    .attr("viewBox", [-width / 2, -height / 2, width, height])
    .classed("svg-content-responsive", true)

  const defs = svg.append('svg:defs');

  // HERE: See we add one image per node
  defs.selectAll("pattern")
    .data(nodes)
    .join(
      enter => {
        // For every new <pattern>, set the constants and append an <image> tag
        const patterns = enter
          .append("pattern")
          .attr("width", 48)
          .attr("height", 48);
        patterns
          .append("image")
          .attr("width", 48)
          .attr("height", 48)
          .attr("x", 0)
          .attr("y", 0);
        return patterns;
      }
    )
    // For every <pattern>, set it to point to the correct
    // URL and have the correct (company) ID
    .attr("id", d => d.id)
    .select("image")
    .datum(d => {
      debugger;
      return d;
    })
    .attr("xlink:href", d => {
      debugger;
      return d.image;
    })

  const link = svg.append("g")
    .attr("stroke-opacity", linkStrokeOpacity)
    .attr("stroke-width", linkStrokeWidth)
    .attr("stroke-linecap", linkStrokeLinecap)
    .selectAll("line")
    .data(links)
    .join("line");

  // Construct the forces.
  const forceNode = d3.forceManyBody();
  const forceLink = d3.forceLink(links).id(({
    index: i
  }) => N[i]);
  if (nodeStrength !== undefined) forceNode.strength(nodeStrength);
  if (linkStrength !== undefined) forceLink.strength(linkStrength);
  forceLink.distance(linkDistance)
  const simulation = d3.forceSimulation(nodes)
    .force(link, forceLink)
    .force("charge", forceNode)
    .force("x", d3.forceX())
    .force("y", d3.forceY())
    .on("tick", ticked);

  const node = svg.append("g")
    .attr("stroke", nodeStroke)
    .attr("stroke-opacity", nodeStrokeOpacity)
    .attr("stroke-width", nodeStrokeWidth)
    .selectAll("circle")
    .data(nodes)
    .join("circle")
    .style("fill", "#fff")
    .style("fill", d => `url(#${d.id})`)
    .attr("r", nodeRadius);

  function ticked() {
    link
      .attr("x1", d => d.source.x)
      .attr("y1", d => d.source.y)
      .attr("x2", d => d.target.x)
      .attr("y2", d => d.target.y);
    node
      .attr("cx", d => d.x)
      .attr("cy", d => d.y);
  }
} // ForceGraph

ForceGraph({
  nodes,
  links
});
line {
  stroke: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js"></script>