首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

SVG 与 XML 商业图表实务(2)

SVG 与 XML 商业图表实务(2)

获取数据绘图从数据开始。这里我使用两家公司 31 天的股票数据。包含股票数据的 XML 文档的一部分如  所示。
清单 3. data.xml 片段
1
2
3
4
5
6
7
8
9
10
11
<stocks>
<stock>
<day high="35.13" low="32" close="33.75" />
<day high="32.25" low="28.75" close="31.75" />
<day high="29" low="28.5" close="28.87" />
<day high="29.25" low="28.75" close="28.75" />
<day high="29.5" low="28.5" close="29.25" />
<day high="30.25" low="29" close="29.25" />
...
</stock>
</stocks>




格式很简单。根标记 <stocks> 包含一组 <stock> 标记。每个 <stock> 标记包含一些 day 标记,带有 high、low 和 close 属性。
接下来要编写将该文件读入内存以便用于生成 SVG 的代码。这里我用了三个 PHP 类,如  所示。
清单 4. Data.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php
class Day
{
  var $low;
  var $high;
  var $close;

  public function __construct( $low, $high, $close )
  {
    $this->low = $low;
    $this->high = $high;
    $this->close = $close;
  }
}

class Trace
{
  var $days = array();
  var $high = 0.0;
  var $low = 100000.0;

  public function addDay( $low, $high, $close )
  {
    $this->days []= new Day( $low, $high, $close );
    if ( $low < $this->low ) $this->low = $low;
    if ( $high > $this->high ) $this->high = $high;
  }

  public function hiloPath( $trans )
  {
    $p = new Path();
    $d = 0;
    foreach( $this->days as $day )
    {
      $x = $trans->xscale( $d );
      $y = $trans->yscale( $day->low );
      $p->add( $x, $y );
      $d += 1;
    }
    for( $d = (count( $this->days ) - 1); $d >= 0; $d -= 1 )
    {
      $x = $trans->xscale( $d );
      $y = $trans->yscale( $this->days[$d]->high );
      $p->add( $x, $y );
    }
    return $p;
  }

  public function closePath( $trans )
  {
    $p = new Path();
    $d = 0;
    foreach( $this->days as $day )
    {
      $x = $trans->xscale( $d );
      $y = $trans->yscale( $day->close );
      $p->add( $x, $y );
      $d += 1;
    }
    return $p;
  }
}

class Data
{
  var $traces = array();
  var $high = 0;
  var $low = 100000;

  function parseXML( $file )
  {
    $data_dom = new DomDocument();
    $data_dom->load( $file );

    $elStocks = $data_dom->getElementsByTagName( 'stock' );
    foreach( $elStocks as $stock )
    {
      $trace = new Trace();

      $days = $stock->getElementsByTagName( 'day' );
      foreach( $days as $day )
      {
        $trace->addDay( (float)$day->getAttribute('low'),
          (float)$day->getAttribute('high'),
          (float)$day->getAttribute('close') );
      }
     
      $this->traces []= $trace;

      if ( $trace->high > $this->high ) $this->high = $trace->high;
      if ( $trace->low < $this->low ) $this->low = $trace->low;
    }
  }
}
?>




Data 类包含文件中的所有数据。每支股票存储在一个 Trace 对象中。每 Trace 对象包含一组 Day 对象,定义了当天的最高价、最低价和收盘价。此外,Trace 对象知道如何为图像中的最高、最低和收盘价部分创建 Path 对象。
Path 对象是一个 PHP 类,是我自己为了方便创建 SVG 路径专门编写的。这个帮助器类在 svg.php 文件中定义,如  所示。
清单 5. Svg.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
interface ITransform
{
  function xscale( $x );
  function yscale( $x );
}

class Transform implements ITransform
{
  protected $ox;
  protected $oy;
  protected $xscale;
  protected $yscale;
  protected $xoffset = 0;
  protected $yoffset = 0;

  public function xscale( $x ) {
    return $this->ox + ( ( $x - $this->xoffset ) * $this->xscale );
  }

  public function yscale( $y ) {
    return $this->oy - ( ( $y - $this->yoffset ) * $this->yscale );
  }
}

class Point
{
  var $x;
  var $y;
  public function __construct( $x, $y )
  {
    $this->x = $x;
    $this->y = $y;
  }
}

class Path
{
  private $points = array();

  public function add( $x, $y )
  {
    $this->points []= new Point( $x, $y );
  }

  public function toSVG()
  {
    $svg = "";
    $svg .= "M ".$this->points[0]->x." ".$this->points[0]->y." ";
    foreach( $this->points as $pt ) {
      $svg .= "L ".$pt->x." ".$pt->y." ";
    }
    return $svg;
  }
}
?>




这里定义了两个类,都很容易理解:Point 和 Path。Point 类表示一个 X-Y 值对,Path 类是一组 Points。ITransform 接口和 Transform 基类更有意思。为了绘制股票图像,必须将美元和每日数据的尺度转化成 SVG 视图坐标。ITransform 接口就是为了完成这项任务而定义的,但是不仅仅完成该任务。
返回列表