2017-01-31 16 views
0

Я использую библиотеку C3.js для создания штабелированной гистограммы (мой текущий код находится в jsfiddle внизу). Проблема в том, что по умолчанию столбцы ... сложенными. Поскольку мне нужно создавать столбцы с минимальными, средними и максимальными значениями, я бы хотел, чтобы значения скорее содержали друг друга, а не стек. Например. если у меня есть min = 10, средний = 50 и max = 100, я бы хотел, чтобы бар имел высоту 100, а не 160. Есть ли встроенный способ поддержки такого поведения?C3.js - сгруппированная гистограмма - могу ли я сделать значения, чтобы содержать вместо стека друг друга?

Мой текущий код:

<div id="chart"></div> 

<script> 
    var chart = c3.generate({ 
     bindTo: '#chart', 
     data: { 
      columns: [ 
       ['min', 10, 25, 15], 
       ['avg', 50, 33, 51], 
       ['max', 100, 75, 200] 
      ], 
      type: 'bar', 
      groups: [ 
       ['min', 'avg', 'max'] 
      ] 
     } 
    }); 
</script> 

Вот jsfiddle с моим кодом: https://jsfiddle.net/gguej6n0/

ответ

2

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

На этот раз я воспользовался функцией err ... (ошибка?), найденной в c3, которая заставила другого пользователя непреднамеренно получить эффект, который Вы хотели.

c3.js generate a stacked bar from JSON payload

В принципе, если вы предоставляете данные в формате JSON вы можете получить эффект, который вы хотите, если вы снабжаем каждую точку привязки в качестве отдельного пункта например, делая это overplot мин и макс на той же колонке, даже если они предназначены для штабелирования

 [{ "x-axis": "0", 
      "min": 30 
     }, 
     { "x-axis": "0", 
      "max": 40 
     }], 

В то время, таким образом, будет складывать их:

 [{ "x-axis": "0", 
      "min": 30, 
      "max": 40 
     }], 

Так что нам нужно, это рутина, чтобы превратить исходные данные столбцов на основе в объект JSON, где каждый элемент данных будет поделен отдельно:

http://jsfiddle.net/gvn3y0q6/5/

var data = [ 
       ['min', 10, 25, 15, 12], 
       ['avg', 50, 33, 51, 24], 
       ['max', 100, 75, 200, 76] 
      ]; 

var json = []; 
data.forEach (function (datum) { 
    var series = datum[0]; 
    for (var i = 1; i < datum.length; i++) { 
    var jdatum = {"x-axis": i-1}; 
    jdatum[series] = datum[i]; 
    json.push (jdatum); 
    } 
}); 

var chart = c3.generate({ 
    data: { 
     x: "x-axis", 
     json:json, 
     keys: { 
      x: "x-axis", 
      value: ["max", "avg", "min"] 
     }, 
     groups: [ 
      ['max', 'avg', 'min'] 
     ], 
     type: 'bar', 
    }, 
    bar: { 
     width: { 
      ratio: 0.95 
     } 
    }, 
    axis: { 
     x: { 
     padding: { 
      left: 0.5, 
      right: 0.5, 
     } 
     } 
    }, 
    tooltip: { 
     grouped: true, 
     contents: function (d, defaultTitleFormat, defaultValueFormat, color) { 
      var data = this.api.data.shown().map (function(series) { 
       var matchArr = series.values.filter (function (datum) { 
        return datum.value != undefined && datum.x === d[0].x; 
       }); 
       matchArr[0].name = series.id; 
       return matchArr[0]; 
      }); 

      return this.getTooltipContent(data, defaultTitleFormat, defaultValueFormat, color); 
     } 
    } 
    }); 

На этот раз скрытие серии не влияет на другие серии. Там по-прежнему нужна подсказка jiggery-pokery tooltip, хотя в противном случае мы получаем только одно значение, указанное во всплывающей подсказке, при зависании над одним из «стеков».Похоже, что данные содержат много пустых значений, что заставляет меня думать, что это какая-то ошибка, которую я использую здесь.

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

+0

Спасибо, похоже, это почти правильное обходное решение - у вас есть +1 для всех ваших усилий до сих пор :-) К сожалению, решение по-прежнему не идеально - оно начинает звучать, когда по меньшей мере одно из значений равно 0. Более того, поскольку штабелированные столбцы теперь представляют собой отдельные точки данных, зависание баров вызывает странный визуальный эффект - например, когда задерживается мин-бар, максимальный бар исчезает. Я также пытаюсь найти решение для этого, но довольно сложно найти рабочее решение, когда оно не предоставляется самой библиотекой ... и я немного обеспокоен тем, что использование потенциальной ошибки в качестве решения может быть рискованным. – PJDev

+0

Исправлено значение, равное нулевой ошибке. Просто ленивое кодирование. я должен был протестировать 'datum.value! = undefined', так как только' datum.value' запрещало нулевые значения. Но вы правы в других точках, непрозрачность при наведении зависает и полагается на что-то похожее на ошибку, которая немного отбрасывает сигналы тревоги :-). Я предполагаю, что вы можете заморозить версию c3.js или добавить запрос функции на страницу c3 github, это не похоже, что она постоянно обновляется. – mgraham

+0

О, я привык писать такие условия, как 'if (value)', поэтому я не заметил, что это было такое простое исправление :-) Итак, теперь решение в целом работает, и я могу принять его в качестве ответа. Я постараюсь решить проблему с угасанием. Опять же, спасибо за помощь! – PJDev

0

Я не знаю ни о чем встроенные, которые сделают бары сливаются друг с другом, как вы описать, но может ли помочь бок о бок? Если это так, удалите группировку.

См https://jsfiddle.net/gguej6n0/1/

var chart = c3.generate({ 
    bindTo: '#chart', 
    data: { 
     columns: [ 
      ['min', 10, 25, 15], 
      ['avg', 50, 33, 51], 
      ['max', 100, 75, 200] 
     ], 
     type: 'bar' 
    }, 
    bar: { 
      width: { 
       ratio: 0.3 
     } 
    } 
}); 
+0

Спасибо за ответ. Из-за количества x тиков, которые могут быть менее (или даже не) читаемыми. Вот почему мне нужна группа. – PJDev

+0

Может ли он работать в сочетании с [перетаскиванием/горизонтальной прокруткой] (http://c3js.org/reference.html#data-selection-draggable)? Это то, что я сделал в одном из наших проектов, чтобы обойти проблему слишком много х тиков. – madshvero

+0

К сожалению, этот вариант не будет работать. В качестве текущего обходного пути я заменил диаграмму диаграммы диаграммой области, и я думаю, что я буду придерживаться этого решения. – PJDev

0

Я не думаю, что c3 имеет «overplot» запрещающую вариант, но вы можете массировать ваши данные ...

В основном обрабатывать данные заранее, чтобы максимально на самом деле не более - ср и ср фактически ср - мин

Затем процедура подсказки восстанавливает правильные суммы для показа пользователя

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

https://jsfiddle.net/gguej6n0/5/

var data = [ 
      ['min', 10, 25, 15], 
      ['avg', 50, 33, 51], 
      ['max', 100, 75, 200] 
     ]; 

    for (var n = data.length-1; n > 0; n--) { 
    for (var m = 1; m < data[n].length; m++) { 
    data[n][m] -= data[n-1][m]; 
    } 
} 


var chart = c3.generate({ 
     bindTo: '#chart', 
    data: { 
     columns: data, 
     type: 'bar', 
     groups: [ 
      ['min', 'avg', 'max'] 
     ] 
    }, 
    tooltip: { 
     contents: function (d, defaultTitleFormat, defaultValueFormat, color) { 
       var dc = d.map (function (dd) { 
        return {value: dd.value, x: dd.x, id: dd.id, name: dd.name, index: dd.index}; 
      }) 
       for (var n= 1; n < dc.length; n++) { 
        dc[n].value += dc[n-1].value; 
      } 
      return this.getTooltipContent(dc, defaultTitleFormat, defaultValueFormat, color); 
     } 
    } 
}); 
+0

Хорошее обходное решение. Это, кажется, исправляет проблему, спасибо! – PJDev

+0

К сожалению, после небольшого тестирования кажется, что этот метод терпит неудачу, когда мы скрываем одну из нижних рядов. Кажется, что данные должны быть пересчитаны для каждого события hide и должны основываться на том, какие серии показаны. – PJDev

+0

ahh, grrr. Я подумал, что это можно исправить, используя обратный вызов .onrendered, но пока слишком поздно, график отобразился. У меня есть еще одна идея, хотя ... – mgraham