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

SVG 中的 XY 曲线图

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (3投票s)

2010 年 6 月 26 日

Zlib

3分钟阅读

viewsIcon

35143

downloadIcon

572

这是一个 HTML 和 SVG 中的演示绘图,其中 JavaScript 控制 SVG。

引言

这个 SVG 演示绘图展示了如何使用 HTML 表单动态修改 SVG。 此网页使用 DOM Level 3 修改绘图,这是一个 XML 转换标准。 我绘制了一些随机函数。 一个是 x=4 函数,另一个是 y=5x-2 函数,另一个是 y=-x^2+5x-2 函数。 这也符合 Jonathon Watt 的页面中编写的 SVG 标准。 他显然是一位 Mozilla 开发者。 我在专业上使用 SVG 时收到了他的指导方针。

背景

SVG 演示绘图尚未在 Firefox 和 Chrome 上运行。 两者显然都有 SVG 问题。 例如,W3C 的这个 SVG 示例可以在 Chrome 和 Opera 中运行,但不能在 Firefox 中运行:http://www.w3.org/TR/SVG/images/animate/animMotion01.svg。 只有 Opera 浏览器支持 JavaScript 动态地,根据 HTML 表单添加大量元素。(我曾经认为原因是 Firefox 和 Chrome 不支持修改根元素,而只支持修改子元素,正如在我的博客中建议的那样。 但是,我错了。)

使用代码

当您进入页面 'default.html' 时,您会得到以下页面

PlotDemo_orig.JPG

您可以轻松地编辑如下参数

PlotDemo_90x800.JPG

您也可以对其进行编辑,使其不渲染任何函数。

PlotDemo_noimage.JPG

我制作了两个 HTML 框架。 左侧框架使用了 40%,右侧框架使用了 60%。 然后,除了用户为左侧框架发送的表单之外,还有一个小表单会触发右侧框架的绘图渲染。 左侧框架调用 JavaScript,在验证提交的是数字后,会将信息提交到右侧框架上的表单。 然后,一旦提交了右侧框架的 JavaScript,它就会触发 JavaScript(以及用于 SVG 并且本质上是 JavaScript 的 ECMAScript)来渲染绘图。 这真是一个链条。

需要从 XY 绘图空间转换为 SVG 空间。 因为,SVG 空间中屏幕的顶部是 0,屏幕的左侧是 0。 因此,我将绘图从顶部转换了 25 像素。(这是最大 y 值。)并从左侧转换了 50 像素。(最小 X 值位于左侧 50 像素处。)所有图形的填充颜色均为 #FFF,因为 SVG 全部是线条和形状。 例如,可以使用以下代码表示 Y 轴

function yCoordinateToScreen(y, minY, maxY) {
     var ySpace=yMinCoord-yMaxCoord;
     var yCoords=maxY-minY;
     var svgIndex = (y-minY)*ySpace/yCoords;
     return yMinCoord-svgIndex;
}

所有对象的渲染都类似于 XML 中的 DOM。 我获取文档节点和组“plot”,我将在其中以 SVG 格式插入 XY 绘图,如下所示

var target=window.document.getElementById("PlotData");
svgDoc=target.getSVGDocument();
svgRoot=svgDoc.getElementById("plot");

首先,这通过在“startup”函数上执行以下操作来渲染刻度线

tick = svgDoc.createElementNS(svgns, "line");
tick.setAttributeNS(svgns, "id", "yTickRight"+i);
tick.setAttributeNS(svgns, "x1", xMaxCoord+4);
tick.setAttributeNS(svgns, "y1", yPos);
tick.setAttributeNS(svgns, "x2", xMaxCoord);
tick.setAttributeNS(svgns, "y2", yPos);
tick.setAttributeNS(svgns, "stroke-width", 2);
tick.setAttributeNS(svgns, "stroke", "black");
svgRoot.appendChild(tick);

现在创建了沿右侧 Y 轴的刻度线。 刻度线将为 4 像素长,2 像素宽。

然后,当左侧框架上的表单提交右侧框架上的绘图表单时,将对每个图形进行特殊排序。 因为这会渲染二次函数,所以需要在其他函数之前渲染二次函数。 否则,二次函数会覆盖以前添加的元素。(即使您使用“折线”元素,它也会覆盖以前添加的其他元素。)渲染二次函数的最佳方法是使用如下路径

var y_val = y2(xMin);
var xScreenCoord= 0;
var yScreenCoord=0;
var data = "";
if (y_val <= yMax && y_val >= yMin) {
    xScreenCoord=xCoordinateToScreen(xMin, xMin, xMax);
    yScreenCoord=yCoordinateToScreen(y_val, yMin, yMax); 
    data= "M"+xScreenCoord + " " + yScreenCoord + " Q";    
}
for (var j=xMin+1; j <= xMax; j++) {
     y_val = y2(j);
     if (y_val <= yMax && y_val >= yMin) {
        xScreenCoord=xCoordinateToScreen(j, xMin, xMax);
        yScreenCoord=yCoordinateToScreen(y_val, yMin, yMax);
        if(data == "") 
          data= "M"+xScreenCoord + " " + yScreenCoord + " Q";
        else
          data += xScreenCoord + " " + yScreenCoord + " ";
     }
}

drawing3.setAttributeNS(svgns, "d", data);
drawing3.setAttributeNS(svgns, "stroke-width", 1);
drawing3.setAttributeNS(svgns, "stroke", "#00F");
drawing3.setAttributeNS(svgns, "fill", "#FFF");
svgRoot.appendChild(drawing3);

然后,这会渲染线条。 之后,这会使用与上述类似的方法渲染原点和渐变。 如果页面重新加载,SVG 绘图演示通过清除页面中以前渲染的元素来刷新页面“plotCalc'函数。

好吧,世界并不完美。 但至少可以尝试务实地解决世界提供的问题。

© . All rights reserved.