65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 PHP 绘制吉他谱

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (5投票s)

2010年7月26日

CC (ASA 3U)

3分钟阅读

viewsIcon

48151

downloadIcon

767

用于绘制吉他谱的 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的圆的大小与品间距大小成比例。因此,如果使用花哨的值,和弦会相应地做出反应

用户有责任根据自己的意愿调整设置。

从代码的角度来看,这在绘制任何内容之前会创建大量的计算。

具体来说,我们需要

  1. 计算弦的数量
  2. 计算用于绘制的实际宽度空间(不包括边距)
  3. 推断每根弦之间的像素空间
  4. 计算上部符号“o”或“x”的大小
  5. 推断总顶部边距
  6. 如果有标题,则计算像素中的文本大小并将其添加到总顶部边距
  7. 推断用于绘制的实际高度空间(不包括边距)
  8. 计算每个品之间的像素大小
<?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:首次发布
© . All rights reserved.