用户可选权重的HTML5六维蛛网图的实现(Tony原创)

首先,我得说一下这个功能的需求:

用户通过点击蛛网图上的点可以改变图中的绿色覆盖物的形状,这样可以通过这个蛛网图获得用户选择的维度的权重,效果图如下:

spider

接下来就是完成这个Canvas的思路了:

1. 我们首先要画5个六边形,我们必须先确定这个六边形的边长,通过边长计算出每个顶点的坐标,从而根据坐标来画出图形。画的过程中,通过canvas的fill方法,因为canvas的透明效果是叠加的,所以设置上下文中的fillStyle就可以实现每个六边形背景颜色的渐变效果了。

2. 将六边形对角的三对顶点连接起来,这样就出现了蛛网。

3. 给每个顶点都画上圆点,以每个顶点为圆心,画一个固定半径的小圆。

4. 添加绿色覆盖物,初始的时候放在每个维度都等于3的点上,然后填充颜色,添加透明效果。

5. 给canvas添加鼠标点击响应事件,通过鼠标的点击,获取鼠标当前点击的坐标,然后遍历5个六边形的所有顶点,通过计算现在点击的坐标与每个顶点之间的距离,判断是否小于等于这个小圆的半径就可以得出用户是否点击了这个小圆,如果用户点击了这个小圆,那么我们就要对整个canvas进行刷新,也可以叫做重绘,把变化的绿色覆盖物的形状画上去。

现在来说说代码,我将canvas的高度、宽度、六边形边长和小圆的半径放在顶部,方便大家配置大小。这里值得注意的是程序需要判断浏览器的类型,因为IE和firefox的offset和layer属性需要减去当前标签到浏览器左上角的距离,而谷歌和safari是不需要管这个标签的外部距离的。

demo地址:http://www.tonitech.com/demo/spider-map

以下是具体的代码:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>用户可选权重的HTML5六维蛛网图demo</title>
<script type='text/javascript' src='../jquery-1.8.3.min.js'></script>
</head>
<body style = "margin:100px">
<input type="text" value="" id="val" />
<script type="text/javascript">
//配置
var height = 400; //canvas的高度
var width = 400; //canvas的宽度
var edgeLength = 100; //六边形的边长
var pointRadius = 6; //小圆的半径
document.write('<canvas id="myCanvas" width="' + width + '" height="' + height + '" style="border:1px solid #c3c3c3;">');
</script>
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
//传入canvas的宽度和高度还有六边形的边长,就可以确定一个六边形的六个点的坐标了
function getHexagonPoints(width, height, edgeLength)
{
	var paramX = edgeLength * Math.sqrt(3) / 2;
	var marginLeft = (width - 2 * paramX) / 2;
	var x5 = x6 = marginLeft;
	var x2 = x3 = marginLeft + paramX * 2;
	var x1 = x4 = marginLeft + paramX;

	var paramY = edgeLength / 2;
	var marginTop = (height - 4 * paramY) / 2;
	var y1 = marginTop;
	var y2 = y6 = marginTop + paramY;
	var y3 = y5 = marginTop + 3 * paramY;
	var y4 = marginTop + 4 * paramY;

	var points = new Array();
	points[0] = [x1, y1];
	points[1] = [x2, y2];
	points[2] = [x3, y3];
	points[3] = [x4, y4];
	points[4] = [x5, y5];
	points[5] = [x6, y6];
	return points;
}

//画六个六边形
function drawHexagon(sixParam) 
{
	for (var i = 0; i < 6; i++) {
		allPoints[i] = getHexagonPoints(width, height, sixParam - i * sixParam / 5);
		ctx.beginPath();
		ctx.fillStyle = "rgba(0,0,0,0.2)";
		ctx.moveTo(allPoints[i][5][0],allPoints[i][5][1]); //5
		for (var j = 0; j < 6; j++) {
			ctx.lineTo(allPoints[i][j][0],allPoints[i][j][1]); //1
		}
		ctx.stroke();
		ctx.closePath();
		ctx.fill();
	}
}

//画交叉的线
function drawLines() 
{
	ctx.beginPath();
	for (var i = 0; i < 3; i++) {
		ctx.moveTo(allPoints[0][i][0],allPoints[0][i][1]); //1-4
		ctx.lineTo(allPoints[0][i+3][0],allPoints[0][i+3][1]); //1-4
		ctx.stroke();
	}
	ctx.closePath();
}

//画覆盖物
function drawCover()
{
	ctx.beginPath();
	ctx.fillStyle = "rgba(50,188,125,0.5)";
	ctx.moveTo(coverPoints[5][0],coverPoints[5][1]); //5
	for (var j = 0; j < 6; j++) {
		ctx.lineTo(coverPoints[j][0],coverPoints[j][1]);
	}
	ctx.stroke();
	ctx.closePath();
	ctx.fill();
}

//描点
function drawPoints(pointRadius) 
{
	ctx.fillStyle="#808080";
	for (var i = 0; i < 5; i++) {
		for (var k = 0; k < 6; k++) {
			ctx.beginPath();
			ctx.arc(allPoints[i][k][0],allPoints[i][k][1],pointRadius,0,Math.PI*2);
			ctx.closePath();
			ctx.fill();
		}
	}
}

//判断用户点击的位置是否在小圆的范围内
function judgeRange()
{
	for (var i = 0; i < 5; i++) {
		for (var k = 0; k < 6; k++) {
			var distance = Math.sqrt((mx - allPoints[i][k][0]) * (mx - allPoints[i][k][0]) + (my - allPoints[i][k][1]) * (my - allPoints[i][k][1]));
			if (distance <= pointRadius) {
				clickPoints[k] = 5 - i;
				//将变化的值显示出来
				$('#val').val(clickPoints);
				//清空
				ctx.clearRect(0, 0, width, height);
				//重绘
				drawHexagon(edgeLength); 
				drawLines();
				//给覆盖物确定变化
				coverPoints[k] = allPoints[i][k];
				drawCover();
				drawPoints(pointRadius);
				return;
			}
		}
	}
}

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var allPoints = [];
var clickPoints = [2, 2, 2, 2, 2, 2];
var mx,my;
drawHexagon(edgeLength); 
drawLines();
//初始化覆盖物
var coverPoints = allPoints[3];
drawCover();
drawPoints(pointRadius);
$(function(){
	//显示用户选择的权重
	$('#val').val(clickPoints);
});

this.mousedown = function(e) {
	//判断浏览器的类型,IE和firefox的offset和layer属性需要减去当前标签到浏览器左上角的距离的。
	if (isFirefox = navigator.userAgent.indexOf("Firefox") > 0 || navigator.userAgent.indexOf("MSIE") > 0) {  
		if (e.layerX || e.layerX == 0) {
			mx = e.layerX - c.offsetLeft;
			my = e.layerY - c.offsetTop;
		} else if (e.offsetX || e.offsetX == 0 ){
			mx = e.offsetX - c.offsetLeft;
			my = e.offsetY - c.offsetTop;
		}
	} else {
		if (e.layerX || e.layerX == 0) {
			mx = e.layerX;
			my = e.layerY;
		} else if (e.offsetX || e.offsetX == 0 ){
			mx = e.offsetX;
			my = e.offsetY;
		}
	}
	judgeRange();
};
c.addEventListener('mousedown', this.mousedown, false); //添加鼠标点击监听事件
</script>
</body>
</html>

 

Tonitech版权所有 | 转载请注明出处: http://www.tonitech.com/1977.html

《用户可选权重的HTML5六维蛛网图的实现(Tony原创)》有11个想法

发表评论