Статьи: Настройка библиотеки Flot для рисования сглаженных графиковЗадачаДля одно корпоративного сайта встала задача в рисовании графиков из заданного массива чисел. Нам требовалось решить следующие задачи:
Для этой задачи мы выбрали бесплатное решение Flot. РеализацияНачнем с простого, с HTML. Создадим файлик image-flot.php со следующим содержимым.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Flot Examples</title>
<link href="layout.css" rel="stylesheet" type="text/css" />
<!--[if IE]><script language="javascript" type="text/javascript" src="/flot/excanvas.min.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="/flot/jquery.js"></script>
<script language="javascript" type="text/javascript" src="/flot/jquery.flot.js"></script>
</head>
<body>
<h1>Flot Examples</h1>
<div id="placeholder" style="width:600px;height:300px;"></div>
<p id="hoverdata">Мышка находится в позиции (<span id="x">0</span>, <span id="y">0</span>).<br /><span id="clickdata"></span></p>
<p id="choices">Графики:</p>
</body>
</html>
Если откроем этот скрипт в браузере, то ничего не увидим, но не стоит растраиваться, мы только начали. Немного пояснений.
Настало время добавить в скрипт наши точки. Не спишите сразу его запускать, чуть ниже будет более подробно рассказано для чего здесь используется PHP.
<script id="source" language="javascript" type="text/javascript">
$(function () {
var datasets = {
"graph1": {
label: "График номер один",
data: [ <?php
printAllPoint(array(
'x' => array(0,50,100,125,150,175,200,220),
'y' => array(245,209,160,135,100,87.5,30,0)
)); ?> ]
},
"graph2": {
label: "График номер два",
data: [ <?php
printAllPoint(array(
'x' => array(0,50,100,125,150,175,200,260),
'y' => array(265,222,190,163,140,129,80,0)
)); ?> ]
},
"point": {
label: "Точка",
data: [ [50, 50] ],
points: { show: true, fill: false }
}
};
});
</script>
Замечательно, видите, не все так сложно как кажется на первый взгляд. Идем дальше. Как вы видите я использую функцию printAllPoint() для заполнения координат x,y. На данном этапе она просто преобразует массив точек в понятный для Flot формат. Чуть дальше она нам будет нужна для сглаживания графиков.
function printAllPoint($arrPoints) {
foreach($arrPoints['x'] as $key => $point) {
print "[" . $point . "," . $arrPoints['y'][$key] . "],";
}
}
Теперь нам нужно вывести данные графики в блоке "placeholder". Добавим следующий JS код в наш скрипт.
// insert checkboxes
Да, вот такой монстрообразный JS код, но давайте в нем немного разберемся. Часть, которая идет перед JS функцией plotAccordingToChoices() отвечает за вывод checkbox'ов (именно в этой части мы будем включать и отключать графики). А сама функция plotAccordingToChoices() отвечает за вывод массива "datasets" в блок "placeholder". Я думаю что детально расписывать работу этой части не стоит, т.к. те, кто хочет разобраться разбирутся сами, а простым людям достаточно сделать Ctrl+C Ctrl+V. Теперь смело запускаем скрипт в браузере.
Ну вот, уже красиво, уже можно подавать пользователям. Но не тут то было, нам еще есть куда улучшать наши с вами детище. Например, сделаем графики сглаженными. Над решением этой задачи я потратил не один день, стыд и позор. Предлагаю вам свой вариант сглаживания графиков. Во первых давайте перепишем PHP функцию printAllPoint(). Теперь она должна выглядеть так:
function printAllPoint($arr) {
$arrPoints = Splines($arr);
foreach($arrPoints as $key => $params) {
print "[".$params['x'].",".$params['y']."],";
}
}
Не трудно догадаться, что у нас появилась еще одна функция, которая занимается поиском дополнительных точек между заданными точками. Входной параметр $s отвечает за кривизну полученной функции.
function Splines($pts = array(), $s = 0.5) {
$arrPoints = array();
$k = 0;
for ($i = 0; $i < count($pts['x']) - 1; $i++) {
$cntElements = count($pts['x']);
$P1x = ($i < 1) ? $pts['x'][ 0 ] : $pts['x'][$i - 1];
$P1y = ($i < 1) ? $pts['y'][ 0 ] : $pts['y'][$i - 1];
$P2x = $pts['x'][$i];
$P2y = $pts['y'][$i];
$P3x = $pts['x'][$i + 1];
$P3y = $pts['y'][$i + 1];
$P4x = ($i < $cntElements - 2) ? $pts['x'][$i + 2] : $pts['x'][$cntElements - 1];
$P4y = ($i < $cntElements - 2) ? $pts['y'][$i + 2] : $pts['y'][$cntElements - 1];
for ($j = 1; $j < 100 + 1; $j++) {
$t = $j * 0.01;
$x = $s * ( -$t * $t * $t + 2 * $t * $t - $t) * $P1x +
$s * ( -$t * $t * $t + $t * $t) * $P2x +
(2 * $t * $t * $t - 3 * $t * $t + 1) * $P2x +
$s * ($t * $t * $t - 2 * $t * $t + $t) * $P3x +
( -2 * $t * $t * $t + 3 * $t * $t) * $P3x +
$s * ($t * $t * $t - $t * $t) * $P4x;
$y = $s * ( -$t * $t * $t + 2 * $t * $t - $t) * $P1y +
$s * ( -$t * $t * $t + $t * $t) * $P2y +
(2 * $t * $t * $t - 3 * $t * $t + 1) * $P2y +
$s * ($t * $t * $t - 2 * $t * $t + $t) * $P3y +
( -2 * $t * $t * $t + 3 * $t * $t) * $P3y +
$s * ($t * $t * $t - $t * $t) * $P4y;
if($x >= 0 and $y >= 0) {
$arrPoints[$k]['x'] = round($x);
$arrPoints[$k]['y'] = round($y);
$k++;
}
}
}
return $arrPoints;
}
Давайте сохраним и посмотрим, что у нас получилось.
Ну не красота ли. Хорошо, давайте теперь вернемся к поставленной задачи. А именно возможности выбирать график по его точке. У Flot есть встроенный механизм для этого. Добавим в JS код следующий кусочек.
// следим за координатами курсора на графике
И немного изменим JS функцию plotAccordingToChoices();
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && datasets[key])
data.push(datasets[key]);
});
if (data.length > 0) {
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 },
grid: { hoverable: true }
});
}
}
Запускаем! Повозив вдоволь мышкой на графику приступаем к дальнейшему изучению. Добавляем еще один кусочек JS кода.
// по клику показывает на каком именно графике стоит мышка
$("#placeholder").bind("plotclick", function (event, pos, item) {
if (item) {
$("#clickdata").text("Вы щелкнули на " + item.dataIndex + " в " + item.series.label + ".");
plot.highlight(item.series, item.datapoint);
}
});
И еще чуть-чуть меняем нашу JS функцию plotAccordingToChoices().
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && datasets[key])
data.push(datasets[key]);
});
if (data.length > 0) {
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 },
grid: { hoverable: true,
clickable: true }
});
}
}
Отлично, чувствуете, что вы владеете миром? Это очень хорошо, тогда запускаем наш скрипт.
Для тех кому не нравится врешний вид стандартного графика его можно легко поменять. Например вот так:
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && datasets[key])
data.push(datasets[key]);
});
if (data.length > 0) {
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 },
grid: { hoverable: true,
clickable: true,
color: "#000", // text
backgroundColor: "#fffeb4", // background yellow
tickColor: "#cecece", // grip gray
borderColor: "#000000" // border black
}
});
}
}
Этот рассказ не претендует на полное описание возможностей библиотеки Flot. Но для базовый понятий мне кажется совсем не плохо. Спасибо вам за внимание. |



