2015-01-22 2 views
1

Я работаю над проектом, который занимается визуальным представлением больших реляционных данных. Мы используем круговую диаграмму для отображения компонентов данных (в порядке). Из-за нехватки места мы показываем только 10 за раз.Читать внутренний и внешний радиус дуги - d3.js

Рассмотрим следующий пример:

Предположим, что у меня есть 100 данных компонентов, из которых я только 10 просмотров на данный момент времени. Логика, которую я использую, я устанавливаю начальный и конечный угол равным 0 (ноль) для других 90 компонентов. Если в течение этих 10 компонентов я расчет начальный и конечный угол, как

ценам ниже
var angle = 360; 
var count = 10; 
if(data.length > count) angle = angle/count; //data is array of data component names 
else angle = angle/data.length; 

//Initially I'll be displaying first ten components 
for(var i=0; i<data.length; i++){ 
    var startAngle = i * angle; 
    var endAngle = startAngle + angle; 
    var pi = = Math.PI/180; 

    var arc = d3.svg.arc() 
     .innerRadius(innerRadius) //dynamic value, calculated based on available space 
     .outerRadius(outerRadius) //dynamic value, calculated based on available space 
     .startAngle((startAngle)*pi) 
     .endAngle((endAngle)*pi); 

    //Hiding rest of the data components 
    if(i >= count){ 
     arc.startAngle(0); 
     arc.endAngle(0); 
    } 

    arcGroup.append("path") 
     .attr("d", arc) 
     .attr("stroke", "#2E2E2E") 
     .attr("stroke-width", "1") 
     .attr("fill","gold"); 

    var text = arcGroup.append("text") 
     .attr("transform", "translate(" + arc.centroid() + ")") 
     .attr("text-anchor", "middle") 
     .attr("font-family","noto_sansregular") 
     .attr("font-size", 40) 
     .attr("font-weight","Bold") 
     .attr("fill", "#000000") 
     .attr("y",0) 
     .style("visibility", "visible") 
     .text(data[i]); 

    //Hiding text of hidden arcs 
    if(i >= count) text.style("visibility", "hidden"); 
} 

Затем, если пользователь хочет, чтобы увидеть остальные компоненты, я обеспечиваю две кнопки для вращения (часы или анти- часы).

Если текущая точка зрения -> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

На поворот одной клеточной по часовой стрелке, в результате чего вид должен быть -> 100, 1, 2, 3, 4, 5, 6, 7, 8, 9

В этом случае мне нужно скрыть компонент «10» и компонент отображения «100» и сдвинуть остаток ячеек. Для этого мне просто нужно изменить начальный и конечный углы дуг. Я могу создать новый объект дуги с расчетными углами.

Проблема в том, что я не знаю, как получить внутренний и внешний радиус дуги, которые динамически создаются.

ответ

1

Так же, как, что,

... 
arcGroup.append("path") 
    .filter(function(d) { 
     // You're Not restricted to the "filter" function 
     var innerRadius = d.innerRadius()(d); 
     var outerRadius = d.outerRadius()(d); 
    }) 
    .attr("d", arc) 
... 
+0

Спасибо @MaxDy – Ajax1986

2

Технически, можно извлечь innerRadius и outerRadius из атрибута из path элементов d, но это потребует разбора DSL и будет утомительным. Эти значения не сохраняются красиво на самих элементах на d3.

Следовательно, было бы лучше, если бы вы пересчитывать innerRadius и outerRadius при обновлении элементов:

function showFromIdx(firstIndex) { 
    argGroup.selectAll('path') 
    .data(d3.range(data.length) 
      .map(function (d) { 
       return (d - firstIndex + data.length) % data.length; 
       }) 
    ) 
    .attr('d', function (d) { 
     // You will have to calculate the radii again here. 
     var innerRadius = foo(d), outerRadius = bar(d); 
     return d3.svg.arc() 
       .startAngle(i < count ? i * angle : 0) 
       .endAngle(i < count ? (i + 1) * angle : 0) 
       .innerRadius(innerRadius) 
       .outerRadius(outerRadius)(d); 
    }); 
} 
+0

Спасибо, теперь я храню внутренний и внешний радиус в переменной, поэтому я могу его повторно использовать. Но теперь я столкнулся с какой-то другой проблемой - когда происходит преобразование, оно вращается, но похоже на повторное рендеринг от точки к дуге. Поскольку я не изменяю внутренний и внешний радиус, это только начальный и конечный угол. Как я могу просто задать только начальный и конечный угол для преобразования? Я видел несколько примеров на attrTween, но для этого нужен dataSet, который я не использую и не хочу использовать, поскольку мне нужен контроль (присвоение уникального идентификатора, цвета, указателя и т. Д. Для каждого компонента пирога) по каждому компоненту пирога – Ajax1986

1

Вот несколько функций, которые я написал, чтобы получить внутренний и внешние радиусы дуг, созданные с помощью d3. Скажите, пожалуйста, если вы ошибаетесь в коде.

function getInnerRadiusFromArc(arc) { 
    var numbersInPattern = _getArcNumbers(arc); 

    // Possibly, that's sector, so it starts from 0. 
    // Or maybe that's something else. 
    if (numbersInPattern.length < 4) { 
    return 0; 
    } 

    // Getting minimum from the array. 
    var innerRadius = Math.min.apply(null, numbersInPattern); 

    return innerRadius; 
} 

function getOuterRadiusFromArc(arc) { 
    var numbersInPattern = _getArcNumbers(arc); 

    // Getting maximum from the array. 
    var outerRadius = Math.max.apply(null, numbersInPattern); 

    return outerRadius; 
} 

function _getArcNumbers(arc) { 
    // Path description parameter, containing necessary data. 
    var pathDescription = arc.getAttribute("d"); 

    // We need to get all patterns like A<number>,<number>. 
    // RegExp source: 
    // http://www.regular-expressions.info/floatingpoint.html 
    const numberRegExp = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/g; 
    var arcPattern = new RegExp("A" + numberRegExp.source + "," + numberRegExp.source, "g"); 
    var arcParameters = pathDescription.match(arcPattern); 

    var numbersInPattern = []; 

    // We get all the numbers from array ["A<number>,<number>", "A<number>,<number>", ...]. 
    for (let parameterIndex = 0; parameterIndex < arcParameters.length; parameterIndex++) { 
    let parameter = arcParameters[parameterIndex]; 

    let numbers = parameter.match(numberRegExp); 

    if (numbers !== null) { 
     numbersInPattern = numbersInPattern.concat(numbers); 
    } 
    } 

    // Transform strings in our array to numbers. 
    numbersInPattern = numbersInPattern.map(function (numberString) { 
    return parseFloat(numberString); 
    }); 

    return numbersInPattern; 
} 
Смежные вопросы