使用 HTML 5 Canvas 的圆形菜单






4.59/5 (6投票s)
使用 HTML 5 Canvas 的圆形菜单
引言
本技巧的目的是演示如何使用 HTML5 Canvas 创建圆形菜单。在使用 HTML 5 之前,我们使用屏幕位置和图像来表示圆形菜单,并且可能需要更多的工作才能创建如下所示的菜单。
本技巧中的代码仅适用于最新的浏览器(已使用 Internet Explorer 11 和 Chrome 进行测试)。
背景
本文的灵感来自我之前使用 WPF 技术编写的另一篇文章。
要了解 HTML5 Canvas ARC 函数,请访问以下链接
Using the Code
代码结构如下- HTML 文件 - 此文件包含
canvas
元素 - circularmenu.js - 创建菜单所需的逻辑
- JQuery 库
从 HTML 开始,我们需要一个“canvas
”元素,并将其包装在“div
”中,如下所示。
<div id="popUp"
style="position:absolute;display:none;width:300px;height:300px;z-index:9000">
<canvas id="myCanvas" width="150" height="150">
</canvas>
</div>
有了 canvas
之后,我们可以使用 JavaScript 将菜单连接到任何 HTML 元素的事件,如下所示。 在此示例中,我使用了元素 (id=showround
) 的 click 事件。
<span id="showRound" style="cursor:pointer">Circular Menu</span>
$(function () {
var dataSource = [ {'key': '1', 'value': 'File', 'color' : 'red'},
{'key': '2', 'value': 'Open', 'color': 'green'},
{'key': '3', 'value': 'Edit', 'color': 'blue'},
{'key': '4', 'value': 'Save', 'color': 'brown'}
];
var pie = new Pie.Menu('popUp', dataSource); //Create the menu object
pie.click(function (data) { //Hooking the callback function during click event
alert(data.key + ' => ' + data.value);
});
$('#showRound').on("click", function (event) {
pie.showMenu(event);
})
}
);
在上面的函数中,我正在创建一个“Pie.Menu
”对象,并将 2 个参数传递给它的构造函数,即传递包含 canvas
的“div
”标签容器和数据数组。 每个数据对象都应该有 key、value 和 color,这些将由“Pie.Menu
”对象使用。 一旦我们有了该对象,就分配一个回调函数,当用户点击 Arc 时将调用该函数。
让我们深入了解位于 *circularmenu.js* 中的“Pie.Menu
”的细节。 它有两个主要功能
measure
- 进行必要的计算draw
- 进行实际的绘制。上述函数将在“showRound
”的 click 事件期间被调用
“measure”做什么?
此函数执行所有数学运算,以确定绘制所需的弧测量。 例如,假设数据源(在构造函数中传递)有 4 个对象。 那么每个弧角为 360 / 4 = 90。一旦我们有了弧角,就可以确定每个弧的起点和终点,如下所示
for (var i = 0 ; i < count; i++) {
var dSource = this.dataSource[i];
var sAngleDeg = angle * i; //Angle of Arc's starting point in Deg
var eAngleDeg = angle * (i + 1); //Angle of Arcs's end point in Deg
var sAngleRad = sAngleDeg * Math.PI / 180; //Angle of Arc's starting point in Radian
var endAngleRad = eAngleDeg * Math.PI / 180; //Angle of Arcs's end point in Radian
var tArc = new Pie.Arc(sAngleRad, endAngleRad, dSource.key, dSource.color);
tArc.arcText = generateArcText(sAngleDeg, eAngleDeg, dSource.value, this.radius, this.thickness, this.width / 2);
this.arcs.push(tArc);
}
“Pie.Arc
”是一个辅助对象,用于保存 Arc
信息。“Pie.Menu
”具有数组属性以保存每个 Arc
。
“Pie.ArcText
”是一个辅助对象,用于保存 Text
信息。“Pie.Arc
”具有数组属性以保存每个文本。
“draw”函数做什么?
此函数迭代“Pie.Arc
”数组并在画布上绘制弧线,如下所示。
for (var i = 0; i < this.arcs.length; i++) {
var tArc = this.arcs[i];
ctx.beginPath();
ctx.arc(this.width / 2, this.height / 2, this.radius, tArc.sAngle, tArc.eAngle);
ctx.lineWidth = this.thickness;
ctx.strokeStyle = tArc.color;
ctx.stroke();
ctx.closePath();
drawText(ctx, tArc);
}
ARC 点击功能
Canvas
元素可以监听 click 事件,该事件进一步调用我们使用“Pie.Menu
”对象注册的回调函数。 但是,我们需要限制仅当鼠标位于 Arc
上时才触发该函数,而不应在 Arc
外部触发。 这是通过使用内置函数“Math.atan2
”将事件点转换为 Angle
并与存储的每个弧的角度进行比较来实现的,如下所示
var pos = findPos(this);
var x = event.pageX - pos.x;
var y = event.pageY - pos.y;
var vX = x - pie.center;
var vY = y - pie.center;
var tR = Math.sqrt(vX * vX + vY * vY) //r * r = x * x + y * y
if (tR >= 60 - pie.thickness / 2 && tR <= 60 + pie.thickness / 2) {
var degRad = Math.atan2(vY, vX); //Convert point to angle
if (degRad < 0) {
degRad = 2 * Math.PI + degRad;
}
for (var i = 0; i < pie.arcs.length; i++) {
var arc = pie.arcs[i];
var tmpStartRad = arc.sAngle;
var tmpEndRad = arc.eAngle;
if (tmpStartRad < 0)
tmpStartRad = 2 * Math.PI + tmpStartRad;
if (tmpEndRad < 0)
tmpEndRad = 2 * Math.PI + tmpEndRad;
if (degRad >= tmpStartRad && degRad <= tmpEndRad) {
//alert(pie.dataSource[i].value);
pie.callback(pie.dataSource[i]);
break;
}
}
}
最后,我将 canvas "mouse move" 连接起来,以便在用户将鼠标悬停在 Arc
上时将光标更改为手形。