Ember.js 当余烬处理数据连接时,d3在余烬中转换
我喜欢在我的手柄文件中定义我的Ember中的d3图表,并尽可能避免d3.select和数据连接。我不想使用d3的数据联接,而是想依赖于Ember的计算属性。实际上,在Ember中的d3可视化中,我倾向于将数据点封装在{{each}}循环中,并且Ember负责在底层数据发生变化时更新图表。这一切都很好,但有一个重要的d3功能,我觉得我正在失去这种方式,即。我喜欢在基础数据的两种状态之间进行转换。有没有办法,同时,依靠余烬进行数据连接,避免d3.select.data舞蹈,并以某种方式仍然能够应用d3转换 下面是一个示例代码,我想在更改高度时将条形图从一种状态转换为另一种状态。这是一个很小的示例,但我认为它是说明性的。提前感谢您的帮助Ember.js 当余烬处理数据连接时,d3在余烬中转换,ember.js,d3.js,Ember.js,D3.js,我喜欢在我的手柄文件中定义我的Ember中的d3图表,并尽可能避免d3.select和数据连接。我不想使用d3的数据联接,而是想依赖于Ember的计算属性。实际上,在Ember中的d3可视化中,我倾向于将数据点封装在{{each}}循环中,并且Ember负责在底层数据发生变化时更新图表。这一切都很好,但有一个重要的d3功能,我觉得我正在失去这种方式,即。我喜欢在基础数据的两种状态之间进行转换。有没有办法,同时,依靠余烬进行数据连接,避免d3.select.data舞蹈,并以某种方式仍然能够应用d
// bar-chart.js
export default Ember.Component.extend({
tagName: "svg",
attributeBindings: ["width", "height"],
width: 950,
height: 600,
padding: { top:..., bottom:..., left:..., right:... },
transformG: function() {
var padding = this.get("padding");
return "translate(%@,%@)".fmt(padding.left, padding.top);
}.property(),
chartW: function() {
...
}.property("width"),
chartH: function() {
...
}.property("height"),
yScale: function() {
var data = this.get("data");
return d3.scale.linear().domain(d3.extent(data, function(d) { return d.value; })).range([...]);
}.property("data", "chartH"),
xScale: function() {
...
}.property("data", "width"),
actions: {
// Some action that modifies the height of the svg
}
});
// bar-chart.hbs
<g class="axis x"></g>
<g class="axis y"></g>
<g class="bars" {{bind-attr transform=transformG width=chartW height=chartH}}>
{{#each d in data}}
{{vertical-bar value=d.value timestamp=d.timestamp yScale=yScale xScale=xScale}}
{{/each}}
<g>
假设子组件{{vertical bar}}负责计算与每个条相关的一些属性。虽然d3进入/更新/退出范例可能会令人困惑/麻烦,但它确实是d3的核心,试图覆盖它,但仍然使用d3的其他部分,如转换,可能会给您带来很多麻烦 例如: d3只绑定一次svg元素,但我认为您在这里所做的工作会在每次数据更改时重新加载元素,而这可能不是您想要的。如果您尝试使用transition,同时还更新了Ember中的数据,那么事情可能会爆炸 我很熟悉d3.select.data舞蹈中令人头疼的问题,但最终这通常意味着我对数据的形状理解不太清楚。您不想这样做有什么技术原因吗?或者,数据中的每个d只是在概念上更简单 替代方案 您可能需要考虑一组中间数据,这些数据由d3生成,但由Ember控制。我目前使用的一种策略是创建一个ObjectProxy数组来包装一些自定义属性,然后将整个内容传递给它d3: 创建{content:{timestamp:d.x,some_属性:d.foo,type:bar} 当您更新这个中间集合时,您可以简单地将整个集合再次传递给d3,并且如果您的输入/更新/退出选择设置正确,它将执行正确的操作 确保这一点的一个技巧是在基准上设置一个唯一的ID,并在选择过程中使用该ID: svg.selectAllrect。data@getmyData,d->d.getid 小心:咖啡脚本= 灰烬w/D3 我认为,在使用D3完成其余工作之前,允许Ember控制输入的数据是您想要做的,否则您只是混淆了职责,您也可以滚动您自己的图形库。上述替代方案为您提供了更多的控制,并将计算属性添加到您的基准中,可以这样使用: selection.transition.attr{x:d->d.getend_x},其中end_x是Ember为您处理的东西
或者:.onclick,d,i=>d.getcontroller.transitionorRouteMyRoute,d.id我很感谢你的回答。我觉得你是对的,但我很想知道别人怎么想。你建议的替代模式实际上或多或少是我一直遵循的模式,直到我考虑让余烬承担更多的责任。正如你所说,没有真正的技术原因,只是在概念上对我更清楚。关于重新渲染,你有一个很好的观点,但没有考虑这个问题。我想知道Netflix的家伙们使用了什么方法,他们是否真的坚持d3连接,而不是让Ember接管。非常感谢。