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

为 Windows 应用商店应用创建自定义控件 (Javascript- WinJS)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2014 年 6 月 26 日

CPOL

4分钟阅读

viewsIcon

15857

WinJS 自定义控件,用于绘制/绘制简单的甜甜圈图表

引言

Windows Library for JavaScript (WinJS) 是一个 CSS 和 JavaScript 文件的库。它包含 JavaScript 对象,组织成命名空间,旨在使使用 JavaScript 开发 Windows Store 应用程序更容易。 WinJS 包含帮助您处理激活、访问存储以及定义您自己的类和命名空间的对象。它还包括一组控件,如 AppBarListViewRatingTimePicker 等。

尽管有很多有用的控件,但它们并不能满足所有需求(例如:用于绘制简单图形、树视图、动画等的通用控件),是时候让我们开发这样的自定义控件了,让我们了解如何操作。

问题定义

让我们考虑一个简单的问题,需要绘制一个甜甜圈图表来显示我们的 Windows Store App 中的百分比 (%) 值,并且它应该能够绑定到 ViewModel 属性。

这就是我们的最终图表的样子

Donut Graph

解决方案

首先。

在 HTML 页面中包含 WinJS 引用,因为我们的控件将使用这些文件中的 API。

<script src="//Microsoft.WinJS.1.0/js/base.js"></script>
<script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

创建自定义 WinJS 控件的几个简单步骤如下

  • 定义控件的 命名空间
  • 初始化控件并定义控件选项(在类构造函数中)
  • 实现绘制甜甜圈图表的代码(我们将使用 HTML5 Canvas
  • 在 HTML/JavaScript 中使用控件。

定义控件的命名空间和类

WinJS 提供 API 用于在 JavaScript 中创建 命名空间,我们将使用相同的 API 来创建我们自己的。

WinJS.Namespace.define()WinJS.Class.define() 分别用于创建 命名空间

WinJS.Namespace.define("Demo.UI", {
    DonutChart: WinJS.Class.define(function (element, options) {
       // Constructor: here we will validate the DOM element, define options and more.
       this.element = element || document.createElement("div");
    },{
       // Properties: here we will declare and define the properties, 
       // private methods and core logic lies here i.e. code to create graph in our case.
       donutValue: {
                    get: function () {
                        return this._donutValue;
                    },
                    set: function (value) {                       
                        this._donutValue = value;
                    }
    }// End of Properties
) // End of Control class definition
}); // End of Namespace definition 

构造函数将接受两个参数 element 和 options,其中 element 是 Element 对象,我们可以根据我们的控件配置 options,例如我们的 radius。现在,我们已经准备好使用我们的 命名空间 了。

初始化控件并定义控件选项

在构造函数中,我们必须验证元素是否存在。如果元素不存在,创建一个元素(在本例中为“div”)并将一组以声明方式指定的选项(属性和事件)添加到控件中。这是使用 WinJS.UI.setOptions() 方法实现的,此方法调用会覆盖控件上可配置选项的默认值。

function MyControl(element, options) {
                this.element = element || document.createElement("div");
                this.element.winControl = this;
                this.options = options;
                // Set option defaults
                this._donutValue = 0;
                // Set user-defined options
                WinJS.UI.setOptions(this, options);
 
                element.textContent = options.donutValue;	// If it fails to plot graph 
								// then display only text
            }

实现绘制甜甜圈图表的代码

我们将使用 HTML5 的一个很棒的功能 Canvas 来绘制图形,将在 _createDonut() 方法中创建甜甜圈图表 [注意_createDonut 被设置为 private 方法,因此不应在控件外部使用此方法]。我们可以在此方法中创建任意数量的 HMTL 元素和逻辑。

这是我们使用 Canvasarc 方法绘制圆(即甜甜圈图表)的代码片段。

_createDonut: function () {
                    var settings = $.extend({
                        // These are the defaults.
                        color1: '#808080',
                        color2: '#107c10',
                        textColor: '#808080',
                        backgroundColor: "transparent",
                        radius: 20,
                        lineWidth1: 1,
                        lineWidth2: 5,
                        donutValue: 0
                    }, this.options);
                    if (this.donutValue > 0) {
                        try{
                            settings.donutValue = this.donutValue;
                            var percentage = settings.donutValue / 100;
                            var id = this.element.getAttribute("id") + "_canvas";
                            var width = this.element.offsetWidth;
                            var height = this.element.offsetHeight;
                            this.element.innerHTML = "";
                            this.element.innerHTML = "<canvas id='" + id + "' 
                            width='" + width + "' height='" + 
                            height + "'></canvas>";
                            var c = document.getElementById(id);
                            var ctx = c.getContext("2d");
 
                            var centerX = c.width / 2;
                            var centerY = c.height / 2;
                            radius = width > height ? height * 0.455 : width * 0.455;
                            //Inner circle
                            ctx.beginPath();
                            ctx.strokeStyle = settings.color1;
                            ctx.lineWidth = settings.lineWidth1;
                            ctx.arc(centerX, centerY, radius, 0 * Math.PI, 2 * Math.PI);
                            ctx.stroke();
                            //Outer Circle
                            ctx.beginPath();
                            ctx.lineWidth = settings.lineWidth2;
                            ctx.strokeStyle = settings.color2;
                            ctx.arc(centerX, centerY, radius, 1.5 * Math.PI, 
                            (1.5 + (2 * percentage)) * Math.PI) //calculating the end angle for arc
 
                            ctx.stroke();
                            //Display text
                            ctx.font = "15px Segoe UI";
                            ctx.fillStyle = settings.textColor;
                            ctx.fillText(settings.donutValue + "%", centerX - 14, centerY + 5);
 
                            clearInterval(this.terminateInterval);
                        }
                        catch (ex) {
                            clearInterval(this.terminateInterval);
                        }
                    }
                    else {
                        this.element.innerHTML = 
                        "<span style='color:black; text-align:center;'>---</span>";
                    }
                }

假设控件给定一个空的 div 元素,在我们的代码中,我们将动态创建一个 Canvas 元素并将其附加到给定的 div 元素。我们使用 JQuery $.extend() 方法将默认选项映射到从 UI 配置的选项。

把这些组合在一起

WinJS.Namespace.define("Demo.UI", {
    DonutChart: WinJS.Class.define(function (element, options) {
       // Constructor: here we will validate the DOM element, define options and more.
       this.element = element || document.createElement("div");
       this.element.winControl = this;
       this.options = options;
       // Set option defaults
       this._donutValue = 0;
       // Set user-defined options
this.terminateInterval = 0;
       WinJS.UI.setOptions(this, options);
element.textContent = options.donutValue;   
    },{
       // Properties: here we will declare and define the properties, 
       // private methods and core logic lies here i.e. code to create graph in our case.
_notZero: 0,
       donutValue: {
                    get: function () {
                        return this._donutValue;
                    },
                    set: function (value) {                        
                           if (this._donutValue > 0) {
                                  clearInterval(this._notZero);
                        }
                           this._donutValue = value;
                           this._notZero = setInterval(this._createDonut.bind(this), 1000);
//I'm using setInterval here because the data for this control is from a ajax request 
//and since WinJS will process the UI even before ajax request is completed so we will call 
//_createDonut() methos in a interval and once data is available clear the Interval.
                       this.terminateInterval = this._notZero;
                        }
},
_createDonut: function () {
              //Copy from above
}
    }// End of Properties
) // End of Control class definition
}); // End of Namespace definition

在 HTML/JavaScript 中使用控件

现在,我们已经创建了所有必要的代码,并且将其保存在例如 *demo.ui.donutchart.js* 中,让我们看看如何在我们的 HTML 中使用它。

包含对 *demo.ui.donutchart.js* 脚本文件的引用

<script src="../../js/customcontrols/demo.ui.donutchart.js"></script>

在 HTML 中,使用 data-win-control 属性设置控件名称 Demo.UI.DonutChart,使用 data-win-options 属性设置提供给构造函数的选项(示例:{ radius: 20, color2: '#107c10' }),并使用 data-win-bindViewModel 属性绑定数据。

所以我们的 HTML 将是

<div id="donut" data-win-bind="winControl.donutValue:AvgPercent " 
data-win-control="Demo.UI.DonutChart" data-win-options="{ radius: 20,  color2: '#107c10' }"></div>

现在,问题是这如何调用控件构造函数并绘制图形。

答案是,当从我们的代码中调用 WinJS.UI.processAll() 方法时 [通常,此方法将在 Windows Store App 解决方案的 *default.js* 中调用]。 WinJS 将解析 DOM,如果找到控件,WinJS 将自动完成控件和 HTML 之间的映射,即 WinJS 将实例化控件并使用创建图表的元素和 data-win-options 中提供的选项作为参数调用构造函数。

最后一件事情,我们将使用 WinJS.Binding.processAll(document.getElementById("container"), ViewModel); 将数据绑定到页面或元素。

现在调试/部署应用程序,我们可以在屏幕上看到所需的图形。

参考文献

© . All rights reserved.