Javascript 什么';是扩展本机d3组件(如d3.svg.axis()的惯用方法吗?

Javascript 什么';是扩展本机d3组件(如d3.svg.axis()的惯用方法吗?,javascript,d3.js,Javascript,D3.js,对于d3中的时间序列可视化,我想突出显示轴上的年份。我通过制作自己的xAxis渲染器实现了这一点,它调用本机的axis函数,然后实现自己的自定义逻辑来格式化它渲染的刻度 我就是这样做的(): 这样可以完成工作,但感觉不对;它并没有真正延伸轴线,只是把它包裹起来。理想情况下,我的customXAxis将继承d3的axis组件的属性,因此我可以这样做: customXAxis.ticks(10) 感谢@meetamit和@drakes把这一切放在一起。以下是我的结论:经过大量的代码检查和黑客攻

对于d3中的时间序列可视化,我想突出显示轴上的年份。我通过制作自己的xAxis渲染器实现了这一点,它调用本机的
axis
函数,然后实现自己的自定义逻辑来格式化它渲染的刻度

我就是这样做的():

这样可以完成工作,但感觉不对;它并没有真正延伸轴线,只是把它包裹起来。理想情况下,我的
customXAxis
将继承d3的
axis
组件的属性,因此我可以这样做:

customXAxis.ticks(10)


感谢@meetamit和@drakes把这一切放在一起。以下是我的结论:

经过大量的代码检查和黑客攻击,并与经验丰富的d3人员交谈,我了解到,
d3.svg.axis()
是一个函数(不是对象或类),因此它不能被扩展或包装。因此,为了“扩展”它,我们将创建一个新的轴,在基础
axis()
上运行一个选择,以选择那些记号,然后从基础
axis()
上一次性复制所有属性,并返回此扩展功能版本

var customXAxis = (function() {
  var base = d3.svg.axis();

  // Select and apply a style to your tick marks
  var newAxis = function(selection) {
    selection.call(base);
    selection.selectAll('.tick', this)
      .classed("year", isYear);
  };

  // Copy all the base axis methods like 'ticks', 'scale', etc.
  for(var key in base) {
    if (base.hasOwnProperty(key)) {
       d3.rebind(newAxis, base, key);
    }
  }

  return newAxis;
})();
customXAxis
现在完全“继承”d3轴组件的属性。您可以安全地执行以下操作:

customXAxis
.ticks(2)
.scale(xScale)
.tickPadding(50)
.tickFormat(dateFormatter);

canvas.append("g").call(customXAxis);
*借助@HerbCaudill的样板代码,并受到@meetamit想法的启发


演示:

是的,你可以做所有这些。以下是与您一起获得的:

要使用这个类,只需调用

myCustomXAxis = InstantiateCustomXAxis();
你现在也可以打电话

myCustomXAxis
  .scale(d3.scale.ordinal())
  .ticks(5)
当然,以下各项将继续发挥作用:

xAxisElement = canvas.append("g")
  .classed("axis x", true)
  .call(myCustomXAxis);
总之
这是在d3中实现类的惯用方法。Javascript还有其他创建类的方法,比如使用
prototype
对象,但是d3自己的可重用代码使用上述方法,而不是prototype方法。其中,
d3.rebind
是将方法调用从自定义类转发到本质上是子类的方法。

不确定这里的“extend”是什么意思。对于你想做的事情,你必须修改D3源代码,当然你可以这样做,然后你可以做任何你喜欢的更改。“扩展”的意思就是我在这里展示的:创建一个自定义轴,生成标准轴生成的东西,然后在该轴上做额外的工作-以一种与原始轴完全相同的方式调用。这里显示的方法是有效的,但是由于某种原因,
xAxis(this)
对d3来说感觉不太熟悉。嗯
.call()
将选择作为参数传递给函数,因此您也可以使用它。这是真的-
this.call(xAxis)
在这种情况下看起来更自然。哦,我实际上是说你有一个
customXAxis
的参数,用它来代替
这个
。谢谢,@Drakes。那不行;看见d3.svg.axis()函数的参数是一个选择,为true,但该代码在呈现axis之前运行,而不是在axis之后运行。@HerbCaudill我已经更新了我的解决方案和jsbin以实现您想要的结果。我真的希望这就是你要找的。我已经一遍又一遍地阅读了d3的源代码,并与其他人进行了交谈,这是最好的。感谢您为此所做的所有工作。我喜欢你们自动重新绑定所有基本对象的方法的方式——我一定会使用它。我已经创建了一个额外的赏金,因为我不能在两个答案之间分配赏金——必须等到明天才能奖励。@HerbCaudill哦,天哪,你们太慷慨了。非常感谢你。让我开心。很高兴为您提供此解决方案。另外,欢迎加入10K俱乐部!很高兴能让你脱颖而出。:)令人惊叹的!谢谢你的指点!我原以为我会慢慢走向10公里,但多亏了你,我才刚刚越过它:)
myCustomXAxis
  .scale(d3.scale.ordinal())
  .ticks(5)
xAxisElement = canvas.append("g")
  .classed("axis x", true)
  .call(myCustomXAxis);