2017-08-03 76 views
2

我正在創建一個JS圖表庫,當我更改數據時,我正努力使用餅圖/圓環圖。我的視覺效果是用SVG元素創建的,創建一個新的圖表很好。我在掙扎的地方是改變現有圖表上的數據。一旦圖表被繪製完成,我不希望圖表在添加或刪除扇區時「開放」。合併和重新排序2個數組

因此,舉例來說,如果我的原始數據(說arrOld)是

arrOld = [ 
    {name: "bacon", amount: 50}, 
    {name: "eggs", amount: 25}, 
    {name: "sausages", amount: 15}, 
    {name: "toast", amount: 10} 
]; 

,我想圖表動畫到一個新的數據陣列(比如,arrNew),這是

arrNew = [ 
    {name: "bacon", amount: 50}, 
    {name: "hash browns", amount: 8}, 
    {name: "eggs", amount: 25}, 
    {name: "toast", amount: 10}, 
    {name: "sausages", amount: 15} 
]; 

我希望新成員"hash browns""bacon""eggs"之間的0°「增長」,迫使它們分開。這部分我已經很成功地實現了。因爲"toast""sausages"已經互換位置,我希望其中一個動畫(壓扁)到0°(然後被移除),而新的替換部門在其新位置「增長」。因此,我將有效有一箇中間陣列(比如,arrTemp),這將是這個樣子:

arrTemp = [ 
    {name: "bacon", amount: 50}, 
    {name: "hash browns", amount: 8, new: true}, 
    {name: "eggs", amount: 25}, 
    {name: "sausages", amount: 15, removeMe:true} 
    {name: "toast", amount: 10}, 
    {name: "sausages", amount: 15, new:true} 
]; 

我實際處理的數據比這個例子方式更復雜,但是這顯示了基本思路。我可以在動畫完成後移除臨時數組,並且動畫需要removeMenew屬性,但在動畫完成後不需要保留。

重要的是,臨時數組包含的成員與原始數組的順序相同(即使它們的"removeMe"屬性設置爲true),因爲那是過渡動畫的起點。

我已經寫了5或6 for ...循環,我真的很接近它的工作,但我的代碼是可怕的,我相信有一個更好的方法來做到這一點。所有我真正做的是合併2個數組:O(

感激地收到任何幫助:O)

這裏是我當前的代碼:

var o; 

//get the wedges from the previous animation call (the "old" array) 
anWedges=gs.wedges[this._drawCall-1].clone(); 

//now find the new members: 
//first set our new array to the current data: 
var wedgesNew=gs.wedges[this._drawCall].clone(); 
//set "precedes" and "follows" properties: 
for (w=0; w<wedgesNew.length; w++){ 
    wedgesNew[w].precedes=null; 
    wedgesNew[w].follows=null; 
    if (w>0){ 
     wedgesNew[w].follows=wedgesNew[w-1].id; 
    } 
    if(w<wedgesNew.length-1){ 
     wedgesNew[w].precedes=wedgesNew[w+1].id; 
    } 
} 

//remove any members from our new array that were in the old one: 
for (o=0; o<anWedges.length; o++){ 
    anWedges[o].new=false; 
    anWedges[o].moved=false; 
    for (w=0; w<wedgesNew.length; w++){ 
     if (anWedges[o].id===wedgesNew[w].id){ 
      wedgesNew.splice(w,1); 
      break; 
     } 
    } 
} 

//add our new array members to the old array: 
for (w=0; w<wedgesNew.length; w++){ 
    wedgesNew[w].new=true; 
    //if its "follow" member doesn't exist, put it at the front: 
    if (wedgesNew[w].follows===null){ 
     anWedges.unshift(wedgesNew[w]); 
    } 
    else{ 
     //otherwise, put it where it should be: 
     for (o=0; o<anWedges.length; o++){ 
      if (anWedges[o].id===wedgesNew[w].follows){ 
       anWedges.splice(o+1, 0, wedgesNew[w]); 
       break; 
      } 
     } 
    } 
} 

//add a "follows" property to any members that don't have one: 
for (o=0; o<anWedges.length; o++){ 
    if (isNil(anWedges[o].follows) && o > 0){ 
     for (w =0; w<gs.wedges[this._drawCall].length-1; w++){ 
      if (gs.wedges[this._drawCall][w+1].id === anWedges[o].id){ 
       anWedges[o].follows=gs.wedges[this._drawCall][w].id; 
      } 
     } 
    } 
} 

//see if we need to move any members: 
var prevID=""; 
for (o=0; o<anWedges.length; o++){ 
    var wRequired=false; 
    for (w=0; w<gs.wedges[this._drawCall].length;w++){ 
     if (gs.wedges[this._drawCall][w].id===anWedges[o].id){ 
      wRequired=true; 
      break; 
     } 
    } 
    if (!wRequired){ 
     anWedges[o].removeMe=true; 
    } 
    else{ 
     if (o>0 && !anWedges[o].new){ 
      if(prevID!=="" && anWedges[o].follows!==prevID && !anWedges[o].removeMe){ 
       var wMoved=cloneObj(anWedges[o]); 
       wMoved.moved=true; 
       anWedges[o].removeMe=true; 
       anWedges[o].id=anWedges[o].id+"_old"; 
       for (w=0;w<anWedges.length;w++){ 
        if (anWedges[w].id===anWedges[o].follows){ 
         anWedges.splice(w+1,0, wMoved); 
         break; 
        } 
       } 
      } 
     } 
     prevID=anWedges[o].id; 
    } 
} 
+1

***「我的代碼太可怕了」***,請將其添加到問題中。 –

+1

感謝妮娜,我已經添加了我的代碼(儘管我認爲它沒有多大幫助!) – MumbleBee

回答

0

好啦,我已經整理了。

我用David Furlong的獨特功能的變化從this question合併兩個陣列:

//returns a NEW array with duplicate members removed 
Array.prototype.unique = function(prop) { 
    var a = this.concat(); 
    for(var i=0; i<a.length; ++i) { 
     for(var j=i+1; j<a.length; ++j) { 
      if (!isNil(prop)){ 
       if (a[i].hasOwnProperty(prop) && a[j].hasOwnProperty(prop)) { 
        if(a[i][prop] === a[j][prop]){ 
         a.splice(j--, 1); 
        } 
       } 
      } 
      else{ 
       if(eve.isEqual(a[i], a[j])){ 
        a.splice(j--, 1); 
       } 
      } 
     } 
    } 
    return a; 
}; 

和該功能可以通過優選的索引對象的數組進行排序:

//sort an array of objects by an object property 
function sortByProperty(prop) { 
    return function (a,b) { 
     if (a.hasOwnProperty(prop) && b.hasOwnProperty(prop)) { 
      return (a[prop] < b[prop]) ? -1 : (a[prop] > b[prop]) ? 1 : 0; 
     } 
    }; 
} 

和我的代碼現在更加簡潔:

var oldWedges=gs.wedges[this._drawCall-1].clone(); 
var newWedges=gs.wedges[this._drawCall].clone(); 

//merge the old and new arrays, omitting duplicate IDs (start with the new array, that way we honour the new order): 
var anWedges = newWedges.concat(oldWedges).unique("id"); 
//tag any new members as new: 
for (n=0; n<anWedges.length;n++){ 
    if (oldWedges.indexOfProp("id", anWedges[n].id) === -1){ 
     anWedges[n].new=true; 
    } 
} 

//check that the order of the old members hasn't changed 
//if it has, tag them for moving: 
for (o=0; o<oldWedges.length;o++){ 
    n = anWedges.indexOfProp("id", oldWedges[o].id); 
    var t=0; 
    var tmp = null; 
    var prev=null; 
    var next=null; 
    if (o>0){ 
     t=o-1; 
     tmp=oldWedges[t]; 
     while (t>0 && anWedges.indexOfProp("id", tmp.id) === -1){ 
      tmp=oldWedges[t]; 
      t-=1; 
     } 
     prev=tmp; 
    } 
    if (o<oldWedges.length-1){ 
     t=o+1; 
     tmp=oldWedges[t]; 
     while (t<oldWedges.length-1 && anWedges.indexOfProp("id", tmp.id) === -1){ 
      tmp=oldWedges[t]; 
      t+=1; 
     } 
     next=tmp; 
    } 
    if (!isNil(prev)){ 
     if (prev.i>=anWedges[n].i){ 
      anWedges[n].moveMe=true; 
     } 
    } 
    if (!isNil(next)){ 
     if (next.i<=anWedges[n].i){ 
      anWedges[n].moveMe=true; 
     } 
    } 
} 

//create duplicate wedges for any that need to move so that we can animate them collapsing: 
for (n=0;n<anWedges.length;n++){ 
    if (anWedges[n].moveMe){ 
     anWedges[n].moveMe=false; 
     var oldWedge=cloneObj(oldWedges[oldWedges.indexOfProp("id", anWedges[n].id)]); 
     oldWedge.sector=oldWedge.sector.clone(); 
     var oldIndex=0; 
     if (oldWedges.indexOfProp("id", oldWedge.id)>0){ 
      var prevID=oldWedges[oldWedges.indexOfProp("id", oldWedge.id)-1].id; 
      oldIndex=anWedges.indexOfProp("id", prevID)+1; 
     } 
     oldWedge.id+="_old"; 
     oldWedge.removeMe=true; 
     anWedges[n].moved=true; 
     anWedges.splice(oldIndex, 0, cloneObj(oldWedge)); 
    } 
} 

//tag any old wedges that are obsolete for removal 
for (n=0;n<anWedges.length;n++){ 
    if (newWedges.indexOfProp("id", anWedges[n].id)===-1){ 
     anWedges[n].removeMe=true; 
    } 
} 

//sort wedges by their preferred order: 
anWedges.sort(sortByProperty("i")); 

它還沒有我想要的那麼整齊,但它適用於我所有的測試用例。 :o)