Какой метод будет лучше всего построить этот сложный граф - PullRequest
26 голосов
/ 27 мая 2011

После 15 лет разработки пользовательского интерфейса я очень мало смотрю и думаю: «Как же я могу это сделать». Это один из тех моментов.

Графический дизайнер продал моим клиентам очень сложный график в форме пятиугольника, состоящего из 5 отдельных треугольников. Дизайнер указал, что каждый треугольник должен быть определенного цвета, чтобы соответствовать брендингу, и каждый должен «заполняться» на основе процента процесса, который представляет каждый цвет. Вы почти должны увидеть изображение, чтобы понять: enter image description here

Я целый день ломал голову, пытаясь понять, как выполнить эту задачу. Клиент указал, что он должен быть совместим во всех основных браузерах, и я собираюсь сказать ему, что это будет IE7 + ради здравомыслия. Это сильно ограничивает методы CSS3, хотя я бы определенно развлекал методы CSS3 отсутствием других идей. Я предпочел бы не вставать допоздна, избивая Action Script, поэтому Flash находится в самом низу моего списка пожеланий. На самом деле я придумал, как это сделать, используя Sprites, но идея создания 250 или 500 треугольников и связанного с ними CSS стоит на одном месте с торговлей Chrome для IE6.

Сайт построен на PHP / MySQL, и мы активно используем Jquery. У нас есть полная версия FusionCharts и HighCharts, а также в случае необходимости. Если есть коммерческий продукт, который может достичь этого, я, безусловно, готов приобрести его, чтобы сделать эту работу.

Как лучше всего решить эту трудную задачу?

Ответы [ 5 ]

27 голосов
/ 27 мая 2011

Если я не смогу найти реализацию , уже написанную , я бы использовал Raphaël .

Это займет значительную работу, но конечный результат должен быть очень хорошим.

Взгляните на некоторые демонстрации, они невероятно гладкие.

Raphaël в настоящее время поддерживает Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ и Internet Explorer 6.0+.


Это казалось интересным, поэтому я решил реализовать это сам с Рафаэлем:

См .: http://jsfiddle.net/2Tsjy/

Должно работать во всех браузерах. Единственной частью, которую я не делал, был текст.

JavaScript:

var paper = Raphael("pentagon"),
    fullNum = [40, 53],
    borderColours = ['#329342','#9e202c','#f47933','#811f5a','#11496c'],
    fillColours = ['#74ae3d','#d01f27','#eaa337','#32133f','#2c7aa1'],
    triangles = [],
    border, fill, st, i;

for (i=0; i<5; i++) {
    border = paper.path(getPercentPath(0)).attr({
        'fill': borderColours[i],
        'stroke-width': 0        
    }),
    fill = paper.path(["M", 116, 123] + "l-44,61 88,0z").attr({
        'stroke': fillColours[i],
        'stroke-width': 6
    });
    triangles.push(border);

    st = paper.set();
    st.push(border, fill);
    st.rotate(i * 72, 116, 113);

    setPercent(i, 30+Math.floor(Math.random()*70));
}

function getPercentPath(percent) {
    var ratio = percent/100;
    return ["M", 116, 128] + "l-" + ratio*fullNum[0] + "," + ratio*fullNum[1] + " " + ratio*fullNum[0]*2 + ",0z";
}
function setPercent(i, percent) {
    triangles[i].attr({
        path: getPercentPath(percent)
    });
}


setInterval(function(){
    for (var i=0; i<5; i++) {
        setPercent(i, 30+Math.floor(Math.random()*70));
    }
}, 2000);

CSS:

#pentagon {
    width: 226px;
    height: 227px;
    border: 1px solid red;
    background: #fff;
    background: rgba(255,255,255,0.8)
}

HTML:

<div id="pentagon"></div>
7 голосов
/ 27 мая 2011

А как насчет <canvas>? Вы можете легко нарисовать один треугольник, а затем нарисовать другие, просто повернув холст 360/5 градусов.

Пример: http://jsfiddle.net/Stijntjhe/dC6kX/

window.onload = function() {
    var ce = document.getElementById('ce');
    var c = ce.getContext('2d');
    c.translate(ce.offsetWidth / 2, ce.offsetHeight / 2);

    for(var pie = 0; pie < 5; pie++) {
        c.save();
        c.rotate(pie/5 * Math.PI * 2);

        c.beginPath();
        c.moveTo(0, -10);
        c.lineTo(-50, -80);
        c.lineTo(50, -80);
        c.lineTo(0, -10);
        c.lineWidth = 5;
        c.lineCap = 'square';
        c.strokeStyle = colors[pie];
        c.stroke();

        c.restore();
    } 
}

становится:

enter image description here

Минусы: Возможно, еще не кросс-браузер.

7 голосов
/ 27 мая 2011

Я бы порекомендовал RaphaelJS (см. http://raphaeljs.com/).. Он совместим с IE7, и вы можете прекрасно выполнять треугольники: вам нужно сделать математику, но вполне возможно.

РЕДАКТИРОВАТЬ: посмотрите на http://www.chittram.com/editor.jsp для быстрого образца некоторых из форм, которые могут быть сделаны. Этот сайт является интерактивным редактором, но основные возможности, которые вам нужны, продемонстрированы.

4 голосов
/ 28 мая 2011

Если он абсолютно должен быть максимально совместимым, я бы сгенерировал SVG-изображение и отобразил его в PNG.Это не так медленно, как звучит для такого изображения с таким небольшим количеством точек.

Вот очень быстрый, очень грязный пример.Предполагается, что у вас есть расширение ImageMagick , хотя в крайнем случае вы можете сбросить SVG в файл и exec() инструмент командной строки, такой как rsvg .Очевидно, что «правильный» ответ включает в себя некую схему кэширования для визуализированного графа.Кроме того, прости меня за то, что я больше не являюсь SVG-ниндзя.

graph.svg.php:

<?php echo '<'; ?>?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="240" height="240"
     xmlns="http://www.w3.org/2000/svg" version="1.1">

  <g transform="translate(120,120) translate(0,15)">
    <polygon fill="none" stroke="green" stroke-width="10" 
              points="0,0 -50,68.82 50,68.82" />
    <g transform="scale(<?php echo $fill['green']; ?>)">
      <polygon fill="green" stroke="green" stroke-width="10" 
                points="0,0 -50,68.82 50,68.82" />
    </g>
  </g>

  <g transform="translate(120,120) rotate(72) translate(0,15)">
    <polygon fill="none" stroke="red" stroke-width="10" 
              points="0,0 -50,68.82 50,68.82" />
    <g transform="scale(<?php echo $fill['red']; ?>)">
      <polygon fill="red" stroke="red" stroke-width="10" 
                points="0,0 -50,68.82 50,68.82" />
    </g>
  </g>

  <g transform="translate(120,120) rotate(144) translate(0,15)">
    <polygon fill="none" stroke="yellow" stroke-width="10" 
              points="0,0 -50,68.82 50,68.82" />
    <g transform="scale(<?php echo $fill['yellow']; ?>)">
      <polygon fill="yellow" stroke="yellow" stroke-width="10" 
                points="0,0 -50,68.82 50,68.82" />
    </g>
  </g>

  <g transform="translate(120,120) rotate(216) translate(0,15)">
    <polygon fill="none" stroke="purple" stroke-width="10" 
              points="0,0 -50,68.82 50,68.82" />
    <g transform="scale(<?php echo $fill['purple']; ?>)">
      <polygon fill="purple" stroke="purple" stroke-width="10" 
                points="0,0 -50,68.82 50,68.82" />
    </g>
  </g>

  <g transform="translate(120,120) rotate(288) translate(0,15)">
    <polygon fill="none" stroke="blue" stroke-width="10" 
              points="0,0 -50,68.82 50,68.82" />
    <g transform="scale(<?php echo $fill['blue']; ?>)">
      <polygon fill="blue" stroke="blue" stroke-width="10" 
                points="0,0 -50,68.82 50,68.82" />
    </g>
  </g>

</svg>

render.php:

<?php

$fill = array(
    'green'  => 0.5,
    'red'    => 0.8,
    'yellow' => 0.55,
    'purple' => 0.4,
    'blue'   => 0.75,
);

ob_start();
include('graph.svg.php');
$svg = ob_get_contents();
ob_end_clean();

$im = new Imagick();
$im->readImageBlob($svg);
$im->setImageFormat('png24');
$png = $im->getImagesBlob();
$im->clear();
$im->destroy();

header('Content-Type: image/png');
header('Content-Length: ' . strlen($png));
echo $png;
exit;

Вывод выглядит так:

Rendered graph

2 голосов
/ 27 мая 2011

Я думаю, что если вам нужно сделать это в JS / CSS, а Flash / HTML5 не вариант, взгляните на удобный прием использования треугольников в CSS:

http://www.howtocreate.co.uk/tutorials/css/slopes

И альтернативная ссылка:

http://css -tricks.com / snippets / css / css-triangle /

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...