GoPdf的简单使用

来源:互联网 发布:java初级工资待遇 编辑:程序博客网 时间:2024/05/16 11:31

GoPdf的简单使用

项目地址:https://github.com/signintech/gopdf

在最近的工作中要求使用go去生成一份PDF文档。一开始是选择的https://github.com/jung-kurt/gofpdf这家的,但是在测试的时候发现这货不支持中文。因此换成了GoPdf。

在生成的PDF的过程中感觉比较烦的就是坐标的计算,GoPdf框架的坐标轴使用左上角开始的,向左为x轴的正方向,向下为y轴的正方向。这的坐标轴的设置倒是和Android的坐标轴设置类似(听说传统pdf的坐标轴是从右下角开始的?)。这样的坐标设计不需要我倒着计算坐标了。

我们写PDF时一般都是使用A4纸的大小,如何设置成A4纸大小官方文档上有说明,对于这个大小,我在使用的时候弄出了一些小小的问题。

设置成A4纸大小:

 pdf.Start(gopdf.Config{ PageSize: gopdf.Rect{W: 595.28, H: 841.89}})

图片绘制

如图:

使用的图片原图:

可以从上图看出绘制的图片有一部分超出了绘制区域。

在出现这个问题后,我google到了如下信息:

分辨率是72像素/英寸时,A4纸的尺寸的图像的像素是595×842;

分辨率是96像素/英寸时,A4纸的尺寸的图像的像素是794×1123;(默认)

分辨率是120像素/英寸时,A4纸的尺寸的图像的像素是1487×2105;

分辨率是150像素/英寸时,A4纸的尺寸的图像的像素是1240×1754;

分辨率是300像素/英寸时,A4纸的尺寸的图像的像素是2480×3508;

那我就想用分辨率是120像素 / 英寸的W和H进行尝试,在进行尝试后发现生成的PDF已经不是A4纸的大小了。

于是我就去github上询问了作者,作者说A4值的大小就是文档中提供的W和H。当得到这个答案后,整个人就懵逼了。那如何将这张图片完整的绘制在指点区域中呢?重新看一下提供的方法:

func (gp *GoPdf) Image(picPath string, x float64, y float64, rect *Rect) error

第一个参数是图片的路径,第二和第三个参数是要绘制的坐标,那最后一个参数是做什么的呢?在之前的方法中我直接设置了nil,后面通过测试,这个参数就是图片要绘制的区域。通过在这个参数中指定绘制图片的区域大小,就能够把这张图片完整的绘制出来。

绘制文字

注:如果要绘制中文内容,请找一个可靠一定的中文字库。不然会出现明明在代码中设置了文字的内容,但是生成的PDF中没有一个现实的中文内容。

字库问题

在这个框架中使用的字库文件只能是ttf文件,不能是ttc文件,如果使用ttc文件会报错。

绘制文字

绘制文字使用的一般方法是:

func (gp *GoPdf) Cell(rectangle *Rect, text string) error

这个rectangle参数一般设置为nil,这个参数具体是做什么的我并没有进行尝试。

在调用这个方法之前需要对字体,字体大小进行设置:

添加字体:

func (gp *GoPdf) AddTTFFont(family string, ttfpath string) error

设置使用的字体和大小:

func (gp *GoPdf) SetFont(family string, style string, size int) error

其中family为之前添加的字体名称,style为使用的风格,size是字体的大小。style支持“”和U两种,一般使用“”。画文字和画图片不同,Cell()方法并没有设设置坐标,因此需要在画文字前使用func (gp *GoPdf) SetX(x float64)func (gp *GoPdf) SetY(y float64) 两个方法来设置文字的起始坐标。把一个文字所占的区域想象成一个矩形区域,设置的xy值也是该矩形区域的左上坐标。因此在计算下一行文字的起始位置,不要忘记了在y轴方向上加上文字的大小。

如果要设置文字的颜色就使用:

func (gp *GoPdf) SetTextColor(r uint8, g uint8, b uint8)

rgb就是指三原色,例如#a8a8a8(灰色,随便举个栗子),那么就可以这样调用:SetTextCoolor(0xa8,0xa8,0xa8)

画直线

画直线使用的方法是:

func (gp *GoPdf) Line(x1 float64, y1 float64, x2 float64, y2 float64)

(x1,y1)为起始坐标,(x2,y2)为结束位置。

设置线的颜色可以使用:

func (gp *GoPdf) SetStrokeColor(r uint8, g uint8, b uint8)

设置线的宽度:

func (gp *GoPdf) SetLineWidth(width float64))

但是线的宽度是从基准线向两边扩展。

画椭圆

func (gp *GoPdf) Oval(x1 float64, y1 float64, x2 float64, y2 float64)

这是画椭圆的方法和我我们在学校里的椭圆方程不同,经过测试,是画一个矩形中的内切矩形。因此只有两个坐标就可以了,一个是左上角坐标,一个是右下角坐标。

组合

带背景颜色的文字

先上效果:

我实现的思路是先画绿色背景。然后在写文字内容。文字和边框周围有一定的间距,为了能够复用我定义了如下的结构体:

type Border struct {    //使用的字体    Family string    // 内容    Content string    //内容大小    ContentSize int    //背景颜色    BackgroundColor [3]uint8    //左内边距    LeftPadding float64    //上内边距    TopPadding float64    //右内边距    RightPadding float64    //下内边距    BottomPadding float64}

因为线的长度和文字的长度有关,因此需要先计算文字的长度:

func (gp *GoPdf) MeasureTextWidth(text string) (float64, error)

在得到文字的长度后,加上LeftPaddingRightPadding就是背景的宽度。背景的高度需要在文字的大小基础上添加上TopPaddingBottomPadding

func (h *Helper) drawBorder(border *Border, x, y float64) (currentX, currentY float64, err error) {    h.PDF.SetX(x)    h.PDF.SetY(y)    h.PDF.SetFont(border.Family, "", border.ContentSize)    //设置成白色    h.PDF.SetTextColor(0xFF, 0xFF, 0xFF)    h.PDF.SetStrokeColor(border.BackgroundColor[0], border.BackgroundColor[1], border.BackgroundColor[2])    //得到线宽    lineheight := float64(border.ContentSize) + border.TopPadding + border.BottomPadding    h.PDF.SetLineWidth(lineheight)    contentLen, err := h.PDF.MeasureTextWidth(border.Content)    if err != nil {        return    }    lineWidth := border.LeftPadding + contentLen + border.RightPadding    h.PDF.Line(x, y+lineheight/2, x+lineWidth, y+lineheight/2)    //写文字内容    h.PDF.SetX(x + border.LeftPadding)    h.PDF.SetY(y + border.TopPadding)    h.PDF.Cell(nil, border.Content)    currentX = x    currentY = y + lineheight    return}

可以在这里面看到,我画线y轴方向,向下添加了半个线高。在线画完之后,重新设置x和y坐标,来进行文字内容的绘制。

最后

在绘制PDF的时候需要注意使用func (gp *GoPdf) AddPage() 来进行添加新页,不然生成的PDF文件是无法打开的。

gopdf这个开源框架中还提供了大量的使用方法,比如画贝塞尔曲线(func (gp *GoPdf) Curve(x0 float64, y0 float64, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64, style string)),设置线的类型(func (gp *GoPdf) SetLineType(linetype string))等等。

使用该框架给我最大的感受就是:要实现什么效果,最重要的还是对效果进行分析,选择正确的方法,计算出正确坐标(这个我感觉比较重要)

0 0
原创粉丝点击