Подтвердить что ты не робот

Какой метод лучше всего построить для этого сложного графа

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

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

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

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

Каков наилучший метод для решения этой сложной задачи?

4b9b3361

Ответ 1

Если бы я не смог найти уже написанную реализацию, я бы использовал 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>

Ответ 2

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

EDIT: посмотрите http://www.chittram.com/editor.jsp для быстрого выбора некоторых форм, которые можно сделать. Этот сайт является интерактивным редактором, но основные возможности, которые вам нужны, демонстрируются.

Ответ 3

Как насчет <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

Против: Возможно, еще не перекрестный браузер.

Ответ 4

Если это абсолютно необходимо как можно более совместимое, я бы сгенерировал 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

Ответ 5

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

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

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

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

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

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