我正在使用HtML5,Canvas,Javascript,我已经创建了一个页面,其中正在读取excel文件,其值显示在里程表..我的整个代码我工作正常,但我还有另一件事,我不能做的是,假设我们在excel文件中有五个值,如此
t1 50
t2 90
t3 10
t4 25
t5 36
所以根据我的代码,它会显示一个速度表中的所有值,但我想在不同的速度表上显示它,比如在另一个速度表90中的50,另一个速度表上的10,依此类推。我不能这样做..我的代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Speedometer HTML5 Canvas</title>
<script src="script copy.js">
</script>
</head>
<body onload='draw(0);'>
<canvas id="tutorial" width="440" height="220">
Canvas not available.
</canvas>
<div id="divHidden" style="visibility: hidden; width: 0px; height: 0px">
<form id="drawTemp">
<input type="text" id="txtSpeed" name="txtSpeed" value="20" maxlength="2" />
<input type="button" value="Draw" onclick="drawWithInputValue();">
<input type="file" id="file" onchange="checkfile(this);" />
<input type="button" id="btnSubmit" onclick="readdata(1, 2)" value="Submit" />
<button onclick="myStopFunction()">Stop Meter</button>
</form>
</div>
</body>
</html>
<script type="text/javascript" language="javascript">
var myVar=setInterval(function(){readdata(1,2)},2000);
function myStopFunction()
{
clearInterval(myVar);
}
function checkfile(sender) {
var validExts = new Array(".xlsx", ".xls", ".csv");
var fileExt = sender.value;
fileExt = fileExt.substring(fileExt.lastIndexOf('.'));
if (validExts.indexOf(fileExt) < 0) {
alert("Invalid file selected, valid files are of " +
validExts.toString() + " types.");
return false;
}
else return true;
}
var xVal = 1;
var yVal = 2
function readdata(x,y) {
x = xVal;
y = yVal;
try {
var excel = new ActiveXObject("Excel.Application");
excel.Visible = false;
var excel_file = excel.Workbooks.Open("D:\\Test.xls");// alert(excel_file.worksheets.count);
var excel_sheet = excel_file.Worksheets("Sheet1");
var data = excel_sheet.Cells(x, y).Value;
//alert(data);
drawWithexcelValue(data);
xVal = xVal + 1;
if(data==null || data=="")
{
myStopFunction();
}
excel.Application.Quit();
}
catch (ex) {
alert(ex);
}
}
</script>
and for speedometer here is my code
/*jslint plusplus: true, sloppy: true, indent: 4 */
(function() {
"use strict";
// this function is strict...
} ());
var iCurrentSpeed = 20,
iTargetSpeed = 20,
bDecrement = null,
job = null;
function degToRad(angle) {
// Degrees to radians
return ((angle * Math.PI) / 180);
}
function radToDeg(angle) {
// Radians to degree
return ((angle * 180) / Math.PI);
}
function drawLine(options, line) {
// Draw a line using the line object passed in
options.ctx.beginPath();
// Set attributes of open
options.ctx.globalAlpha = line.alpha;
options.ctx.lineWidth = line.lineWidth;
options.ctx.fillStyle = line.fillStyle;
options.ctx.strokeStyle = line.fillStyle;
options.ctx.moveTo(line.from.X,
line.from.Y);
// Plot the line
options.ctx.lineTo(
line.to.X,
line.to.Y
);
options.ctx.stroke();
}
function createLine(fromX, fromY, toX, toY, fillStyle, lineWidth, alpha) {
// Create a line object using Javascript object notation
return {
from: {
X: fromX,
Y: fromY
},
to: {
X: toX,
Y: toY
},
fillStyle: fillStyle,
lineWidth: lineWidth,
alpha: alpha
};
}
function drawOuterMetallicArc(options) {
/* Draw the metallic border of the speedometer
* Outer grey area
*/
options.ctx.beginPath();
// Nice shade of grey
options.ctx.fillStyle = "rgb(127,127,127)";
// Draw the outer circle
options.ctx.arc(options.center.X,
options.center.Y,
options.radius,
0,
Math.PI,
true);
// Fill the last object
options.ctx.fill();
}
function drawInnerMetallicArc(options) {
/* Draw the metallic border of the speedometer
* Inner white area
*/
options.ctx.beginPath();
// White
options.ctx.fillStyle = "rgb(255,255,255)";
// Outer circle (subtle edge in the grey)
options.ctx.arc(options.center.X,
options.center.Y,
(options.radius / 100) * 90,
0,
Math.PI,
true);
options.ctx.fill();
}
function drawMetallicArc(options) {
/* Draw the metallic border of the speedometer
* by drawing two semi-circles, one over lapping
* the other with a bot of alpha transparency
*/
drawOuterMetallicArc(options);
drawInnerMetallicArc(options);
}
function drawBackground(options) {
/* Black background with alphs transparency to
* blend the edges of the metallic edge and
* black background
*/
var i = 0;
options.ctx.globalAlpha = 0.2;
options.ctx.fillStyle = "rgb(0,0,0)";
// Draw semi-transparent circles
for (i = 170; i < 180; i++) {
options.ctx.beginPath();
options.ctx.arc(options.center.X,
options.center.Y,
i,
0,
Math.PI,
true);
options.ctx.fill();
}
}
function applyDefaultContextSettings(options) {
/* Helper function to revert to gauges
* default settings
*/
options.ctx.lineWidth = 2;
options.ctx.globalAlpha = 0.5;
options.ctx.strokeStyle = "rgb(255, 255, 255)";
options.ctx.fillStyle = 'rgb(255,255,255)';
}
function drawSmallTickMarks(options) {
/* The small tick marks against the coloured
* arc drawn every 5 mph from 10 degrees to
* 170 degrees.
*/
var tickvalue = options.levelRadius - 8,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickRad = 0,
onArchX,
onArchY,
innerTickX,
innerTickY,
fromX,
fromY,
line,
toX,
toY;
applyDefaultContextSettings(options);
// Tick every 20 degrees (small ticks)
for (iTick = 10; iTick < 180; iTick += 20) {
iTickRad = degToRad(iTick);
/* Calculate the X and Y of both ends of the
* line I need to draw at angle represented at Tick.
* The aim is to draw the a line starting on the
* coloured arc and continueing towards the outer edge
* in the direction from the center of the gauge.
*/
onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);
fromX = (options.center.X - gaugeOptions.radius) + onArchX;
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
toX = (options.center.X - gaugeOptions.radius) + innerTickX;
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;
// Create a line expressed in JSON
line = createLine(fromX, fromY, toX, toY, "rgb(127,127,127)", 3, 0.6);
// Draw the line
drawLine(options, line);
}
}
function drawLargeTickMarks(options) {
/* The large tick marks against the coloured
* arc drawn every 10 mph from 10 degrees to
* 170 degrees.
*/
var tickvalue = options.levelRadius - 8,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickRad = 0,
innerTickY,
innerTickX,
onArchX,
onArchY,
fromX,
fromY,
toX,
toY,
line;
applyDefaultContextSettings(options);
tickvalue = options.levelRadius - 2;
//alert(tickValue);
// 10 units (major ticks)
for (iTick = 10; iTick < 180; iTick += 10) {
iTickRad = degToRad(iTick);
/* Calculate the X and Y of both ends of the
* line I need to draw at angle represented at Tick.
* The aim is to draw the a line starting on the
* coloured arc and continueing towards the outer edge
* in the direction from the center of the gauge.
*/
onArchX = gaugeOptions.radius - (Math.cos(iTickRad) * tickvalue);
onArchY = gaugeOptions.radius - (Math.sin(iTickRad) * tickvalue);
innerTickX = gaugeOptions.radius - (Math.cos(iTickRad) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(iTickRad) * gaugeOptions.radius);
fromX = (options.center.X - gaugeOptions.radius) + onArchX;
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + onArchY;
toX = (options.center.X - gaugeOptions.radius) + innerTickX;
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY;
// Create a line expressed in JSON
line = createLine(fromX, fromY, toX, toY, "rgb(127,127,127)", 3, 0.6);
// Draw the line
drawLine(options, line);
}
}
function drawTicks(options) {
/* Two tick in the coloured arc!
* Small ticks every 5
* Large ticks every 10
*/
drawSmallTickMarks(options);
drawLargeTickMarks(options);
}
function drawTextMarkers(options) {
/* The text labels marks above the coloured
* arc drawn every 10 mph from 10 degrees to
* 170 degrees.
*/
var innerTickX = 0,
innerTickY = 0,
iTick = 0,
gaugeOptions = options.gaugeOptions,
iTickToPrint = 0;
applyDefaultContextSettings(options);
// Font styling
options.ctx.font = 'italic 10px sans-serif';
options.ctx.textBaseline = 'top';
options.ctx.beginPath();
// Tick every 20 (small ticks)
for (iTick = 10; iTick < 180; iTick += 20) {
innerTickX = gaugeOptions.radius - (Math.cos(degToRad(iTick)) * gaugeOptions.radius);
innerTickY = gaugeOptions.radius - (Math.sin(degToRad(iTick)) * gaugeOptions.radius);
// Some cludging to center the values (TODO: Improve)
if (iTick <= 10) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
} else if (iTick < 50) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX - 5,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
} else if (iTick < 90) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else if (iTick === 90) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 4,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else if (iTick < 145) {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 10,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY);
} else {
options.ctx.fillText(iTickToPrint, (options.center.X - gaugeOptions.radius - 12) + innerTickX + 15,
(gaugeOptions.center.Y - gaugeOptions.radius - 12) + innerTickY + 5);
}
// MPH increase by 10 every 20 degrees
iTickToPrint += Math.round(2160 / 216);
}
options.ctx.stroke();
}
function drawSpeedometerPart(options, alphaValue, strokeStyle, startPos) {
/* Draw part of the arc that represents
* the colour speedometer arc
*/
options.ctx.beginPath();
options.ctx.globalAlpha = alphaValue;
options.ctx.lineWidth = 5;
options.ctx.strokeStyle = strokeStyle;
options.ctx.arc(options.center.X,
options.center.Y,
options.levelRadius,
Math.PI + (Math.PI / 360 * startPos),
0 - (Math.PI / 360 * 10),
false);
options.ctx.stroke();
}
function drawSpeedometerColourArc(options) {
/* Draws the colour arc. Three different colours
* used here; thus, same arc drawn 3 times with
* different colours.
* TODO: Gradient possible?
*/
var startOfGreen = 10,
endOfGreen = 200,
endOfOrange = 280;
drawSpeedometerPart(options, 1.0, "rgb(82, 240, 55)", startOfGreen);
drawSpeedometerPart(options, 0.9, "rgb(198, 111, 0)", endOfGreen);
drawSpeedometerPart(options, 0.9, "rgb(255, 0, 0)", endOfOrange);
}
function drawNeedleDial(options, alphaValue, strokeStyle, fillStyle) {
/* Draws the metallic dial that covers the base of the
* needle.
*/
var i = 0;
options.ctx.globalAlpha = alphaValue;
options.ctx.lineWidth = 3;
options.ctx.strokeStyle = strokeStyle;
options.ctx.fillStyle = fillStyle;
// Draw several transparent circles with alpha
for (i = 0; i < 30; i++) {
options.ctx.beginPath();
options.ctx.arc(options.center.X,
options.center.Y,
i,
0,
Math.PI,
true);
options.ctx.fill();
options.ctx.stroke();
}
}
function convertSpeedToAngle(options) {
/* Helper function to convert a speed to the
* equivelant angle.
*/
var iSpeed = (options.speed / 10),
iSpeedAsAngle = ((iSpeed * 20) + 10) % 180;
// Ensure the angle is within range
if (iSpeedAsAngle > 180) {
iSpeedAsAngle = iSpeedAsAngle - 180;
} else if (iSpeedAsAngle < 0) {
iSpeedAsAngle = iSpeedAsAngle + 180;
}
return iSpeedAsAngle;
}
function drawNeedle(options) {
/* Draw the needle in a nice read colour at the
* angle that represents the options.speed value.
*/
var iSpeedAsAngle = convertSpeedToAngle(options),
iSpeedAsAngleRad = degToRad(iSpeedAsAngle),
gaugeOptions = options.gaugeOptions,
innerTickX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * 20),
innerTickY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * 20),
fromX = (options.center.X - gaugeOptions.radius) + innerTickX,
fromY = (gaugeOptions.center.Y - gaugeOptions.radius) + innerTickY,
endNeedleX = gaugeOptions.radius - (Math.cos(iSpeedAsAngleRad) * gaugeOptions.radius),
endNeedleY = gaugeOptions.radius - (Math.sin(iSpeedAsAngleRad) * gaugeOptions.radius),
toX = (options.center.X - gaugeOptions.radius) + endNeedleX,
toY = (gaugeOptions.center.Y - gaugeOptions.radius) + endNeedleY,
line = createLine(fromX, fromY, toX, toY, "rgb(255,0,0)",5, 0.9);
drawLine(options, line);
// Two circle to draw the dial at the base (give its a nice effect?)
drawNeedleDial(options, 0.6, "rgb(127, 127, 127)", "rgb(255,255,255)");
drawNeedleDial(options, 0.2, "rgb(127, 127, 127)", "rgb(127,127,127)");
}
function buildOptionsAsJSON(canvas, iSpeed) {
/* Setting for the speedometer
* Alter these to modify its look and feel
*/
var centerX = 210,
centerY = 210,
radius = 140,
outerRadius = 200;
// Create a speedometer object using Javascript object notation
return {
ctx: canvas.getContext('2d'),
speed: iSpeed,
center: {
X: centerX,
Y: centerY
},
levelRadius: radius - 10,
gaugeOptions: {
center: {
X: centerX,
Y: centerY
},
radius: radius
},
radius: outerRadius
};
}
function clearCanvas(options) {
options.ctx.clearRect(0, 0, 800, 600);
applyDefaultContextSettings(options);
}
function draw() {
/* Main entry point for drawing the speedometer
* If canvas is not support alert the user.
*/
var canvas = document.getElementById('tutorial'),
options = null;
// Canvas good?
if (canvas !== null && canvas.getContext) {
options = buildOptionsAsJSON(canvas, iCurrentSpeed);
// Clear canvas
clearCanvas(options);
// Draw the metallic styled edge
drawMetallicArc(options);
// Draw thw background
drawBackground(options);
// Draw tick marks
drawTicks(options);
// Draw labels on markers
drawTextMarkers(options);
// Draw speeometer colour arc
drawSpeedometerColourArc(options);
// Draw the needle and base
drawNeedle(options);
} else {
alert("Canvas not supported by your browser!");
}
if (iTargetSpeed == iCurrentSpeed) {
clearTimeout(job);
return;
} else if (iTargetSpeed < iCurrentSpeed) {
bDecrement = true;
} else if (iTargetSpeed > iCurrentSpeed) {
bDecrement = false;
}
if (bDecrement) {
if (iCurrentSpeed - 10 < iTargetSpeed)
iCurrentSpeed = iCurrentSpeed - 1;
else
iCurrentSpeed = iCurrentSpeed - 5;
} else {
if (iCurrentSpeed + 10 > iTargetSpeed)
iCurrentSpeed = iCurrentSpeed + 1;
else
iCurrentSpeed = iCurrentSpeed + 5;
}
job = setTimeout("draw()", 5);
}
function drawWithInputValue() {
var txtSpeed = document.getElementById('txtSpeed'); //alert(txtSpeed.value);
if (txtSpeed !== null) {
iTargetSpeed = txtSpeed.value;
// Sanity checks
if (isNaN(iTargetSpeed)) {
iTargetSpeed = 0;
} else if (iTargetSpeed < 0) {
iTargetSpeed = 0;
} else if (iTargetSpeed > 80) {
iTargetSpeed = 80;
}
job = setTimeout("draw()", 5);
}
}
function drawWithexcelValue(val) {
var txtSpeed = val; //alert(txtSpeed.value);
if (txtSpeed !== null) {
iTargetSpeed = txtSpeed;
// Sanity checks
if (isNaN(iTargetSpeed)) {
iTargetSpeed = 0;
} else if (iTargetSpeed < 0) {
iTargetSpeed = 0;
} else if (iTargetSpeed > 80) {
iTargetSpeed = 80;
}
job = setTimeout("draw()", 5);
}
}
答案 0 :(得分:1)
您可以通过向绘图功能添加x-offset(1-5)来生成多个速度表
我假设您的选项变量存储t1,t2,t3,t4,t5及其速度:
您没有提供足够的选项代码,因此简化的选项可能如下所示。
(根据您的实际情况调整):
options=[
{t:1,speed:50},
{t:2,speed:90},
{t:3,speed:10},
{t:4,speed:25},
{t:5,speed:36},
];
然后在你的绘图函数中,你需要遍历每个“t”:
function draw(){
// Clear canvas
for(varti=0;t<options.length;t++){
option=options[t];
// Draw the metallic styled edge
// Draw thw background
// Draw tick marks
// Draw labels on markers
// Draw speeometer colour arc
// Draw the needle and base
}
}
在你的drawMetallicArc(etc)函数中,你会绘制一个从左边偏移的速度表,根据你绘制的“t”:
还假设您希望每个车速表的中心间隔50px。
然后你可以像这样计算5个速度表中的每一个的中心-x
centerX = t * 50;
要说明,假设每个速度表的半径为15,y坐标为60。
你的drawMetallicArc函数如下所示:
function drawMetallicArc(option){
var y=60;
var radius=15;
var x=option.t*50;
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
ctx.closePath();
ctx.strokeStyle="blue";
ctx.stroke();
}
当然,您可以类似地修改其他每个绘制函数以使用x-offsets。
这是代码和小提琴:http://jsfiddle.net/m1erickson/93SY5/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px;}
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
options=[
{t:1,speed:50},
{t:2,speed:90},
{t:3,speed:10},
{t:4,speed:25},
{t:5,speed:36},
];
draw();
function draw(){
// Clear canvas
for(var i=0;i<options.length;i++){
option=options[i];
// Draw the metallic styled edge
drawMetallicArc(option);
// Draw thw background
// Draw tick marks
// Draw labels on markers
drawTextMarkers(option);
// Draw speeometer colour arc
// Draw the needle and base
}
}
function drawMetallicArc(option){
var y=60;
var radius=15;
var x=option.t*50;
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
ctx.closePath();
ctx.strokeStyle="blue";
ctx.stroke();
}
function drawTextMarkers(option){
var y=60
var radius=15
var top=y-radius-5;
var x=option.t*50-5; // -5 for digit spacing
ctx.fillText(option.speed,x,top);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=100></canvas>
</body>
</html>
[另外:再看一下代码]
600多行是要看的很多代码......。无论如何:
现在,您正在读取readdata()中的1个excel值,然后调用
drawWithexcelValue(data);
我假设您将更改此内容以读取readdata()中的5个excel值 - t1,t2,t3,t4,t5
var multipleData = [50,90,10,25,36];
drawWithexcelValue(multipleData);
您的drawWithexcelValue会将值限制在0-80范围内,然后调用draw()
在绘图中,您需要处理多值数组
中的每个值for(var t=0;t<multipleData.length;t++){
// build options for this “t” value
options = buildOptionsAsJSON(canvas,multipleData[t],t);
// now call all draw-X functions using current “options”
}
buildOptionsAsJSON使用“t”值来改变当前车速表的中心点:
关键是这个中心X计算向右移动每个新的速度表:
X = outerRadius * t + 10; // +10 is just to space the speedometers apart
这是完整的buildOptionsAsJSON():
function buildOptionsAsJSON(canvas, iSpeed, t) {
var centerX = 0,
centerY = 210,
radius = 140,
outerRadius = 200;
// Create a speedometer object using Javascript object notation
return {
ctx: canvas.getContext('2d'),
speed: iSpeed,
center: {
X: outerRadius * t + 10, // 10 is horizontal spacing
Y: centerY
},
levelRadius: radius - 10,
gaugeOptions: {
center: {
X: outerRadius * t +10, // +10 is horizontal spacing
Y: centerY
},
radius: radius
},
radius: outerRadius
};
}