Introduction
The SVG Demo Plot demonstrates how to modify SVG using HTML forms dynamically. This web page modifies the plot using DOM Level 3, which is an XML transformation standard. I plotted some random functions. One is an x=4 function, another a y=5x-2 function, and another a y=-x^2+5x-2 function. This also complies with the SVG standards written in Jonathon Watt's page. He apparently is a Mozilla developer. I received his guidelines when working with SVG professionally.
Background
The SVG Demo Plot does not yet work on Firefox and Chrome. Both apparently have issues with SVG. For example, this SVG example from W3C works in both Chrome and Opera, but not in Firefox: http://www.w3.org/TR/SVG/images/animate/animMotion01.svg. Only the Opera browser supports JavaScript dynamically, adding lots of elements based on HTML forms. (I thought that the reason was that Firefox and Chrome do not support modifying the root element, but only support modifying the children, as suggested in my blog. However, I was wrong.)
Using the code
When you enter the page 'default.html', you get the following page:
You could easily edit the parameters like below:
You could also edit it so that it renders no functions.
I made two HTML frames. I used 40% for the left and 60% for the right frame. Then, besides the form that the user sends for the left frame, a little form would trigger the plot to render for the right frame. The left frame calls JavaScript that would submit information to the form on the right frame after validating that numbers were submitted. Then, once the JavaScript for the right frame gets submitted, it triggers JavaScript (and ECMAScript, which is used for SVG and essentially is JavaScript) to render the plot. It is kind of a chain all right.
There is a need for transformation from XY plot space to SVG space. Because, the top of the screen in SVG space is 0 and the left of the screen is 0. Henceforth, I transformed the plot 25 pixels from the top. (This is the maximum y.) And 50 pixels from the left. (The minimum X is located 50 pixels from the left.) All figures, have the fill #FFF because SVG is all lines and shapes. This could be expressed using the code below for the Y-axis, for example:
function yCoordinateToScreen(y, minY, maxY) {
var ySpace=yMinCoord-yMaxCoord;
var yCoords=maxY-minY;
var svgIndex = (y-minY)*ySpace/yCoords;
return yMinCoord-svgIndex;
}
All of the object rendering is similar to DOM in XML. I get the document node and the group 'plot', which is where I will insert the XY plot, in SVG, as follows:
var target=window.document.getElementById("PlotData");
svgDoc=target.getSVGDocument();
svgRoot=svgDoc.getElementById("plot");
First this renders the ticks by doing the following on the 'startup' function:
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);
Now a tick along the right side Y-axis is created. The tick will be 4 pixels long and 2 pixels wide.
Then when the form for the plot is submitted on the right frame by the form on the left frame, a special ordering is done for each of the figures. Because this renders a quadratic function, this needs to render the quadratic function before the other functions. Otherwise, the quadratic function will overlap the elements that were formerly added. (Even if you use a 'polyline' element, that will overlap the other elements that were formerly added as well.) The best way to render a quadratic function is to use a path as follows:
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);
Then this renders the lines. Afterwards, this renders the origins and then the gradients, using a similar method as above. The SVG Plot Demo refreshes the page by ridding the page of the formerly rendered elements in the 'plotCalc
' function if the page reloads.
Well, the world is not perfect. But one could at least try to pragmatically solve the problems that the world offers.