移动端的select解决方案

lucky-select

https://github.com/gaofeiyu/lucky-select.git

移动端的select解决方案,可级联(现在只有二级联动)。 组件参考自新浪的微招聘,致敬!

基本指令说明

单级指令 singleSelectorPopup 二级联动指令 doubleSelectorPopup 上面两个指令主要是生成下拉部分

参数

//初始化的值
title 标题
initData 初始化的值
data 下拉数据
getRightListData 二级联动通过该属性的方法过滤生成二级菜单,单级联动不存在该属性

这里的data为数组,包含两个必要键值

{id:1,name:"id对应的展示名称"}

方法

  • show(val) val为初始化的对象
  • hide() 隐藏
  • onConfirm() 确认
  • onCancel() 取消

selector单级指令

该指令是在singleSelectorPopup基础上封装的选择的部分,供使用者参考。

        scope: {value: "=", options: "=", name: "@", readonly:"@", index:"="},
        template: "<span class='selector' ng-click='showPopup();'>{{str}}</span>",
        restrict: "EA",

参数说明

  • value 显示在前台的值
  • options 下拉的数据
  • name 下拉标题
  • readonly 是否只读(不弹出下拉,只展示值)
  • index 当前选择值的索引

效果

例图1 例图2

overlay遮罩指令

通用的遮罩指令,也可以用在其他组件上。

指令说明

replace: true,
template: '<div id="overlay"  ng-click="bindClick();"></div>',
restrict:"EA"

方法

  • show(hideCallback) hideCallback会在hide里面回调
  • hide()
  • clear()

总结一下写grunt脚本的思路

今天终于写个接近最终版的脚本,简单总结一下思路。
先确定我都要干什么,总结如下:

【cssmin】压缩css

【uglify】压缩js

【cssmin】合并css到style.css

【uglify】合并js库/框架文件到lib.js

【uglify】合并自定义js到script.js

【copy】复制需要处理的html到目标地点(单页面项目只涉及到一个文件)

【usemin】然后处理目标文件

【filerev】处理目标文件版本号问题(对合并后的制定文件,现在只写了js和css)

 

弄清思路后一步步操作,这个脚本总算是正常工作了。

 

和一些说明有所不同的是,我这里没有用concat、jshint、clean。

concat是被cssmin和uglify的功能替代掉了,不写也可以合并。

jshint没用主要是因为对自己代码不是特别有自信,用了以后感觉要花好多时间调试…

clean是真心用不上。

 

参考文章:

http://ericnishio.com/blog/compile-less-files-with-grunt
http://www.xuanfengge.com/npm-installation-did-not-succeed-and-github-will-not-open-solutions.html
https://www.npmjs.org/package/grunt-html-build
https://www.npmjs.org/package/grunt-contrib-concat
https://www.npmjs.org/package/grunt-contrib-less
https://www.npmjs.org/package/grunt-contrib-watch

 

grunt-usemin(中文文档)

grunt-usemin的作用

usemin用来生成优化后(合并,压缩)的脚本,然后以此替换html文件里面的javascript, css和其他脚本的引用

使用方式

npm install grunt-usemin --save-dev

任务

usemin通过两个内置的任务来完成上述的功能,分别是useminPrepare和usemin,同时还需要其它一些优化工具(cssmin,concat等)来完成优化工作。usemin通过动态的为这些优化工具插件生成子任务的方式来实现整个的目标。

usemin的两个内置的任务

  • useminPrepare 准备配置文件。配置文件是根据结构化的文件(如html)里面的块声明来生成的。最终把这些应用替换成优化后的文件引用。在这个过程中,为每个优化的步骤生成了很多的名为generated的子任务,这些优化的步骤每步都是一个grunt插件,下面将会列举出来。
  • usemin 把结构化文件(html)的块声明里面的文件引用替换。如果那些脚本文件有打过版本声明的,将会用版本声明的文件应用来替换。这个个过程会直接修改结构化文件(如html)的内容。

你必须手动的install和load构建过程中需要的依赖插件 基本例子:

grunt.registerTask('build', [
    'useminPrepare',
    'concat:generated',
    'cssmin:generated',
    'uglify:generated',
    'filerev',
    'usemin'
    ]);

useminPrepare任务

useminPrepare 在之前配置基础上,生成新的配置文件,在这个新的配置文件里定义了文件整个处理过程。默认情况下js文件会做concat,uglify处理,css文件会做concat,cssmin处理。

结构化文件(html)的块声明

<!-- build:<type>(alternate search path) <path> -->
    ... HTML Markup, list of script / link tags.
    <!-- endbuild -->
  • type 文件类型 可以是css,js,或者其他自定义类型(后面会讲到)。如果都不是构建脚本会忽略。这个引用块只会在开发环境出现,最后的build成功后不会出现。
  • alternate search path (可选的)默认情况下那些脚本文件的查找都是相对当前处理的文件的。
  • path 优化后文件的输出目录。
<!-- build:js js/app.js -->
    <script src="js/app.js"></script>
    <script src="js/controllers/thing-controller.js"></script>
    <script src="js/models/thing-model.js"></script>
    <script src="js/views/thing-view.js"></script>
    <!-- endbuild -->

处理流程

整个处理流程分很多步骤:每个步骤处理完后,useminPrepare就会修改配置文件,确保整个流程正确的执行。

默认的处理流程是合并后压缩。除此之后,在合并压缩之后可以定义一个后置的处理函数来做一个额外的工作,来修改配置文件。

下面看一个例子,使用了默认的处理流程。

下面是block声明
<!-- build:js js/app.js -->
<script src="js/app.js"></script>
<script src="js/controllers/thing-controller.js"></script>
<script src="js/models/thing-model.js"></script>
<script src="js/views/thing-view.js"></script>
<!-- endbuild -->

处理后的生成的配置文件如下:

{
    concat:
    generated: {
    files: [
    {
    dest: '.tmp/concat/js/app.js',
    src: [
    'app/js/app.js',
    'app/js/controllers/thing-controller.js',
    'app/js/models/thing-model.js',
    'app/js/views/thing-view.js'
    ]
    }
    ]
    }
    },
    uglify: {
    generated: {
    files: [
    {
    dest: 'dist/js/app.js',
    src: [ '.tmp/concat/js/app.js' ]
    }
    ]
    }
    }
    }

指南

默认情况下usemin会把当前处理的文件作为‘根文件系统’,所有其他的相对路径,都是参照此路径。这个方式也同样适用绝对路径。如果需要改变‘根文件系统’,你需要在option中从定义root属性(下面会提到)

concat/cssmin/uglify这些任务的配置是useminPrepare生成的,没有必要专门为这些任务定义配置文件了。

options

dest string类型,默认为null 处理后的文件的基准输出路径。 staging string类型,默认.tmp 临时文件的输出路径(上面的例子提到过) root string|array类型,默认null 处理文件路径时的参考的’根文件系统’ flow object类型 默认{ steps: { js: [‘concat’, ‘uglifyjs’], css: [‘concat’, ‘cssmin’] }, post: {} } 通这个选项能在每个目标之前或者所有目标之前配置处理流程。你也能单独的配置steps属性或者post属性。

例如,为html目标改变js文件的处理流程:

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    html: {
    steps: {
    js: ['uglifyjs']
    },
    post: {}
    }
    }
    }
    }

为全部目标改变js文件的处理流程:

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    steps: {
    js: ['uglifyjs']
    },
    post: {}
    }
    }
    }

通过post属性,自定义处理配置文件

useminPrepare: {
    html: 'index.html',
    options: {
    flow: {
    steps: {
    js: ['uglifyjs']
    },
    post: {
    js: [{
    name: 'uglifyjs',
    createConfig: function (context, block) {
    var generated = context.options.generated;
    generated.options = {
    foo: 'bar'
    };
    }
    }]
    }
    }
    }
    }

自定义处理步骤和后置处理器

自定义处理步骤和后置处理器有两个属性 + name string类型 在name指定相应的处理步骤上生效 + createConfig 函数 有两个参数 context block 返回配置对象

context conetxt对象包含了当前step/post-processor运行的一些信息,作为主力流程中的一步,必须要有处理输入的相关目录和文件的配置,同时也必须有输出相关的文件和目录。

context属性: + inDir 输入文件的目录 + inFiles 输入文件 + outDir 输出文件的目录 + outFiles 输出文件 + last 是否是处理步骤的最后一步 + options 此处理步骤的一些可选项

block 例子说明:

<!-- build:js scripts/site.js -->
    <script src="foo.js"></script>
    <script src="bar.js"></script>
    <script src="baz.js"></script>
    <!-- endbuild -->

被解析为block对象如下:

var block = {
    type: 'js',
    dest: 'scripts/site.js',
    src: [
    'foo.js',
    'bar.js',
    'baz.js'
    ],
    raw: [
    '    <!-- build:js scripts/site.js -->',
    '    <script src="foo.js"></script>',
    '    <script src="bar.js"></script>',
    '    <script src="baz.js"></script>',
    '    <!-- endbuild -->'
    ]
    };

usemin任务

usemin任务会做两件事 + 首先会把block替换为一行,这个引用指向之前流程生成的优化后的脚本文件。 + 之后如果找到打过版本的文件,就会用打过版本的文件引用替换当前的引用。

脚本文件的搜索

默认情况下,usemin会使用一个grunt-filerev插件map对象, 这个对象是grunt.filerev.summary,如果没找到就会到磁盘去检索,这样会需要更多的时间。

使用options.revmap会提供一个地图对象,供usemin任务查找

说明

当usemin尝试使用打过版本的文件替换当前引用(也就是之前提到的第2步操作时),就会收集脚本的所有搜索目录。最终生成一个目录的树,并尝试找到打过版本的文件。搜索目录默认是结构化文件(html)的目录,可以通过options重新指定。

例子1: dist/html/index.html有如下内容

<link rel="stylesheet" href="styles/main.css">
    <img src="../images/test.png">

默认情况下就会在dist/html/下搜索打过版本的文件。 + style/main.css将会在dist/html/styles搜索那么版本文件,例如:dist/html/style/main.1234.css就匹配,最终会替换。 + images/test.png将会在 dist/iamges搜索。

换成如下内容

<link rel="stylesheet" href="/styles/main.css">
    <img src="/images/test.png">

搜索的路径仍然不变是上面的dist/html/stylesdist/html/images,现在假如我们的脚本是在另一个目录dist/assets下,我们可以配置options,使得最终的搜索路径在dist/assets下面,例如可能就会有这样的结果:dist/assets/images/test.875487.pngdist/assets/styles/main.98090.css

options

assetsDirs array 类型 脚本搜索的目录 patterns object 类型 用户自定义替换。加入要把js文件里面的所有image.png替换为打过版本后的文件,就可以采用如下定义方式:

usemin: {
    js: '*.js',
    options: {
    assetsDirs: 'images',
    patterns: {
    js: [
    [/(image\.png)/, 'Replacing reference to image.png']
    ]
    }
    }
    }

patterns的key必须出现目标targets中,每个pattern有四个参数,最后两个是可选的,第一个参数表示那些引用是要替换的blockReplacements object 类型 默认值{ css: function (block) { … }, js: function (block) { … } } 由此可以控制替换的具体细节,返回值为最终替换的字符串。 例如:

usemin: {
    html: index.html,
    options: {
    blockReplacements: {
    less: function (block) {
    return '<link rel="stylesheet" href="' + block.dest + '">';
    }
    }
    }
    }
    //less必须和block的type相匹配.

revmap object 类型 声明版本的文件匹配,之后在版本文件的查找替换时是一个依据。 例如:

{
    "foo.png": "foo.1234.png"
    }

小结

useminPrepare任务必须声明输入,临时目录和输出路径。最终输出正确的配置文件,确保正确的文件处理流程。usemin任务,只是处理最终的输出文件。所有的脚本文件必须输出到最后的输出目录中。

useminPrepare 为整个构建过程,生成正确的配置文件,确保每步流程的处理顺序和期望的一致。在block声明的文件,有的是绝对路径,有的是相对路径,路径的文件引用是在搜索路径下(input)查找, 默认情况下就是正在文件本身所在的路径。

usemin 把images,scripts,css…的这些引用,替换为打过版本的文件引用。

例子

app
    |
    +- assets
    |  +- js
    |     +- index.js
    |     +- rank.js
    |  +- css
    |     +- layout.css
    +- index.html
    +- dist

index.html的内容

<!-- build:css(.) /assets/css/layout.min.css -->
    <link rel="stylesheet" href="/assets/css/layout.css"/>
    <!-- endbuild-->
    <!--build:js(.) /assets/js/app.min.js -->
    <script type="text/javascript" src="/assets/js/rank.js"></script>
    <script type="text/javascript" src="/assets/js/index.js"></script>
    <!-- endbuild -->

Gruntfile.js

/**
    * Created by Administrator on 2014/7/15.
    */
    module.exports = function(grunt){
    grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    clean: {
    build: ['.tmp/'],
    release: ['dist/']
    },
    jshint: {
    all: ['assets/**/*.js']
    },
    copy: {
    html: {
    files: [
    {src: ["index.html"], dest: "dist/"}
    ]
    }
    },
    useminPrepare: {
    html: ['dist/index.html']
    },
    filerev: {
    options: {
    length: 8
    },
    generated: {
    files:[
    {src: "dist/assets/**/*.min.js"},
    {src: "dist/assets/**/*.min.css"}
    ]
    }
    },
    usemin: {
    options: {
    assetsDirs: ['dist/']
    },
    html: 'dist/index.html'
    }
    });
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-cssmin');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-usemin');
    grunt.loadNpmTasks('grunt-filerev');
    grunt.registerTask('build', [
    'clean',
    'jshint',
    'copy',
    'useminPrepare',
    'concat:generated',
    'cssmin:generated',
    'uglify:generated',
    'filerev',
    'usemin',
    'clean:build'
    ]);
    }

为angular强化Http请求

我先说问题,代码下面一起给出

添加patch

前两天了解到除了get、post、put还有一个叫patch的相对较新的提交方法,主要是用来做局部更新的意思。
但是angular没有这个方法。

改变请求的格式

angular在提交中文内容是会有乱码出现的情况,编码解码也不行,如果用过zepto的同学可能也遇到过这样的问题。结果导致无法提交服务端想要的信息。

增加请求拦截

对于请求的成功和失败进行拦截操作,比如对401做跳转登录页面的操作。

下面是代码
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
//增加拦截服务
$httpProvider.interceptors.push('userStateInterceptor');
//增加patch请求方法
$httpProvider.defaults.headers.patch = {
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
}
/**
* The workhorse; converts an object to x-www-form-urlencoded serialization.
* @param {Object} obj
* @return {String}
*/
var param = function (obj) {
var query = '', name, value, fullSubName, subName, subValue, innerObj, i;
for (name in obj) {
value = obj[name];
if (value instanceof Array) {
for (i = 0; i < value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if (value instanceof Object) {
for (subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += param(innerObj) + '&';
}
}
else if (value !== undefined && value !== null)
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
return query.length ? query.substr(0, query.length - 1) : query;
};
// Override $http service's default transformRequest
$httpProvider.defaults.transformRequest = [function (data) {
return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
}];
}]).service("userStateInterceptor", ['$location','$q', function ($location,$q) {
//定义拦截操作
var interceptor = {
'request': function (config) {
return config;
},
'response': function (response) {
return response;
},
'requestError': function (rejection) {
return $q.reject(response);
},
'responseError': function (response) {
//这里做401的拦截
switch (response.status) {
case 401:
$location.path('login');
break;
}
return $q.reject(response);
}
}
return interceptor;
}]);

angular1.2到1.3有给新手的坑

今天跟小伙伴散布angular,我下了最新的项目seed给小伙伴们用,然后小伙伴们用原始的教程进入angularJs。

然后就悲剧了…

最新版本1.3.8不再支持函数的控制器匹配
function PhoneListCtrl($scope) {
$scope.phones = [
{"name": "Nexus S",
"snippet": "Fast just got faster with Nexus S."},
{"name": "Motorola XOOM™ with Wi-Fi",
"snippet": "The Next, Next Generation tablet."},
{"name": "MOTOROLA XOOM™",
"snippet": "The Next, Next Generation tablet."}
];
}

会报error:ng[area]…..这样的错误。

虽然这个方式实在各个读物和入门示例中广泛使用的方式,但因为该方式生成了全局的函数,这并不是推荐的,也不符合MVC思想,所以…

不过还是等我读了源码再说更深入,那么现在只能是以下面的方式引入控制器:


angular.module('myApp', []).controller('PhoneListCtrl',['$scope',
function($scope){
}]);

jQuery无冲突处理方案

有一些特殊情况,jQuery可能会与其他的类库同时存在,比如zepto(通常是在某些人犯迷糊的时候)。

在这个时候“$”这个命名空间会出现冲突(或覆盖)。

简单的做法我们可以用“jQuery”或“Zepto”来替代“$”,并在代码中建立属于相关类库的作用域即可,作为命名空间来避免冲突。

那么有没有其他的办法呢。

 

jQuery 核心 – noConflict() 方法

在jquery里面有一个这样的方法可以改变jQuery的命名空间。

可以去看w3cSchool里面的解释

在《JavaScript框架设计》的第一章中就两次提到了这个方案。

我这里cv一下jquery的源代码供参考
//jquery1.2
var _jQuery = window.jQuery , _$ = window.$;
jQuery.extend({
noConflict: function(deep){
window.$ = _$;
if(deep)
window.jQuery = _jQuery
return jQuery;
}
})

要注意的是该方法只对单文件的类库框架有用。

如何对动态加载方式引入的文件解决冲突问题之后再做讨论,不在这里赘述。

禁用触摸设备的全局滚动

我们通过event.preventDefault;来取消事件的默认操作,如果禁用触摸设备的全局滚动我们可以用:

document.body.ontouchmove = function (event) {
event.preventDefault();
}

不过winphone的手机不支持这个方法,可以用下面的方法加在css中兼容:
-ms-touch-action: none;

如果想通过触发恢复全局滚动只要移除上面的事件就可以了,具体可以通过我之前的文章了《event.preventDefault和恢复元素默认事件》解下。

js中的数据类型

截取字符的时候,整型不可以使用indexOf会报错。
可以用取余取整去截取整型字符,或者转成字符串。
另外在比较上如果不用全等(===)就要注意判断的关系,可以看下以下的例子。
“0”==0 true;

0==false true;
“0”==false true;
false==”false” false;
然而即使”0″==0 为 true,
if(“0”) {alert(1)} 会执行 其他两个不会执行。

给一个判断js数据类型的方法供大家研究。

function getType(o)
{
var _t;
return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase();
}

display和offset的关系

事情来自于lazyload的编写,这里以图片()为例:
1.display:none的图片同样会请求;
2.另外设置了display:none元素element.offsetTop 取不到值 
而 
$(selector).offset().top取到的值等于scollerTop的值 。
因此我们在做通过滚动判断图片是否在屏幕中的时候,要考虑标签切换时图片的读取状态和加载规则。

SVG 与 Canvas:如何选择

文章来源:https://msdn.microsoft.com/zh-cn/library/gg193983

本主题一开始将对 SVG 与 Canvas 进行简要比较,接下来会讨论大量的比较代码示例,如光线跟踪和绿屏。

注意  为了查看本主题中包含的很多示例,你必须使用支持 SVG 和 Canvas 元素的浏览器(如 Windows Internet Explorer 9)。

 

简介

HTML 不断演变以提供更好、更丰富的标准图形来帮助改进客户体验。 为 Web 开发人员创造了使用基于标准的 Web 技术创建图形丰富的交互网站和应用程序的机会,而无需使用专用的技术或编写浏览器特定的代码。以下各节介绍了矢量图形的概念并执行相应操作:

  • 区分即时模式和保留模式之间的差异
  • 介绍用于即时模式图形的 HTML5 Canvas 元素并提供对 Canvas 的概述
  • 介绍可缩放矢量图形 (SVG)、一组用于保留模式图形的 HTML5 元素并提供对 SVG 的概述
  • 指导新开发人员和有经验的开发人员对矢量图形和 HTML5 使用其中一个矢量图形模型(或同时使用两者,具体取决于方案)

矢量图形

矢量图形不是新概念。它们是全部基于矢量来表示图像的几何基元(形状、点、线条和多边形)。在 1960 年代后期,向 Logo 编程语言添加了矢量图形语言(海龟绘图)来支持用于执行绘图功能的海龟机器人。虽然图形世界在复杂性方面已经发生了重大的演变,但是存在的基本概念是相同的。

矢量图形的复杂性范围从简单到适中再到相当复杂。下面是一些基本示例。

  • 简单 – 一个文档或插图中的标注。
  • 适中 – 图表、关系图和地图等插图。
  • 复杂 – 类似那些用于工程的文档。

尽管前面的示例在性质上是静态的,但是矢量图形也支持交互性,这是一项可显著扩展方案的关键功能。矢量图形为 Web、桌面和设备上的应用程序提供交互和静态的格式。

矢量图形方案的简要概述

在当今 Web 上

  • 网页中使用矢量图形作为背景图像以支持高 DPI 和“收缩”缩放功能。
  • 地图属性(如 Bing 地图)用来执行线路查找操作。
  • 显示实时的图表和图形的交互式股票网站。
  • 选择和其他地图
  • 航班或音乐厅的座位图。
  • 游戏。

在办公室中

  • Microsoft Office Word(用于剪贴画)、PowerPoint 和 Excel 以及 Visio 形状等高效工具。
  • 输出矢量图形格式的 CAD 工具。
  • 呈现交互图表和图形的 Oracle 和 Microsoft Dynamics 应用程序等企业工具。

在设备上

  • 使得图形用户界面更加丰富。
  • 用户交互小工具和图标。
  • 完整 PDA 用户体验。

专业设计器和使用工具

专业的 Web 设计人员在如下工具集中查看矢量图形:

  • 用于创建高质量静态图像(可以导出为 SVG)的 Adobe Illustrator
  • 可以导出为基于 XML 的矢量语言的 Adobe Flash Professional
  • 用于 Windows Presentation Foundation (WPF) 和 Silverlight 的 Microsoft Expression Blend

请务必注意,矢量图形已经在桌面、设备和 Web 上存在很长时间了。

HTML5 图形技术

借助 HTML5,开发人员或设计人员现在可以使用基于标准的技术来创建以前的体验。这样可消除对插件的安装(50% 的网站放弃访问均与插件的安装相关),从而可以极大地改善用户体验。目前,图形由浏览器原生提供,而对于 Internet Explorer 9,则利用 Microsoft Windows 和硬件加速图形的功能。

下一节概述了两种全新但不同的技术、这两种技术的使用方法以及各自的优势和限制。使用一个矢量图形方案谱表来讨论用于为每个方案选择最佳技术的方法。

下图显示了存在于矢量图形中的一个常规方案谱表。每一个方案都可能会更接近于 canvas 或 svg,这意味着一种技术相对于其他技术更适合该方案。如果方案位于谱表中间,那么选择任一技术都是可行的

矢量图形方案谱表几乎所有矢量图形都可以使用上述任一种技术来绘制,但有时根据任务的不同,会有非常多的工作要由开发人员或计算机完成。 当我们检查每种技术的用例,然后将其应用于常见方案时,我们会进一步了解此谱表。

技术简介

下一节介绍了用于在 HTML5 中创建矢量图形的技术,从而建立对早期存在的方案的讨论。

使用示例

若要使用以下示例,请将以下代码示例用作模板。可以使用此模板来开发 SVG 而非 HTML。此模板在本主题的每个示例中使用。由于格式原因,你可以使用脚本以及样式。此模板还包含一个 Meta 标记,这使得可以在本地文件共享上更轻松地进行 SVG 开发。这些示例使用下面的格式。首先提供有意义的代码,然后链接到完整代码。

<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=9"/>
    <style type="text/css" media="screen">
    </style>
    <script type="text/javascript">
    </script>
  </head>
  <body>
  </body>
</html>

http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/template.htm (单击“查看源文件”即可查看此标记)。

SVG

SVG 用于描述可缩放矢量图形,这是一个保留在内存中模型中的保留模式图形模型,而内存中模型可通过重新呈现的代码结果进行操作。这不同于即时模式,该模式将稍后讨论。在 HTML5 中同时提供这两种模式。

SVG 是一个保留模式模型,作为对独立供应商(Microsoft 和 Adobe)所提出的两个建议的回应,在 1999 年引入。成立了 W3C SVG 工作组,并且在 2001 年 SVG 规范达到了“建议的状态”。目前,我们按照 SVG 1.1 第 2 版工作,该版本在编写本文时处于“最后征求意见”阶段。

尽管 SVG 可以作为独立文件进行提供,但是最初着重于将它与 HTML 自然集成。

类似于 HTML,SVG 也是使用元素、属性、和样式来构建文档。首次将 <svg> 元素引入到文档中时,该元素的行为非常类似于 <div> 且作为 HTMLDocument 的一部分,但它包含附加接口 SVGDocument(SVGDocument 提供与矢量图形的更深入、更丰富的交互)。

元素

尽管外部 <svg> 包装适合于 HTML 框模型,但是大多数情况下,内部模型都会从该包装中分离出来,因为矢量不局限于简单的框。这种分离要求扩展 SVG 中的属性才能提供丰富的图形。

例如:

<svg height="1000px" width="1000px">	
  <rect id="myRect" height="100px" width="100px" fill="blue"/>
</svg>

http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/bluerect.htm

注意  为了呈现此内容以及以下很多示例,你必须使用支持 SVG 和 Canvas 元素的浏览器(如 Internet Explorer 9)。

之前的 HTML 代码将创建一个正方形,长宽均为 100 像素,并使用蓝色背景进行填充。

SVG 蓝色正方形此 <rect> 元素保留在 HTML 文档的文档对象模型 (DOM) 中。就像其他 HTML 元素一样,可通过多种不同的方式设置 SVG 的样式。下面的示例是一个表。

样式设置

开发人员可能会注意到属性是类似的。SVG 同时具有属性和演示属性。此处看起来描述有点随意,但关键在于可以按照 CSS 样式规则设置演示属性的样式。

四个矩形使用几种不同的方法进行填充。

<!--No fill (defaults the color to #000000)-->
<rect id="myRect1" height="100%" width="100%" >

<!--using the-->
<rect id="myRect2" height="100%" width="100%" class="greenrect"/>

<!--using the style="fill:pink"-->	
<rect id="myRect3" height="100%" width="100%" style="fill:pink"/> 

<!--using the attribute fill="red"-->	
<rect id="myRect4" height="100%" width="100%" fill="red"/>

四个带颜色的 SVG 正方形第一个示例演示省去一个属性会在图形上产生可视效果。在此示例中,颜色默认为黑色。

第二个示例演示使用 class=”greenrect” 来填充矩形。包含的用于填充此矩形的 CSS 的形式为:

rect.greenrect {fill:green;}

第三个示例使用内联样式将填充设置为粉色。最后一个示例使用相应属性填充红色。此示例还演示了 CSS 选择器的用法。样式还包括:

rect:hover {fill:yellow;}

这针对所有矩形建立一个规则,即鼠标悬停在这些矩形之上时颜色更改为黄色。

这些对于有经验的 Web 开发人员来说应该都不是新内容了。此处提供这些示例是为了强调相似性(使用样式、样式表、类和选择器)以及差异(样式不适用于所有属性,仅适用于演示属性、新属性或不一致的属性)。

http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/svgstyling.htm

可编程性

属性 API 及其他 DOM 操作仍应用并遵循当前的属性规则。例外情况是,演示应用程序基于样式所取代的属性(如果适用)。

如果这些属性是通过核心属性或通过其各自的 DOM 方法进行设置的,则将影响这些属性的演示,并且基础 DOM 将相应地发生更改(注意使用 SVG DOM 设置高度的不同语法):

document.getElementById("myDiv").style.height = "200px";
// alternatively
//document.getElementById("myDiv").style="height;200px";

document.getElementById("myRect").height.baseVal.value = 200;
// alternatively
//document.getElementById("myRect").setAttribute("height","200px");

交互

SVG 的另一个关键区分因素是能够进行代码交互且不复杂。正如 SVG 具有一个类似 HTML 的可编程 DOM 一样,它还具有事件模型。检查下面比矩形或正方形更复杂的图形:路径。

使用路径可绘制任意形状,例如在该示例中为表示美国的阿拉斯加州和夏威夷州的两个形状。

阿拉斯加州和夏威夷州http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/svginteractivity.htm

触发创建之前指定的警报的事件。这些复杂形状(像更简单的矩形)也会响应 CSS 选择器。使用一行 CSS 即可实现简单的突出显示机制:

path:hover {fill:yellow;}

Canvas

另一种向用户提供更丰富的图形体验的方法,通过 <canvas> 标记提供,该标记由 Apple for Safari 在 HTML5 中或在其他图形小工具中引入。它在绘制即时模式图形(包括矩形、路径和图像)方面公开更具编程性的体验,与 SVG 类似。即时模式图形呈现是一个“触发即忘”模型,该模型将图形直接呈现到屏幕上,但随后对所完成的操作不保留任何上下文。与保留模式相反,不保存呈现的图形;要在每次需要新框架时描述整个场景,开发人员需要重新调用所有必需的绘图命令,而不考虑实际更改(SVG 已知拥有“场景图”)。

元素

为了使用画布 (Canvas) 功能,Web 开发人员直接引入了一个 Canvas 元素:

<canvas id="myCanvas" width="1200px" height="1200px"></canvas>

然后使用 <canvas> 传统的2D基础库 API 来绘制图像和矢量。

使用 JavaScript 代码执行对画布上图形的操作,通过添加对图形的支持可以获得 Web 开发人员熟悉使用的优势。

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");

如前面提到的,存在与 SVG 中相似的形状和对象,举例来说,开发人员可以使用下面的代码来绘制矩形:

ctx.fillStyle = "rgb(0,0,255)";
ctx.fillRect(10, 10, 100, 100);

稍后将讨论这些方法的优缺点以及适当的方案。

最终结果与在 SVG 中相同。http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasintro.htm

Canvas 蓝色正方形但正如 SVG 一样,Canvas 具有更复杂的几何基元,区别在于这些基元采用函数形式。

事件的可编程性

为了能够绘制比矩形更复杂的图形(如前面显示的夏威夷地图),canvas API 提供了一个路径 API,该路径 API 支持与 SVG 中的 <path> 元素相似的命令,只是你要对每一行代码段调用相应的 API,而不是在单个属性中列出它们:

ctx.beginPath();
ctx.moveTo(233.08751,519.30948);
ctx.lineTo(235.02744,515.75293);
ctx.lineTo(237.29070000000002,515.42961);
ctx.lineTo(237.61402,516.23791);
ctx.lineTo(235.51242000000002,519.30948);
ctx.lineTo(233.08751,519.30948);
ctx.closePath();

有关夏威夷地图,请参阅 http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasmap.htm

路径 API 并不局限于 moveTo 和 arc,它包含相同的 SVG 方向相位(包括二次曲线和贝塞尔曲线)。

通过有限的事件和功能可以捕获鼠标在图像上的位置。因为不存在图形保留知识,所以编程人员必须转换 mouseX 标记的单个元素上的 mouseY<canvas> 坐标,然后将该命令相应地传送到位于内存中结构中的形状。第三方库为支持更复杂的路径而存在,这包括内置isPointInPath API,但后者被限制为最后路径绘制。因而与 SVG 不同,既没有任何样式也不支持多个几何图上的命中检测。另外,因为 Canvas 不支持可伸缩性,所以缩放时夏威夷地图将很快失真:

夏威夷地图在缩放时显示失真Canvas 是一个功能强大的低级别 API,开发人员利用它可以提供新的图形体验。

Canvas 与 SVG 的简要摘要

下面是简要摘要,可帮助你确定何时使用 Canvas 而不使用 SVG 或者何时使用 SVG 而不使用 Canvas 来创建矢量图形。

Canvas SVG
基于像素(动态 .png) 基于形状
单个 HTML 元素 多个图形元素,这些元素成为 DOM 的一部分
仅通过脚本修改 通过脚本和 CSS 修改
事件模型/用户交互颗粒化 (x,y) 事件模型/用户交互抽象化 (rect, path)
图面较小时、对象数量较大 (>10k)(或同时满足这二者)时性能更佳 对象数量较小 (<10k)、图面更大(或同时满足这二者)时性能更佳

 

在上表中,考虑这二者在现有软件方面的意象模型。Canvas 类似于 MSPaint,在其中,你可以使用形状和其他工具来绘制和创建图像。SVG 类似于 Office PowerPoint 幻灯片,它具有可编程的支持并且能够添加主题。

何时使用 <canvas>、何时使用 SVG:方案

这一节介绍这两种技术的技术优势和限制,包括用于确定一种技术何时相对于另一种技术更适合的常用方法。应该注意的是,SVG 和 <canvas> 都能实现几乎相同的结果,功能也完全重复。介绍以下特定情况非常重要:<canvas> 明显好于 SVG,或相反,二者组合更加合适,或可以使用和考虑任一技术。

矢量图形方案谱表这些方案比较清晰地描述了更适合使用 SVG 的情况、更适合使用 Canvas 的情况,以及其他介于这之间的情况。它们描述了每种技术的优缺点,以便开发人员可以了解相应技术的行为并针对其应用程序做出好的选择。

从性能方面选择

有时存在一些外部影响,要求独立于(或几乎独立于)功能选择技术。有关使用 Canvas 或 SVG 的问题,存在两个主要区别。

有时开发人员的知识、技能组合和现有资产会对技术的选择起到重大作用。如果开发人员具备低级别图形 API 方面的深层知识,但在 Web 技术方面知识有限,则很可能会选择 Canvas 技术。

另外,性能对于高流量的网站来说是绝对关键的。可以对这两种技术的性能特征加以比较。这可能会要求开发 Canvas 没有附带的辅助功能、自定义样式以及更粒度化的用户交互功能。虽然 Canvas 通常被视为具有高性能,但是并不意味着它就是明显的选择。下图显示了 SVG 对象和 Canvas 对象之间在呈现时间上的差异。

Canvas 与 SVG 性能一般情况下,随着屏幕大小的增大,画布将开始降级,因为需要绘制更多的像素。随着屏幕上的对象数目增多,SVG 将开始降级,因为我们正不断将这些对象添加到 DOM 中。这些度量不一定准确,以下方面的不同一定会引起变化:实现和平台、是否使用完全硬件加速的图形,以及 JavaScript 引擎的速度。

高保真度的复杂矢量文档

高保真度的复杂矢量文档已经成为并将继续成为 SVG 的最有效点,原因主要有两个。存在足够多的极为详细的文档,包括由 CAD 程序生成的那些文档,针对这些文档,SVG 的 scalable 部分提供了独立文档形式或嵌入网页中的文档形式的详细视图。通过该技术还可以进行高保真打印。SVG 的声明性性质向工具、客户端或服务器端提供从数据库生成形状的能力。 最后,我们看到了政府机构的发展,因工程图(为了专利)或工业图(为了城市规划目的)缘故从建议支持转变为对 SVG 的必需支持。这种转变还将继续,因为对于公众使用的电子文档(如下),政府部门越来越不是只喜欢一家供应商:

  • 建筑图、工程图和楼层图
  • 电子图、航空图和示意图
  • 组织结构图
  • 地图
  • 生物图

以下各图显示了前一方案中可以保留的详细信息示例。第一个图像显示可以在测试驱动网站上找到的网页快照。它包含呼吸系统图和元素周期表。

http://ie.microsoft.com/testdrive/Graphics/RealWorldDataAndDiagrams/Default.xhtml

缩小的元素周期表第二个图像显示同一张图放大 1000% 后的效果

放大的元素周期表尽管考虑到观察大的示意图的有用性,但在需要细化到细节处时或者出于工程目的需要打印整个示意图时,具有可缩放性的 S 将变得足够清晰和有价值。出于这些原因,我们将高保真度的复杂矢量文档放在谱表的远端,接近 SVG,如下图中所示。

高保真的文档显示在接近 SVG 的谱表端这些文档也可以受益于交互性,这是 SVG 使这些方案最适合于保留图形模式的第二方面。

增强的 Web 图形

SVG 作为图像格式

SVG 另外还常用于简单图像,无论是应用程序还是网页中的图像,大图像还是小图像。由于 SVG 要加载到 DOM 中,或者创建图像前至少要进行解析,所以性能会稍微有所下降,但相比于呈现网页的成本(大约几毫秒),这种下降是极其微小。

在文件大小方面(为了评估网络流量的目的),下面演示的两个图像是一样的,只差了 1K(SVG 稍微大点,没有压缩)。

两个蓝色球体的图像与以前一样,因为 SVG 作为图像格式是可缩放的,所以如果开发人员想要以更大的比例使用该图像,或者用户使用高 DPI的屏幕,则可移植网络图形 (PNG) 要么会变得异常,要么需要更大形式的文件来实现保真。

两个蓝色球体的图像SVG 因此可以充当非常好的图像替换格式,甚至对网页上最简单的图像也是如此。静态 WebApp/网页图像因此落在谱表的 SVG 端。

静态图像显示在接近于 SVG 的谱表端

像素操作

在谱表的另一端,当使用 Canvas 时可以获得快速的绘图速度,且不需要保留相应信息。存在若干种最适合于 <canvas> 的实时数据方案。使用光线跟踪在像平面上通过像素跟踪光线路径并模拟其与虚拟对象相遇的效果,可以水化图像。 下图显示了这种模拟。

使用 Canvas 的光线跟踪示例

需要很多计算,因此速度依赖于浏览器中的 JavaScript 引擎速度。然而尽管大多数情况下本地代码无可置疑要更快一些,但是随着 JavaScript 引擎逐渐成熟,我们开始看到在像程序集和 C++ 这样的时期内这种差距在缩小。

光线跟踪(通常在 Web 上的背景中完成)获得的效果甚为广泛。范围从创建许多不同的视觉效果(包括根据其他简单矢量图形创建逼真的图像)到应用照片过滤器以去除红眼。

因为 Canvas API 允许开发人员读写像素,所以这里唯一的限制是速度和想象力。上一个示例由 Adam Burmister 提供并且位于 http://labs.flog.co.nz/raytracer/ 上。 在此示例中,可通过大量的库来实现创建最终图像所需的计算,但主结束函数是 fillRect

setPixel: function(x, y, color){
  var pxW, pxH;
  pxW = this.options.pixelWidth;
  pxH = this.options.pixelHeight;

  this.canvas.fillStyle = color.toString();
  this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
},

出于此原因,高性能图形(如光线跟踪器)作为 Canvas 方案落在谱表的最左端,如下图所示。

高性能图形在谱表上靠近 Canvas注意生成上述光线跟踪器的作者 注意 因为该方案将产生静态图像,所以桌面软件经过了很好的调整以适合光线跟踪器所需的大量浮动操作。

下至金属像素操作的有趣实现是图像的过滤器应用。过滤器已存在于 Web 上,且需要显著的处理速度(受益于其对图形管道中更深层的硬件加速图形的应用),因此开发人员可以试用边缘检测或其他数学表达式等算法。

实时数据

对于更常见的方案,Canvas 非常适合输出实时数据。请注意如何简便地确定这些方案,因为已经表明使用 Canvas 难以进行用户交互。因此,下面将讨论非交互的实时数据可视化。

今天的天气数据可以通过特定间隔内服务器上生成的图像非常静态地呈现,也可以尽可能快地通过客户端第三方插件呈现。尽管 ECWMF 已经研究过使用 SVG 而不使用服务器生成的图像如何节省成本,但是 Canvas 在天气模式(以及其他快速的实时数据)的大多数图形表示形式方面,明显是赢家。下图显示以图形方式显示在地图上的天气模式。

显示在地图上的天气模式

如你可以从上图中看到的,没有必要存在大的绘图图面,而且屏幕上的对象数量是相当高的。通过使用 Canvas API,可以在不影响 DOM 的情况下快速绘制(和擦除)这些对象。尽管可以使用 SVG Ellipse 完成此操作,但是将它们加载到 DOM 中以及通过动画修改它们的成本是非常高的。事实上,无论你是在图像中还是在数据动画中看到大量的形状(尤其是不相似的形状)要进行分析,通常都会指出 Canvas 是要使用的技术。这里的实际限制是受 CPU 速度和 JavaScript 引擎速度的控制,能多快可视化显示数据。但除了占用 CPU 的光线跟踪方案之外,仍然可以实现合理的动画。Reasonable 描述客户端可以使用 JavaScript 执行的操作与服务器可以通过电线计算和封送的操作之间的相对动画。

此方案似乎是 <canvas> 的关键用例。

复杂场景和实时动画在谱表上偏向 Canvas

像素替换(绿屏)

另一个使用 Canvas 的可能情况是,在视频上进行颜色检测以便用其他场景或图像替换背景色。像光线跟踪器或过滤器一样,因 JavaScript 中当前性能速度限制的缘故,很可能会使用桌面软件预处理任何需要高的最终产品质量的现实方案。但是,由于 <canvas> 是为低级别像素读取和写入设计的,因此诸如 greenscreen 替换之类的方案甚至无法使用 SVG 完成。

从两个视频中读写像素到另一个视频中所需的代码要求使用两个视频、两个画布和一个最终画布。一次捕捉视频上的一帧,然后绘制到两个单独的画布上。这样允许读回数据。

ctxSource1.drawImage(video1, 0, 0, videoWidth, videoHeight);
ctxSource2.drawImage(video2, 0, 0, videoWidth, videoHeight);

因此,下一步是检索每个绘制图像的句柄,以便你可以检查每个单独的像素。

currentFrameSource1 = ctxSource1.getImageData(0, 0, videoWidth, videoHeight);
currentFrameSource2 = ctxSource2.getImageData(0, 0, videoWidth, videoHeight);

获取后,代码将浏览绿屏的像素数组,搜索绿色像素,如果找到,代码将用背景场景中的像素替换所有绿色像素。

for (var i = 0; i < n; i++) 
{
  // Grab the RBG for each pixel:
  r = currentFrameSource1.data[i * 4 + 0];
  g = currentFrameSource1.data[i * 4 + 1];
  b = currentFrameSource1.data[i * 4 + 2];

  // If this seems like a green pixel replace it:
  if ( (r >= 0 && r <= 59) && (g >= 74 && g <= 144) && (b >= 0 && b <= 56) ) // Target green is (24, 109, 21), so look around those values.
  {
    pixelIndex = i * 4;
    currentFrameSource1.data[pixelIndex] = currentFrameSource2.data[pixelIndex];
    currentFrameSource1.data[pixelIndex + 1] = currentFrameSource2.data[pixelIndex + 1];
    currentFrameSource1.data[pixelIndex + 2] = currentFrameSource2.data[pixelIndex + 2];
    currentFrameSource1.data[pixelIndex + 3] = currentFrameSource2.data[pixelIndex + 3];
  }
}

最后,像素数组将写入到目标画布中。

ctxDest.putImageData(currentFrameSource1, 0, 0);

http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/canvasgreenscreen.htm(若要完整地查看 greenscreen 代码,请查看该页的源代码。)

Canvas 与 SVG 谱表

组合/交叉方案

以下方案可以在 SVG 或 Canvas 中完成,都可以获得适当的结果,但你可能会更喜欢一项技术胜过另一项技术。

图表和图形

需要矢量图形的图表和图形的谱表很宽广。大部分这些图形最好使用 SVG 进行创建,因为它们具有下列三个特征之一:

  • 图形是从可以轻松转换为 XML (SVG) 的现有数据生成的
  • 它们需要用户交互
  • 优点是可在网页上设置样式

我们使用可显著增加方案范围的交互功能来扩展高保真文档方案。 其中包括:

  • 交互的组织结构图和流程图
  • 数据图(环形图、条形图、散点图)
  • 交互式地图 – 路径查找
  • 建筑图、工程图和楼层图
  • 航班或音乐厅的座位图

已经确定快速的实时数据处理已针对 Canvas 进行了更好地优化(主要取决于速度)。

二维游戏

制作休闲游戏(此处定义为 Web 上的简单二维游戏)时,开发人员需要在 canvas 和 svg 之间做出选择。因为历史上游戏库一直利用较低级别的图形 API,所以将倾向于选择 <canvas>

当库的其他组成部分(如受欢迎的物理引擎)比图形层要明显深时,图形将变成实现细节。边框、速度、大小和位置等图形几何将传递给引擎,而引擎随后将用速度、碰撞和位置进行响应。图形位于堆栈中的最高层。

通过由同一作者开发的两个游戏来演示独立于游戏逻辑的图形概念,旨在说明 <svg> 和 <canvas>SVG-oids 和 canvas-pinball。一个出色的、独立于游戏引擎的图形层示例是将 canvas-pinball 与 SVG-Dice 进行比较(当两者都使用相同的物理引擎时)。

尽管游戏和演示逻辑是不同的,但是这两个游戏的物理引擎都会跟踪位置、碰撞、速度以及游戏组成部分的其他物理方面。

对于 canvas-pinball,自定义的更高级别的动画管理器通过使用一系列 Canvas API 重新绘制场景。

if (animationsInProgress) {
  ctx.save();
  ctx.lineWidth = 2.0;
  ctx.beginPath();
  ctx.moveTo(89, 322);
  ctx.lineTo(101, 295);
    .
    .
    .
  ctx.stroke();
  ctx.restore();
  ctx.moveTo(tVp.x, tVp.y);
}

对于 SVG Dice,自定义的更高级别的动画管理器使用组转换通过 DOM 在屏幕上重新定位现有图形。

if (animationsInProgress) 
{
  this.rotation += (this.circleBody.m_linearVelocity.x/20);
  var transFormString = "translate(" +
    Math.round(this.circleBody.m_position.x) + "," +
    Math.round(this.circleBody.m_position.y) + ") scale (" +
    this.scale.toString() + ") rotate(" +
    Math.round(this.rotation).toString() + "," +
    Math.round(this.xTrans).toString() + "," +
    Math.round(this.yTrans).toString() + ")";
    this.die2.setAttribute("transform", transFormString);
}

一种技术要重新绘制和重新定位形状,而另一种技术只需重新定位,但需要在内存中维护形状,这会带来成本。此成本对于大多数休闲游戏来说都是相当低的,但预期是使用较低级别的 API 实现即时模式图形的游戏更加让人熟悉。

高级方案

可能大部分功能强大的方案都会涉及组合整个图形、样式和文档技术。

用户界面设计

几年前可能就在争论 SVG 是否是适合用于用户界面设计的技术。这些要求与 SVG 一致。事实上,Linux 操作系统的至少一个前端完全建立在 SVG 之上。滑块、复选框、圆形按钮等控件以及其他标准固有控件集中的非框控件都很适合在矢量图形中使用。但是,随着 CSS 的最近和未来开发(包括圆角、渐变、过滤器和打印机事件),可以通过标准的框模型 HTML 文档中心构造来开发大多数这些控件。其他控件(尤其是使用最新 CSS Grid 和 Flexbox 模型的控件)都更好地面向 HTML 元素,至少作为容器。

此处提供了一个丰富的数据驱动图表的示例。 尽管该示例的输出没有架构好,但显示的最终结果正确。 图形和图表控件是众所周知的难开发,但第三方以及 Microsoft 已经成功了。 通过在客户端或服务器端提供最新的数据绑定抽象,客户端的 Web 呈现主要保持静态或者需要插件,这样可减轻开发人员的负担。 下面我们利用了 SVG 的丰富性来提供增强的用户体验。 无论代码如何(将传递给客户端,又或许在将来更多的声明性交互中使用),图表都用两个关键组件来呈现。 工具和数据。图形工具或背景是基本的静态 SVG:

<rect id="tipsh" x="20" y="100" width="194" height="34" rx="5" ry="5" />
<rect id="tip" x="20" y="100" width="190" height="30" rx="5" ry="5" />
<text id="tiptxt" x="40" y="120" font-size="12" font-family="Arial" fill="#ffffff" visibility="hidden">milliseconds</text>
<polygon id="arrow" points="10,110 20,105 20,115" style="fill:#ffffff" />
<line x1="3" x2="460" y1="359" y2="359" style="stroke:#cccccc;stroke-width:1"/>

然后每个单独的数据点要么传递到客户端并进行操作,要么在服务器上生成:

<text x="10" y="348" font-size="12" font-family="Arial">{Page}.svg</text>
<rect x="115" y="350" width="86" height="8" style="fill:url(#inverseblue);filter:url(#Gaussian_Blur);" rx="12" ry="12"/>
<rect x="115" y="333" width="86" height="17" rx="12" ry="12" onmouseover="changeColor(evt)" onmousemove="changeText(evt,'2 milliseconds')" onmouseout="changeTextNotOver(evt)" />
<text x="171" y="345" font-size="11" font-family="Arial" fill="#ffffff">6.1%</text>

http://samples.msdn.microsoft.com/workshop/samples/graphicsInHTML5/svgchart.htm

结论

通过最新浏览器中提供的现有矢量图形技术的分析功能,可以交互方式使用标准 Web 技术来满足现有的和新的方案。 从今以后,我们将拥有巨大的机会可以让声明性动画支持广告版位。 通过使用方案驱动的功能开发,我们可以在竞争中处于领先地位,并在 Web 应用程序和网页中提供基于标准的图形丰富的体验。