realtimechart.js
来自「AJAX and PHP: Building Responsive Web Ap」· JavaScript 代码 · 共 245 行
JS
245 行
// SVG namespace
var svgNS = "http://www.w3.org/2000/svg";
// the SVG document handler
var documentSVG = null;
// will store the root <g> element that groups all chart elements
var chartGroup = null;
// how often to request new data from server?
var updateInterval = 1000;
// coordinates (in pixels) used to translate the chart
var x = 50, y = 50;
// chart's dimension (in pixels)
var height = 300, width = 500;
// chart's axis origin
var xt1 = 0, yt1 = 0;
// chart's axis maximum values
var xt2 = 50, yt2 = 100;
// number of horizontal and vertical axis divisions
var xDivisions = 10, yDivisions = 10;
// default text width and height for initial display (recalculated
// afterwards)
var defaultTextWidth = 30, defaultTextHeight = 20;
// will retain references to the chart units for recalculating positions
var xIndexes = new Array(xDivisions + 1);
var yIndexes = new Array(yDivisions + 1);
// will store the text node that displays the selected chart node
var currentNodeInfo;
// retains the latest values generated by server
var lastX = -1, lastY = -1;
// shared svg elements
var chartGroup, dataGroup, dataPath;
// initializes chart
function init(evt)
{
/**** Prepare the group that will contain all chart data ****/
// obtain SVG document handler
documentSVG = evt.target.ownerDocument;
// create the <g> element that groups all chart elements
chartGroup = documentSVG.createElementNS(svgNS, "g");
chartGroup.setAttribute("transform", "translate(" + x + " " + y + ")");
/**** Prepare the group that will store the Y and Y axis and numbers ****/
axisGroup = documentSVG.createElementNS(svgNS, "g");
// create the X axis line as a <path> element
axisPath = documentSVG.createElementNS(svgNS, "path");
// the axis lines will be black, 2 pixels wide
axisPath.setAttribute("stroke", "black");
axisPath.setAttribute("stroke-width", "2");
/**** Create the division lines for the X and Y axis ****/
// create the path definition text for the X axis division lines
pathText = "M 0 " + height;
// adds divisions to the X axis (differently for last division)
for (var i = 0; i <= xDivisions; i++)
pathText += "l 0 5 l 0 -5 " +
((i == xDivisions) ? "" : ("l " + width/xDivisions + " 0"));
// create the path definition text for the Y axis division lines
pathText += "M 0 " + height;
// adds one division to the Y axis (differently for last division)
for (var i = 0; i <= yDivisions; i++)
pathText += "l -5 0 l 5 0 " +
((i == yDivisions) ? "" : ("l 0 -" + height / yDivisions));
// add the path definition (the <d> attribute) to the path
axisPath.setAttribute("d", pathText);
// add the path to the axis group
axisGroup.appendChild(axisPath);
/**** Create the text nodes for the X and Y axis ****/
// adds text nodes for the X axis
for (var i = 0; i <= xDivisions; i++)
{
// creates the <text> node for the division
t = documentSVG.createElementNS(svgNS, "text");
// stores the node for future reference
xIndexes[i] = t;
// creates the text for the <text> node
t.appendChild(documentSVG.createTextNode(
(xt1 + i * ((xt2 - xt1) / xDivisions)).toFixed(1)));
// sets the X and Y attributes for the <text> node
t.setAttribute("x", i * width / xDivisions - defaultTextWidth / 2);
t.setAttribute("y", height + 30 + defaultTextHeight);
// when the graph first loads, we want the text nodes invisible
t.setAttribute("stroke", "white");
// add the <text> node to the axis group
axisGroup.appendChild(t);
}
// adds text nodes for the Y axis
for (var i = 0; i <= yDivisions; i++)
{
// creates the <text> node for the division
t = documentSVG.createElementNS(svgNS, "text");
// stores the node for future reference
yIndexes[i] = t;
// creates the text for the <text> node
t.appendChild(documentSVG.createTextNode(
(yt1 + i * ((yt2 - yt1) / yDivisions)).toFixed(1)));
// sets the X and Y attributes for the <text> node
t.setAttribute("x", -30 -defaultTextWidth);
t.setAttribute("y", height - i * height / yDivisions
+ defaultTextHeight / 2);
// when the graph first loads, we want the text nodes invisible
t.setAttribute("stroke", "white");
// add the <text> node to the axis group
axisGroup.appendChild(t);
}
// add the axis group to the chart
chartGroup.appendChild(axisGroup);
/**** Prepare the <path> element that will draw chart's data ****/
dataPath = documentSVG.createElementNS(svgNS, "path");
dataPath.setAttribute("stroke", "black");
dataPath.setAttribute("stroke-width", "1");
dataPath.setAttribute("fill", "none");
// add the data path to the chart group
chartGroup.appendChild(dataPath);
/**** Final initialization steps ****/
// add the chart group to the SVG document
documentSVG.documentElement.appendChild(chartGroup);
// this is needed to correctly display text nodes in Firefox
setTimeout("refreshXYIndexes()", 500);
// initiate repetitive server requests
setTimeout("updateChart()", updateInterval);
}
// this function redraws the text for the axis units and makes it visible
// (this is required to correctly position the text in Firefox)
function refreshXYIndexes()
{
// redraw text nodes on the X axis
for (var i = 0; i <= xDivisions; i++)
if (typeof xIndexes[i].getBBox != "undefined")
try
{
textWidth = xIndexes[i].getBBox().width;
textHeight = xIndexes[i].getBBox().height;
xIndexes[i].setAttribute("x", i*width/xDivisions - textWidth/2);
xIndexes[i].setAttribute("y", height + 10 + textHeight);
xIndexes[i].setAttribute("stroke", "black");
}
catch(e) {}
// redraw text nodes on the Y axis
for (var i = 0; i <= yDivisions; i++)
if (typeof yIndexes[i].getBBox != "undefined")
try
{
twidth = yIndexes[i].getBBox().width;
theight = yIndexes[i].getBBox().height;
yIndexes[i].setAttribute("y", height-i*height/yDivisions
+theight/2);
yIndexes[i].setAttribute("x", -10 -twidth);
yIndexes[i].setAttribute("stroke", "black");
}
catch(e) {}
}
// called when mouse hovers over chart node to display its coordinates
function createPointInfo(x, y, whereX, whereY)
{
// make sure you don't display more coordinates at the same time
if (currentNodeInfo) removePointInfo();
// create text node
currentNodeInfo = documentSVG.createElementNS(svgNS, "text");
currentNodeInfo.appendChild(documentSVG.createTextNode("("+x+","+y+")"));
// set coordinates
currentNodeInfo.setAttribute("x", whereX.toFixed(1));
currentNodeInfo.setAttribute("y", whereY - 10);
// add the node to the group
chartGroup.appendChild(currentNodeInfo);
}
// removes the text node that displays chart node coordinates
function removePointInfo()
{
chartGroup.removeChild(currentNodeInfo);
currentNodeInfo = null;
}
// draws a new point on the graph
function addPoint(X, Y)
{
// save these values for future reference
lastX = X;
lastY = Y;
// start over (reload page) after the last value was generated
if (X == xt2)
window.location.reload(false);
// calculate the coordinates of the new node
coordX = (X - xt1) * (width / (xt2 - xt1));
coordY = height - (Y - yt1) * (height / (yt2 - yt1));
// draw the node on the chart as a blue filled circle
var circle = documentSVG.createElementNS(svgNS, "circle");
circle.setAttribute("cx", coordX); // X position
circle.setAttribute("cy", coordY); // Y position
circle.setAttribute("r", 3); // radius
circle.setAttribute("fill", "blue"); // color
circle.setAttribute("onmouseover",
"createPointInfo(" + X + "," +
Y + "," + coordX + "," + coordY + ")");
circle.setAttribute("onmouseout", "removePointInfo()");
chartGroup.appendChild(circle);
// add a new line to the new node on the graph
current = dataPath.getAttribute("d"); // current path definition
// update path definition
if (!current || current == "")
dataPath.setAttribute("d", " M " + coordX + " " + coordY);
else
dataPath.setAttribute("d", current + " L " + coordX + " " + coordY);
}
// initiates asynchronous request to retrieve new chart data
function updateChart()
{
// builds the query string
param = "?lastX=" + lastX + ((lastY != -1) ? "&lastY=" + lastY : "");
// make the request through either AJAX
if (window.getURL)
// Supported by Adobe's SVG Viewer and Apache Batik
getURL("svg_chart.php" + param, handleResults);
else
// Supported by Mozilla, implemented in ajaxRequest.js
ajaxRequest("svg_chart.php" + param, handleResults);
}
// callback function that reads data received from server
function handleResults(data)
{
// get the response data
if (window.getURL)
responseText = data.content;
else
responseText = data;
// split the pair to obtain the X and Y coordinates
var newCoords = responseText.split(",");
// draw a new node at these coordinates
addPoint(newCoords[0], newCoords[1]);
// restart sequence
setTimeout("updateChart()", updateInterval)
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?