Svg.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\debug\models\timeline;
  8. use yii\base\Object;
  9. use yii\debug\panels\TimelinePanel;
  10. use yii\helpers\StringHelper;
  11. /**
  12. * Svg is used to draw a graph using SVG
  13. *
  14. * @author Dmitriy Bashkarev <dmitriy@bashkarev.com>
  15. * @since 2.0.8
  16. */
  17. class Svg extends Object
  18. {
  19. /**
  20. * @var int Max X coordinate
  21. */
  22. public $x = 1920;
  23. /**
  24. * @var int Max Y coordinate
  25. */
  26. public $y = 40;
  27. /**
  28. * @var string Stroke color
  29. */
  30. public $stroke = '#1e6823';
  31. /**
  32. * @var array Listen messages panels
  33. */
  34. public $listenMessages = ['log', 'profiling'];
  35. /**
  36. * @var array Color indicators svg graph.
  37. */
  38. public $gradient = [
  39. 10 => '#d6e685',
  40. 60 => '#8cc665',
  41. 90 => '#44a340',
  42. 100 => '#1e6823'
  43. ];
  44. /**
  45. * @var string Svg template
  46. */
  47. public $template = '<svg width="{x}" height="{y}" viewBox="0 0 {x} {y}" preserveAspectRatio="none"><defs>{linearGradient}</defs><g><polygon points="{polygon}" fill="url(#gradient)"/><polyline points="{polyline}" fill="none" stroke="{stroke}" stroke-width="1"/></g></svg>';
  48. /**
  49. * ```php
  50. * [
  51. * [x, y]
  52. * ]
  53. * ```
  54. * @var array Each point is define by a X and a Y coordinate.
  55. */
  56. protected $points = [];
  57. /**
  58. * @var TimelinePanel
  59. */
  60. protected $panel;
  61. /**
  62. * @inheritdoc
  63. */
  64. public function __construct(TimelinePanel $panel, $config = [])
  65. {
  66. parent::__construct($config);
  67. $this->panel = $panel;
  68. foreach ($this->listenMessages as $panel) {
  69. if (isset($this->panel->module->panels[$panel]->data['messages'])) {
  70. $this->addPoints($this->panel->module->panels[$panel]->data['messages']);
  71. }
  72. }
  73. }
  74. /**
  75. * @return string
  76. */
  77. public function __toString()
  78. {
  79. if ($this->points === []) {
  80. return '';
  81. }
  82. return strtr($this->template, [
  83. '{x}' => StringHelper::normalizeNumber($this->x),
  84. '{y}' => StringHelper::normalizeNumber($this->y),
  85. '{stroke}' => $this->stroke,
  86. '{polygon}' => $this->polygon(),
  87. '{polyline}' => $this->polyline(),
  88. '{linearGradient}' => $this->linearGradient()
  89. ]);
  90. }
  91. /**
  92. * @return bool Has points
  93. */
  94. public function hasPoints()
  95. {
  96. return ($this->points !== []);
  97. }
  98. /**
  99. * @param array $messages log messages. See [[Logger::messages]] for the structure
  100. * @return int added points
  101. */
  102. protected function addPoints($messages)
  103. {
  104. $hasPoints = $this->hasPoints();
  105. $memory = $this->panel->memory / 100; // 1 percent memory
  106. $yOne = $this->y / 100; // 1 percent Y coordinate
  107. $xOne = $this->panel->duration / $this->x; // 1 percent X coordinate
  108. $i = 0;
  109. foreach ($messages as $message) {
  110. if (empty($message[5])) {
  111. break;
  112. }
  113. ++$i;
  114. $this->points[] = [
  115. ($message[3] * 1000 - $this->panel->start) / $xOne,
  116. $this->y - ($message[5] / $memory * $yOne),
  117. ];
  118. }
  119. if ($hasPoints && $i) {
  120. usort($this->points, function ($a, $b) {
  121. return ($a[0] < $b[0]) ? -1 : 1;
  122. });
  123. }
  124. return $i;
  125. }
  126. /**
  127. * @return string Points attribute for polygon path
  128. */
  129. protected function polygon()
  130. {
  131. $str = "0 $this->y ";
  132. foreach ($this->points as $point) {
  133. list($x, $y) = $point;
  134. $str .= "{$x} {$y} ";
  135. }
  136. $str .= $this->x - 0.001 . " {$y} {$this->x} {$this->y}";
  137. return StringHelper::normalizeNumber($str);
  138. }
  139. /**
  140. * @return string Points attribute for polyline path
  141. */
  142. protected function polyline()
  143. {
  144. $str = "0 $this->y ";
  145. foreach ($this->points as $point) {
  146. list($x, $y) = $point;
  147. $str .= "{$x} {$y} ";
  148. }
  149. $str .= "$this->x {$y}";
  150. return StringHelper::normalizeNumber($str);
  151. }
  152. /**
  153. * @return string
  154. */
  155. protected function linearGradient()
  156. {
  157. $gradient = '<linearGradient id="gradient" x1="0" x2="0" y1="1" y2="0">';
  158. foreach ($this->gradient as $percent => $color) {
  159. $gradient .= '<stop offset="' . StringHelper::normalizeNumber($percent) . '%" stop-color="' . $color . '"></stop>';
  160. }
  161. return $gradient . '</linearGradient>';
  162. }
  163. }