<!DOCTYPE html>
<html>
<head>
<title>A Dial Showing the Degrees of a Circle</title>
<style>
body {
background: #eeeeee;
}
#canvas {
background: #ffffff;
cursor: crosshair;
margin-left: 10px;
margin-top: 10px;
-webkit-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
-moz-box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
box-shadow: 4px 4px 8px rgba(0,0,0,0.5);
}
</style>
</head>
<body>
<canvas id='canvas' width='850' height='650'>
Canvas not supported
</canvas>
<script >
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
//圆心
CENTROID_RADIUS = 2,
CENTROID_STROKE_STYLE = 'rgba(0, 0, 0, 0.9)',
CENTROID_FILL_STYLE = 'rgba(80, 190, 240, 0.6)',
RING_INNER_RADIUS = 150,
RING_OUTER_RADIUS = 80,
ANNOTATIONS_FILL_STYLE = 'rgba(0, 0, 230, 0.9)',//数字填充样式
ANNOTATIONS_TEXT_SIZE = 12,
TICK_WIDTH = 10,
TICK_LONG_STROKE_STYLE = 'rgba(100, 140, 230, 0.9)',
TICK_SHORT_STROKE_STYLE = 'rgba(100, 140, 230, 0.7)',
TRACKING_DIAL_STROKING_STYLE = 'rgba(100, 140, 230, 0.5)',
GUIDEWIRE_STROKE_STYLE = 'goldenrod',
GUIDEWIRE_FILL_STYLE = 'rgba(250, 250, 0, 0.6)',
circle = { x: canvas.width/2,
y: canvas.height/2,
radius: 150
};
// Functions..........................................................
function drawCentroidGuidewire(loc,value) {
var angle = -Math.PI/(180/value), //半圆的一半
radius, endpt;
radius = circle.radius + RING_INNER_RADIUS;
if (loc.x >= circle.x) {
endpt = { x: circle.x + radius * Math.cos(angle),
y: circle.y + radius * Math.sin(angle)
};
}
else {
endpt = { x: circle.x - radius * Math.cos(angle),
y: circle.y - radius * Math.sin(angle)
};
}
context.save();
context.strokeStyle ="red";
context.fillStyle = GUIDEWIRE_FILL_STYLE;
context.beginPath();
context.moveTo(circle.x, circle.y);
context.lineTo(endpt.x, endpt.y);
context.stroke();
// context.beginPath();
// context.strokeStyle = TICK_LONG_STROKE_STYLE;
// context.arc(endpt.x, endpt.y, 5, 0, Math.PI*2, false); //小圆
// context.fill();
// context.stroke();
//
context.restore();
}
//.......................................................
// 虚线圆圈
function drawCanvas(r) {
context.setLineDash([4, 4]);
context.strokeStyle = '#bababa';
context.beginPath();
context.arc(circle.x, circle.y, r, 0, Math.PI * 2);
context.stroke();
}
//........................................................
function drawGrid(color, stepx, stepy) {
context.save()
context.shadowColor = undefined;
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.strokeStyle = color;
context.fillStyle = '#ffffff';
context.lineWidth = 0.5;
context.fillRect(0, 0, context.canvas.width,
context.canvas.height);
for (var i = stepx + 0.5;
i < context.canvas.width; i += stepx) {
context.beginPath();
context.moveTo(i, 0);
context.lineTo(i, context.canvas.height);
context.stroke();
}
for (var i = stepy + 0.5;
i < context.canvas.height; i += stepy) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
}
context.restore();
}
//主方法
function drawDial() {
var loc = {x: circle.x, y: circle.y};
drawCentroid();
// drawCentroid2();
drawCentroidGuidewire(loc,90);
drawCentroidGuidewire(loc,320);
drawRing();
drawTickInnerCircle();
drawTicks();
drawAnnotations();
drawCanvas(80);
drawCanvas(190);
}
//圆心小圆
function drawCentroid() {
context.beginPath();
context.save();
context.strokeStyle = CENTROID_STROKE_STYLE;
context.fillStyle = CENTROID_FILL_STYLE;
context.arc(circle.x, circle.y,
CENTROID_RADIUS, 0, Math.PI*2, false);
context.stroke();
context.fill();
context.restore();
}
//画圆
/**
function drawCentroid2() {
context.beginPath();
context.save();
context.strokeStyle = CENTROID_STROKE_STYLE;
//context.fillStyle = "#ffffff";
context.arc(circle.x, circle.y,
RING_INNER_RADIUS/4*4, 0, Math.PI*2, false);
context.stroke();
// context.fill();
context.restore();
}
**/
//画线
function drawRing() {
drawRingOuterCircle();
context.strokeStyle = 'rgba(0, 0, 0, 0.1)';
context.arc(circle.x, circle.y,
circle.radius + RING_INNER_RADIUS,
0, Math.PI*2, false);
context.fillStyle = 'rgba(100, 140, 230, 0.1)';
context.fill();
context.stroke();
}
function drawRingOuterCircle() {
context.shadowColor = 'rgba(0, 0, 0, 0.7)';
context.shadowOffsetX = 3,
context.shadowOffsetY = 3,
context.shadowBlur = 6,
context.strokeStyle = TRACKING_DIAL_STROKING_STYLE;
context.beginPath();
context.arc(circle.x, circle.y, circle.radius +
RING_OUTER_RADIUS, 0, Math.PI*2, true);
context.stroke();
}
function drawTickInnerCircle() {
context.save();
context.beginPath();
context.strokeStyle = 'rgba(0, 0, 0, 0.1)';
context.arc(circle.x, circle.y,
circle.radius + RING_INNER_RADIUS - TICK_WIDTH+10,
0, Math.PI*2, false);
context.stroke();
context.restore();
}
//画刻度
function drawTick(angle, radius, cnt) {
var tickWidth = cnt % 4 === 0 ? TICK_WIDTH : TICK_WIDTH/2;
context.beginPath();
context.moveTo(circle.x + Math.cos(angle) * (radius - tickWidth),
circle.y + Math.sin(angle) * (radius - tickWidth));
context.lineTo(circle.x + Math.cos(angle) * (radius),
circle.y + Math.sin(angle) * (radius));
context.strokeStyle = TICK_SHORT_STROKE_STYLE;
context.stroke();
}
//画刻度
function drawTicks() {
var radius = circle.radius + RING_INNER_RADIUS,
ANGLE_MAX = 2*Math.PI,
ANGLE_DELTA = Math.PI/36, //设置刻度间隔
tickWidth;
context.save();
for (var angle = 0, cnt = 0; angle < ANGLE_MAX;
angle +=ANGLE_DELTA, cnt++) {
drawTick(angle, radius, cnt++);
}
context.restore();
}
//
function drawAnnotations() {
var radius = circle.radius + RING_INNER_RADIUS;//30 60 文本位置
context.save();
context.fillStyle = ANNOTATIONS_FILL_STYLE;
context.font = ANNOTATIONS_TEXT_SIZE + 'px Helvetica';
for (var angle=0; angle < 2*Math.PI; angle += Math.PI/6) {
context.beginPath();
context.fillText((angle * 180 / Math.PI).toFixed(0)+"°",//
circle.x + Math.cos(angle) * (radius - TICK_WIDTH*2+30),
circle.y - Math.sin(angle) * (radius - TICK_WIDTH*2+30));
}
context.restore();
}
// Initialization....................................................
context.shadowOffsetX = 2;
context.shadowOffsetY = 2;
context.shadowBlur = 4;
context.textAlign = 'center';
context.textBaseline = 'middle';
drawGrid('lightgray', 10, 10);
drawDial();
</script>
</body>
</html>