65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 HTML 5 Canvas 的圆形菜单

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (6投票s)

2014年10月25日

CPOL

2分钟阅读

viewsIcon

23218

downloadIcon

337

使用 HTML 5 Canvas 的圆形菜单

引言

本技巧的目的是演示如何使用 HTML5 Canvas 创建圆形菜单。在使用 HTML 5 之前,我们使用屏幕位置和图像来表示圆形菜单,并且可能需要更多的工作才能创建如下所示的菜单。

本技巧中的代码仅适用于最新的浏览器(已使用 Internet Explorer 11 和 Chrome 进行测试)。

背景

本文的灵感来自我之前使用 WPF 技术编写的另一篇文章。

要了解 HTML5 Canvas ARC 函数,请访问以下链接

Using the Code

代码结构如下
  1. HTML 文件 - 此文件包含 canvas 元素
  2. circularmenu.js - 创建菜单所需的逻辑
  3. 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”的细节。 它有两个主要功能

  1. measure - 进行必要的计算
  2. 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 上时将光标更改为手形。

© . All rights reserved.