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





5.00/5 (1投票)
WinJS 自定义控件,用于绘制/绘制简单的甜甜圈图表
引言
Windows Library for JavaScript (WinJS) 是一个 CSS 和 JavaScript 文件的库。它包含 JavaScript 对象,组织成命名空间,旨在使使用 JavaScript 开发 Windows Store 应用程序更容易。 WinJS 包含帮助您处理激活、访问存储以及定义您自己的类和命名空间的对象。它还包括一组控件,如 AppBar
、ListView
、Rating
、TimePicker
等。
尽管有很多有用的控件,但它们并不能满足所有需求(例如:用于绘制简单图形、树视图、动画等的通用控件),是时候让我们开发这样的自定义控件了,让我们了解如何操作。
问题定义
让我们考虑一个简单的问题,需要绘制一个甜甜圈图表来显示我们的 Windows Store App 中的百分比 (%) 值,并且它应该能够绑定到 ViewModel
属性。
这就是我们的最终图表的样子
解决方案
首先。
在 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 元素和逻辑。
这是我们使用 Canvas
的 arc
方法绘制圆(即甜甜圈图表)的代码片段。
_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-bind
从 ViewModel
属性绑定数据。
所以我们的 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);
将数据绑定到页面或元素。
现在调试/部署应用程序,我们可以在屏幕上看到所需的图形。