2017-01-03 1 views
0

D3에 익숙하지 않은 점은 JSON과 같은 복잡한 데이터 세트가 처리되는 방식에 대해 약간의 불확실성이 있음을 의미합니다. 일반적으로 JSON을 트래버스 할 때 나는 루프와 같은 것들을 D3으로 중첩합니다. 나를 돌 보시는 것 같아.D3 Traversing Internal JSON

내가 데이터 바인딩 D3에에 대한 자습서를 다음,이 해낸했다 : 그것은 잘 작동

var dataset = [{ 
    "bread": "Honey Bread", 
    "ingredients": [{ 
    "ingredient": "Whole Wheat Flour", 
    "quantity": 1 
    }, { 
    "ingredient": "Water", 
    "quantity": 1 
    }, , { 
    "ingredient": "Honey", 
    "quantity": 1 
    }, { 
    "ingredient": "Yeast", 
    "quantity": 1 
    }, , { 
    "ingredient": "Salt", 
    "quantity": 1 
    }] 
}, { 
    "bread": "Grain Bread", 
    "ingredients": [{ 
    "ingredient": "Freshly Milled Whole Wheat Flour", 
    "quantity": 1 
    }, { 
    "ingredient": "Water", 
    "quantity": 1 
    }, , { 
    "ingredient": "Honey", 
    "quantity": 1 
    }, { 
    "ingredient": "Yeast", 
    "quantity": 1 
    }, , { 
    "ingredient": "Salt", 
    "quantity": 1 
    }] 
}] 
var svg = d3.select(".images") 
    .append("svg") 

var circles = svg.selectAll("circle") 
    .data(dataset) 
    .enter() 
    .append("circle"); 

circles.attr("cx", function(d, i) { 
    return (i * 50) + 25; 
    }) 
    .attr("cy", function() { 
    return 25; 
    }) 
    .attr("r", function(d) { 
    console.log(d); 

    for (var i = 0; i < d.ingredients.length; i++) { 
     return d.ingredients[i].quantity; 
    } 
    }) 

, 내 문제는 첫 번째 개체 노드에 도달 것을 의미하는 최종 return에 루프를 종료하고 하나만 할당합니다 (1).

그래서 어떻게하면 각 성분에 대한 원이 생길 수 있습니까? 다른 방법을 사용합니까, 아니면 간단하게 조정할 필요가있는 코드입니까?

답변

1

먼저 데이터 세트의 최상위 레벨을 사용하여 2 <g> 요소를 생성 할 수 있습니다. 최상위 레벨에서 가장 개의 요소를 가지고 있기 때문에

var breads = svg.selectAll(".bread") 
    .data(dataset) 
    .enter().append("g") 
    .attr("class", "bread"); 

코드가 상기 두 <g> 요소를 생성한다.

// For each bread get the ingredients, then bind 
// and create a circle element for each associated ingredient 
var ingredients = breads.selectAll(".ingredients") 
    .data(function(d) { 
    return d.ingredients; 
    }) 
    .enter().append("circle") 
    .attr("class", "ingredient"); 

전체 작업 예 :

var dataset = [{ 
 
    "bread": "Honey Bread", 
 
    "ingredients": [{ 
 
    "ingredient": "Whole Wheat Flour", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Water", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Honey", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Yeast", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Salt", 
 
    "quantity": 1 
 
    }] 
 
}, { 
 
    "bread": "Grain Bread", 
 
    "ingredients": [{ 
 
    "ingredient": "Freshly Milled Whole Wheat Flour", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Water", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Honey", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Yeast", 
 
    "quantity": 1 
 
    }, { 
 
    "ingredient": "Salt", 
 
    "quantity": 1 
 
    }] 
 
}]; 
 

 
var svg = d3.select("svg"); 
 
var breads = svg.selectAll(".bread") 
 
    .data(dataset) 
 
    .enter().append("g") 
 
    .attr("transform", function(d, i) { 
 
    return "translate(0," + i * 100 + ")"; 
 
    }) 
 
    .attr("class", "bread"); 
 

 
// Draw the circles 
 
var ingredients = breads.selectAll(".ingredients") 
 
    .data(function(d) { 
 
    return d.ingredients; 
 
    }) 
 
    .enter().append("circle") 
 
    .attr("class", "ingredient") 
 
    .attr("r", 40) 
 
    .attr("cx", function(d, i) { 
 
    return 2 * 40 * (i + 1); 
 
    }) 
 
    .attr("cy", 100); 
 

 
// Add the ingredient label 
 
var labels = breads.selectAll(".label") 
 
    .data(function(d) { 
 
    return d.ingredients; 
 
    }) 
 
    .enter().append("text") 
 
    .attr("class", "label") 
 
    .attr("x", function(d, i) { 
 
    return 2 * 40 * (i + 1); 
 
    }) 
 
    .attr("y", 100) 
 
    .text(function(d) { 
 
    return d.ingredient; 
 
    });
.ingredient { 
 
    fill: yellow; 
 
    stroke: red; 
 
    stroke-width: 2; 
 
} 
 
.label { 
 
    text-anchor: middle; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div class="images"> 
 
    <svg height="300" width="800"></svg> 
 
</div>

JS Fiddle version

2

데이터 세트 변수에 두 개의 객체 (각 재료에 빵이있는 유형)가 있고 "데이터 세트"를 "서클"에 바인딩 했으므로 두 개의 원 (각 빵마다 하나씩) 만 얻습니다. .

반경을 성분 수의 함수로 지정하려면 (예를 들어 보았 듯이) 반경 함수에서 d.ingredients.length 만 반환하면됩니다.

각 재료에 원을 원한다면 재료를 부모 빵 객체가 아닌 "원"에 바인딩해야합니다. 이것을하기위한 한 가지 방법은 그들이 속한 빵의 종류에 대한 속성을 가진 성분 객체의 배열을 만드는 것입니다 : var ingredients = [{이름 : 꿀, 양 : 5, 빵 : 허니 빵}, ...] . 이것을 서클에 바인딩하면 모든 재료에 대해 원이 생기며 한 번에 여러 개의 빵 요리법을 표시하려는 경우와 같이 빵의 유형에 따라 원의 색상을 선택할 수 있습니다.

+0

가 일부를 제공 할 수

그런 다음 중첩 된 재료를 만들 수 bread 요소를 사용할 수 있습니다 예제 c 마지막 시나리오에 대한 ode? 그것이 내가 향하는 것입니다. 각 성분에 대한 원은 부모 빵 개체가 아닌 서클에 바인딩됩니다. –