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

D3 v3升级至v5后出现‘Cannot read properties of null (reading 'transition')’错误求助

D3 v3升级v5后"Cannot read properties of null (reading 'transition')"错误修复

问题背景

将D3可视化项目从v3升级到v5,已完成d3.svg.arc→d3.arc、d3.layout.pie→d3.pie等API适配,但运行时抛出错误:

"Cannot read properties of null (reading 'transition')"

错误原因

  • 缓动函数写法变更:D3 v5废弃了v3中.ease('cubic')的字符串参数写法,必须传入d3.easeCubic这类函数引用,否则过渡对象初始化失败返回null,触发transition读取错误。
  • 弧生成器调用方式:v3中直接将弧生成器函数传给.attr("d")的写法,在v5中需显式调用(如arc()而非arc),否则无法生成正确的路径字符串。
  • SVG属性兼容性:v3中的xlink:href属性在v5中需改为标准href,D3 v5会自动处理SVG命名空间。

修复步骤

  • 替换缓动函数:将.ease('cubic')改为.ease(d3.easeCubic)
  • 修正弧生成器调用:所有.attr("d", arc)改为.attr("d", arc())
  • 更新SVG图片属性:将xlink:href替换为href
  • 清理冗余代码:移除未使用的pie生成器

修复后的完整代码

JavaScript

// set the dimensions and margins of the graph
var margin = {
    top: 50,
    right: 30,  
    bottom: 10,
    left: 50
  },
  width = 900 - margin.left - margin.right,
  height = 150 - margin.top - margin.bottom;

// append the svg object to the body of the page
var svg = d3.select("#chart")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform",
    "translate(" + margin.left + "," + margin.top + ")");

var outerRadius = 45;
var innerRadius = outerRadius - 5;
var color = ['#ec1561', '#2a3a46', '#ec1561'];

var data = [
  {
    "value": 90,
    "variance": 6
  }
];

var percent = d3.max(data, function(d) {
    return d.value;
  });

var arc = d3.arc()
  .innerRadius(30)
  .outerRadius(35)
  .startAngle(0)
  .endAngle(2 * Math.PI);

var arc2 = d3.arc()
  .innerRadius(30)
  .outerRadius(35)
  .startAngle(0)
  .endAngle(2 * Math.PI);

//The circle is following this
var arcDummy = d3.arc()
  .innerRadius((outerRadius - innerRadius) / 2 + innerRadius)
  .outerRadius((outerRadius - innerRadius) / 2 + innerRadius)
  .startAngle(0);

var arcLine = d3.arc()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius)
  .startAngle(0);

//background
var path = svg.append('path')
  .attr("d", arc())
  .attr("fill", color[1])
  .attr("opacity", 0.2);

var path2 = svg.append('path')
  .attr("d", arc2())
  .attr("fill", color[1])
  .attr("opacity", 0.2);

var pathForeground = svg.append('path')
  .datum({ endAngle: 0 })
  .attr("d", arcLine({ endAngle: 0 }))
  .attr("fill", "#137A76");

//Dummy Arc for Circle
var pathDummy = svg.append('path')
  .datum({ endAngle: 0 })
  .attr("d", arcDummy({ endAngle: 0 }))
  .attr("fill", color[0]);

var endCircle = svg.append('circle')
  .attr("r", 0)
  .attr("transform", 'translate(0,' + (-outerRadius + 7) + ')')
  .attr("stroke", color[0])
  .attr("stroke-width", 5)
  .attr("fill", color[2]);

var middleTextCount = svg.append('text')
  .datum(0)
  .text(function(d) {
    return d + '%';
  })
  .attr("class", 'middleText')
  .attr("text-anchor", 'middle')
  .attr("dy", 0)
  .attr("dx", 75)
  .attr("fill", '#ec1561')
  .attr("font-size", '20px');

svg
  .data(data)
  .append("svg:image")
  .attr("y", 20)
  .attr("x", 50)
  .attr("width", 8)
  .attr("href", function(d) {
    if (d.variance < 0 ) {
      return "https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/Red_Arrow_Down.svg/2048px-Red_Arrow_Down.svg.png";
    } else {
      return "https://upload.wikimedia.org/wikipedia/commons/thumb/5/50/Green_Arrow_Up.svg/1200px-Green_Arrow_Up.svg.png";
    }
  });

svg 
  .append("svg:image")
  .attr("y", -25)
  .attr("x", -25)
  .attr("width", 50)
  .attr("href", "https://cdn-icons-png.flaticon.com/512/2879/2879567.png");

svg 
  .append("text")
  .attr("class", "title")
  .attr("y", 15)
  .attr("x", 50)
  .text("Positive Feedback");

svg 
  .data(data)
  .append("text")
  .attr("class", "varweek")
  .attr("y", 27)
  .attr("x", 62)
  .text(function(d) {
    return d.variance + '% vs last week';
  });

var gradient = svg.append("defs")
  .append("linearGradient")
  .attr("id", "gradient")
  .attr("x1", "0%")
  .attr("y1", "0%")
  .attr("x2", "0%")
  .attr("y2", "100%")
  .attr("spreadMethod", "pad");

gradient.append("stop")
  .attr("offset", "0%")
  .attr("stop-color", "#DA0D91")
  .attr("stop-opacity", 0.05);

gradient.append("stop")
  .attr("offset", "100%")
  .attr("stop-color", "#DA0D91")
  .attr("stop-opacity", 1);

var arcTweenOld = function(transition, percent, oldValue) {
  transition.attrTween("d", function(d) {
    var newAngle = (percent / 100) * (2 * Math.PI);
    var interpolate = d3.interpolate(d.endAngle, newAngle);
    var interpolateCount = d3.interpolate(oldValue, percent);

    return function(t) {
      d.endAngle = interpolate(t);
      var pathForegroundCircle = arcLine(d);

      middleTextCount.text(Math.floor(interpolateCount(t)) + '%');

      var pathDummyCircle = arcDummy(d);
      var coordinate = pathDummyCircle.split("L")[1].split("A")[0];

      endCircle.attr('transform', 'translate(' + coordinate + ')');

      return pathForegroundCircle;
    };
  });
};

var oldValue = 0;

var animate = function() {
  pathForeground.transition()
    .duration(750)
    .ease(d3.easeCubic)
    .call(arcTweenOld, percent, oldValue);

  oldValue = percent;
};

setTimeout(animate, 0);

CSS

@import url('https://fonts.googleapis.com/css2?family=Georama:ital@1&display=swap');

body {
    background-color: #1B1F2A;
    width: 100%;
    font-family: 'Georama', sans-serif;
    height: 100%;
}

.widget {
    margin: 0 auto;
    width:350px;
    margin-top:50px;
    background-color: #222D3A;
    border-radius: 5px;
    box-shadow: 0px 0px 1px 0px #06060d;
}

.header{
    background-color: #29384D;
    height:40px;
    color:#929DAF;
    text-align: center;
    line-height: 40px;
    border-top-left-radius: 7px;
    border-top-right-radius: 7px;
    font-weight: 400;
    font-size: 1.5em;
    text-shadow: 1px 1px #06060d;
}

.chart-container{
    padding:25px;
}

.shadow {
    -webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.1) );
    filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.1) );
}

.title {
  font-family: 'Georama', sans-serif;
  fill: white;
  font-size: 11px;
}

.varweek {
  fill: white;
  font-size: 9px;
  opacity: 0.25
}

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart" class="chart-container"></div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 22:01:01