📜 ⬆️ ⬇️

An example of a pie chart in SVG using Raphael and PHP

During the development of one of our projects, we are faced with the need to give a large number of graphics in the client html. From the point of view of minimizing the load on the server, building volumetric graphics on the client side is the only right decision. When searching for ready-made and appropriate JS solutions from this area, we are thoroughly hooked on the Raphael JS library, which makes it easy to draw vector graphics in all current browsers. Having understood the functionality and having debugged several functions for creating the main types of diagrams, we decided to share here our own experiences.

An example of a pie chart in SVG using Raphael and PHP

So. The following example creates Raphael and PHP pie charts in SVG format, represented in the image. We tried to describe the source code in as much detail as possible in order to help all those who did not find the time or the strength to figure it out for themselves.

File circle.php:
')
<?php //        , //        function start_paper($id, $width, $height) { return 'var r = Raphael("' .$id .'", ' .$width .', ' .$height .');'; } //    function paper_circle_chart($params) { //   ""     //   3D    $shadow_width = floor(($params['radius']-$params['inradius'])*0.47); $pradius = $params['radius'] - $shadow_width; //     $outradius = $params['radius'] + $params['text_radius']; //   $total = array_sum($params['data']); $i = 0; $prev = 0; $fangel = 0; $code = ''; $pcode = ''; $pline = ''; $ptext = ''; $pstext = ''; $center = ''; $begin = true; //      foreach ($params['data'] as $k => $v) { //     $color = $params['colors'][$i]; //      if ($v == 0) { $i++; continue; } //       -    elseif ($v == $total) { $pend = deg2rad(45); $code = ' r.circle(' .$params['centerx'] .', ' .$params['centery'] .', ' .$params['radius'] .').attr({"fill": "' .$color .'"})'; if (count($params['texts'])) { $dxc = round($params['centerx'] + $pradius * sin($pend), 2); $dyc = round($params['centery'] - $pradius * cos($pend), 2); $dxc1 = round($params['centerx'] + $outradius * sin($pend), 2); $dyc1 = round($params['centery'] - $outradius * cos($pend), 2); $dxc2 = $dxc1 + $params['text_width']; $dxc3 = $dxc1 + round($params['text_width']/2, 2); $dyc2 = $dyc1 - $params['text_minus']; $dyc3 = $dyc1 + $params['text_plus']; $pcode .= ' r.circle(' .$dxc .', ' .$dyc .', ' .$params['point_radius'] .')'; $pline .= ' r.path("M'. $dxc .','. $dyc .' L'. $dxc1 .','. $dyc1 .' L'. $dxc2 .','. $dyc1 .'")'; $ptext .= ' r.text(' .$dxc3 .', ' .$dyc2 .', "100 %")'; $pstext .= ' r.text(' .$dxc3 .', ' .$dyc3 .', "' .$params['texts'][$i] .'")'; } } //  -    else { $percent = $v / $total; $angel = 360 * $percent; $rad = deg2rad($angel); $end = $prev + $rad; $pend = $prev + $rad/2; $dx = round($params['centerx'] + $params['radius'] * sin($prev), 2); $dy = round($params['centery'] - $params['radius'] * cos($prev), 2); $dxp = round($params['centerx'] + $params['radius'] * sin($end), 2); $dyp = round($params['centery'] - $params['radius'] * cos($end), 2); if ($percent > 0.5) $sec = 1; else $sec = 0; if (!$begin) $code .= ','; $code .= ' r.path("M' .$params['centerx'] .',' .$params['centery'] .' L' .$dx .',' .$dy .' A' .$params['radius'] .',' .$params['radius'] .' 0 ' .$sec .',1 ' .$dxp .',' .$dyp .' z").attr({"fill": "' .$color .'"})'; if (count($params['texts'])) { $dxc = round($params['centerx'] + $pradius * sin($pend), 2); $dyc = round($params['centery'] - $pradius * cos($pend), 2); $dxc1 = round($params['centerx'] + $outradius * sin($pend), 2); $dyc1 = round($params['centery'] - $outradius * cos($pend), 2); if (($fangel + $angel/2) > 180) { $dxc2 = $dxc1 - $params['text_width']; $dxc3 = $dxc1 - round($params['text_width']/2, 2); } else { $dxc2 = $dxc1 + $params['text_width']; $dxc3 = $dxc1 + round($params['text_width']/2, 2); } $dyc2 = $dyc1 - $params['text_minus']; $dyc3 = $dyc1 + $params['text_plus']; if (!$begin) { $pcode .= ','; $ptext .= ','; $pstext .= ','; $pline .= ','; } $pcode .= ' r.circle(' .$dxc .', ' .$dyc .', ' .$params['point_radius'] .')'; $pline .= ' r.path("M'. $dxc .','. $dyc .' L'. $dxc1 .','. $dyc1 .' L'. $dxc2 .','. $dyc1 .'")'; $ptext .= ' r.text(' .$dxc3 .', ' .$dyc2 .', "' .round($percent * 100) .' %")'; $pstext .= ' r.text(' .$dxc3 .', ' .$dyc3 .', "' .$params['texts'][$i] .'")'; } $i++; $begin = false; $prev = $end; $fangel += $angel; } } //   ""     if ($code) $code = ' var st = r.set(); st.push(' .$code .' ); st.attr({"stroke": "none"});'; //   ""     if ($pline) $pline = ' var st = r.set(); st.push(' .$pline .' ); st.attr({"stroke": "' .$params['line_color'] .'"});'; //   ""  " "      if ($pcode) $pcode = ' var st = r.set(); st.push(' .$pcode .' ); st.attr({"fill": "' .$params['text_color'] .'", "stroke": "' .$params['stroke_color'] .'"});'; //   "", ""  ""      if ($ptext) $ptext = ' var st = r.set(); st.push(' .$ptext .' ); st.attr({"font-family": "' .$params['font'] .'", "font-size": "' .$params['text_name'] .'", "fill": "' .$params['text_color'] .'", "cursor": "default"});'; //   "", ""  ""      if ($pstext) $pstext = ' var st = r.set(); st.push(' .$pstext .' ); st.attr({"font-family": "' .$params['font'] .'", "font-size": "' .$params['text_small'] .'", "fill": "' .$params['text_color'] .'", "cursor": "default"});'; //        $inradius = ''; if ($params['inradius'] > 0) { $inradius = ' r.circle(' .$params['centerx'] .', ' .$params['centery'] .', ' .$params['inradius'] .').attr({"fill": "' .$params['center_text_back'] .'", "stroke": "none"});'; if ($params['shadow']) $inradius .= ' r.circle(' .$params['centerx'] .', ' .$params['centery'] .', ' .($params['radius']-$shadow_width+floor($shadow_width/2)) .').attr({"fill": "none", "stroke": "#FFFFFF", "stroke-width": "' .$shadow_width .'", "stroke-opacity": "0.15"});'; if ($params['center_text']) { $center = ' r.text(' .$params['centerx'] .', ' .$params['centery'] .', "' .$params['center_text'] .'").attr({"font-family": "' .$params['font'] .'", "font-size": "' .$params['center_text_size'] .'", "fill": "' .$params['center_text_color'] .'", "cursor": "default"});'; } } return $code .$inradius .$pline .$pcode .$ptext .$pstext .$center; } ?> 

File test.php:

 <?php include("circle.php"); $params = array ( //   'font' => 'PT Sans, Tahoma', //  'text_color' => '#212121', //   'line_color' => '#494949', //    'text_width' => 40, //      'text_radius' => 14, //         'point_radius' => 3, //     (          ) 'stroke_color' => '#EFEFEF', //    'text_name' => 13, //      'text_small' => 11, //      'text_minus' => 10, //       'text_plus' => 8, //       'centerx' => 100, //     x 'centery' => 100, //     y 'radius' => 42, //    'inradius' => 19, //    'center_text_back' => '90-#e7e7e7-#ffffff:60', //    'center_text' => 416, //      'center_text_size' => 14, //       'center_text_color' => '#212121', //       'data' => array( //   139, 112, 89, 76), 'texts' => array ( //   ,     '', '', ' ', '' ), 'colors' => array ( //   '0-#08b2ff-#0e56d4', '0-#fffa17-#ffba17', '0-#e0070e-#f15722', '0-#BCE408-#5FBB00' ), 'shadow' => 1 //    3D    ); //  ,  <head></head>  js ,  <body></body> - <div></div> // c       start_paper() $head = start_paper('diagram', 200, 200) .paper_circle_chart($params); $body = '<div id="diagram"></div>'; echo ' <!DOCTYPE html> <html> <head> <title>  SVG   Raphael  PHP</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script src="/raphael-min.js"></script> <script> window.onload = function () {' .$head .' }; </script> </head> <body>' .$body .' </body> </html>'; ?> 

The above source code is fully working. Anyone who wants to dig out and understand the material presented can independently download the library and assemble three files (circle.php, test.php and raphael-min.js) into a single unit.

Demo given example here .
More illustrative and diverse example from our project here .

How the gradient fill works (0- # BCE408- # 5FBB00) in terms of the Raphael syntax and other points regarding the functions of this library and their parameters are described in sufficient detail in the documentation . By the way, the detailed documentation, wide functionality and cross-browser compatibility of this solution are, from our point of view, the indisputable advantage of this library over similar means.

We hope that our experience will be useful to all those who first encountered the task of constructing vector graphics in html using JS. We will try to answer all questions and comments on this topic.

Source: https://habr.com/ru/post/180659/


All Articles