You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3.js制作Isotype百分比图:动态实现技术问询

Hey there! Let's break down how to build that dynamic Isotype-style chart you're aiming for, plus share the key terms you need to find more resources.

First off, the chart you're referencing is indeed an Isotype Chart (also called a Pictogram Chart or Icon Chart). Since you're placing these icons on a map, you might also hear this referred to as a Proportional Icon Map—these are the core keywords you can use to search for tutorials and examples.

Right now, your code uses GeoJSON features but doesn't tie them to any numerical data. Instead of manually editing the JSON, you can load your geographic data and your numerical data (e.g., percentages, counts) separately, then match them using a shared identifier (like region ID or name). Here's how to do that with parallel data loading:

// Load both geo data and your value data in parallel
Promise.all([
  d3.json(yourGeoUrl),
  d3.json(yourValueDataUrl) // Or d3.csv if your data is in CSV format
]).then(function([geoData, valueData]) {
  // Match value data to each geographic feature
  geoData.features.forEach(feature => {
    const matchedData = valueData.find(item => item.regionId === feature.properties.regionId);
    feature.properties.value = matchedData ? matchedData.percentage : 0; // Use your value field here
  });

  // Rest of your existing code to create groups, paths, etc.
  const group = canvas.selectAll("g")
    .data(geoData.features)
    .enter()
    .append("g");

  // ... your area path code here ...
});

Step 2: Generate Icons Based on Values

Instead of a single rectangle per centroid, you'll generate multiple icons proportional to your value. For example, if a region has a 30% value and you use 10 icons to represent 100%, you'd draw 3 filled icons. Here's how to handle that:

// Inside your data processing block, after creating the group
group.each(function(d) {
  const centroid = path.centroid(d);
  const value = d.properties.value;
  const totalIconsFor100Percent = 10; // Adjust this to your desired icon count
  const iconCount = Math.round((value / 100) * totalIconsFor100Percent);

  // Create a sub-group to hold icons, positioned at the centroid
  const iconGroup = d3.select(this)
    .append("g")
    .attr("transform", `translate(${centroid[0] - (totalIconsFor100Percent * 12)/2}, ${centroid[1]})`); // Center the icon grid

  // Generate the icons
  iconGroup.selectAll("rect")
    .data(d3.range(totalIconsFor100Percent)) // Create all placeholder icons first
    .enter()
    .append("rect")
    .attr("x", (_, i) => (i % 5) * 12) // Space icons 2px apart (10px width + 2px gap)
    .attr("y", (_, i) => Math.floor(i / 5) * 12)
    .attr("width", 10)
    .attr("height", 10)
    .style("fill", (_, i) => i < iconCount ? "orange" : "#eee"); // Fill based on value
});

Step 3: Add Dynamic Input Support

To make this driven by dynamic inputs (like user form entries), wrap your icon update logic in a reusable function. Then listen for input changes to refresh the chart:

// Define a reusable update function
function updateChart(newValueData) {
  // Re-match new values to geo features
  geoData.features.forEach(feature => {
    const matchedData = newValueData.find(item => item.regionId === feature.properties.regionId);
    feature.properties.value = matchedData ? matchedData.percentage : 0;
  });

  // Update existing icon groups
  canvas.selectAll("g").each(function(d) {
    const value = d.properties.value;
    const totalIconsFor100Percent = 10;
    const iconCount = Math.round((value / 100) * totalIconsFor100Percent);

    d3.select(this).select("g").selectAll("rect")
      .style("fill", (_, i) => i < iconCount ? "orange" : "#eee");
  });
}

// Example: Listen for a slider input change
d3.select("#percentage-slider").on("input", function() {
  // Assume you get new data based on the input value
  const updatedData = getUpdatedDataFromInput(this.value);
  updateChart(updatedData);
});

Key Search Terms to Explore More

  • Isotype Chart / Pictogram Chart: The core chart type you're building
  • Proportional Icon Map: For map-based icon charts like yours
  • D3.js enter/update/exit: The pattern used to dynamically update elements in D3
  • D3.js data joining: How to link your data to DOM elements

内容的提问来源于stack exchange,提问作者louislugas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:59:08