Диаграмма Санки в javascript

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


person 321zeno    schedule 28.12.2010    source источник
comment
Связанный вопрос: stats.stackexchange.com/questions/24074/   -  person Thilo    schedule 05.03.2012


Ответы (7)


В случае, если это полезно для других: я извлек код рисования диаграммы sankey javascript здесь:

http://tamc.github.com/Sankey/

Оригинальное использование находится на этом правительственном сайте Великобритании:

http://2050-calculator-tool.decc.gov.uk/pathways/2022222122222103332220023211022330220130233022012/sankey

person Tom Counsell    schedule 14.07.2011

Это базовая диаграмма Санки с использованием raphaeljs.

function Sankey(x0, y0, height, losses) {
    var initialcolor = Raphael.getColor();
    var start = x0 + 200;
    var level = y0 + height;
    var heightunit = height / 100;
    var remaining = 100 * heightunit;

    function drawloss(start, level, loss) {
        var thecolor = Raphael.getColor();
        paper.path("M" + (start - 100) + "," + (level - loss) + "L" + start + "," + (level - loss)).attr({stroke: thecolor});
        paper.path("M" + (start - 100) + "," + level + "L" + start + "," + level).attr({stroke: thecolor});
        paper.path("M " + start + "," + level + " Q" + (start + 100) + "," + level + " " + (start + 100) + "," + (level + 100)).attr({stroke: thecolor});
        paper.path("M " + start + "," + (level - loss) + " Q" + (start + 100 + loss) + "," + (level - loss) + " " + (start + 100 + loss) + "," + (level + 100)).attr({stroke: thecolor});
        paper.path("M " + (start + 100) + "," + (level + 100) + " L " + (start - 10 + 100) + "," + (level + 100) + " L " + (start + loss / 2 + 100) + "," + (level + 110) + " L " + (start + loss + 10 + 100) + "," + (level + 100) + " L " + (start + loss + 100) + ", " + (level + 100)).attr({stroke: thecolor});
    }

    function drawremaining(start, level, loss) {
        paper.path("M 100," + y0 + "L" + (start + 100) + "," + y0).attr({stroke: initialcolor});
        paper.path("M" + (start - 100) + "," + level + "L" + (start + 100) + "," + level).attr({stroke: initialcolor});
        paper.path("M " + (start + 100) + " " + y0 + " L " + (start + 100) + " " + (y0 - 10) + " L " + (start + 110) + " " + (y0 + loss / 2) + " L " + (start + 100) + " " + (level + 10) + " L " + (start + 100) + " " + level).attr({stroke: initialcolor});
    }

    function drawstart(x0, y0, width, height) {
        paper.path("M " + x0 + "," + y0 + "L" + (x0 + width) + "," + y0).attr({stroke: initialcolor});
        paper.path("M " + x0 + "," + (y0 + height) + "L" + (x0 + width) + "," + y0 + height)).attr({stroke:  initialcolor});
        paper.path("M " + x0 + "," + y0 + "L" + x0 + "," + (y0 + height)).attr({stroke: initialcolor});
    }

    drawstart(x0, y0, 100, height);

    for (var i in losses) {
        drawloss(start, level, losses[i] * heightunit);
        remaining -= losses[i] * heightunit;
        level -= losses[i] * heightunit;
        start += 100;
    }
}

И я использую это так:

<div id="notepad" style="height:1000px; width:1000px; background: #eee"></div>
<script type="text/javascript">
    var paper = Raphael(document.getElementById("notepad"), 1020, 1000);
    var losses=[50, 30, 5];
    Sankey(10, 100, 200, losses);
</script>
person 321zeno    schedule 28.12.2010

D3.js использует плагин для создания диаграмм Санки.

http://bost.ocks.org/mike/sankey/

person cmonkey    schedule 17.10.2012

Вот довольно подробное объяснение того, как работает код Sankey DIAgram Майка Бостока на основе D3: http://www.d3noob.org/2013/02/sankey-diagrams-description-of-d3js-code.html

Я реализовал это на сервере приложений на основе Grails, и это работает.

person Aml    schedule 05.08.2013

Google Charts включает диаграмму Санки: https://developers.google.com/chart/interactive/docs/gallery/sankey

person Motin    schedule 27.01.2015

Спасибо zenify за то, что поставили меня на путь, мне пришлось переделать часть скопированного выше кода, чтобы заставить его работать, но это определенно дает хорошую отправную точку. Приведенный ниже код можно скопировать в файл .htm, и вам просто нужно иметь raphael-min.js в том же каталоге, чтобы он работал.

С уважением / Колм

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" class="JS">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Raphael makes Sankey</title>
<script type="text/javascript" src="raphael-min.js"></script>
<script type="text/javascript">
function Sankey(x0,y0,height,losses){
    initialcolor= Raphael.getColor();
    var start=x0+200;
    var level=y0+height;    
    var heightunit=height/100;
    var remaining=100*heightunit;

function drawloss(start,level,loss){
    var thecolor=Raphael.getColor();
    paper.path("M"+(start-100)+","+(level-loss)+"L"+start+","+(level-loss)).attr({stroke: thecolor});
    paper.path("M"+(start-100)+","+(level)+"L"+start+","+(level)).attr({stroke: thecolor});
    paper.path("M "+start+","+level+" Q"+(start+100)+","+level+" "+(start+100)+","+(level+100)).attr({stroke: thecolor});
    paper.path("M "+start+","+(level-loss)+" Q"+(start+100+loss)+","+(level-loss)+" "+(start+100+loss)+","+(level+100)).attr({stroke: thecolor});
    paper.path("M "+(start+100)+","+(level+100)+" L "+(start-10+100)+","+(level+100)+" L "+(start+(loss/2)+100)+","+(level+110)+" L "+(start+(loss)+10+100)+","+(level+100)+" L "+(start+(loss)+100)+", "+(level+100)).attr({stroke: thecolor});
}

function drawremaining(start,level,loss){
    paper.path("M 100,"+y0+"L"+(start+100)+","+y0).attr({stroke: initialcolor});
    paper.path("M"+(start-100)+","+(level)+"L"+(start+100)+","+(level)).attr({stroke: initialcolor});
    paper.path("M "+(start+100)+" "+y0+" L "+(start+100)+" "+(y0-10)+" L "+(start+110)+" "+(y0+(loss/2))+" L "+(start+100)+" "+(level+10)+" L "+(start+100)+" "+(level)).attr({stroke: initialcolor});
}

function drawstart(x0, y0, width, height){
    paper.path("M "+x0+","+y0+"L"+(x0+width)+","+y0+"").attr({stroke: initialcolor});
    paper.path("M "+x0+","+(y0+height)+"L"+(x0+width)+","+y0+height+"").attr({stroke:  initialcolor});
    paper.path("M "+x0+","+y0+"L"+x0+","+(y0+height)+"").attr({stroke: initialcolor});
}

    drawstart(x0,y0,100,height);
    for (var i in losses){
      drawloss(start,level,losses[i]*heightunit);
      remaining-=losses[i]*heightunit;
      level-=losses[i]*heightunit;
      start+=100;
    }
    drawremaining(start, level, remaining);
}
</script>
</head>
<body id="blog">
    <div id="notepad" style="height:1000px; width:1000px; background: #eee"></div>
    <script type="text/javascript">
    var paper = Raphael(document.getElementById("notepad"), 1020, 1000);
    var losses=[50, 30, 5];
    Sankey(10, 100, 200, losses);
    </script>
</body>
</html>
person Colm O'G    schedule 30.12.2010
comment
Замечательно! Теперь у вас есть идеи о том, как созданные диаграммы могут быть экспортированы в формат изображения, который может быть сохранен пользователем? - person 321zeno; 31.12.2010
comment
Хм, это выше моего понимания на данный момент. На данный момент я думаю об идее плагина jquery, который воздействует на таблицу данных html, где вы вводите идентификатор таблицы, столбец данных и столбец заголовка для плагина. Мечта заключается в том, что он генерирует sankey, а также расширяет таблицу, чтобы вы могли динамически переупорядочивать различные значения, устанавливать угол/длину стрелки и миллион других вещей. - person Colm O'G; 05.01.2011

Обновление 2020:

Для тех, кто пытается воплотить в жизнь примеры D3 Sankey, я нашел это очень простое видеоруководство. Работал как шарм для меня :)

https://reactviz.holiday/sankey/

Кроме того, в случае, если вы не можете заставить это работать, у react-google-charts есть довольно красивая альтернатива, с которой не может быть проще работать (по крайней мере, реализация примера была просто копированием -вставить весь компонент отсюда https://react-google-charts.com/sankey-diagram ):

import Chart from "react-google-charts";


<Chart
  width={600}
  height={'300px'}
  chartType="Sankey"
  loader={<div>Loading Chart</div>}
  data={[
    ['From', 'To', 'Weight'],
    ['A', 'X', 5],
    ['A', 'Y', 7],
    ['A', 'Z', 6],
    ['B', 'X', 2],
    ['B', 'Y', 9],
    ['B', 'Z', 4],
  ]}
  rootProps={{ 'data-testid': '1' }}
/>
person DurkoMatko    schedule 21.06.2020