2013-08-20 182 views
2

當我將Extjs和D3結合在一起時,我正在深入研究一些非常有趣的內容。Extjs + D3:渲染衝突

一般來說,ExtJS呈現整個頁面的主框架,D3呈現該框架中某個div的動態圖形。

由於Extjs中的渲染邏輯非常複雜,我放置D3渲染邏輯的地方似乎非常重要。

在這裏,我嘗試了兩種:

1)投入「initComponent」

[ExtJS] 
Ext.define('EDS.view.selector.Container', { 
extend: 'Ext.panel.Panel', 
alias : 'widget.selectorcontainer', 

    initComponent: function(){ 
     renderSelectorOrgView(); 
    } 
} 

[D3] 
function renderSelectorOrgView(divId, divHeight, divWidth) { 
    var svg = d3.select("#" + divId).append("svg"); 
    .... 
} 

的問題是,它只是沒有因爲「initComponent」期間的工作,股利是不完全產生。

2)投入全球Ext.onReady()

事實證明,這是D3只能選擇空的結果。我想原因是類似於1)

3)投入的OnRender()

按道理這應該工作正常的。事實上D3可以完美地獲得div和它的屬性。但問題是,ExtJS渲染過程完全被這段代碼破壞了。整個佈局已損壞。所以我錯過了onRender()中的任何重要內容?

Ext.define('EDS.view.selector.Container', { 
extend: 'Ext.panel.Panel', 
alias : 'widget.selectorcontainer', 

layout: 'fit', 
onRender: function(){ 

    //// Render D3 
    // Selector 
    console.log("onRender"); 
    console.log(this.height); 
    console.log(this.width); 

    var divId = Ext.getCmp('selector-organization').id; 
    var divHeight = Ext.get(divId).getHeight(); 
    var divWidth = Ext.get(divId).getWidth(); 
    console.log(divHeight); 
    console.log(divWidth); 
    renderSelectorOrgView(divId, divHeight, divWidth); 

}, 
} 

回答

1

如果可以將D3對象呈現爲HTML標記的字符串,則可以在面板模板中包含該字符串。另一種方法是讓Ext JS組件像往常一樣渲染自己,然後在boxready事件處理程序中注入新的標記。無論哪種方式都可以避免渲染衝突。

+0

在DOM元素完全呈現後'boxready'被觸發,並且在稍後的渲染中不會更改? – SolessChong

+0

Ext JS組件首先被渲染到DOM中,然後進行佈局(分配的尺寸)。 'boxready'事件在第一個佈局之後觸發,並且只觸發一次。之後,組件的佈局(尺寸)可以更改,但其DOM標記通常不會。 –

1

您必須在onRender添加this.callParent(arguments);。在這裏,你完全取代了Panel自己的渲染邏輯,這就是爲什麼它最終破裂。

您也可以參見thisthis其中討論類似主題的問題。

3

使您的d3代碼與extjs一起工作的最佳方式是將d3代碼保存在不同的html中。然後在你的extjs面板中使用autoLoad配置並給出html的url。

{ 
    xtype : 'panel', 
    title : 'd3Graph', 
    autoLoad : { url : 'd3code.html', scripts : true} // your HTML file containing d3 code. 
} 

我試過這個,它適用於我,沒有任何錯誤。

另一種方法是使用contentEl配置並在渲染d3可視化的配置中給出div的名稱。