canvas 实现的百分比仪表盘

define(function(require) {

/**

*

* @param {Object} option

* {

* max:最大值

*  min:最小值

*  value:当前值

*  stage:6 分几段

* time:3000, 指针动画时间

*  backgroundColor:背景色

*  x:0,

*  y:0,

*  radius:0

* }

*/

 

 

/**

* 使用:

* cp.init('.main').setOption({

min: 0,

max: 120,

value: 80,

stage: 6,

time: 2000,

x: 85,

y: 90,

radius: 85

});

});

*/

 

var self = {},

DOM_KEY = '_KEY_',

_KEY = Date.now() + 0,

_instances = {};

 

self.init = function(dom) {

if (typeof dom == 'string')

dom = document.querySelector(dom);

dom instanceof Array && (dom = dom[0]);

 

var key = dom.getAttribute(DOM_KEY);

!key && dom.setAttribute(DOM_KEY, ++_KEY);

 

if (_instances[_KEY]) {

return _instances[_KEY];

} else {

_instances[_KEY] = new Render(dom);

}

return this;

};

 

self.setOption = function(option) {

_instances[_KEY]._setOption(option);

};

self.getOption = function() {

return _instances[_KEY]._getOption();

};

self.refresh = function() {

_instances[_KEY]._refresh();

}

 

 

function Render(dom) {

dom.innerHTML = '';

this.dom = dom;

this.time = 3000;

this.backgroundColor = '#2E8FC5';

this.radius = null;

this.centerPoint = {};

// 首尾空余的角度 默认10度

this.vacantAngle = 10;

 

 

}

Render.prototype = {

_setOption: function(option) {

var defaultOption = {

min: 0,

max: 100,

value: 0,

stage: 5,

time: 2000,

backgroundColor: 'rgba(80,191,239,1)',

x: 150,

y: 120,

radius: 100

};

option = require('./util').clone(true, defaultOption, option);

 

this.max = option.max;

this.min = option.min;

this.value = option.value;

this.stage = option.stage;

option.time && (this.time = option.time);

option.backgroundColor && (this.backgroundColor = option.backgroundColor);

this.centerPoint.x = option.x * 2;

this.centerPoint.y = option.y * 2;

this.radius = option.radius * 2;

this._init();

},

_init: function() {

this._create()._render();

},

_getOption: function() {

return {

max: this.max,

min: this.min,

stage: this.stage

};

},

_refresh: function(option) {

option.max && (this.max = option.max);

option.min && (this.min = option.min);

option.stage && (this.stage = option.stage);

option.time && (this.time = option.time);

option.backgroundColor && (this.backgroundColor = option.backgroundColor);

option.x && (this.centerPoint.x = option.x * 2);

option.y && (this.centerPoint.y = option.y * 2);

option.radius && (this.radius = option.radius * 2);

option.value && (this.value = option.value);

},

_render: function() {

var w = this.middleCanvas.width,

h = this.middleCanvas.height;

 

 

// 默认圆心在下边框的中心点处

if (!this.centerPoint.x || !this.centerPoint.y) {

this.centerPoint = {

x: w * 0.5,

y: h

};

}

 

if (!this.radius) {

// 判断宽高哪个长,决定半圆的半径

this.radius = w >= h ? h : w / 2;

}

/**

* 绘制背景

*/

function renderBackground() {

var w = this.bottomCanvas.width,

h = this.bottomCanvas.height,

ctx = this.bottomCanvas.getContext('2d');

ctx.save();

ctx.fillStyle = this.backgroundColor;

ctx.fillRect(0, 0, w, h);

ctx.restore();

}

 

 

 

function renderCompass() {

var ctx = this.middleCanvas.getContext('2d');

 

/* 绘制内圆 */

// 默认半径的2/3作为内圆的半径

var innerRadius = this.radius * 0.6;

 

 

ctx.save();

 

 

// 绘制内圆

ctx.beginPath();

ctx.arc(this.centerPoint.x, this.centerPoint.y, innerRadius, Math.PI, Math.PI * 2, false);

ctx.strokeStyle = 'rgba(144,238,249,1)';

ctx.lineWidth = 3;

ctx.stroke();

 

// 绘制段点

// 默认10度画一个

var radian = Math.PI / 180 * this.vacantAngle;

var point = {};

var point2 = {};

var tmpRadius = innerRadius * 0.95;

for (var i = 1, len = 180 / this.vacantAngle; i < len; i++) {

point.x = this.centerPoint.x + Math.cos(radian * i + Math.PI) * innerRadius;

point.y = this.centerPoint.y + Math.sin(radian * i + Math.PI) * innerRadius;

point2.x = this.centerPoint.x + Math.cos(radian * i + Math.PI) * tmpRadius;

point2.y = this.centerPoint.y + Math.sin(radian * i + Math.PI) * tmpRadius;

ctx.beginPath();

ctx.moveTo(point.x, point.y);

ctx.lineTo(point2.x, point2.y);

ctx.stroke();

}

ctx.restore();

 

 

// 绘制外圆

ctx.save();

ctx.strokeStyle = 'white';

ctx.fillStyle = 'white';

ctx.font = "26px arial,sans-serif";

ctx.textAlign = 'center';

ctx.textBaseline = 'middle';

ctx.lineWidth = 5;

 

var longNumer = this.stage * 2 + 1;

var smallNumer = longNumer * 2 - 1;

// 头尾各空10度

var radian = Math.PI / 180 * (180 - this.vacantAngle * 2) / (smallNumer - 1);

var longRadius = this.radius * 0.9;

var smallRadius = (this.radius - longRadius) * 0.5 + longRadius;

var longCount = 0;

var textRadius = innerRadius + (longRadius - innerRadius) * 0.5;

for (var i = 0; i <= smallNumer - 1; i++) {

 

 

if (i % 2 == 0) {

point.x = this.centerPoint.x + Math.cos(radian * i + Math.PI * 190 / 180) * this.radius;

point.y = this.centerPoint.y + Math.sin(radian * i + Math.PI * 190 / 180) * this.radius;

point2.x = this.centerPoint.x + Math.cos(radian * i + Math.PI * 190 / 180) * longRadius;

point2.y = this.centerPoint.y + Math.sin(radian * i + Math.PI * 190 / 180) * longRadius;

ctx.beginPath();

ctx.moveTo(point.x, point.y);

ctx.lineTo(point2.x, point2.y);

ctx.stroke();

 

if (longCount % 2 == 0) {

// 绘制文字

ctx.fillText(parseInt(this.min + (this.max - this.min) / this.stage * longCount * 0.5), this.centerPoint.x + Math.cos(radian * i + Math.PI * 190 / 180) * textRadius, this.centerPoint.y + Math.sin(radian * i + Math.PI * 190 / 180) * textRadius);

}

 

longCount++;

} else {

point.x = this.centerPoint.x + Math.cos(radian * i + Math.PI * 190 / 180) * smallRadius;

point.y = this.centerPoint.y + Math.sin(radian * i + Math.PI * 190 / 180) * smallRadius;

point2.x = this.centerPoint.x + Math.cos(radian * i + Math.PI * 190 / 180) * longRadius;

point2.y = this.centerPoint.y + Math.sin(radian * i + Math.PI * 190 / 180) * longRadius;

ctx.beginPath();

ctx.moveTo(point.x, point.y);

ctx.lineTo(point2.x, point2.y);

ctx.stroke();

}

}

ctx.restore();

 

}

 

function renderIndicator() {

var ctx = this.topCanvas.getContext('2d');

ctx.save();

 

ctx.beginPath();

ctx.arc(this.centerPoint.x, this.centerPoint.y, 7, Math.PI * 1.5, Math.PI * 0.5, false);

ctx.arc(this.centerPoint.x - this.radius * 0.9, this.centerPoint.y, 2, Math.PI * 0.5, Math.PI * 1.5, false);

ctx.strokeStyle = 'rgba(83,231,243,1)';

ctx.lineWidth = 3;

ctx.fillStyle = 'rgba(144,238,249,1)';

ctx.closePath();

ctx.stroke();

ctx.fill();

ctx.restore();

}

 

 

renderBackground.call(this);

renderCompass.call(this);

renderIndicator.call(this);

this._setValue(this.value);

},

_setValue: function(val) {

this.value = val;

 

var angle = val / (this.max - this.min) * (180 - this.vacantAngle * 2) + this.vacantAngle;

this.topCanvas.style.transformOrigin = this.centerPoint.x / 2 + 'px ' + this.centerPoint.y / 2 + 'px';

 

this.topCanvas.style.transform = 'rotate(' + angle + 'deg)';

this.topCanvas.style.webkitTransform = 'rotate(' + angle + 'deg)';

},

_create: function() {

/*

* 两层画布:

* canvas是罗盘

* topCanvas 是支持

*/

var width = this.dom.clientWidth,

height = this.dom.clientHeight;

 

// 设置容器的基本样式

this.dom.style.position = 'relative';

this.dom.style.overflow = 'hidden';

 

// 底层的画布 绘制背景

var bottomCanvas = document.createElement('canvas');

bottomCanvas.style.position = 'absolute';

bottomCanvas.style.top = 0;

bottomCanvas.style.left = 0;

bottomCanvas.width = width * 2;

bottomCanvas.height = height * 2;

bottomCanvas.style.width = width + 'px';

bottomCanvas.style.height = height + 'px';

this.dom.appendChild(bottomCanvas);

this.bottomCanvas = bottomCanvas;

 

 

// 中间层的画布 绘制罗盘

var middleCanvas = document.createElement('canvas');

middleCanvas.style.position = 'absolute';

middleCanvas.style.top = 0;

middleCanvas.style.left = 0;

middleCanvas.width = width * 2;

middleCanvas.height = height * 2;

middleCanvas.style.width = width + 'px';

middleCanvas.style.height = height + 'px';

this.dom.appendChild(middleCanvas);

this.middleCanvas = middleCanvas;

 

 

// 上层的画布 绘制指针

var topCanvas = document.createElement('canvas');

topCanvas.style.position = 'absolute';

topCanvas.style.top = 0;

topCanvas.style.left = 0;

topCanvas.width = width * 2;

topCanvas.height = height * 2;

topCanvas.style.width = width + 'px';

topCanvas.style.height = height + 'px';

topCanvas.style.transition = 'transform ease-in-out ' + this.time * 0.001 + 's';

topCanvas.style.transition = '-webkit-transform ease-in-out ' + this.time * 0.001 + 's';

topCanvas.style.transform = 'rotate(' + this.vacantAngle + 'deg)';

topCanvas.style.webkitTransform = 'rotate(' + this.vacantAngle + 'deg)';

this.dom.appendChild(topCanvas);

this.topCanvas = topCanvas;

return this;

}

}

 

 

 

 

return self;

});

posted on 2015-03-12 13:09  djawh  阅读(521)  评论(0编辑  收藏  举报

导航