CSS-Windows8-应用开发教程-四-

95 阅读1小时+

CSS Windows8 应用开发教程(四)

原文:CSS for Windows 8 app development

协议:CC BY-NC-SA 4.0

十、替代和定义样式

image 注意你已经了解了 CSS 以及它是如何在 Windows 8 应用中实现的。现在是时候开始创建你自己的风格,覆盖和扩展 WinJS 提供的风格,让你的应用程序有自己的个性,同时符合微软的设计原则。

这一章的目标是学习如何按照我们的需要来设计我们的应用程序。好的设计不完全是客观的,但是有很多原则适用,当然也有很多围绕好的 Windows 8 设计的原则可以极大地促进你的应用程序的成功。

为了控制我们的应用程序中的 UI,我们将首先找到 WinJS 样式表中定义的应用于我们的应用程序中的元素的样式规则,然后我们将覆盖这些规则中定义的样式属性,或者我们将添加自己的属性来扩展它们。此外,我们将创建自己的样式规则,应用于页面上的元素或者我们编写的自定义控件。

定位样式选择器

在我们可以覆盖和扩展 WinJS 中定义的样式规则之前,我们必须找到影响相关视觉元素的一个或多个规则。有这么多的规则,这不是一个微不足道的任务。

我们已经看到,WinJS 为我们提供了丰富的样式,这就是为什么在没有任何样式代码的情况下,我们从一个看起来像 Windows 8 应用程序的应用程序开始。WinJS 库中的样式不仅数量众多,而且有些还相当长。清单 10-1 显示了在ui-light.css样式表中可以找到的许多样式规则选择器中的两个。第一个简单地选择了一个按钮,但是第二个显示了它们可以变得多具体,并且为列表视图中没有“selection style filled”的选定的、悬停的容器选择了选择边框。

清单 10-1 。一个非常简单和一个非常复杂的风格选择器

button {
   ...
}

.win-listview:not(.win-selectionstylefilled)
    .win-container.win-selected:hover .win-selectionborder {
   ...
}

如果没有 DOM Explorer 中的 Trace Style 窗格的帮助,发现在哪里以及如何应用样式规则将是一项充满猜测的艰巨任务。它将原本痛苦的任务变成了无痛的任务。

让我们通过一个练习来发现相关的风格规则。首先,我们将寻找影响 ListView 控件的规则。

练习 10-1:在列表视图中定位选择边框

当您在 ListView 中选择一个项目时,您会得到一些视觉指示器,让您知道您已经选择了一个项目。您可以在 ListView 上设置属性,以确定用户是否可以选择零个、一个或多个项目。在本练习中,我们将深入研究动态 DOM,并找到决定 ListView 的选择边框和复选标记的样式规则。毕竟,如果我们要改变他们,我们必须找到他们。

清单 10-2 恢复了第七章中的一个列表视图示例。在图 10-1 中,注意列表项 5 上的边框、角填充和勾号。

清单 10-2 。这里有一些你以前在第七章中见过的代码。这是一个绑定到一系列数字的列表视图。

<!-- HTML snippet -->

<div id="list" data-win-control="WinJS.UI.ListView"></div>

<div id="template" data-win-control="WinJS.Binding.Template">

<div class="grid">

<div data-win-bind="innerText:this"></div>

</div>

</div>

/* CSS snippet */

.win-listview {

height: 100%;

}

.win-listview .win-item .grid {

display:-ms-grid;

-ms-grid-rows:160px;

-ms-grid-columns:160px;

background-color:gray;

color:white;

}

.win-listview .win-item .grid div {

font-size: 36px;

font-weight: bold;

-ms-grid-column-align: center;

-ms-grid-row-align: center;

}

//JavaScript snippet

var numbersList = new WinJS.Binding.List();

var list = document.querySelector("#list").winControl;

list.itemTemplate = document.querySelector("#template");

list.itemDataSource = numbersList.dataSource;

for (var i = 1; i <= 11; i++) {

numbersList.push(i);

}

9781430249832_Fig10-01.jpg

图 10-1 。右键单击第五个项目后,可以看到选择样式

该图块的这些额外功能之所以存在,是因为该项已被选中。我们知道所选项目的样式将会在 WinJS 库中,并且因为我们已经选择在这个页面上使用ui-light.css文件,所以我们知道它将会在那个文件中。让我们看看这个边框和复选标记是在样式表中什么地方定义的,这样我们就有希望修改它们。

在本练习中,您可以使用本书附带的示例项目,该项目可在www.apress.com/9781430249832http://codefoster.com/cssbookcode获得。

  1. Run the app in debug mode by pressing F5.

    当您按下F5或选择 Debug | Start Debugging 时,您的应用程序就会启动,Visual Studio 会将其调试工具与其相关联,并为您提供 DOM Explorer。你应该在 Visual Studio 中看到类似图 10-2 的东西。

    9781430249832_Fig10-02.jpg

    图 10-2 。当 Visual Studio 2012 在调试模式下运行时,非常有用的 DOM Explorer 始终可用(但仅适用于 HTML/JS 应用程序)

  2. 在运行的应用程序中,导航到第十章的部分,然后导航到清单 10-2 。

  3. 通过右键单击选择项目编号 5。

  4. Switch to Visual Studio and press the Select Element button (CTRL + B) at the top of the DOM Explorer.

    Visual Studio 应该会将您切换到正在运行的应用程序,您应该会注意到,将鼠标悬停在元素上方会以蓝色突出显示它们,以便更容易选择您想要的目标。

  5. Click on the selected ListView item.

    选择目标元素应该会将您带回 Visual Studio 中的 DOM Explorer,您选择的元素会在 DOM 中突出显示,并允许您查看定义元素的 HTML 标记。它是 live DOM,因此它不局限于您在开发中在.html文件中创作的 HTML,而是甚至包括可能已经在运行时以编程方式附加的 DOM 元素。这让人松了一口气,因为几乎整个 ListView 都是由 WinJS 在运行时创建的。记住,我们在标记中声明 ListView 所做的只是<div data-win-control="WinJS.UI.ListView"></div>

    顺便说一句,如果您不能直接单击您感兴趣的元素,您可以尝试只在它附近单击,然后通过在 DOM Explorer 中手动导航 DOM 来完成对确切元素的定位。

  6. Locate the div with a class value of win-selectionbordercontainer, expand it, and select one of its child elements.

    当您选择 ListView 项目时,您被带回 Visual Studio,并且很可能 DOM 中突出显示的元素是<div class="grid">,再往下一点,您应该会看到添加了更多的div元素(当您选择项目编号 5 时),其中一个元素有一个类win-selectionbordercontainer

    如果您展开这个div,您会发现它有四个单独的div元素组成了所选项目的边框。选择其中一个。图 10-3 应该清楚地表明选择哪个元素。

    9781430249832_Fig10-03.jpg

    图 10-3 。win-selectionbordercontainer 仅在选择项目时出现在 DOM 中

  7. Select the Trace Styles tab in the right pane of the DOM Explorer.

    您应该会看到一个影响所选元素的所有样式属性的列表,该列表应该类似于图 10-4 。

    9781430249832_Fig10-04.jpg

    图 10-4 。应用于所选对象的所有样式及其值和跟踪信息都显示在 DOM Explorer 的“跟踪样式”窗格中

    在查找颜色的来源时,Visual Studio 做的一件非常有用的事情是在“跟踪样式”窗格中的值旁边呈现一个小的正方形颜色样本。我意识到当你读到这里的时候,图 10-4 可能会以灰度呈现,但是请相信我,它显示的颜色和我们在图 10-1 中所选项目周围看到的颜色是一样的。因此,看起来我们已经找到了样式属性的来源。

  8. 展开其中一个边框颜色属性以查看原点。

例如,当你扩展border-left-color属性时(通过点击它旁边的小三角符号),你会看到类似于图 10-5 的东西。

9781430249832_Fig10-05.jpg

图 10-5 。“跟踪样式”窗格不仅显示样式规则的值,还显示它的定义位置

最右边的一列告诉我们这个样式规则已经在ui-light.css文件中定义了。我们可能已经猜到了,因为我们的大部分规则都在里面。单击文件名将在 Visual Studio 中启动该文件。如果您尚未安装 Visual Studio 2012 Update 1,您将被带到该文件,但不幸的是,您不会直接导航到样式规则。但是,安装了 Update 1 后,您将直接进入有问题的规则。您不能依赖的一件事是跟踪样式窗格和实际 CSS 文件之间的样式规则是一字不差的。有时类和伪类选择器的顺序会被重新安排。我发现图 10-5 中的样式规则来源于ui-light.css的 2250–2252 行:

win-listview:not(.win-selectionstylefilled) .win-container.win-selected .win-selectionborder {

border-color: rgb(70, 23, 180);

}

找到了所选 ListView 项目具有边框颜色rgb(70, 23, 180)(深紫色)的来源和原因,我们就有了覆盖该边框颜色或向其添加其他属性所需的工具。

然而,在我们开始覆盖和添加属性之前,让我们再看一个样式规则位置的练习。

练习 10-2:定位进度元素的填充颜色

在本练习中,我们将找到赋予progress元素填充颜色的样式规则。清单 10-3 和产生的图 10-6 显示了这些简单的进度元素之一。你可以看到进度值左边的区域默认填充了我们在 ListView 中发现的选择矩形的颜色:深紫色。

清单 10-3 。一个简单的进度标签填充到 60%

<!-- HTML snippet -->

<progress value="60" max="100"></progress>

9781430249832_Fig10-06.jpg

图 10-6 。填充区域用颜色表示,而未填充区域是浅灰色

在这个练习中,遵循你在练习 10-1 中使用的相同步骤,你应该得到一个看起来像图 10-7 的跟踪样式窗格。

9781430249832_Fig10-07.jpg

图 10-7 。“跟踪样式”窗格还指示哪些样式已被覆盖。如果您希望应用一种样式,但不知道哪一个规则覆盖了它,这将非常有帮助

如图 10-7 所示,扩展颜色属性揭示了与上一个练习有些不同的东西。有两条规则,第一条被删除了。这表明第一个样式规则在该元素上生效,但是后来(在样式表的后面)被另一个更具体的或后续的规则覆盖。回想一下第三章中的内容,这种有意的样式级联是 CSS 的一个正常功能,跟踪样式窗格非常有助于告诉我们哪些规则被应用了,哪些没有,以及为什么。

单击有问题的规则旁边的样式表链接,将我们带到ui-light.css文件中的第 2172–2175 行,它们是:

progress {

background-color: rgba(0, 0, 0, 0.2);

color: rgb(70, 23, 180);

}

我们再次找到了罪魁祸首。这个样式规则不仅确定填充颜色是相同的深紫色,而且确定背景颜色(未填充部分的颜色)是 20%不透明度的黑色。

覆盖和扩展样式

WinJS 自带的样式表是烤出来的。它们是只读的,不建议也没有必要考虑更改它们。相反,您应该覆盖并扩展内置样式。

覆盖样式

在前面的练习中,我们学习了如何找出影响 UI 中某个元素的样式规则,这很重要。重要的是要知道为什么有些元素看起来像它们的样子或者被放置在它们的位置。在ui-light.css样式表中定位样式规则似乎无关紧要,因为该文件是只读的,我们没有希望对其进行修改。

确实我们不能(或者至少不应该!)改变 WinJS 样式表中的样式,但是我们能够改变特定元素的外观,我们通过覆盖规则中的样式属性来实现。

请记住,WinJS 样式表是在所有其他样式表之前定义的。清单 10-4 展示了一个典型的 HTML 文件的<head>在 Windows 8 应用程序中的样子。

清单 10-4 。来自 Windows 8 HTML 页面的典型< head >部分,显示了样式表被引用的顺序


<head>
    <meta charset="utf-8" />
    <title>Lorem Ipsum</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <link href="lorem.css" rel="stylesheet" />
    <script src="lorem.js"></script>
</head>

首先声明的是ui-light.css样式表,随后是仅适用于该页面的lorem.css样式表。这意味着假设特异性相同或更高,我们在lorem.css中定义的样式规则中的属性将覆盖来自ui-light.css的样式规则中的属性。

如果你还不清楚第三章中的特异性这个话题,你可能会想重温一下,因为这是它出现的地方。如果ui-light.css使用比lorem.css中的规则更具体的样式规则来设置属性,那么前者将获胜,并且没有覆盖。

这意味着我们可以简单地在本地 CSS 文件中编写一个样式规则(在前面的例子中为lorem.css),匹配已经存在的样式规则的选择器,并期望样式规则中的属性覆盖ui-light.css中的属性。你可以在清单 10-5 中看到这样的例子。

清单 10-5 。下面的进度规则与 WinJS 样式表中已存在的规则选择器相匹配。不过,定义的属性在 WinJS 样式表之后,所以我们可以预期它们会被覆盖。

<!-- HTML snippet -->
<progress value="60" max="100"></progress>

/* CSS snippet */
progress {
    background-color: gray;
    color: lightgray;
}

正如你在图 10-8 中看到的,我们的覆盖相当于反转了进度条 ?? 的颜色。填充区域现在更亮(lightgray),未填充区域现在更暗(gray)。

9781430249832_Fig10-08.jpg

图 10-8 。正如所料,填充颜色是浅灰色,背景(未填充)现在更深了

可以将术语important!(包括感叹号)添加到样式属性中,以强制发生覆盖,即使特异性值已经以其他方式确定。

清单 10-6 显示了一个 HTML 段落,它有两个似乎都适用的样式规则。但是,在特异性方面,ID 选择器胜出,所以即使.error样式规则在#footerText规则之后,它也不会有任何影响。

清单 10-6 。两个样式规则竞争设置元素的文本颜色

<!-- HTML snippet -->
<p id="footerText" class="error">
    There was an error loading the file.
</p>

/* CSS snippet */
#footerText {
    color: black;
}

.error {
    color: red;
}

然而,我们可以用清单 10-7 中的强制覆盖。

清单 10-7 。两个样式规则竞相设置同一个元素

<!-- HTML snippet -->
<p id="footerText" class="error">
    There was an error loading the file.
</p>

/* CSS snippet */
#footerText {
    color: black;
}

.error {
    color: red  important! ;
}

我建议不要使用important!关键字。今天可能会产生预期的结果,但是明天你就会遇到麻烦。这是一个明确的代码味道,通常会导致糟糕的 CSS 架构,难以阅读和维护。

扩展样式

在 WinJS(或任何其他)库中定位样式规则不仅有助于我们覆盖它们定义的属性,而且有助于我们添加它们没有定义的属性。使用相同的选择器确保了我们添加的属性将总是应用于完全相同的元素,并节省了我们从头开始编写选择器的时间。

让我们再看一下 progress 控件来说明如何扩展一个样式。在清单 10-5 中,我们覆盖了一个样式属性,方法是在本地样式表中用与 WinJS 样式表相同的选择器定义一个样式规则,然后重新定义一个已经存在的属性。为了扩展样式,我们做了同样的事情,除了我们添加了最初没有定义的样式属性。

我们在清单 10-5 中重新定义的进度样式规则已经包含了一个color属性。在清单 10-8 中,我们改变了覆盖属性,给进度控件一个灰色的填充颜色和一个白色的未填充颜色,并且我们添加了一个新的属性(border),这在 WinJS 中没有定义。

清单 10-8 。除了覆盖已经存在的样式属性,我们还可以指定没有的新属性

<!-- HTML snippet -->
<progress value="60" max="100"></progress>

/* CSS snippet */
progress {
    background-color: white;
    color: gray;
    border: 1px solid gray;
}

添加灰色的实线边框给了我们的 progress 元素一个包含框,如图 10-9 所示。

9781430249832_Fig10-09.jpg

图 10-9 。边框赋予此进度指示器全新的外观

一些例子有助于了解什么样的样式覆盖和扩展在 Windows 8 应用程序中是有用的。我们已经看到了进度控制的例子。接下来我们再看两个。我们将看看:

  • 格式化范围输入元素上的滑块
  • 更改分级控制中的默认图标

格式化范围输入元素上的滑块

让我们来改变默认的范围输入元素(<input type="range"/>),使用户触摸的滑块是圆形的,其轮廓颜色与元素较低的填充颜色相匹配。图 10-10 显示了一个范围输入元素的默认外观。

9781430249832_Fig10-10.jpg

图 10-10 。范围输入元素的默认外观

“跟踪样式”窗格为我们提供了一些关于样式的有用信息,这些样式使范围输入元素看起来如此,并帮助我们知道在我们自己的样式选择器中使用什么选择器来覆盖和扩展属性并影响我们所追求的更改。清单 10-9 显示了我们应该放在本地样式表中的 CSS 来完成这个任务。

清单 10-9 。用于在范围输入上获得圆形滑块的 HTML 和 CSS

<!-- HTML snippet -->
<input type="range" />

/* CSS snippet */
input[type=range]::-ms-track {
    height:16px;
}
input[type=range]::-ms-fill-lower {
    background-color:gray;
}

input[type=range]::-ms-thumb {
    background-color:white;
    border:1px solid gray;
    height:14px;
    width:14px;
    border-radius:14px;

}

9781430249832_Fig10-11.jpg

图 10-11。对于你的应用程序的个性来说,圆形滑块可能是一个更好的设计选择

更改评级控件中的默认图标

接下来,我们将看看评级控制。与 range input 元素不同,Rating 控件是由 WinJS 提供的自定义控件。一般来说,WinJS 控件会比基本 HTML 元素更复杂,因为它们通常由大量的基本 HTML 元素组成。当深入 WinJS 控件了解如何覆盖和扩展样式时,“跟踪样式”窗格是我们最好的朋友。

我将改变默认的 5 颗星星的数量,然后我将改变图标,以摆脱无聊,旧的恒星系统。通常,评级系统使用五颗星,并要求用户从一到五进行评级。这是一个常见的系统,但假设我们正在为一家鸡肉餐馆开发一个应用程序。我们可能想给顾客一个从 1 到 10 的系统,用鸡而不是星星来评价他们的饭菜。这才是有个性的应用!

图 10-12 显示了选择了三颗星的评级控件的默认外观。

9781430249832_Fig10-12.jpg

图 10-12 。默认分级控制使用星形图标和最高分级值 5

我在http://office.microsoft.com的时候在免费的微软 Office 图片库里发现了一个小鸡图标。然后我用我最喜欢的矢量编辑工具——CorelDRAW——为图像可能出现的所有状态做了四种变化。结果如图 10-13 中的所示。

9781430249832_Fig10-13.jpg

图 10-13 。小鸡图标的四种变体,涵盖了分级控制元素可能处于的每个状态

在清单 10-10 中,我声明了一个 Rating 控件,并给了它一个任意的值 6.4 来说明控件如何显示部分值。通常averageRating的值不会被硬编码,而是从数据表中计算出来。

通过简单的搜索,很容易在ui-light.css文件中找到评级控制样式。请注意样式规则如下所示:


.win-rating .win-star:before {
    content: "\E082";
}

如果你还记得《??》第三章,那么content属性是一个有趣的属性,它通过样式化来添加内容。这就是默认分级控制获得星级的方式。如果你能找到一个合适的,你可以改变这里引用的字符,但是你也可以放弃这个字符而使用一个图像来代替。这就是我们在清单 10-10 中所做的。再看覆盖.win-rating .win-star:before的样式规则。它清除了内容值,因此省略了星形符号。

一旦星星消失了,我们可以自由地添加我们自己的图像,你可以在清单 10-10 中的样式规则中看到我们是如何做的。

清单 10-10 。把五星变成十只鸡的密码

<!-- HTML snippet -->
<div class="chicken" data-win-control="WinJS.UI.Rating"
    data-win-options="{averageRating: 6.4, maxRating: 10}"></div>

/* CSS snippet */
.win-rating.chicken .win-star:before
{
    content: ""; /*hide the default star glyph*/
}

.win-rating.chicken .win-star
{
    background-repeat: no-repeat;
    background-origin: content-box; /*to allow putting padding between chickens*/
    background-position: left;
    height: 30px;
    background-size: 100% 100%;
}

.win-rating.chicken .win-star.win-empty, .win-rating.chicken .win-star.win-tentative.win-empty
{
    background-image: urlimg/chicken_empty.svg");
}

.win-rating.chicken .win-star.win-full, .win-rating.chicken .win-star.win-tentative.win-full
{
    background-image: urlimg/chicken_full.svg");
}

.win-rating.chicken .win-star.win-disabled.win-empty
{
    background-image: urlimg/chicken_disabled_empty.svg");
}

.win-rating.chicken .win-star.win-disabled.win-full
{
    background-image: urlimg/chicken_disabled_full.svg");
}

图 10-14 显示了生成的小鸡图标。我设计的chicken_empty.svg图像看起来像一个占位符,这样用户就能清楚地知道他能选择多少种可能的鸡肉评级。

9781430249832_Fig10-14.jpg

图 10-14 。我们看到平均 10 只鸡中有 6.4 只

也有可能(尽管清单 10-10 中的代码还没有到此为止)区分用户选择的图像和代表所有用户选择的平均图像。我们可以通过向一些规则添加一个类.win-user并向其他规则添加一个类.win-average来实现。

覆盖和扩展已经定义的样式规则是非常常见的,但 WinJS 样式表实际上只是一个起点,您会发现有很多理由在您的应用程序中创建自己的样式规则。在下一节中,我们将会看到一些技巧以及一些在应用程序中定义我们自己风格的策略。

定义样式

在很多情况下,你会覆盖现有的风格,更多的情况下,你会定义自己的风格。对于您自己的样式定义,您可能正在创建简单的类规则,或者您可能正在创建您自己的整个自定义控件,包括它自己的类、它自己的默认样式,以及任何开发人员使用它来覆盖它的样式的能力,就像我们对 WinJS 库所做的那样。

在下面的每个例子中,我都将包含完整的代码清单。目标是学习 CSS 样式,并且解决方案的整个上下文应该对此有所帮助。您将在 CSS 样式中看到前缀,如.lst1011,它将 CSS 的范围限定为特定的代码清单。

ListView 中的特色项目

举个例子,假设我们正在开发一个销售点应用程序的 hub 页面,上面有两个 ListView 控件。第一个是产品列表,第二个是可能适用的折扣列表。折扣列表中的项目都是相同的,但是产品列表中的项目可能是“特色”的,以引起注意。特色项目的概念应该只适用于第一个列表。特色项目应该有一个纯灰色的背景,而所有其他非特色项目应该有一个简单的白色背景。使用 ID 选择器将样式限定在适当的列表中,使用类选择器处理特色项目。

本例中的解决方案相当简单,但是它涉及到针对产品列表(而不是折扣列表),并且在产品列表中,它涉及到区分特色产品和其他产品。显然可能有不止一个特色项目,所以我们应该使用一个类选择器。类选择器就是为此而生的。

清单 10-11 中的表示了整个解决方案,下面是对代码的解释。

清单 10-11 。在列表视图中显示项目的完整解决方案代码

<!-- lst1011.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Listing 10-11</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <link href="lst1011.css" rel="stylesheet" />
    <script src="lst1011.js"></script>
</head>
<body>
    <div class="lst1011 fragment">
        <section aria-label="Main content" role="main">

            <div id="productsList" data-win-control="WinJS.UI.ListView"></div>
            <div id="discountsList" data-win-control="WinJS.UI.ListView"></div>

            <div id="productItemTemplate" data-win-control="WinJS.Binding.Template">
                <div xsdata-win-bind="className:isFeatured
                    lst1011.Converters.isFeaturedToString;" >
                    <h3 data-win-bind="innerText:name"></h3>
                    <div data-win-bind="innerText:price" class="win-type-xx-small"></div>
                </div>
            </div>
            <div id="discountItemTemplate" data-win-control="WinJS.Binding.Template">
                ...
            </div>
        </section>
    </div>
</body>
</html>

/* lst1011.css */
.lst1011 #productsList .widget {
    width:200px;
    height:100px;
    border: 1px solid gray;
    padding:10px;
}
.lst1011 #productsList .widget.featured {
    background-color: lightgray;
}

// lst1011.js
(function () {
    "use strict";

    var products = [
        {name: "Widget 1", isFeatured: true, price: 72.99},
        {name: "Widget 2", isFeatured: false, price: 149.99},
        {name: "Widget 3", isFeatured: true, price: 14.99},
        {name: "Widget 4", isFeatured: true, price: 50.99},
        {name: "Widget 5", isFeatured: false, price: 71.99},
        {name: "Widget 6", isFeatured: false, price: 65.99},
        {name: "Widget 7", isFeatured: false, price: 66},
        {name: "Widget 8", isFeatured: false, price: 165.99},
        {name: "Widget 9", isFeatured: true, price: 60.99},
        {name: "Widget 10", isFeatured: false, price: 6.99}
    ];

    WinJS.Namespace.define("lst1011.Converters", {
        isFeaturedToString: WinJS.Binding.converter(function(value) {
            return (value ? "widget featured" : "widget");
        })
    });

    WinJS.UI.Pages.define("/pages/chapter10/lst1011/lst1011.html", {
        ready: function (element, options) {
            var productsList = element.querySelector("#productsList").winControl;
            productsList.itemDataSource = new WinJS.Binding.List(products).dataSource;
            productsList.itemTemplate = element.querySelector("#productItemTemplate");

        }
    });

})();

9781430249832_Fig10-15.jpg

图 10-15。特色项目以灰色背景突出显示

lst 1011 . html

lst1011.html文件声明了产品和折扣列表视图及其惟一的 ID 属性。这个 ID 属性很重要,因为它允许我们确定将要创建的样式的范围,以便只影响产品列表。

产品项模板中的第一个 div 包含一个名为data-win-bind的属性,在该属性中我们定义了(粗体)数据绑定项的一个属性(isFeatured)和元素的一个属性(className)。我们还实现了一个叫做转换器的东西,这当然不在我们的主题范围之内。然而,我想让您注意到这一点,这样您就不会想知道属性值isFeatured如何变成类名,比如widget featured

lst1011.js

lst1011.js 文件负责的列表绑定也超出了范围,但是您已经见过几次了,所以无论如何您可能会学到语法。然而,代码定义了一个小部件数组,每个小部件都有一个名为isFeatured的属性,其中的布尔值true应该表示一个特色产品。这个简单的数组变成了一个绑定。列表,以便它可以绑定到 ListView。

lst1011.css

最后,我们的 lst1011.css 文件使特色项目真正脱颖而出。它定义了两个样式规则:一个用于具有widget类的项目,另一个用于同时具有widgetfeatured类的项目。

所有的小部件都应用了第一个规则,但是只有有特色的小部件获得了额外的background-color属性,该属性将项目的背景设置为lightgray

自定义 WinJS 控件

在下面的例子中,假设我们发现自己重复了一些我们不希望的标记,因此我们决定创建一个自定义的 WinJS 控件来封装它。我们发现重复的标记是地址字段:地址、城市、州和邮政编码。在我们的应用程序中,我们需要收集帐单和送货地址。

WinJS 不仅提供了许多自定义的复合控件供我们使用,还允许我们创建自己的控件。我们完全用 JavaScript 创建控件,然后用与内置 WinJS 控件相同的方式在 HTML 中声明它们。在我看来,这是一个非常优雅和强大的模式。

从消费页面(我们实际上使用这个自定义控件),我们仍然需要访问地址控件的单个元素,这样我们就可以,例如,向地址字段添加一些 CSS 属性。这正是我们在这个例子中要做的。我们将在两个控件中的地址周围添加一个双边框,以显示我们具有该功能。清单 10-12 把所有这些都放在一起,后面是对每个文件的解释。

清单 10-12 。创建自定义 WinJS 控件并在标记中轻松声明其中两个控件的代码

<!-- lst1012.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Listing 10-12</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <link href="lst1012.css" rel="stylesheet" />
    <script src="AddressControl.js"></script>
    <script src="lst1012.js"></script>
</head>
<body>
    <div class="lst1012 fragment">
        <section aria-label="Main content" role="main">
            <h3>Billing Address</h3>
            <div data-win-control="lst1012.Controls.Address"></div>

            <h3>Shipping Address</h3>
            <div data-win-control="lst1012.Controls.Address"></div>
        </section>
    </div>
</body>
</html>

/* lst1012.css */
.lst1012 .abc-address {
    background-color: lightgray;
}

// lst1012.js
(function () {
    "use strict";

    WinJS.UI.Pages.define("/pages/chapter10/lst1012/lst1012.html", {
        ready: function (element, options) {

        }
    });
})();

// AddressControl.js
WinJS.Namespace.define("lst1012.Controls", {
    Address: WinJS.Class.define(
        function (element) {
            element.innerHTML =
                "Address: <input class='abc-address ' style='width:300px;'/><br/>" +
                "City/St/Zip: <input class='abc-city '/><select class='abc-state '>
                <option></option><option>Alabama</option><option>Alaska</option>
                <option>...</option></select><input class='abc-zip ' style='width:80px;'/><br/>";
        }
    )

});

9781430249832_Fig10-16.jpg

图 10-16。两个地址字段都按照我们确定的方式进行了样式化,因为地址字段被赋予了一个类名,并且页面样式表中的规则已经将该类作为目标

地址控制

AddressControl.js文件完成了定义自定义地址控件的所有工作,我们完全控制它生成的标记,包括控件消费者可以使用的类属性(粗体)。

此时,这些类属性是您真正需要注意的唯一事情,所以如果您现在推迟了 JavaScript 学习,您可以浏览文件的其余部分。请注意,我已经大大简化了自定义控件的创建。一个实现良好的自定义控件当然会有更多的功能。

lst 1012 . html

lst1012.html文件中,您会注意到对AddressControl.js文件的引用和引用控件的标记(粗体)。我在这里手动声明了自定义控件的两个实例,但是它们也可以在 ListView 的模板中声明,或者动态添加到页面中。

lst 1012 . CSSt1]

最后,lst1012.css中一个简单的 CSS 规则证明了我们可以通过在地址字段周围添加双边框来访问单个元素。如果您是自定义控件的作者和消费者,那么您将不会有问题匹配类定义(在您的控件的 JavaScript 文件中)和样式定义(在您的 CSS 文件中)。如果您正在使用第三方控件,那么发现它们定义了什么元素和类是一件简单的事情,就像我已经展示的那样使用 DOM Explorer。

lst1012.js

lst1012.js文件本质上是空的,但是我把它留在了清单中,这样你就知道它没有在你背后做任何事情。

摘要

我们已经看到了如何深入 DOM 并查看其元素的结构,无论这些元素是由我们显式编写的还是通过包含自定义 WinJS 控件编写的。然后,我们学习了如何从 WinJS 库中找到已经应用于这些元素的样式规则。

找到这些元素和已经针对它们的样式规则是理解如何覆盖和扩展这些样式以赋予应用程序我们自己的品牌和个性的重要的第一步。

除了覆盖现有的内容,我们还能够显式地创建自己的元素和类,或者通过创建自定义控件,然后定义自己的样式来控制它们的外观。

本章中的例子是你可以在你的应用程序中设计元素的无数方法中的一个很小的例子。请记住,您也可以使用相同的技术在其他 CSS 库中定位和覆盖样式(我们将在附录 A 中讨论除 WinJS 之外的 CSS 库)。

十一、附录 A:CSS 库和资源

image 注意一些你可能想加入书签的链接。

我们已经大致介绍了 CSS,并重点介绍了它如何应用于创建 Windows 8 应用程序,但我可以向您保证,还有更多的内容需要介绍。要掌握 CSS 和 Windows 8 应用程序的创建,你需要花费数百个小时实际编写应用程序,并且你需要大量的信息。我不能用几百个小时来帮助你,但幸运的是,我可以提供大量的信息。

在这个附录中,我将尝试从大量的信息中提取 CSS 的精髓。我会介绍一些 CSS 库,助手,以及一些对我帮助很大的学习和参考网站。

图书代码

image www.apress.com/9781430249832http://codefoster.com/cssbookcode

本书中的清单包含了相当多的代码,您可能希望选择复制一些代码粘贴到您自己的项目中。你可以通过访问www.apress.com/9781430249832或我的网站http://codefoster.com/cssbookcode获得这本书的所有源代码,在那里你将被引导到 CodePlex 上的源代码。代码编译成一个 Windows 8 应用程序,该应用程序按章节索引这本书的所有代码列表,并让您看到它们的运行。

代码方式

image codeshow.codeplex.com

codeSHOW 是一个用 HTML、CSS 和 JavaScript 编写的 Windows 8 应用程序,唯一的宗旨是帮助你学习用 HTML、CSS 和 JavaScript 制作自己的应用程序。你可以通过访问codeshow.codeplex.com访问 codeSHOW 项目的所有源代码,或者如果你安装了 Windows 8,你可以浏览 aka.ms/codeshowapp 并下载该应用程序。

codeSHOW 应用程序展示了许多演示,并允许你查看代码来一窥创建它所用的 HTML、CSS 和 JavaScript。这是学习如何实现一个你知道你需要的特性的好方法。然而,这并不是应用程序架构中的重要一课。为此,欢迎您从 CodePlex 链接下载 codeSHOW 项目本身的完整源代码,并看看 codeSHOW 是如何创建的。

环球网财团

image w3.org/style/css

万维网联盟(又称 W3C)是处理互联网底层技术的国际标准机构(有很多)。W3C 于 90 年代中期在麻省理工学院(MIT)成立。它是由一个叫蒂姆·伯纳斯·李的人创建的,直到今天他还是代理主管。

正如你可能想象的那样,W3C 有自己的工作要做,促进对如此多的 web 标准提案的讨论,然后决定该组织将推荐哪些标准。每一个被提议的标准都经历了四个阶段:工作草案、候选推荐、提议推荐,最后是 W3C 推荐(REC)。

如果你在 web stack 工作,你应该经常访问w3.org网站。其他所有的讨论(包括这本书)甚至 web 标准的实现相对于w3.org来说都是猜想,而w3.org才是所有应该被衡量的标准。

你会期望一个来自网络标准组织的相当不错的网站,而w3.org不会让人失望。要深入研究所有关于 CSS 的 W3 标准,请访问w3.org/Style/CSS/,花些时间四处看看。

微软开发者网络(MSDN)

image http://msdn.microsoft.com/en-us/library/ie/ms531209(v=vs.85).aspx

MSDN 网络是一个巨大的图书馆,是各种微软开发(包括 CSS)的大量文档来源。你肯定会发现微软实现 CSS 标准的一些角落,我在本书中没有找到足够的篇幅来介绍。

当你已经在 CSS 的某些方面参考了 W3C 标准,并且想知道 Internet Explorer 或 Windows 8 应用程序中行为的细微差别时,我建议你看看 MSDN。

CSS 技巧

image css-tricks.com

Chris Coyier 的 CSS 技巧让我受益匪浅。这是一个美丽的网站,有丰富的关于 CSS 的信息。这些文章是一流的,信息量大得惊人。我通常要么搜索网站,要么滚动到底部,点击“更多博客文章”来浏览文章。

CSS Tricks 不仅有高质量的文章,社区论坛也不错。你可以在 CSS 问题上得到一些真正的帮助,希望你能从别人那里找到一些你可以回答的问题。当我寻找一点设计灵感时,我倾向于访问 CSS 技巧。画廊区在这方面特别有效。

Web 平台文档

image webplatform.org

Web Platform Docs 网站是一个完全由社区驱动的 Web 平台文档网站。它在所有重要的 web 技术上提供了很多帮助,比如 HTML、CSS、JavaScript、SVG 等等。

在我看来,这个网站还处于初级阶段,设计还有点困难,但它是一个很好的开放平台,可以用来学习网络平台,帮助教授他人,培养社区。

减去

image lesscss.org

这不仅仅是另一个链接到一个有好的 CSS 文档的站点。哦不。少即是多!LESS 是一个非常简单但是非常有帮助的 CSS 助手。LESS 允许我们以一种更加智能和程序化的方式来描述我们的风格。

我们编写更少的代码并在 HTML 页面上引用它,就像我们使用 CSS 一样,但是在页面被请求之前,处理器将更少的代码转换成 CSS,这就是我们的 HTML 文件所能看到的全部内容。LESS 创建了您本可以自己创建但不想创建的 CSS。

在得到处理之前,并非所有 LESS 代码都是有效的 CSS 代码。相反,所有 CSS 代码都是有效的少代码。这意味着你可以把你现有的 CSS 文件(无论其大小)转换成一个更小的文件,只要改变它们的文件扩展名。然后,您可以开始一次引入一个较少的功能。

LESS 还允许定义变量、混合、嵌套规则以及函数和操作。让我们花一点时间来看看这些,然后看看如何在 Windows 8 中设置得更少。

变量

为了引入变量,让我们用一个例子:你的设计者(即使你是你的设计者 ??)告诉你你的主题颜色将是 R71 G82 B49,你可以想象你将会在你的 CSS 文件中洒满 ??。这种特定的颜色可能会成为主页上项目的边框、标题中文本的颜色以及应用程序栏的背景。

在整个文件中散布这样的值会让你觉得很糟糕。这意味着如果你的设计师改变了主意,你将会在不止一个地方改变颜色,你将会犯一个错误。

但是,如果您使用较少,您有机会定义一个变量来表示这种原色。你甚至可以称这个变量为primaryColor。在列出 A-1 的中可以看到这种颜色的定义以及随后从几个地方引用它的例子。

列举 A-1。 一个少变量用来存储一种颜色

@primaryColor: rgb(71,82,49);

#myListView .win-item {
    border: 1px solid @primaryColor;
    color: @primaryColor;
}

.win-appbar { background-color: @primaryColor; }

列出 A-1 展示了实际颜色——rgb(71,82,49)——是如何只定义一次的。如果在将来的某个时候,我们的设计师通知我们,这个色调应该调整一点,它只需要在一个地方完成。

Mixins

Mixins 允许我们中混合一个类和另一个类。也就是说,我们可以让一个类继承另一个类的所有样式属性。在清单 A-2 中,您将看到一个设置边框和背景颜色的引用类(.reference)。两个后续的类(.styleA.styleB)应该都采用相同的边框和背景颜色属性,但也需要添加一些自己的属性。

清单 A-2。 少了一个混信的例子

.reference {
    border: 1px solid black;
    background-color: gray;
}

.styleA {
    .reference;
    font-size: large;
}

.styleB {
    .reference;
    font-weight: bold;
}

在某些情况下,Mixins 可以节省大量的输入。

除了简单地引用另一个类,您还有机会用 mixin 向被引用的样式传递一个参数。明白我在清单 A-3 中的意思。

清单 A-3。 带有传递参数的 mixin

.reference (@borderWidth: 1px) {
    border: @borderWidth solid black;
    background-color: gray;
}

.styleA {
    .reference;
    font-size: large;
}

.styleB {
    .reference(2px);
    font-weight: bold;
}

你能看到那里发生了什么吗?.reference样式现在接受一个名为borderWidth的参数,默认值为1px.styleA属性包含了.reference,但是没有为borderWidth参数指定一个值,因此它获得了.reference规则的所有属性,并为边框宽度指定了一个默认值。然而,.styleB属性包括。reference但是为borderWidth参数指定了一个值2px,因此它获得了具有 2 像素边框的.reference规则的属性。

Mixins 允许一些定义非常优雅的 CSS,这些 CSS 具有表达性、简洁和集中化,因此易于维护。

嵌套规则

你可能已经注意到一些 CSS 样式的选择器会变得很长。要访问主节中名为myDivdiv元素中的类error列表中的列表项,您最终会得到类似于section[role=main] #myDiv .error li { ... }的东西,它们甚至会比这长得多。

为了避免这种情况,可以使用 LESS 的嵌套规则。嵌套规则允许您在一个规则中定义另一个规则,推论是每个规则的父选择器应该应用于它。清单 A-4 中的两个 CSS 部分具有相同的效果。

列举 A-4。 对 CSS 类进行比较,以较少使用嵌套规则

/* using classic CSS */
section[role=main] {
    font-size: large;
}

section[role=main] #myDiv {
    font-weight: bold;
}

section[role=main] #myDiv .error li {
    color: red;
}

/* using LESS nested rules */
section[role=main] {
    font-size: large;
    #myDiv {
        font-weight: bold;
        .error {
            li {
                color: red;
            }
        }
    }
}

请注意在列出 A-4 的经典 CSS 部分中出现的冗余。这种重复导致维护困难和代码容易出错。在这种情况下,LESS 版本并没有短很多,但关键是它的定义更符合逻辑,可读性和可维护性更好。

请记住,即使你的应用程序中使用了更少的内容,客户端最终还是会使用生成的 CSS。这不是浏览器引擎必须要破译的东西。它仍然以预期的格式接收 CSS 样式规则。

功能和操作

我们应该关注的 LESS 的最后一个特性是它提供的函数和操作。

LESS 给了我们一些计算值的智能方法,很多时候计算出的值是有帮助的。如果一个基线长度是 10 个像素,但是一些元素应该比我们应该能够计算的差多或少 2 个像素,不是吗?

函数和运算经常与变量一起使用。我们来看几个例子。首先,我们将查看列表 A-5 中的一些长度计算。

清单 A-5。 少计算确定边框宽度

@borderWidth: 10px;

.styleA {
    border-width: (@borderWidth - 2);
    border-style: solid;
    border-color: black;
}

.styleB {
    border-width: (@borderWidth + 2);
    border-style: solid;
    border-color: black;
}

清单 A-5 中的.styleA规则会产生一个 8 像素的边框,而.styleB规则会产生一个 12 像素的边框。当您决定更改基本边框宽度时,比显式指定这些值更有优势。此时,所有计算的边界都会自动调整。

这些计算也可以在颜色上完成,并且有一些函数给了我们一些更好的功能。添加颜色可能与您的直觉相反,但它实际上只是添加颜色的单个红色、绿色和蓝色成分。一种十六进制颜色#123456加上另一种颜色#111111会产生一种颜色#234567。颜色也可以相乘、相除或相减。

除了基本的数学运算,还有一些颜色函数可用。如果我有一个基色#77C121,并且想要一个暗 10%的颜色,我可以避免设计时往返于我最喜欢的图形包,而是只使用 LESS 的darken()函数。我将在清单 A-6 中展示一个这样的例子。

清单 A-6。 使用变暗()函数来计算更暗的颜色

@baseColor: #77C121;

.normal {
    background-color: @baseColor;
}

.disabled {
    background-color: darken(@baseColor, 10%);
}

在清单 A-6 中,一个被禁用的项目会自动获得一个比基色暗 10%的阴影。这大概是我在 LESS 里最喜欢的一招了。能够创建基本调色板,然后从中表达衍生颜色,这是一种非常优雅的应用程序风格。对基色的简单改变相当于自动创建全新的衍生配色方案。

设置

设置您的 Windows 8 应用程序以减少使用并不困难。

首先,让我们回忆一下典型的 web 架构,以及 LESS 适合它的地方。CSS 通常存在于 web 项目中,从静态服务器文件提供给客户端。对于使用 LESS 的 web 项目,CSS 代码本质上是动态的,因为 LESS 处理器必须从 LESS 代码中生成它。这个过程既可以发生在服务器上,也可以发生在客户端。

在 Windows 8 应用中,我们的架构与典型的 web 应用略有不同。Windows 8 设备既是服务器又是客户端,因此有效地消除了服务器和客户端之间的界限。因此,对于应用程序,我建议按照以下步骤使用 LESS JavaScript 库进行处理:

  1. 更改 CSS 文件的扩展名。css 到。较少的
  2. 将您的样式表引用更改为:<link rel="stylesheet/less" type="text/css" href="myLessStylesheet.less">。注意rel(关系)属性值- stylesheet/less
  3. lessjss.org下载less.js库,放到你的 Windows 8 应用的js文件夹中。请记住,如果您使用 Windows 资源管理器将它直接放入应用程序的文件夹结构中,那么您需要在 Visual Studio 中显示隐藏的文件,然后右键单击less.js文件并选择“包含在项目中”。
  4. 添加对您下载的less.js库的引用。我建议你把这个放在default.html页面上。它应该看起来像:<script src="/js/less.js" type="text/javascript"></script>

我觉得你现在穿得少了,我想你会喜欢的。

其他在线图库

image cssflavor.com``csscollection.com``csselite.com``csstemplates.net

你可以在网上找到许多图库,它们可以作为学习工具、灵感来源和项目模板来源。CSS Flavor、CSS Collection、CSS Elite 和 CSS Templates 等网站包含使用 CSS 创建的示例网站的良好集合。

花些时间浏览这些网站提供的图库,当你找到一个你喜欢的模板或一个有你正在寻找的样式或布局功能的模板时,只需复制并研究它的 CSS 样式表。请务必阅读各种网站的使用说明,以确保您符合要求。

当你需要针对一条信息来实现一个新功能或解决一个具有挑战性的问题时,像我在本附录中概述的那些参考网站是非常好的,但是仅仅花时间浏览内容也是非常有益的。尝试一下,你会发现自己学到了你从来不知道自己需要的东西。浏览在线 CSS 图库是学习如何应用所学理论的另一个好方法。所以不要随便找好的代码就用。写好代码,分享出来!成为开发者社区的一员是加速你学习的另一种方式,也是享受学习的一种方式。

十二、附录 B:样式化 SVG

image 注意太多的现代开发者忽略了矢量图形在图像生成和显示解决方案方面的强大功能。

SVG 格式介绍

可缩放矢量图形(SVG) 是用于定义基于矢量图形的的 XML 格式。像 HTML、CSS 和 JavaScript 一样,SVG 是 W3C 的众多项目之一。这也不是一个新项目——它从 1999 年就开始了。

尽管 SVG 很难获得关注,但我认为这有几个不同的原因。一个原因是矢量图形不像位图那样为人们所熟悉。很多人都知道像 Adobe Photoshop 这样的图形软件包,但是很少有人深入研究 Adobe Illustrator 或其他任何处理矢量图形的优秀工具。如果你是矢量图像编辑的新手,那么让我澄清一下。

首先,考虑位图图像如何存储为颜色值的二维矩阵。当正方形颜色值(像素)足够小时,人眼会被骗去看图像。另一方面,矢量图像的存储方式完全不同。在矢量插图中,我们使用的不是像素的集合,而是对象的集合,这些对象可能是熟悉的形状(如矩形和椭圆形),也可能是由许多点和曲线值定义的复杂线条。反过来,这些对象由顶点(或其他基本形状描述符)组成。存储的是这些顶点或形状描述符,而不是像素矩阵。

当您比较位图和矢量图形时,SVG 有一些很大的优势。其中一些优势会影响图形的创建(当你从零开始或者编辑一个现有图形的时候),其他的会影响矢量图像在一个正在运行的应用中的使用。

对于图形创建,SVG 的一些显著优势是:

  • 以矢量格式创建和存储的插图可缩放。这意味着你存储多大的矢量插图并不重要,因为你总是可以从它生成你喜欢的位图。您可以使用相同的矢量图像来打印邮票或路边广告牌。
  • 矢量插图更容易修改。组成合成图像的所有组件对象都单独存在,并且可以单独修改。你可以打开一个摩托车的矢量图像,只选择前灯,然后修改它的形状。对于位图图像来说,这一壮举要困难得多。
  • 由于可以进行修改以匹配您自己项目的配色方案,因此使用基于矢量的库存图像通常要容易得多。

在跑步应用中使用矢量图像的其他一些显著优势包括:

  • 对于几乎所有的图像,矢量版本将会小得多。描述一个圆的形状并不需要像用像素明确描绘它那样多的信息。
  • 矢量插图,由描述的物体形状组成,更容易动画化。软件可以计算两点之间的中间步骤,颜色值的差异,甚至是将一个形状变形为另一个形状的数学模型。用同样的方式制作像素动画几乎是不可能的。
  • 矢量插图可以根据用户碰巧使用的屏幕大小调整大小。Windows 8 会自动缩放应用中的所有资产。为了让你的位图图像看起来不错,你必须提供它的多个版本。但是,如果资源是矢量图像,您不需要这样做,并且可以确保它在任何大小下看起来都很棒。

我发现太多的开发者(甚至设计师!)仍然试图在 Photoshop 等位图编辑器中完成所有的图形工作。位图编辑器对于照片、绘画和许多其他事情来说是非常优秀的,但是在许多图形创建用例中,学习和切换到矢量包将极大地提高您的生产力。

我选择的矢量编辑器是 CorelDRAW。我已经使用 Corel 的矢量包很多年了,发现它的界面非常精确和直观。还有一些其他专业的矢量设计应用程序可供你研究,但是如果你正在寻找一个仍然提供很多功能的免费应用程序,试试 inkscape.org 的 InkScape。这个开源的矢量图形编辑器做的非常好。InkScape 没有自己的矢量文件格式,而是完全依赖于 SVG 格式。

矢量图像的另一个主要优点是可以制作动画。因为矢量图像是被描述的对象(而不仅仅是像素),所以它们可以被动态地改变形状,并且因为矢量图像是由离散的元素组成的,所以那些元素可以被相当容易地移动。想象一下一只基于向量的狗的下颚移动来模拟说话。

HTML 中嵌入的 SVG

SVG 只是 XML,而 HTML 几乎是 XML,所以这两种语言很好地结合在一起,SVG 可以毫不费力地嵌入到 HTML 文档中。这两种语言都类似于 XML,这也是 CSS 能够自然地对它们进行样式和布局的原因。

过去,在 HTML 中嵌入 SVG 要困难得多,但是 HTML5 使它变得容易得多。HTML 不是严格意义上的 XML,但 SVG 是,所以嵌入式 SVG 需要清楚地定界并给定一个适当的名称空间。清单 B-1 显示了在 HTML 中放入一些 SVG 的样子。

***清单 B-1。***SVG 中带有填充属性的简单圆

<!-- HTML snippet -->
<!DOCTYPE html>
<head>
<title>SVG</title>
<meta charset="utf-8" />
</head>
<body>
<h2>SVG in HTML5</h2>
<svg id="mySvg" height="200" FontName2">http://www.w3.org/2000/svg ">
    <circle id="graycircle" r="75" cx="75" cy="75" fill="gray" />
</svg>
</body>
</html>

清单 B-1 中的代码描述了你在图 B-1 中看到的半径为 75 像素的圆。它在一个具有与http://www.w3.org/2000/svg相等的xmlns (XML 名称空间)属性的svg标签中这样做。如果名称空间对你来说是新的,只需知道这实际上并没有链接到 w3.org 网站。它只是使用这个 URL 作为名称空间来惟一地将这个标记的内容标识为 SVG。

9781430249832_AppB-01.jpg

图 B-1 。灰色圆圈

SVG 的 CSS 属性

在清单 B-1 中,我们以一个灰色圆圈结束,因为我们使用了值为grayfill属性。您可以在 SVG 元素上使用类似这样的各种属性来设计它们的样式,但是我不推荐这种方法。最好所有的样式都在 CSS 中完成,以便以后可以修改。清单 B-2 产生了与清单 B-1 相同的灰色圆圈,只是这次的灰色填充是在一个单独的样式表中使用 CSS 样式属性提供的,而不是使用 fill 属性。

清单 B-2。 同样的灰色圆圈除了使用了 CSS 属性

<!-- HTML snippet -->
<!DOCTYPE html>
<head>
<title>SVG</title>
<meta charset="utf-8" />
</head>
<body>
<h2>SVG in HTML5</h2>
<svg id="mySvg" height="200" FontName2">http://www.w3.org/2000/svg ">
    <circle id="graycircle" r="75" cx="75" cy="75" />
</svg>
</body>
</html>

/* CSS snippet */
#graycircle {
    fill: gray;
}

这是我将在本附录中介绍的所有内容的基础。我们将探索可以在 CSS 中指定的影响 SVG 图形的各种样式属性。您会发现这些属性中有许多是 HTML 共有的,但也有一些是 SVG 特有的。我将介绍一些更常见的属性。有关所有可用属性的更多信息,请访问http://www.w3.org/TR/SVG11/propidx.html,在那里您可以找到详尽的参考资料。

填充

在 HTML 中,使用color属性来指定像文本这样的东西的前景色,使用背景色来指定应该填充元素背景的颜色。在 SVG 中,使用fill属性来指定图形元素的颜色。你已经在清单 B-2 中看到了这一点,其中我们的圆圈用灰色填充

除了指定元素应该填充的颜色,您还可以指定不透明度。在清单 B-3 中,我使用 CSS 网格将一个 SVG 元素堆叠在一段文本的顶部。添加一个设置为0.5 (50%)的fill-opacity属性,然后通过 SVG 使段落可见,正如你在图 B-2 中清楚看到的。

清单 B-3。 一个部分不透明的灰色圆圈,使其在一段文本上透明

<!-- HTML snippet -->
<div id="parent">
    <p id="text">Lorem ipsum dolor sit amet . . . </p>
    <svg id="mySvg" height="200" FontName2">http://www.w3.org/2000/svg ">
        <circle id="graycircle" r="75" cx="75" cy="75" />
    </svg>
</div>

/* CSS snippet */
.lstb03 #parent {
    display:-ms-grid;
}

.lstb03 #text {
    width:300px;

}
.lstb03 #graycircle {
    fill: gray;
    fill-opacity: 0.5;
}

9781430249832_AppB-02.jpg

图 B-2 。一个部分透明的圆圈显示它下面的段落文本

fill-rule 属性确定当样式引擎应用填充以确定形状的哪些部分被填充时所使用的算法。这两个选项是nonzeroevenodd。你不需要知道这些算法是如何工作的细节。我总是两个都尝试,看看哪一个能给我想要的结果。图 B-3 中的图形是 W3C 如何说明这两种算法之间的一些差异的。

9781430249832_AppB-03.jpg

图 B-3 。填充闭合形状的两种不同方法

笔画

笔画是独立的线条(直线或曲线)或环绕形状的线条。您将使用描边属性来设定描边的颜色、宽度、不透明度等等。

您可能想知道的前两个与笔画相关的属性是strokestroke-width。属性stroke控制笔画的颜色,属性stroke-width控制粗细。清单 B-4 设置了这两个属性,在我们正在处理的灰色圆圈周围添加了一条黑线。

清单 B-4。 给我们的灰色圆圈添加一个粗黑的轮廓

<!-- HTML snippet -->
<svg id="mySvg" height="200" FontName2">http://www.w3.org/2000/svg ">
    <circle id="graycircle" r="75" cx="75" cy="75" />
</svg>
/* CSS snippet */
.lstb04 #graycircle {
    fill: gray;
    fill-opacity: 0.5;
    stroke:black;
    stroke-width: 4px;
}

在清单 B-4 的中描述的圆圈将有一个 4 像素的黑色边框,正如你在图 B-4 中看到的。

9781430249832_AppB-04.jpg

图 B-4 。stroke 属性在我们的元素周围添加一个轮廓

除了这两个简单的属性,还有很多与中风相关的属性。分别是:stroke-dasharraystroke-dashoffsetstroke-linecapstroke-linejoinstroke-miterlimitstroke-opacity。这些属性允许您控制 SVG 元素上线条的许多其他方面,例如线条的虚线/圆点,以及线条在拐角周围和线条末端的行为。

关于这些扩展属性和 SVG 元素笔画所有方面的更深入的信息可以在http://www.w3.org/TR/SVG11/painting.html#StrokeProperties的 W3.org 上找到。

标记

标记是出现在线条两端或中间的字形。标记最常用于在元素末端创建箭头,但实际上标记可用于显示任何自定义形状,并使其出现在任何顶点。

创建标记是一个两步过程。首先定义标记的形状,然后将该标记定义应用于任何 SVG 元素。你可以在http://www.w3.org/TR/SVG11/painting.html#Markers找到标记的详细解释。

过滤器

滤镜就像镜头一样,可以将许多不同的效果应用到 SVG 图形的某些区域。你可以在 SVG 圆形的内容中添加一个滤镜,比如对圆形及其内容应用高斯模糊。图 B-5 是一个过滤器运行的好例子(同样来自 W3C)。

9781430249832_AppB-05.jpg

图 B-5 。一个应用过滤器的 W3C 示例

当然,使用您最喜欢的图形应用程序也可以实现该过滤器提供的相同效果,但是在运行时应用该过滤器有巨大的优势。在运行时应用的过滤器可以被你的应用程序的逻辑作为目标,因此可以有条件地应用。例如,只有当用户将鼠标悬停在图像上时,滤镜才会生效。同样,这可以通过提供多个位图图像的传统方式来实现,但是这种技术肯定有一定的限制。图像您想要一个过滤器的效果是动画。实际上用传统的方法是不可能做到的。

滤镜效果分两个阶段添加到元素中。首先使用filter 元素创建一个过滤器,然后使用filter 属性将该过滤器应用于一个元素。

过滤器是相对复杂的,所以为了简洁起见,我就不深入讨论了。然而,我确实想提到它们的一般功能,并让您知道它们是可用的。如果您想深入了解滤波器的主题,请访问http://www.w3.org/TR/SVG11/filters.html#FilterProperty

面具

蒙版是一种将透明层(也称为 alpha 通道)应用到任何 SVG 元素的方法,方法是提供一个显式蒙版,然后应用它。面具也可能是一个很长的话题,但是你至少应该知道它们是什么。

关于应用程序中相对冗长的属性(如遮罩、标记和过滤器)的快速说明:试图手动定义这些属性是疯狂的,因为记住语法并花时间键入它们是不允许的。通常,当您使用 Adobe Illustrator、CorelDRAW 或 InkScape 等矢量编辑图形软件时,这些会自动应用。

你可以在http://www.w3.org/TR/SVG/masking.html找到更多关于面具的信息。

指针事件

正如你已经看到的,SVG 形状有一个内部(?? 填充 ??)和一个外部(?? 描边 ??)。填充或描边中的一个或两个可能具有值none,因此将呈现不可见。这意味着当用户点击你的元素时需要做出一个有趣的选择。如果您创建了一个没有填充的圆,并在另一个元素的顶部结束,您可能希望也可能不希望该圆捕获单击事件。对于笔画来说也是如此。

在这种情况下,pointer-events属性是您指定行为的机会。默认情况下,这个值是visiblePainted,这是一个非常直观的选择,所以您可能不需要经常更改这个属性。

pointer-events属性的可用值有:visiblePaintedvisibleFillvisibleStrokevisiblepaintedfillstrokeallnone。设置了visiblePainted(默认)后,只有当元素被填充且可见时,元素才会捕捉填充上的点击(和其他指针事件),只有当笔画被设置且可见时,元素才会捕捉笔画上的点击。设置了visibleFill之后,如果你的元素是可见的(即使你的元素没有被填充),那么这个元素将会在填充时捕获点击。).设置了visibleStroke后,如果元素可见,它将捕获笔画上的点击(即使您没有设置笔画),但它不会捕获填充上的点击。使用paintedfillstroke值具有相似的功能,除了它们忽略元素是否实际可见。all值将导致总是点击——即使您没有设置填充或描边,并且两者都设置为不可见!最后,none值不会传递给指针事件。

如果将编程逻辑添加到像 SVG 这样的动态的、基于向量的图形语言中的想法让你兴奋,那么花些时间研究一下http://www.w3.org/TR/SVG/interact.html#PointerEventsProperty的指针事件。

能见度

就像 HTML 元素一样,SVG 元素的可见性可以被操纵来显示或隐藏单个元素,并且就像 HTML 一样,visible属性的值是visiblehiddencollapse。然而,collapse值的行为就像hidden一样,它隐藏了元素。visible值显然允许元素显示。

这就是我在这篇关于在 HTML 应用中使用 CSS for SVG 的简介中所要介绍的全部内容,但我想看看这些概念在 Windows 8 中的一些实际应用。

运用你所学的知识

让我们在几个例子中实现一些我们已经学到的 SVG CSS 概念。我们首先来看看如何在应用程序的背景中使用 SVG 图像作为带水印的图像。接下来,我们将创建一些自定义的 SVG 图像,显示在 ListView 的主项目标题后面。最后,我们将使用 JavaScript 动态构建一个时间线图形来生成 SVG。

带有 SVG 水印的背景图像

这里的目标是找到一个好的帆船的 SVG 图像,然后将它放置在我们的应用程序的背景中,光线要足够亮,这样它就不会阻碍出现在它上面的视觉元素和文本。

当我寻找好的矢量图像时,我通常从 office.microsoft.com 开始。如果你进行图像搜索,你可以指定你正在寻找的插图并且你希望它们的大小是可调整的,这将指示矢量图像应该被返回。这些图像通常是另一种矢量图像格式—WMF (Windows 图元文件)。要将图像保存为 SVG,您只需从网站上复制图像,粘贴到您的软件包中,然后将其保存为 SVG 文件。

我找到了一个我想使用的帆船图像(图 B-6 ),将其保存为 SVG,并且清单 B-5 显示了生成的 SVG 代码。我特意将 SVG 文件的全部内容留在清单中,这样您就可以了解描述这个简单的帆船需要多少 SVG 代码。

9781430249832_AppB-06.jpg

图 B-6 。简单的帆船图像

作为比较,SVG 格式的帆船在未压缩时占用 7098 字节的磁盘空间,在压缩时占用 3505 字节的磁盘空间。如果我们愿意,这个 7kb 的文件可以用来创建一艘 75 英尺高的帆船。同一艘帆船以 768 像素的高度呈现为未压缩的全色(尽管我意识到这不是必需的)位图,占用了 1,983,798 字节。以无损格式(PNG)压缩位图会将其压缩到 35,410 字节,但您肯定会看到矢量格式比位图有更大的优势。

清单 B-5。 组成一艘简单帆船的整个 SVG 文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" " http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd ">
<!-- Creator: CorelDRAW X6 -->
<svg FontName2">http://www.w3.org/2000/svg " xml:space="preserve" width="509px" height="571px"
version="1.1" style="shape-rendering:geometricPrecision;
text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 50900 57045"
 xmlns:xlink=" http://www.w3.org/1999/xlink ">
 <defs>
  <style type="text/css">
   <![CDATA[
    .fil0 {fill:black}
   ]]>
  </style>
 </defs>
 <g id="Layer_x0020_1">
  <metadata id="CorelCorpID_0Corel-Layer"/>
  <g id="_695569408">
   <polygon class="fil0" points="22632,2398 22872,2368 23112,2308 23292,2188 23472,2038 23621,1859
23741,1679 23801,1439 23831,1199 23801,959 23741,719 23621,540 23472,360 23292,210 23112, 90
22872,30 22632,0 22392,30 22153,90 21973,210 21793,360 21643,540 21523,719 21463,959 21433,1199
21463,1439 21523,1679 21643,1859 21793,2038 21973,2188 22153,2308 22392,2368 "/>
   <polygon class="fil0" points="23741,5845 23681,6865 23561,9562 23352,13399 23142,17896
22932,22482 22782,26649 22722,29857 22752,31595 22932,32015 23382,32375 24011,32704 24850,33004
25840,33244 26919,33484 28118,33634 29347,33783 30606,33843 31865,33903 33094,33873 34263,33813
35312,33694 36212,33514 36961,33304 37531,33004 37890,32554 38100,31835 38160,30906 38070,29827
37890,28568 37590,27189 37201,25720 36781,24191 36271,22662 35762,21163 35192,19665 34653,18286
34113,16997 33604,15858 33154,14898 32734,14149 32315,13399 31775,12500 31146,11481 30456,10342
29707,9203 28957,8034 28178,6895 27398,5875 26649,4976 25960,4227 25300,3717 24761,3447 24311,3507
23981,3867 23771,4646 "/>
   <polygon class="fil0" points="8843,28178 9652,28687 10522,29167 11451,29587 12440,29946
13429,30246 14419,30516 15378,30726 16307,30936 17206,31086 18046,31205 18795,31295 19425,31385
19964,31415 20384,31445 20624,31475 20714,31475 20504,8933 20324,9113 19844,9652 19065,10462
18106,11511 16967,12800 15738,14239 14449,15798 13160,17446 11901,19125 10732,20774 9742,22392
8933,23921 8393,25300 8184,26499 8303,27458 "/>
   <polygon class="fil0" points="29017,35372 27968,35312 26949,35282 25960,35192 24970,35132
24041,35042 23112,34953 22213,34833 21313,34743 20414,34623 19515,34503 18615,34383 17686,34233
16757,34113 15828,33963 14838,33843 13849,33694 12860,33544 11811,33304 10702,33034 9562,32704
8393,32345 7254,31985 6115,31595 5036,31205 3987,30816 3058,30456 2188,30126 1439,29827 839,29587
390,29377 90,29257 0,29227 570,30186 989,31265 1319,32375 1589,33544 1829,34743 2068,35912
2338,37051 2668,38130 3088,39149 3627,40079 4347,40858 5216,41517 6325,41997 7674,42267 9323,42357
11271,42177 12740,41997 14149,41847 15468,41727 16727,41667 17896,41637 19035,41637 20084,41667
21073,41727 22033,41817 22932,41937 23771,42057 24581,42177 25330,42327 26050,42477 26739,42627
27398,42776 28028,42926 28628,43076 29197,43226 29767,43346 30306,43466 30846,43556 31385,43646
31895,43676 32435,43706 32944,43706 33484,43676 34023,43586 34563,43466 35132,43316 35702,43106
36301,42866 36931,42567 37560,42237 38190,41877 38819,41517 39479,41098 40108,40708 40738,40288
41338,39869 41907,39449 42477,39029 43016,38610 43496,38220 43945,37860 44365,37531 44755,37231
45055,36961 45384,36691 45744,36421 46104,36182 46493,35942 46853,35732 47243,35522 47633,35342
48022,35162 48412,35012 48802,34863 49191,34713 49551,34593 49911,34443 50270,34323 50600,34203
50900,34083 50360,34173 49791,34263 49191,34353 48562,34443 47872,34533 47183,34623 46434,34683
45684,34743 44935,34833 44125,34893 43346,34953 42537,34983 41727,35042 40888,35102 40079,35132
39269,35162 38460,35222 37650,35252 36841,35282 36092,35312 35312,35312 34593,35342 33873,35372
33184,35372 32524,35372 31895,35402 31295,35402 30756,35402 30246,35402 29797,35402 29377,35372 "/>
   <polygon class="fil0" points="32464,48442 31745,48322 31056,48232 30336,48112 29617,47992
28867,47902 28088,47782 27219,47663 26319,47513 25330,47393 24281,47243 23112,47093 21823,46943
20444,46763 18915,46583 17266,46404 15438,46194 13729,45984 12350,45774 11301,45564 10552,45384
10042,45204 9802,45025 9742,44845 9862,44695 10132,44575 10522,44425 11031,44335 11571,44245
12170,44155 12770,44095 13340,44065 13879,44065 14359,44065 14838,44065 15318,44095 15768,44095
16277,44125 16817,44185 17386,44245 18016,44305 18735,44365 19545,44485 20444,44575 21433,44725
22572,44875 23831,45055 25240,45264 26829,45474 28418,45714 29887,45894 31205,46044 32345,46164
33304,46254 34053,46314 34623,46314 34983,46254 35072,46164 34953,46044 34563,45834 33903,45594
32944,45294 31685,44965 30126,44545 28238,44065 27219,43826 26199,43616 25180,43436 24161,43286
23172,43166 22213,43076 21223,42986 20294,42926 19365,42896 18436,42896 17566,42866 16697,42896
15858,42926 15048,42956 14239,43016 13489,43076 12770,43136 12081,43196 11421,43286 10821,43376
10252,43436 9712,43526 9203,43616 8753,43676 8363,43766 8004,43826 7704,43886 7434,43945 7254,44005
7104,44035 7014,44065 6985,44065 6355,44755 5995,45324 5905,45834 6055,46224 6415,46553 6955,46823
7674,47003 8543,47153 9503,47273 10582,47333 11751,47393 12920,47423 14149,47453 15348,47483
16547,47543 17686,47603 18705,47693 19605,47752 20384,47842 21073,47902 21703,47992 22302,48052
22932,48142 23561,48232 24251,48352 25030,48472 25900,48592 26949,48712 28148,48862 29527,49041
31146,49221 33004,49431 34803,49611 36242,49791 37321,49911 38100,50031 38610,50121 38879,50181
38939,50241 38819,50270 38550,50300 38190,50300 37770,50300 37321,50300 36841,50300 36421,50270
36062,50270 35822,50270 35582,50270 35282,50300 34923,50300 34473,50330 33963,50360 33424,50390
32824,50450 32195,50480 31505,50510 30816,50570 30126,50600 29407,50630 28687,50660 27968,50660
27249,50690 26559,50690 25840,50690 25090,50720 24311,50720 23502,50750 22632,50810 21793,50840
20924,50900 20054,50960 19185,51020 18316,51080 17476,51140 16637,51230 15858,51290 15108,51380
14389,51440 13729,51530 13130,51619 12590,51679 12081,51769 11631,51859 11211,51949 10851,52039
10522,52159 10192,52309 9892,52459 9622,52639 9383,52848 9113,53088 8873,53358 8633,53628 8393,53988
8124,54347 7944,54737 7914,55097 8004,55426 8214,55726 8513,55996 8873,56236 9263,56446 9682,56626
10102,56775 10492,56895 10821,56985 11061,57045 11241,57045 11301,57045 11181,56985 10941,56895
10282,56685 9712,56446 9293,56146 9083,55846 9083,55456 9353,55037 9982,54527 10941,53928
11541,53628 12140,53388 12800,53148 13489,52968 14209,52789 15018,52639 15858,52549 16787,52429
17806,52369 18885,52309 20084,52249 21403,52219 22812,52189 24341,52159 25990,52129 27788,52099
29557,52069 31086,52009 32405,51949 33574,51859 34563,51799 35432,51679 36152,51589 36811,51470
37381,51350 37920,51230 38400,51110 38909,50990 39389,50870 39929,50750 40528,50660 41188,50540
41757,50420 42057,50330 42117,50181 41967,50061 41607,49941 41098,49791 40438,49641 39659,49491
38819,49371 37890,49221 36931,49071 35942,48922 35012,48802 34083,48682 33214,48562 "/>
  </g>
 </g>
</svg>

现在是时候让 SVG 文件包含在一些 HTML 后面了。在我们的 HTML 中,实际上有几种显示 SVG 的方法。

  • 我们实际上可以将清单 B-5 中的 SVG 代码粘贴到我们的页面中,或者使用 JavaScript 将它附加到我们的 DOM 中。
  • img标签直接支持 SVG 文件,所以我们可以使用类似于<img src="sailboat.svg"/>.的东西
  • 我们还可以设置希望它显示在后面的元素的background-image属性。

在这种情况下,没有理由不使用img标签或设置background-image属性。这更容易,也更符合我们的情况。如果要对 SVG 进行操作、设计样式或制作动画,我们需要将 SVG 代码添加到 DOM 中(手动或使用 JavaScript)。在这种情况下,我们不是,所以我们将保持简单。清单 B-6 将帆船图形放在主div元素后面,将它们放入一个网格中。你可以在图 B-7 中看到结果。

清单 B-6。 在一段文字后面添加帆船水印

<!-- HTML snippet -->
<div class="grid">
    <img id="sailboat" src="sailboat.svg"/>
    <div id="main">
        Ut commodo consequat leo . . .
    </div>
</div>

/* CSS snippet */
.lstb06 #sailboat {
    opacity:0.05;
}

.lstb06 .grid {
    display:-ms-grid;
}

.lstb06 #main {
    border:solid 1px gray;
    font-size:large;
    width:500px;
    height:500px;
    padding:10px;
}

9781430249832_AppB-07.jpg

图 B-7 。一艘几乎透明的黑色帆船在段落文本后面显得非常暗淡

集线器上精美的 SVG 磁贴

许多 Windows 8 应用程序使用内置的 ListView 控件来显示项目网格。典型的 Windows 8 网格项目是矩形的,看起来像瓷砖。你不会拘泥于这种外观,尽管它实现的极简主义和效率是一个应该考虑的强大设计功能。

让我们假设您正在创建一个绘画应用程序,您的网格的一部分显示了所有正在绘制文档的用户,您希望这些项目以一种形状来表示,这种形状看起来大致像一个矩形,只是由几个笔画组成。在这种情况下,我们仍然希望有瓷砖——除了有点花哨。在这种情况下,您可以渲染出一个位图并将其放在每个项目的后面,但是您会失去我提到的 SVG 的优势。因此,让我们使用 SVG,让我们自己创建图形。

我跳到 CorelDRAW 上,很快找到了一个笔刷,让我可以创建图 B-8 中的图形。

9781430249832_AppB-08.jpg

图 B-8 。一个使用 CorelDRAW 生成的图形,我们希望用于我们的中心瓷砖

CorelDRAW 可以将图形保存为 SVG。我不会列出这段代码,因为它相当长——不过仍然只有大约 125kb 未压缩。

我们的下一步是在 ListView 的图块后面获得图形。清单 B-7 应该可以搞定。

清单 B-7。 一个带有 CSS 的 ListView,将笔画图形放在每个项目的后面

<!-- HTML snippet -->
<section aria-label="Main content" role="main">
    <div id="listview" data-win-control="WinJS.UI.ListView"></div>
</section>

<!--Templates-->
<div id="itemtemplate" data-win-control="WinJS.Binding.Template">
    <h2 data-win-bind="innerText:name"></h2>
</div>

/* CSS snippet */
.lstb07 #listview .win-item {
    display:-ms-grid;
    -ms-grid-columns:1fr;
    -ms-grid-rows:1fr;
    width:250px;
    height:174px;
    background: url(paint.svg) no-repeat;
    background-size:250px auto;
}

    .lstb07 #listview .win-item h2 {
        -ms-grid-column-align:center;
        -ms-grid-row-align:center;
        color:white;
        font-family:'Segoe WP';
        font-size:40px;
        font-weight:bold;
        position:relative;
        top:-10px;
    }

// JavaScript snippet
var list = new WinJS.Binding.List(
    [{ name: "Doc1" }, { name: "Doc2" }, { name: "Doc3" }]
);
var listview = element.querySelector("#listview").winControl;
listview.itemDataSource = list.dataSource;
listview.itemTemplate = element.querySelector("#itemtemplate");
listview.onloadingstatechanged = function (e) { debugger; };

所有这些代码的结果是一个 ListView,就像你在图 B-9 中看到的那样,带有定制的项目形状和覆盖的文本。

9781430249832_AppB-09.jpg

图 B-9 。生成的笔画项目赋予项目一些特征

使用 SVG 构建的时间线图形

前两个应用程序使用了包含 SVG 的简单方法——即使用img标签和background-image CSS 属性,并简单地引用一个 SVG 文件。现在让我们采取一个稍微困难一点的方法,让我们更好地控制我们的矢量图像。

假设我们想要创建一个简单的时间线图形,其中包含一个代表某个时间长度的灰色条,然后是每个时间点的白点。为了实现这一点,我们将创建 SVG 图像,然后查看它是如何组成的。

我在 CorelDRAW 重新开始。这次我创建了一个非常简单的灰色时间线,用白点标记时间点。同样,这个特殊的图形非常简单,我当然可以通过在记事本中手动编写 SVG 来编写它,但是在现实生活中,您可能会使用更复杂的图形。我创建的简单时间线图形可以在图 B-10 中看到。

9781430249832_AppB-10.jpg

图 B-10 。我们希望用 JavaScript 动态构建的时间线

然后我生成了 SVG,对它进行了一些调整,然后使用记事本查看它(清单 B-8 )。

***清单 B-8。***CorelDRAW 为图 B-10 中的时间轴图形生成的 SVG 代码。

<svg FontName2">http://www.w3.org/2000/svg " width="1000px" height="200px" >
 <defs>
  <style type="text/css">
   <![CDATA[
    .str0 {stroke:black;stroke-width:2}
    .fil0 {fill:gray}
    .fil1 {fill:white}
   ]]>
  </style>
 </defs>
 <g>
  <rect class="fil0" x="30" y="90" width="940" height="20"/>
  <circle class="fil1 str0" cx="30" cy="100" r="10"/>
  <circle class="fil1 str0" cx="70" cy="100" r="10"/>
  <circle class="fil1 str0" cx="400" cy="100" r="10"/>
  <circle class="fil1 str0" cx="970" cy="100" r="10"/>
 </g>
</svg>

元素本身在g元素内部。这些元素的样式在嵌入的样式表中。我们将使用本文档告诉我们的关于如何创建时间线图形的内容,并使用 JavaScript 自己创建它。这将给我们以编程方式放置点的灵活性。我们还将提取 CSS 样式,将它们放入文档的样式表中,并为它们赋予更有意义的类名。很高兴我们所有的风格都在一个地方。就像 HTML 一样,我们希望 SVG 是图形结构的定义,让样式表处理颜色等。清单 B-9 和图 B-11 展示了如何动态创建这个时间线。

清单 B-9。 构建时间轴的 HTML、CSS 和 JavaScript

<!-- HTML snippet -->
<div id="container"></div>

/* CSS snippet */
.lstb09 .circle {
    stroke:black;
    stroke-width:2;
    fill:white;
}

.lstb09 .line {
    fill:gray;
}

// JavaScript snippet
var points = [0,1,3,7,10];
var container = element.querySelector("#container");

//transform the points and generate SVG
var result;
points.forEach(function (p) {
    result += format("    <circle class='circle' cx='{0}' cy='100' r='10'/>", (p * 94) + 30);
});

//add resulting SVG to the DOM
container.innerHTML = format(
    "<svg xmlns=' http://www.w3.org/2000/svg ' width='1000px' height='200px' >" +
    "  <g>" +
    "    <rect class='line' x='30' y='90' width='940' height='20'/>" +
    "    {0}" +
    "  </g>" +
    "</svg>", result);

9781430249832_AppB-11.jpg

图 B-11 产生的时间线正是我们所寻找的,现在可以很容易地改变这些值

将它转换成 WinJS 自定义控件是一个好主意,这样您就可以使用<div data-win-control="MyApp.Controls.Timeline"></div>在代码中的任何地方创建它们。

顺便说一句,如果你想更深入地使用 JavaScript 来生成和操作 SVG 图形,在http://www.farinspace.com/top-svg-javascript-libraries-worth-looking-at/有一个很棒的帖子,它将向你介绍 11 个 JavaScript 库,这些库将对你有所帮助。

您已经了解了令人兴奋的 SVG 空间,并看到了它如何增强您的 Windows 8 应用程序。我们研究了许多影响 SVG 元素的 CSS 样式属性(尽管肯定不是全部),并在 Windows 8 应用中浏览了三个强大的 SVG 应用。

我希望你在阅读这篇文章时学到了一些东西,但更重要的是,我希望你受到启发,去尝试它,研究你不知道的领域,这样你就可以掌握将 SVG 编织到你的应用程序中,并使用 CSS 对它进行样式化。