?php
function plugin_graphradar_convert()
{
return "#graphradar: You MUST use svggraphs plugin.";
}
function plugin_graphradar_draw($argg, $lib)
{
global $vars;
// 描画領域 初期値。 $cw=100; $ch=100; // キャンバスサイズデフォルト $offx = 0; $offy =0; // キャンバス上のグラフ開始座標。
//グラフタイトル $gtitle = ""; // タイトル文字列 $tx = round($cw/3); $ty=20; //タイトル座標デフォルト $titlestyle=array(0 => 'black'); // タイトル用のスタイル指定データ
// グラフ座標軸関連 $cx= ($cw+$offx)/2; $cy= ($ch+$offy)/2; $r = ($cw>$ch)? $ch/2.5 : $cw/2.5;
// グラフの最高値 $vmax = 100;
// 補助線情報 $scales = array();
// グラフ項目変数 $data = array(); //実データ $keyname = array(); // 軸の名称 $keyoffset = array(); //軸表示文字列の位置補正 $linemarker = array(); //マーカーの指定データ
$color = array(); // 色 $fillcolor = array(); // 塗りつぶし色
$datacount = 0; // テスト用パラメータ。将来はdata countとかを使う
$legend=""; $legendx =0; $legendy=0; $legendw =0; $legendh=0;
// 引数処理 foreach( $argg as $key => $arg){ // 明示的なコメント除外。これがないとコメントに"="をかけないので。 if( mb_substr($arg,0,2)=="//") continue; if( mb_substr($arg,0,1)=="#") continue;
if(strpos($arg,'=')){ $argss= $lib->trimexplode('=',$arg); switch ($argss[0]) { case 'w': //幅指定 $cw = ctype_digit($argss[1])? $argss[1]: $cw; break; case 'h': //高さ指定 $ch = ctype_digit($argss[1])? $argss[1]: $ch; break; case 'offx': //オフセット位置指定 $offx = is_numeric($argss[1])? $argss[1]: $offx; break; case 'offy': //オフセット位置指定 $offy = is_numeric($argss[1])? $argss[1]: $offy; break;
case 'tx': //タイトル座標x $tx = ctype_digit($argss[1])? $argss[1]: $tx; break; case 'ty': //タイトル座標y $ty = ctype_digit($argss[1])? $argss[1]: $ty; break; case 'title': $gtitle=htmlsc($argss[1]); break; case 'titlestyle': $titlestyle= $lib->trimexplode(',',$argss[1]); break;
case 'keyname': // keyは "key1,key2,key3,..." という文字列構造。 $keyname= $lib->trimexplode(',',$argss[1]); break;
case 'keyoffset': // keyoffsetは "name:offx,offy" という文字列構造。 // まず名前チェック。 $datas=$lib->trimexplode(':',$argss[1]); if(! $datas[1]=="") $tmpname=htmlsc($datas[0]);
//オフセットの2値のチェック。 $datas=$lib->trimexplode(',',$datas[1]); $keyoffset[$tmpname]=array(); $keyoffset[$tmpname][0]=is_numeric($datas[0])? $datas[0]: 0; $keyoffset[$tmpname][1]=is_numeric($datas[1])? $datas[1]: 0; break;
case 'data': // dataは "name:1,2,3,..." という構造。 $datas=$lib->trimexplode(':',$argss[1]); if(! $datas[1]=="") { $data[htmlsc($datas[0])] = $datas[1]; }
break; case 'color': $datas=$lib->trimexplode(':',$argss[1]); if(! $datas[1]=="") { //array_push($data,$argss[1]); $color[htmlsc($datas[0])] = $datas[1]; } break;
case 'fillcolor': // データ名:色名[,塗りつぶし率」とする。 $datas=$lib->trimexplode(':',$argss[1]); if(! $datas[1]=="") { $fillcolor[htmlsc($datas[0])] = $datas[1]; } break;
case 'marker': //$linestyle= $lib->trimexplode(',',$argss[1]); $datas=$lib->trimexplode(':',$argss[1]); if(! $datas[1]=="") { $linemarker[htmlsc($datas[0])] = $datas[1]; }
break;
case 'vmax': $vmax = ctype_digit($argss[1])? $argss[1]: $vmax; //array_push($noshow_target,htmlsc($argss[1]));
break;
case 'scale': // scalesは "sc1,sc2,sc3,..." という数値の列。 $scales = $lib->trimexplode(',', $argss[1]); break;
case 'scalevalue': // scalevalueは "sc1:value1,sc2:value2,sc3:value3,..." という数値の列。 $scales2 = $lib->trimexplode(',', $argss[1]); break; case 'legend': $legend=htmlsc($argss[1]); break;
case 'legendx': //タイトル座標x $legendx = is_numeric($argss[1])? $argss[1]: $legendx; break; case 'legendy': //タイトル座標y $legendy = is_numeric($argss[1])? $argss[1]: $legendy; break;
default: // 知らないコマンド。捨てる。 break; } }else{ // 入力行に = がないケース。 // 先頭にカンマがある場合、pukiwiki表/cvsによるデータとみなす。 if( mb_substr($arg,0,1)!=",") continue;
// この場合、最初の有効要素をキーとみなす。 $datas=$lib->trimexplode(',',$arg); // 最初の1つ目は必ず捨てる。 $tmp = array_shift($datas); $tmp = array_shift($datas); if(! $tmp=="") $data[$tmp] = implode(",",$datas); } }
// 引数解析が終わった。データ行の数をチェックする。 if(count($data)<=0) return "#graphradar: No Data";
// グラフ座標 再計算 $cx= ($cw+$offx)/2; $cy= ($ch+$offy)/2;
$r = ($cw>$ch)? $ch/2.5 : $cw/2.5;
// データ構造の解析。 $dcount =0; $dtable = array();
$datacount = count($keyname); foreach($data as $key => $value){ //////tomoseDBG("data:".$key."/".$value); $tmp =explode(",",$value); $tmp = array_map('trim', $tmp); // 各行にtrim()をかける if(count($tmp)<$datacount){ return "#graphradar: to few item in one-line."; } $dcount = (count($tmp)>$dcount)?count($tmp):$dcount; $dtable[$key] = $tmp; } // キャンバスサイズを基準に、グラフ領域を決める //$eow = $cw-10; $eoh = $ch-15; //$clipx = $eow-$offx; $clipy=$eoh - $offy;
$html = ''; $html2 = '';
$html =<<<EOD
svg xmlns="http://www.w3.org/2000/svg" width="$cw" height="$ch" viewBox="0 0 $cw $ch">
!--
circle cx="$cx" cy="$cy" r="$r" stroke="none" stroke-width="1" fill="white"/>
- >
EOD;$precol='lightgrey';
// 軸 $stroke=""; for($i=0 ; $i<$datacount; $i++){ $sangle= $i*360/$datacount;
$endx= intval($cx + $r * sin($sangle / 180 * pi())); $endy= intval($cy - $r * cos($sangle / 180 * pi()));
$stroke=$stroke." ".$endx.",".$endy; $tmpname= $keyname[$i];
$textx= intval($cx -(8*mb_strlen($tmpname)) + 1.1*$r * sin($sangle / 180 * pi()));
$texty= intval($cy +6 - 1.1*$r * cos($sangle / 180 * pi())); if(array_key_exists(0,$keyoffset[$tmpname] )) $textx+=$keyoffset[$tmpname][0]; if(array_key_exists(1,$keyoffset[$tmpname] )) $texty+=$keyoffset[$tmpname][1]; //下記は下のhtmlに入っていたがスマホだと表示が崩れるため削除 //<line x1="$cx " y1="$cy" x2="$endx" y2="$endy" stroke="gray" stroke-width="1"/>
$html2 .=<<<EOD <text x="$textx" y="$texty" fill="white">$tmpname</text> EOD;
}
$html .=<<<EOD
polygon points="$stroke" stroke="white" fill="#232f3b" />
EOD;
$html .= $html2;
// scale の対応関係を格納する連想配列 $scalesMap = array();
// scales と scales2 の値を結合して連想配列にする foreach ($scales as $index => $values) { $scalesMap[$values] = isset($scales2[$index]) ? $scales2[$index] : ''; } // スケールデータ foreach ($scales as $values) { $scaleValue = isset($scalesMap[$values]) ? $scalesMap[$values] : '';
$yy = intval($cy - $values * $r / $vmax); $html .= '<text x="'.($cx + 5).'" y="'.$yy.'" fill="white">'.htmlspecialchars($scaleValue).'</text>';
$stroke =""; for ($i = 0; $i < $datacount; $i++) { $sangle = $i * 360 / $datacount; $endx = intval($cx + $r * ($values / $vmax) * sin($sangle / 180 * pi())); $endy = intval($cy - $r * ($values / $vmax) * cos($sangle / 180 * pi())); $stroke = $stroke." ".$endx.",".$endy; } $html .= '<polygon points="'.$stroke.'" stroke="LightGray" fill="none" />'; }
// scale と scalevalue の対応を表示する例 //foreach ($scales as $values) { // $scaleValue = isset($scalesMap[$values]) ? $scalesMap[$values] : ''; // echo "Scale: $values, ScaleValue: " . htmlspecialchars($scaleValue) . "\n"; //}
for ($i = 0; $i < $datacount; $i++) { $r2 = ($cw>$ch)? $ch/2.0 : $cw/2.0 ; $sangle = $i * 360 / $datacount; $endx = intval($cx + $r2 * ($values / $vmax) * sin($sangle / 180 * pi())); $endy = intval($cy - $r2 * ($values / $vmax) * cos($sangle / 180 * pi()));
// 頂点から中心への線を含む座標を計算 $vertexToCenterLine = '<line x1="'.$cx.'" y1="'.$cy.'" x2="'.$endx.'" y2="'.$endy.'" stroke="lightgray" stroke-width="1"/>';
// 頂点から中心への線を描画 $html .= $vertexToCenterLine; }
// レーダー用のデータ作成 foreach( $dtable as $lname =>$tline){ $stroke =""; $i=0; $lstyle="";
foreach($tline as $key => $value){
$sangle= $i*360/$datacount;
$endx= intval($cx + $r*($value/$vmax) * sin($sangle / 180 * pi())); $endy= intval($cy - $r*($value/$vmax) * cos($sangle / 180 * pi()));
$stroke=$stroke." ".$endx.",".$endy; //$lcolor = $color[$key]; $i=$i+1;
} $lcolor = ($color[$lname])?$color[$lname]:"black"; $wcolor=$lib->trimexplode(',',($fillcolor[$lname])); $wcolor[1]=is_numeric($wcolor[1])?$wcolor[1]:0.2;
$fcolor = ($wcolor[0])?$wcolor[0]:"none"; $fopa = $wcolor[1];
// マーカー $mwork = ""; if($linemarker[$lname]!=""){ $mwork = "m_".$lname; $mwork2= ""; $workprm = $lib->trimexplode(',',$linemarker[htmlsc($lname)]); $worksize = 9; $worksize2=floor($worksize/2); foreach($workprm as $ppp){ $pmode = mb_substr($ppp,0,1); $parg = mb_substr($ppp,1); $parg =is_numeric($parg)?$parg:9; $worksize=$parg; $worksize2=floor($worksize/2)+1;
switch ($pmode) { case 'c': $mwork2= '<circle cx="'.$worksize2.'" cy="'.$worksize2.'" r="'.($worksize2-1).'" stroke="white" stroke-width="1" fill="'.$lcolor.'"/>'; break; case 'd': $mwork2= '<polygon points="'.$worksize2.',1 '.($worksize).','.($worksize).' 0,'.($worksize).'" stroke="white" stroke-width="1" fill="'.$lcolor.'"/>'; break;
case 'x': //$mwork2= '<line x1="1" y1="1" x2="'.($worksize-1).'" y2="'.($worksize-1).'" stroke="'.$lcolor.'" stroke-width="1"/>'.'<line x1="'.($worksize-1).'" y1="1" x2="1" y2="'.($worksize-1).'" stroke="'.$lcolor.'" stroke-width="1"/>'; $mwork2= '<line x1="1" y1="1" x2="'.($worksize-1).'" y2="'.($worksize-1).'" stroke="white" stroke-width="3" stroke-linecap="round" />'.
'<line x1="'.($worksize-1).'" y1="1" x2="1" y2="'.($worksize-1).'" stroke="white" stroke-width="3" stroke-linecap="round" />'.'<line x1="1" y1="1" x2="'.($worksize-1).'" y2="'.($worksize-1).'" stroke="'.$lcolor.'" stroke-width="1"/>'.
'<line x1="'.($worksize-1).'" y1="1" x2="1" y2="'.($worksize-1).'" stroke="'.$lcolor.'" stroke-width="1"/>';
break;
default: case 's': $mwork2= ' <rect x="1" y="1" width="'.($worksize-1).'" height="'.($worksize-1).'" stroke="white" stroke-width="1" fill="'.$lcolor.'"/>';
break;
}
}
$worksize2=($worksize/2)+1;
$html .= <<<EOD
marker id="$mwork" markerWidth="$worksize" markerHeight="$worksize" refX="$worksize2" refY="$worksize2">
$mwork2/marker>
EOD;$lstyle .= ' marker-mid="url(#'.$mwork.')"'; $lstyle2 = ' marker-start="url(#'.$mwork.')"'; $linestyle[htmlsc($lname)] = $lstyle;
}
// レーダーチャートの頂点を結ぶ多角形を描画 $html .= '<polygon points="'.$stroke.'" stroke="'.$lcolor.'" fill="'.$fcolor.'" fill-opacity="'.$fopa.'" '.$lstyle.$lstyle2.' />';
}
//----------------- // タイトル if(! $gtitle==""){ $html .= $lib->CreateTitle( $gtitle, $tx, $ty , $titlestyle ); }
//----------------- //凡例。 if($legend!=""){ $html .=$lib->CreateLegend( $data, $color, $legendx, $legendy ,$linestyle); }
$html .='</svg>';
/*
// for debug $tbltxt=""; foreach($data as $key => $value){ $tbltxt .= ",".$key.",".$value."\n"; } $html .= convert_html($tbltxt);
return $html;
}
?>
管理者: nattu
PukiWiki 1.5.4 © 2001-2022 PukiWiki Development Team | PHP: 7.4.33. 変換時間: 0.003 秒