使用 PHP 绘制吉他谱






4.60/5 (5投票s)
用于绘制吉他谱的 PHP 类
引言
这是一个PHP类,可以绘制吉他和弦,或者任何其他弦乐器的和弦图。
它大量使用了GD2图像库,用很少的代码就能构建出美观的和弦图。
背景
作为一名尤克里里琴手(同时也是一个糟糕的吉他手),我浏览了大量的网站,这些网站显示吉他和弦的方式像“x23240”,或者根本没有和弦的任何描述。
我想,通过几行PHP代码,我可以开发一个高度可定制的类来显示这些和弦。
Using the Code
这个类命名为“chord
”,并且可以用很少的代码轻松使用。代码
<?php
include('chord.inc.php');
$c = new chord(array('x',3,2,0,1,0));
$c->draw();
?>
它会输出一个像这样的PNG文件

关注点
这个类的主要优点是它的高度可定制性。通过更多的函数调用,您可以设置标题、边距、字体大小、自定义颜色和自定义背景图片等。



还添加了对大横按和弦的支持。例如,以下和弦...

...是通过使用
<?php
include('chord.inc.php');
$c = new chord(array('x','x',0,0,0,8));
$c->setShowZeros(false);
$c->setMarginRight(20);
$c->setBarreChord(7,3,6);
$c->setStartingFret(5);
$c->draw();
?>
我希望这个类在任何PHP5设置下都能开箱即用,但同时也要让用户在需要时深入了解这个类。
例如,一个有趣的机制是字体。正如您可能知道的,PHP中的GD2有5种内置字体,分别用1到5的数字表示。它们是相当丑陋的像素字体,但它们可以开箱即用。为了支持内置字体和用户上传到其Web服务器上的自定义TTF字体,`setFontxxx`方法中包含一些小的逻辑。
<?php
function setFontTitle($v)
{
if(is_int($v))
{
//1 to 5 is the correct range for built in fonts
if($v >= 1 && $v <= 5)
$this->fontTitle = $v;
else
throw new Exception('Built in font must be in 1 to 5 range');
}
else if(is_string($v))
{
$this->fontTitle = $v;
}
else
{
throw new Exception
('Use a TTF file or a number representing a built in font');
}
} ?>
通过这种逻辑,您可以执行$c->setFontTitle('arial.ttf');
或$c->setFontTitle(5);
。然后,在绘制时,该类会调用“imagestring
”或“imagettftext
”,这是PHP函数,分别用于使用内置字体或TTF字体绘制文本。
其余有趣的逻辑位于类的draw()
方法中。为了支持任何大小的和弦,添加了大量的逻辑。默认情况下,PNG图片将是90x120,但由于用户可以设置任何大小,因此最终结果必须保持一致。
因此,表示要按压的string
的圆的大小与品间距大小成比例。因此,如果使用花哨的值,和弦会相应地做出反应

用户有责任根据自己的意愿调整设置。
从代码的角度来看,这在绘制任何内容之前会创建大量的计算。
具体来说,我们需要
- 计算弦的数量
- 计算用于绘制的实际宽度空间(不包括边距)
- 推断每根弦之间的像素空间
- 计算上部符号“o”或“x”的大小
- 推断总顶部边距
- 如果有标题,则计算像素中的文本大小并将其添加到总顶部边距
- 推断用于绘制的实际高度空间(不包括边距)
- 计算每个品之间的像素大小
<?php
$nbStrings = count($this->data);
$realWidth = $this->width - $this->margin['left'] - $this->margin['right'];
$stringSpacing = ($realWidth / ($nbStrings-1));
$upperSymbolSize = intval(round($stringSpacing *
$this->upperSymbolSize)); //space needed to draw the "o" or "x"
$totalTopMargin = $this->margin['top'] + $upperSymbolSize;
$titleMargin = 0;
//if there's a title, compute additional top margin induced
if(!empty($this->title))
{
if(is_int($this->fontTitle))
{
$titleMargin = imagefontheight($this->fontTitle);
}
else
{
$box = imagettfbboxextended($this->fontTitleSize,
0, $this->fontTitle, $this->title);
$titleMargin = $box['height'];
}
}
$totalTopMargin += $titleMargin;
$realHeight = $this->height - $totalTopMargin - $this->margin['bottom'];
$fretsSpacing = $realHeight / ($this->maxFrets);
?>
当我们拥有所有这些值时,其余的代码就很容易了:绘制网格;在需要的地方绘制内容,就完成了!
历史
- 2010-07-25:首次发布