我正在创建一个JS图表库,当我更改数据时,我正在努力使用饼图/圆环图。我的视觉效果是使用SVG元素创建的,创建新图表很好。我正在努力改变现有图表上的数据。绘制图表后,我不希望图表在添加或删除扇区时“打开”。
例如,如果我的原始数据(比如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}
];
我实际处理的数据比这个例子更复杂,但这显示了基本的想法。我可以在动画完成后删除临时数组,动画需要removeMe
和new
属性,但动画结束后不需要保留。
临时数组必须包含与原始数组相同顺序的成员(即使它们可能将"removeMe"
属性设置为true
),因为这是它的起点。过渡动画。
我为...循环写了5或6,我真的很接近它的工作,但我的代码很糟糕,我确信有更好的方法。我真正做的就是合并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;
}
}
答案 0 :(得分: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)