SVG文件与DOM

SVG(Scalable Vector Graphics)是一种基于XML的矢量图像格式,支持DOM,具有良好的可读性、交互性和动态性。SVG图像可以被搜索引擎抓取,方便文本操作,并广泛应用于手机等移动设备,提供高质量的动态交互体验。在QT中,可以利用DOM解析SVG文件并绘制图形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SVG:可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式。SVG由W3C制定,是一个开放标准。 SVG严格遵从XML语法,并用文本格式的描述性语言来描述图像内容,因此是一种和图像分辨率无关的矢量图形格式。

 

SVG的特点

1.基于XML

  为了保证网络图像能够顺利地和目前已经由W3C开发的D0M1,DOM2,CSS,XML,XPointer,XSLT,XSL,SMIL,HTML,XHTML技术,以及其他标准化技术,如ICC,URI,UNICODE,RGB,ECMAScr ipt/JavaScript,Java协调一致,SVG是完全基于x M L(EXtensibleMarkup Language可扩展置标语言), 并能和上述各项技术相融会的新一代的网络图像格式。SVG并非仅仅是一种图像格式, 由于它是一种基于XML的语言,也就意味着它继承了XML的跨平台性和可扩展性,从而在图形可重用性上迈出了一大步。如SVG可以内嵌于其他的XML文档中,而SVG文档中也可以嵌入其他的XML内容,各个不同的SVG图形可以方便地组合, 构成新的SVG图形。

2.采用文本来描述对象

  SVG包括3种类型的对象: 矢量图形(包括直线、曲线在内的图形边)、点阵图像和文本。各种图像对象能够组合、变换,并且修改其样式,也能够定义成预处理对象。

  与传统的图像格式不同的是,svG采用文本来描述矢量化的图形,这使得svG图像文件可以像HTML网页一样有着很好的可读性。当用户用图像工具输出svG后,可以用任何文字处理工具打开SVG图像,并可看到用来描述图像的文本代码。掌握了svG语法的人甚至可以只用一个记事本便可以读出图像中的内容来。

  svG文件中的文字虽然在显示时可呈现出各种图像化的修饰效果,但却仍然是以文本的形式存在的,可以选择复制、粘贴。由于SVG内的文字都以文本的形式出现在XML文件中, 这些信息可以为搜索引擎所用,而以往搜索引擎通常无法搜索到写在点阵图像中的文字。这些文本信息还可以帮助视力有残疾而无法看到图形的人,可以通过其他方式(如声音)来传送这些信息。

 

3.具有交互性和动态性

  由于网络是动态的媒体,SVG要成为网络图像格式,必须要具有动态的特征,

这也是区别于其它图像格式的一个重要特征。SVG是基于XML的,它提供无可匹敌的动态交互性。你可以在svG文件中嵌入动画元素(如运动路径、渐现或渐隐效果、生长的物体、收缩、快速旋转、改变颜色等),或通过脚本定义来达到高亮显示、声音、动画等效果。

4.完全支持DOM

  D0M(Document Object Model文档物件模型)是一种文档平台,它允许程序或脚本动态的存储和上传文件的内容、结构或样式。由于SVG完全支持DOM, 因而SVG文档可以通过一致的接口规范与外界的程序打交道。SVG以及SVG中的物件元素完全可以通过脚本语言接受外部事件的驱动,例如鼠标动作,实现自身或对其他物件、图像的控制等。这也是电子文档应具备的优秀特性之一。

 

 

SVG在手机上的应用

由于SVG是基于XML的, 因而能制作出空前强大的动态交互图像。即SVG图像能对用户动作做出不同响应, 例如高亮、声效、特效、动画等。 作为SVG技术的一个应用,SVG在手机等无线手持设备上的应用将是3G时代最重要的应用之一。支持SVG的手机,允许用户查看高质量的矢量图形及动画,同时,由于SVG采用文本传输,尺寸也会非常小,速度将会更快。目前,市面上已经有100多款智能手机提供此服务,其中包括诺基亚、摩托等巨头的产品,由此可见,SVG手机将成为3G时代的一个最重要的市场制高点,也将是国内手机厂商应对和超越海外兵团的一个突破口。

 

 

介绍在QT中如何利用DOM来解析SVG文件并根据解析的SVG中绘图元素来绘制图形

SVG文件使用XML表示的矢量图形文件,每种图形都是用XML标签表示,例如在SVG文件中画折线的标签如下:

<polyline fill="none" stroke="red" stroke-width="2" points="100,200,100,100"></polyline>

其中polyline表示画折线,fill属性表示填充颜色,一般用来设置给brush,stroke属性表示画笔的颜色,一般用来设置给pen,stroke-width属性表示画笔的宽度,也用来设置给pen,points表示折线的点。

 

给出一个比较简单的通过解析SVG文件,获取到绘图元素然后进行图形绘制的例子

SVG文件:

 

<?xml version="1.0" standalone="no"?>
<svg>
  <rect fill="none" stroke="red" stroke-width="2" id="testRect" x="10" y="10" width="50" height="50"></rect>
  <circle fill = "#7dff64" stroke="blue" stroke-width="2" cx="70" cy="70" r="10"></circle>
  <text stroke="blue" stroke-width="2" x="90" y="90" font-family="arial" font-size="10">liangkaiming</text>
</svg>

 

解析代码:

将SVG文件数据内容读到QDomDocument对象中:

void Widget::readSvg(QString fileName)

{
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly))
    {
        return;
    }
    if(!doc->setContent(&file))
    {
        file.close();
        return;
    }
    file.close();
    bDraw = true;
}

 

根据SVG中画笔和画刷的属性来设置用于绘制的Pen和Brush的属性

void Widget::setPenAndBrush(QPainter &painter, QDomElement &element)

{
    bool ok;
    QPen pen;
    QBrush brush;
    QString fill = element.attribute("fill");
    if(fill != "none")
    {
        QRgb color = (QRgb)fill.toInt(&ok,16);
        brush.setColor(QColor(color));
    }
    QString stroke = element.attribute("stroke");
    if(stroke != "none")
    {
        if(stroke == "blue")
            pen.setColor(Qt::blue);
        else if(stroke == "red")
            pen.setColor(Qt::red);
        else
        {
            QRgb color = (QRgb)stroke.toInt(&ok,16);
            pen.setColor(QColor(color));
        }
    }
    QString strokeWidth = element.attribute("stroke-width");
    pen.setWidth(strokeWidth.toInt());
    painter.setPen(pen);
    pen.setBrush(brush);
}

 

通过从SVG文件中读取出绘图元素的属性来绘制图形

void Widget::paintEvent(QPaintEvent *event)

{
    if(!bDraw)
    {
        return;
    }
    QPainter painter(this);
    QDomElement root = doc->documentElement();
    QDomElement child = root.firstChildElement();
    QRect rect;
    while(!child.isNull())
    {
        if(child.tagName() == "rect")
        {
            setPenAndBrush(painter,child);
            rect.setRect(child.attribute("x").toInt(),child.attribute("y").toInt(),child.attribute("width").toInt(),child.attribute("height").toInt());
            painter.drawRect(rect);
        }
        else if(child.tagName() == "circle")
        {
            setPenAndBrush(painter,child);
            int cx = child.attribute("cx").toInt();
            int cy = child.attribute("cy").toInt();
            int r = child.attribute("r").toInt();
            rect.setRect(cx-r,cy-r,2*r,2*r);
            painter.drawEllipse(rect);
        }
        else if(child.tagName() == "text")
        {
            setPenAndBrush(painter,child);
            int x = child.attribute("x").toInt();
            int y = child.attribute("y").toInt();
            QFont font;
            font.setFamily(child.attribute("font-family"));
            font.setPointSize(child.attribute("font-size").toInt());
            painter.setFont(font);
            painter.drawText(x,y,child.text());
        }
        child = child.nextSiblingElement();
    }
}

注意是在QPaintEvent消息的处理函数paintEvent中来处理的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值