快速入门:添加 SemanticZoom (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

了解如何使用 SemanticZoom 控件在同一内容的两个视图之间缩放。

先决条件

什么是 SemanticZoom 控件?

SemanticZoom 控件可使用户在同一内容的两个不同视图之间切换。其中一个是内容的主视图。第二个视图是相同内容以不同方式呈现的视图,它使用户可以快速在其中导航。例如,查看通讯簿时,用户可以放大一个字母,查看与该字母关联的名称。

若要提供此缩放功能,SemanticZoom 控件使用另外两个控件:一个控件提供放大视图,另一个控件提供缩小视图。

<div data-win-control="WinJS.UI.SemanticZoom">   
                
    <!-- The control that provides the zoomed-in view goes here. -->

    <!-- The control that provides the zoomed-out view goes here. -->

</div>

这些控件可以是实现 IZoomableView 接口的任意两个控件。WinJS 提供用于实现 IZoomableView 接口的控件:ListView 控件。本快速入门中的示例展示如何使用带有两个 ListView 控件的 SemanticZoom

不要将语义上的缩放与光学缩放混淆。尽管它们的交互和基本行为(基于缩放比例显示更多或更少细节)一致,但是光学缩放是指调整内容区域或对象(如照片)的放大倍数。

创建你的数据

若要使用 SemanticZoom,需要一个包含分组信息的 IListDataSource。 创建 IListDataSource 的一种方式是创建 WinJS.Binding.List。每个 WinJS.Binding.List 有一个 dataSource 属性,该属性返回一个包含你的数据的 IListDataSource

  1. 在你的项目中添加新的 JavaScript 文件以包括你的数据。将它命名为 "data.js"。

  2. 在刚创建的 data.js 文件中,创建将为你的 ListView 控件提供数据的基础数据源。以下示例根据 JSON 对象的一个数组 (myData) 创建一个 WinJS.Binding.List

    
    // Start of data.js
    (function () {
        "use strict";
    
    
    
        var myData = [
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Lavish Lemon Ice", text: "Sorbet", picture: "images/60Lemon.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Marvelous Mint", text: "Gelato", picture: "images/60Mint.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Creamy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Succulent Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Very Vanilla", text: "Ice Cream", picture: "images/60Vanilla.png" },
        { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Orangy Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Absolutely Orange", text: "Sorbet", picture: "images/60Orange.png" },
        { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Triple Strawberry", text: "Sorbet", picture: "images/60Strawberry.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Double Banana Blast", text: "Low-fat frozen yogurt", picture: "images/60Banana.png" },
        { title: "Green Mint", text: "Gelato", picture: "images/60Mint.png" }
        ];
    
        // Create a WinJS.Binding.List from the array. 
        var itemsList = new WinJS.Binding.List(myData);
    

    注意  此数据指的是几个图像。要获取图像,请下载 ListView 分组和 SemanticZoom 示例,然后从示例复制图像到你的项中。你还可使用你自己的图像—,只需确保已更新了数据中的 picture 属性的值。

     

    提示  

    除了 WinJS.Binding.List,你还可以使用 StorageDataSource 或自定义 VirtualizedDataSource。有关创建自定义数据源的详细信息,请参阅如何创建自定义数据源

     

  3. 创建一个包含分组信息的数据源版本。 如果你使用的是 WinJS.Binding.List,则可以调用它的 createGrouped 方法来创建 List 的分组版本。createGrouped 方法采用以下三个参数:

    • getGroupKey:一个函数,在给出列表中的某个项目时,返回该项目所属的组密钥。
    • getGroupData:一个函数,在给出列表中的某个项目时,返回代表该项目所属的组的数据对象。
    • compareGroups:一个函数,对两个组进行比较,并在第一个组小于第二个组的情况下返回一个负值,在两个组相等时返回零,在第一个组大于第二个组时返回一个正值。

    此示例使用 List.createGrouped 方法创建 List 的分组版本。它使用每个项的标题的第一个字母来定义组。

        // Sorts the groups.
        function compareGroups(leftKey, rightKey) {
            return leftKey.charCodeAt(0) - rightKey.charCodeAt(0);
        }
    
        // Returns the group key that an item belongs to.
        function getGroupKey(dataItem) {
            return dataItem.title.toUpperCase().charAt(0);
        }
    
        // Returns the title for a group.
        function getGroupData(dataItem) {
            return {
                title: dataItem.title.toUpperCase().charAt(0)
            };
        }
    
        // Create the groups for the ListView from the item data and the grouping functions
        var groupedItemsList = itemsList.createGrouped(getGroupKey, getGroupData, compareGroups);
    
  4. 使你的数据可以访问程序的其他部分。此示例使用 WinJS.Namespace.define 使分组的列表可公开访问。

        WinJS.Namespace.define("myData",
            {
                groupedItemsList: groupedItemsList
            }); 
    
    
    })(); // End of data.js
    

创建两个 ListView 控件

正如之前所述,SemanticZoom 控件需要其他两个用于实现 IZoomableView 接口的控件:一个用于提供放大的视图,另一个用户提供缩小的视图。

  1. 在将要包含 SemanticZoom 的 HTML 页面的 head 部分中,添加对上一步中创建的数据文件的引用。

    
    
        <!-- Your data file. -->
        <script src="/js/data.js"></script>
    
  2. 为你的 ListView 对象定义 3 个模板:一个用于放大的项目视图、一个用于放大视图中的组标头,另一个用于缩小视图中的组标头。

    <!-- Template for the group headers in the zoomed-in view. -->
    <div id="headerTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
        <div class="simpleHeaderItem">
            <h1 data-win-bind="innerText: title"></h1>
        </div>
    </div>
    
    <!-- Template for the ListView items in the zoomed-in view. -->
    <div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
        <div class="mediumListIconTextItem">
            <img class="mediumListIconTextItem-Image" data-win-bind="src: picture" />
            <div class="mediumListIconTextItem-Detail">
                <h4 data-win-bind="innerText: title"></h4>
                <h6 data-win-bind="innerText: text"></h6>
            </div>
        </div>
    </div>
    
    <!-- Template for the zoomed out view of the semantic view. -->
    <div id="semanticZoomTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
        <div class="semanticZoomItem">
            <h1 class="semanticZoomItem-Text" data-win-bind="innerText: title"></h1>
        </div>
    </div>
    
  3. 在 HTML 中,定义两个 ListView 控件。第一个控件提供放大的视图,而第二个控件提供缩小的视图。

    • 将用于放大的 ListViewitemDataSource 设置为 myData.groupedItemList.dataSource,它是包含要显示的项目的 IListDataSource。将其 groupDataSource 设置为 myData.groupedItemsList.groups.dataSource,它是包含组信息的 IListDataSource
    • 对于缩小的 ListView,将其 itemDataSource 设置为 myData.groupedItemList.groups.dataSource,它是包含组信息的 IListDataSourceListView 从该位置获取要显示的组标题。

    该示例创建了两个 ListView 控件,并将其配置为使用你刚创建的模板。

    
    
        <!-- The zoomed-in view. -->    
        <div id="zoomedInListView"
            data-win-control="WinJS.UI.ListView" 
            data-win-options="{ itemDataSource: myData.groupedItemsList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), groupHeaderTemplate: select('#headerTemplate'), groupDataSource: myData.groupedItemsList.groups.dataSource, selectionMode: 'none', tapBehavior: 'none', swipeBehavior: 'none' }"
        ></div>
    
        <!--- The zoomed-out view. -->
        <div id="zoomedOutListView"
            data-win-control="WinJS.UI.ListView"
            data-win-options="{ itemDataSource: myData.groupedItemsList.groups.dataSource, itemTemplate: select('#semanticZoomTemplate'), selectionMode: 'none', tapBehavior: 'invoke', swipeBehavior: 'none' }"
        ></div>
    
  4. 在你的 CSS 文件中,定义用于模板和 ListView 控件的样式。如果跳过该步骤,你的应用仍将运行,但它的外观会受到影响。

    /* Template for headers in the zoomed-in ListView */
    .simpleHeaderItem
    {
        width: 50px;
        height: 50px;
        padding: 8px;
    }   
    
    /* Template for items in the zoomed-in ListView */  
    .mediumListIconTextItem
    {
        width: 282px;
        height: 70px;
        padding: 5px;
        overflow: hidden;
        display: -ms-grid;
    }
    
        .mediumListIconTextItem img.mediumListIconTextItem-Image 
        {
            width: 60px;
            height: 60px;
            margin: 5px;
            -ms-grid-column: 1;
        }
    
        .mediumListIconTextItem .mediumListIconTextItem-Detail
        {
            margin: 5px;
            -ms-grid-column: 2;
        }
    
    /* Template for items in the zoomed-out ListView */
    .semanticZoomItem
    {
        width: 130px;
        height: 130px;
        background-color: rgba(38, 160, 218, 1.0);
    }   
    
        .semanticZoomItem .semanticZoomItem-Text
        {
            padding: 10px;
            line-height: 150px;
            white-space: nowrap;
            color: white;
        }
    
    /* CSS for the zoomed-in ListView */
    #zoomedInListView
    {
        width: 600px;
        height: 300px;
        border: solid 2px rgba(0, 0, 0, 0.13);
    }
    
    #semanticZoomDiv 
    {
        width: 600px;
        height: 300px;
        border: solid 2px rgba(0, 0, 0, 0.13);
    }
    
  5. 运行应用。你会看到两个 ListView 控件:

    两个 ListView 控件

第一个 ListView 提供放大的视图,而第二个提供缩小的视图。请注意,这两个控件都使用水平布局。我们建议数据的放大视图和缩小视图始终使用相同的布局。

添加 SemanticZoom 控件

在你的标记中,创建 SemanticZoom 控件并将你的 ListView 控件移到其中。

<div id="semanticZoomDiv" data-win-control="WinJS.UI.SemanticZoom">   
            
    <!-- The zoomed-in view. -->    
    <div id="zoomedInListView"
        data-win-control="WinJS.UI.ListView" 
        data-win-options="{ itemDataSource: myData.groupedItemsList.dataSource, itemTemplate: select('#mediumListIconTextTemplate'), groupHeaderTemplate: select('#headerTemplate'), groupDataSource: myData.groupedItemsList.groups.dataSource, selectionMode: 'none', tapBehavior: 'none', swipeBehavior: 'none' }"
    ></div>

    <!--- The zoomed-out view. -->
    <div id="zoomedOutListView"
        data-win-control="WinJS.UI.ListView"
        data-win-options="{ itemDataSource: myData.groupedItemsList.groups.dataSource, itemTemplate: select('#semanticZoomTemplate'), selectionMode: 'none', tapBehavior: 'invoke', swipeBehavior: 'none' }"
    ></div>

</div>

现在,在运行该应用时,你将看到一个 ListView,而且可以在你定义的两个视图之间缩放。

SemanticZoom 控件的缩小和放大视图

注意  不要在 SemanticZoom 控件的子控件上设置边框。 如果你在 SemanticZoom 及其子控件上设置边框,则 SemanticZoom 边框以及视野范围内的子控件的边框都将可见。在放大/缩小时,子控件的边框会随着内容一起缩放,而且看上去不太好看。仅在 SemanticZoom 控件上设置边框。

 

使用 SemanticZoom

在两个视图之间缩放:

输入机制 缩小 放大
触摸 扩大 收缩,点击
键盘 Ctrl + 减号、Enter Ctrl + 加号、Enter
鼠标 Ctrl + 向后滚动鼠标滚轮 Ctrl + 向前滚动鼠标滚轮

 

针对自定义控件使用 SemanticZoom

若要针对 ListView 以外的控件使用 SemanticZoom,则必须实现 IZoomableView 接口。有关展示具体做法的示例,请参阅自定义控件的 SemanticZoom 示例

保持 SemanticZoom 的可响应性

用户可以在 SemanticZoom 的放大视图和缩小视图之间快速顺畅地进行切换,这一点很重要。这表示,SemanticZoom 控件的子控件在加载其数据时不应该让应用等待。将 ListView(或已自定义用于实现 IZoomableViewFlipView 版本)与 SemanticZoom 结合使用时,使用模板函数,该函数会在控件在视图中可见但项目不可见的情况下创建占位符。有关在项模板中使用占位符的更多信息,请参阅 FlipView.itemTemplate。如果将自定义控件与 SemanticZoom 结合使用,则当项目可能不可见时实现进度环并使用占位符。

示例

摘要和后续步骤

你已经了解如何创建使用两个 ListView 控件的 SemanticZoom 来创建放大和缩小视图。

现在,可以通过阅读 SemanticZoom 控件指南和清单来了解有关何时以及如何使用 SemanticZoom 的更多信息。

相关主题

SemanticZoom 控件指南和清单

SemanticZoom

语义缩放示例

ListView