#chart(line, 月別売上推移){{
,山田,田中,吉田
4月, 120, 150,158
5月, 135, 180,177
6月, 150, 170,161
7月, 180, 210,170
8月, 110,166,156
9月, 130,140,175
}}
#chart(bar, 月別売上推移){{
,山田,田中,吉田
4月, 120, 150,158
5月, 135, 180,177
6月, 150, 170,161
7月, 180, 210,170
8月, 110,166,156
9月, 130,140,175
}}
<?php
/**
* PukiWiki/HAIK用 カンマ区切りグラフ描画プラグイン
* ヘッダー行対応版
*/
function plugin_chart_convert() {
global $vars;
$args = func_get_args();
$type = isset($args[0]) ? $args[0] : 'line';
$title = isset($args[1]) ? $args[1] : '';
// HAIKのソース走査(ブロックボディ抽出)
$lines = get_source($vars['page']);
$body_lines = [];
$found = false;
foreach ($lines as $line) {
if (preg_match('/^#chart/', $line)) { $found = true; continue; }
if ($found && preg_match('/^}}$/', trim($line))) break;
if ($found) $body_lines[] = $line;
}
$labels = []; $series = []; $series_names = [];
foreach ($body_lines as $idx => $line) {
$line = trim($line);
if ($line === '') continue;
$cols = str_getcsv($line);
// 1行目がヘッダー(1列目が空か、数値以外)の場合の処理
if ($idx === 0 && !is_numeric($cols[1])) {
array_shift($cols); // 先頭の空列を除く
$series_names = $cols;
continue;
}
$labels[] = array_shift($cols);
foreach ($cols as $i => $val) {
$series[$i][] = floatval(trim($val));
}
}
$chart_id = 'chart_' . md5(uniqid(mt_rand(), true));
// JSON生成
$js_datasets = [];
$colors = ['54, 162, 235', '255, 99, 132', '75, 192, 192', '255, 159, 64'];
foreach ($series as $i => $data) {
$name = isset($series_names[$i]) ? $series_names[$i] : '系列 ' . ($i + 1);
$color = $colors[$i % count($colors)];
$js_datasets[] = "{
label: '{$name}',
data: " . json_encode($data) . ",
borderColor: 'rgba({$color}, 1)',
backgroundColor: 'rgba({$color}, 0.2)',
borderWidth: 2,
tension: 0.3
}";
}
$output = '<div style="width:100%; max-width:800px; margin:20px auto;">';
if ($title) $output .= '<h5 style="text-align:center;background-color:#f0f0f0;padding:10px;font-size:1.2em;">' . htmlspecialchars($title) . '</h5>';
$output .= '<canvas id="'.$chart_id.'"></canvas></div>';
$output .= '<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>';
$output .= "<script>
document.addEventListener('DOMContentLoaded', function(){
new Chart(document.getElementById('{$chart_id}'), {
type: '{$type}',
data: {
labels: " . json_encode($labels, JSON_UNESCAPED_UNICODE) . ",
datasets: [" . implode(',', $js_datasets) . "]
},
options: { responsive: true }
});
});
</script>";
return $output;
}