首先让我们假设手机性能并不是很好。
1、做位移动画translate比trbl更流畅;
2、通过backface-visibility可以开启gpu性能;
3、动画期间transform的属性应该是保持一致的,不然部分手机(小米3)只会做最后定义的动作;
4、在ios6的情况下如果动画不用translate3D,内容多了切换会出现花屏(更准确说应该是translateZ);
5、安卓部分机型不支持对:before元素的动画;
首先让我们假设手机性能并不是很好。
1、做位移动画translate比trbl更流畅;
2、通过backface-visibility可以开启gpu性能;
3、动画期间transform的属性应该是保持一致的,不然部分手机(小米3)只会做最后定义的动作;
4、在ios6的情况下如果动画不用translate3D,内容多了切换会出现花屏(更准确说应该是translateZ);
5、安卓部分机型不支持对:before元素的动画;
本主题一开始将对 SVG 与 Canvas 进行简要比较,接下来会讨论大量的比较代码示例,如光线跟踪和绿屏。
HTML 不断演变以提供更好、更丰富的标准图形来帮助改进客户体验。 为 Web 开发人员创造了使用基于标准的 Web 技术创建图形丰富的交互网站和应用程序的机会,而无需使用专用的技术或编写浏览器特定的代码。以下各节介绍了矢量图形的概念并执行相应操作:
矢量图形不是新概念。它们是全部基于矢量来表示图像的几何基元(形状、点、线条和多边形)。在 1960 年代后期,向 Logo 编程语言添加了矢量图形语言(海龟绘图)来支持用于执行绘图功能的海龟机器人。虽然图形世界在复杂性方面已经发生了重大的演变,但是存在的基本概念是相同的。
矢量图形的复杂性范围从简单到适中再到相当复杂。下面是一些基本示例。
尽管前面的示例在性质上是静态的,但是矢量图形也支持交互性,这是一项可显著扩展方案的关键功能。矢量图形为 Web、桌面和设备上的应用程序提供交互和静态的格式。
专业的 Web 设计人员在如下工具集中查看矢量图形:
请务必注意,矢量图形已经在桌面、设备和 Web 上存在很长时间了。
借助 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 用于描述可缩放矢量图形,这是一个保留在内存中模型中的保留模式图形模型,而内存中模型可通过重新呈现的代码结果进行操作。这不同于即时模式,该模式将稍后讨论。在 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
之前的 HTML 代码将创建一个正方形,长宽均为 100 像素,并使用蓝色背景进行填充。
此 <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"/>
第一个示例演示省去一个属性会在图形上产生可视效果。在此示例中,颜色默认为黑色。
第二个示例演示使用 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> 标记提供,该标记由 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
但正如 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 或者何时使用 SVG 而不使用 Canvas 来创建矢量图形。
Canvas | SVG |
---|---|
基于像素(动态 .png) | 基于形状 |
单个 HTML 元素 | 多个图形元素,这些元素成为 DOM 的一部分 |
仅通过脚本修改 | 通过脚本和 CSS 修改 |
事件模型/用户交互颗粒化 (x,y) | 事件模型/用户交互抽象化 (rect, path) |
图面较小时、对象数量较大 (>10k)(或同时满足这二者)时性能更佳 | 对象数量较小 (<10k)、图面更大(或同时满足这二者)时性能更佳 |
在上表中,考虑这二者在现有软件方面的意象模型。Canvas 类似于 MSPaint,在其中,你可以使用形状和其他工具来绘制和创建图像。SVG 类似于 Office PowerPoint 幻灯片,它具有可编程的支持并且能够添加主题。
这一节介绍这两种技术的技术优势和限制,包括用于确定一种技术何时相对于另一种技术更适合的常用方法。应该注意的是,SVG 和 <canvas> 都能实现几乎相同的结果,功能也完全重复。介绍以下特定情况非常重要:<canvas> 明显好于 SVG,或相反,二者组合更加合适,或可以使用和考虑任一技术。
这些方案比较清晰地描述了更适合使用 SVG 的情况、更适合使用 Canvas 的情况,以及其他介于这之间的情况。它们描述了每种技术的优缺点,以便开发人员可以了解相应技术的行为并针对其应用程序做出好的选择。
有时存在一些外部影响,要求独立于(或几乎独立于)功能选择技术。有关使用 Canvas 或 SVG 的问题,存在两个主要区别。
有时开发人员的知识、技能组合和现有资产会对技术的选择起到重大作用。如果开发人员具备低级别图形 API 方面的深层知识,但在 Web 技术方面知识有限,则很可能会选择 Canvas 技术。
另外,性能对于高流量的网站来说是绝对关键的。可以对这两种技术的性能特征加以比较。这可能会要求开发 Canvas 没有附带的辅助功能、自定义样式以及更粒度化的用户交互功能。虽然 Canvas 通常被视为具有高性能,但是并不意味着它就是明显的选择。下图显示了 SVG 对象和 Canvas 对象之间在呈现时间上的差异。
一般情况下,随着屏幕大小的增大,画布将开始降级,因为需要绘制更多的像素。随着屏幕上的对象数目增多,SVG 将开始降级,因为我们正不断将这些对象添加到 DOM 中。这些度量不一定准确,以下方面的不同一定会引起变化:实现和平台、是否使用完全硬件加速的图形,以及 JavaScript 引擎的速度。
高保真度的复杂矢量文档已经成为并将继续成为 SVG 的最有效点,原因主要有两个。存在足够多的极为详细的文档,包括由 CAD 程序生成的那些文档,针对这些文档,SVG 的 scalable 部分提供了独立文档形式或嵌入网页中的文档形式的详细视图。通过该技术还可以进行高保真打印。SVG 的声明性性质向工具、客户端或服务器端提供从数据库生成形状的能力。 最后,我们看到了政府机构的发展,因工程图(为了专利)或工业图(为了城市规划目的)缘故从建议支持转变为对 SVG 的必需支持。这种转变还将继续,因为对于公众使用的电子文档(如下),政府部门越来越不是只喜欢一家供应商:
以下各图显示了前一方案中可以保留的详细信息示例。第一个图像显示可以在测试驱动网站上找到的网页快照。它包含呼吸系统图和元素周期表。
http://ie.microsoft.com/testdrive/Graphics/RealWorldDataAndDiagrams/Default.xhtml
第二个图像显示同一张图放大 1000% 后的效果
尽管考虑到观察大的示意图的有用性,但在需要细化到细节处时或者出于工程目的需要打印整个示意图时,具有可缩放性的 S 将变得足够清晰和有价值。出于这些原因,我们将高保真度的复杂矢量文档放在谱表的远端,接近 SVG,如下图中所示。
这些文档也可以受益于交互性,这是 SVG 使这些方案最适合于保留图形模式的第二方面。
SVG 另外还常用于简单图像,无论是应用程序还是网页中的图像,大图像还是小图像。由于 SVG 要加载到 DOM 中,或者创建图像前至少要进行解析,所以性能会稍微有所下降,但相比于呈现网页的成本(大约几毫秒),这种下降是极其微小。
在文件大小方面(为了评估网络流量的目的),下面演示的两个图像是一样的,只差了 1K(SVG 稍微大点,没有压缩)。
与以前一样,因为 SVG 作为图像格式是可缩放的,所以如果开发人员想要以更大的比例使用该图像,或者用户使用高 DPI的屏幕,则可移植网络图形 (PNG) 要么会变得异常,要么需要更大形式的文件来实现保真。
SVG 因此可以充当非常好的图像替换格式,甚至对网页上最简单的图像也是如此。静态 WebApp/网页图像因此落在谱表的 SVG 端。
在谱表的另一端,当使用 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 方案落在谱表的最左端,如下图所示。
注意生成上述光线跟踪器的作者 注意 因为该方案将产生静态图像,所以桌面软件经过了很好的调整以适合光线跟踪器所需的大量浮动操作。
下至金属像素操作的有趣实现是图像的过滤器应用。过滤器已存在于 Web 上,且需要显著的处理速度(受益于其对图形管道中更深层的硬件加速图形的应用),因此开发人员可以试用边缘检测或其他数学表达式等算法。
对于更常见的方案,Canvas 非常适合输出实时数据。请注意如何简便地确定这些方案,因为已经表明使用 Canvas 难以进行用户交互。因此,下面将讨论非交互的实时数据可视化。
今天的天气数据可以通过特定间隔内服务器上生成的图像非常静态地呈现,也可以尽可能快地通过客户端第三方插件呈现。尽管 ECWMF 已经研究过使用 SVG 而不使用服务器生成的图像如何节省成本,但是 Canvas 在天气模式(以及其他快速的实时数据)的大多数图形表示形式方面,明显是赢家。下图显示以图形方式显示在地图上的天气模式。
如你可以从上图中看到的,没有必要存在大的绘图图面,而且屏幕上的对象数量是相当高的。通过使用 Canvas API,可以在不影响 DOM 的情况下快速绘制(和擦除)这些对象。尽管可以使用 SVG Ellipse 完成此操作,但是将它们加载到 DOM 中以及通过动画修改它们的成本是非常高的。事实上,无论你是在图像中还是在数据动画中看到大量的形状(尤其是不相似的形状)要进行分析,通常都会指出 Canvas 是要使用的技术。这里的实际限制是受 CPU 速度和 JavaScript 引擎速度的控制,能多快可视化显示数据。但除了占用 CPU 的光线跟踪方案之外,仍然可以实现合理的动画。Reasonable 描述客户端可以使用 JavaScript 执行的操作与服务器可以通过电线计算和封送的操作之间的相对动画。
此方案似乎是 <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 代码,请查看该页的源代码。)
以下方案可以在 SVG 或 Canvas 中完成,都可以获得适当的结果,但你可能会更喜欢一项技术胜过另一项技术。
需要矢量图形的图表和图形的谱表很宽广。大部分这些图形最好使用 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 应用程序和网页中提供基于标准的图形丰富的体验。
说问题之前,先看一张图。
图中要求蓝色问号图标显示在文本末尾。
关于这个问题和app的同学讨论过,app同学表示实现有难度,让设计同学改了设计稿,将icon放到第一行文本后面,就如同第二行的“成人票”后面那样。
那么wap端能否实现这个效果呢,闭目思考下…
答案:能。
我们可以把icon直接写在文本后面,这样不就显示在行尾了么。
如果如此简单,app同学怎会轻易示弱,如果第二行只有icon(文字填满第一行),岂不是很难看。
那么我们绝对定位该icon到末尾。
.icon{position:absolute; right:-20px; bottom:0;}
然后我们希望这个元素能定位到我们想要的地方,那么我们希望这个元素的范围是这个样子的。
到此就比较明显了(虽然已开始我也没想到),只要设置该元素为内联属性(display:inline)就可以达到这样的效果了。
总结:虽然用了绝对定位,但从结构上来讲也还是合理的,主流浏览器都没问题,所以是个可行的方案。
最近看了《隐秘而伟大》,套用到这个问题上,inline虽然是行内元素的默认属性,但也有伟大的一面呀。
PNG图像格式介绍:
PNG是20世纪90年代中期开始开发的图像文件存储格式,其目的是企图替代GIF和TIFF文件格式,同时增加一些GIF文件格式所不具备的特性。流式 网络图形格式(Portable Network Graphic Format,PNG)名称来源于非官方的“PNG’s Not GIF”,是一种位图文件(bitmap file)存储格式,读成“ping”。PNG用来存储灰度图像时,灰度图像的深度可多到16位,存储彩色图像时,彩色图像的深度可多到48位,并且还可 存储多到16位的α通道数据。
IE6下PNG背景透明的显示问题
PNG格式比起GIF来表现色彩更丰富,特别是表现渐变以及背景透明的渐变要比GIF格式出色很多,目前,最新的浏览器基本上都支持PNG格式。但是IE6不支持PNG背景透明,会显示一个灰色的框。
IE6下PNG背景透明的解决办法
.pngImg { background:url(image.png); _background:url(image.gif);}
注意上文的_号,目前IE7,8以及Firefox浏览器等都不支持此CSS语法,只有IE6识别。因此,其他浏览器会调用PNG,而IE6刚调用GIF。
background:url(a.png) repeat-x 0 0; _background:none; _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=”a.png” ,sizingMethod=”crop”);
上面的原理是其他调用PNG,IE6,则先设背景没有,然后调用滤镜使之显示PNG图片。
缺陷:IE6下背景无法平铺,这个问题很严重。同时在性能上也有小问题,页面中次数不是很多的时候该办法还是可行的。
AlphaImageLoader滤镜会导致该区域的链接和按钮无效,解决的办法是为链接或按钮添加:position: relative;这样条代码,使其相对浮动。AlphaImageLoader无法设置背景的重复,所以对图片的切图精度会有很高的精确度要求。
解决IE下的链接无效可用最后面的方法:
三.利用JS解决html中的img(插入在网页中的png图像)png背景灰问题
页面中插入一段js即可。原理同上,只是将img标签用<span>标签替换掉,并且通过滤镜设置该<span>标签的background。它会将所有插入的PNG都如此处理。
<!–[if IE 6]>
<script>
function correctPNG()
{
for(var i=0; i<document.images.length; i++)
{
var img = document.images[i];
var imgName = img.src.toUpperCase();
if (imgName.substring(imgName.length-3, imgName.length) == “PNG”)
{
var imgID = (img.id) ? “id='” + img.id + “‘ ” : “”;
var imgClass = (img.className) ? “class='” + img.className + “‘ ” : “”;
var imgTitle = (img.title) ? “title='” + img.title + “‘ ” : “title='” + img.alt + “‘ “;
var imgStyle = “display:inline-block;” + img.style.cssText;
if (img.align == “left”) imgStyle = “float:left;” + imgStyle;
if (img.align == “right”) imgStyle = “float:right;” + imgStyle;
if (img.parentElement.href) imgStyle = “cursor:hand;” + imgStyle;
var strNewHTML = “<span “+ imgID + imgClass + imgTitle + “style=”” + “width:” + img.width + “px; height:” + img.height + “px;” + imgStyle + “;”
+ “filter:progid:DXImageTransform.Microsoft.AlphaImageLoader” + “(src='” + img.src + “‘, sizingMethod=’scale’);”></span>”;
img.outerHTML = strNewHTML;
i = i-1;
}
}
}
window.attachEvent(“onload”, correctPNG);
</script>
<![endif]–>
四.调用iepngfix.htc解决IE6PNG背景灰及拉伸问题
此方法来自:http://www.twinhelix.com/css/iepngfix/ 此方法基于Winodws平台,在Linux下不支持htc,没有验证过,但有网友发文证实。
以下片段添加至css文件
<div class=”pngImg”>PNG背景图片</div> <img src=”png图片” class=”pngImg” alt=””>
详细的应用方法这里就不介绍啦。
在逼不得已且身不由己必须使用PNG的情况下,这种方法应该是比较优秀的,虽然不能完美的解决IE6的平铺,但是至少是实现了拉伸,使得很多情况下可以代替平铺来使用。当然效率的问题任然是存在
.div { FILTER: alpha(opacity=20); moz-opacity: 0.2; opacity: 0.2;}
测试IE6,IE7,IE8,FF2,FF3均通过。提示:IE6,IE7需设置一个宽度(100%也行),否则看不到效果。
六.DD_belatedPNG,解决IE6不支持PNG绝佳方案
整个互联网上解决这个IE6的透明PNG的方案也是多不胜数,从使用IE特有的滤镜或是e xpression,再到javascript+透明GIF替代.但是这些方法都有一个缺点,就是不支持CSS中backgrond-position与 background-repeat.
而我今天介绍DD_belatedPNG,只需要一个理由,就是它支持backgrond-position与background-repeat.这是其他js插件不具备的.同时DD_belatedPNG还支持a:hover属性,以及<img>.
看Demo: http://www.ediyang.com/demo/DD_Png/
原理
这个js插件使用了微软的VML语言进行绘制,而其他多数解决PNG问题的js插件用的是AlphaImageLoader滤镜.
使用方法
1.在这里下载DD_belatedPNG.js文件.
http://dillerdesign.com/experiment/DD_belatedPNG/#download
2.在网页中引用,如下:
<!–[if IE 6]>
<script src=”DD_belatedPNG.js” mce_src=”DD_belatedPNG.js”></script>
<script type=”text/javascript”> /* EXAMPLE */ DD_belatedPNG.fix(‘.png_bg’); /* 将 .png_bg 改成你应用了透明PNG的CSS选择器,例如我例子中的’.trans’*/ </script> <![endif]–>
3.有2种调用函数,一种是DD_belatedPNG.fix(),如上代码.另一种是fix(),这中方法需要在函数内指出css选择器名.
使用a:hover请留意
5-25 更新:如果你也像jutoy同学一样想要用透明PNG作为a:hover时的背景图片,那么你需要留意你的代码,需要以”a:hover”来作为选择器. 否则可能会导致无法成功.同时我也更新了demo,请需要的更新查看.接着我们看看正确的代码:
<!–[if IE 6]>
<script type=”text/javascript” src=”js/DD_belatedPNG.js” ></script>
<script type=”text/javascript”> DD_belatedPNG.fix(‘.trans,.box a:hover’); </script>
<![endif]–>
七.通过 javascript 和 css 滤镜解决 IE 整站 png 背景透明问题
<script type=”text/javascript” language=”javascript”>
function enablePngImages()
{ var imgArr = document.getElementsByTagName(“IMG”);
for(i=0; i<imgArr.length; i++){
if(imgArr[i].src.toLowerCase().lastIndexOf(“.png”) != -1)
{
imgArr[i].style.filter = “progid:DXImageTransform.Microsoft.AlphaImageLoader(src='” + imgArr[i].src + “‘, sizingMethod=’auto’)”;
imgArr[i].src = “spacer.gif”;
}
if(imgArr[i].currentStyle.backgroundImage.lastIndexOf(“.png”) != -1)
{
var img = imgArr[i].currentStyle.backgroundImage.substring(5,imgArr[i].currentStyle.backgroundImage.length-2);
imgArr[i].style.filter = “progid:DXImageTransform.Microsoft.AlphaImageLoader(src='”+img+”‘, sizingMethod=’crop’)”;
imgArr[i].style.backgroundImage = “url(spacer.gif)”;
}
}
}
function enableBgPngImages(bgElements)
{
for(i=0; i<bgElements.length; i++)
{
if(bgElements[i].currentStyle.backgroundImage.lastIndexOf(“.png”) != -1)
{ //alert(bgElements[i]);
var img = bgElements[i].currentStyle.backgroundImage.substring(5,bgElements[i].currentStyle.backgroundImage.length-2);
bgElements[i].style.filter = “progid:DXImageTransform.Microsoft.AlphaImageLoader(src='”+img+”‘, sizingMethod=’crop’)”;
bgElements[i].style.backgroundImage = “url(spacer.gif)”;
}
}
}
</script>
<img src=”pngpic.png” alt=”” border=”0″ />
<!–[if lt IE 7]>
<script type=’text/javascript’>
var bgElements; enablePngImages(); if(bgElements){ enableBgPngImages(bgElements); }
</script>
<![endif]–>
.pngImg {behavior: url(iepngfix.htc);}
以下片段添加至html文件一.IE6使用gif,其他则使用png来解决PNG背景灰
根据转载说个注意事项,DD_belatedPNG.js这个插件和iepng.js新版本的用法是一样的,虽然js代码不一样,但是最后为png生成的代码没看到有什么区别(就连产生的问题都是一样的),所以用哪个都可以。就是关于DD_belatedPNG.js插件,ie6的选择器是必加的,否则该插件可能会对ie8正常的png图片带来不正常的影响。另外在包含大量png的页面中,根据布局的差异,这个插件仍然会产生一些问题,透明是可以透明,但是会改变图片的位置,具体原因没有深研究,目测是因为插件对图片处理后给图片一个绝对定位(position),所以在一些特殊布局下页面就会走形,因此如果一定要用到png图片,一定要多测试。
在网站中通常要显示各种尺寸的图片,但图片的尺寸不一定符合显示的要求。如果直接指定img的width和height属性的话图片又很可能会被挤压的变形。下面这个代码可以把图片放进一个imgBox,并根据imgBox的大小来按比例缩放图片以适应他,同时图片会在imgBox中居中显示。来看代码:
首先是HTML:
1<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
2<html xmlns=”http://www.w3.org/1999/xhtml”>
3<head>
4<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
5<title>按比例自动缩放图片</title>
6
7<script type=”text/javascript” src=”js/jquery.js”></script>
8<script type=”text/javascript” src=”js/drawImg”></script>
9</head>
10
11<body>
12<div id=”imgBox” style=”width:500px; height:400px; background:#cccccc; overflow:hidden”>
13 <img id=”img1″ alt=”” src=”images/1.jpg” onload=”DrawImg(500,400);” />
14</div>
15</body>
16</html>
再是JavaScript:
1function DrawImg(boxWidth,boxHeight)
2{
3 var imgWidth=$(“#img1”).width();
4 var imgHeight=$(“#img1”).height();
5 //比较imgBox的长宽比与img的长宽比大小
6 if((boxWidth/boxHeight)>=(imgWidth/imgHeight))
7 {
8 //重新设置img的width和height
9 $(“#img1”).width((boxHeight*imgWidth)/imgHeight);
10 $(“#img1”).height(boxHeight);
11 //让图片居中显示
12 var margin=(boxWidth-$(“#img1”).width())/2;
13 $(“#img1”).css(“margin-left”,margin);
14 }
15 else
16 {
17 //重新设置img的width和height
18 $(“#img1”).width(boxWidth);
19 $(“#img1”).height((boxWidth*imgHeight)/imgWidth);
20 //让图片居中显示
21 var margin=(boxHeight-$(“#img1”).height())/2;
22 $(“#img1”).css(“margin-top”,margin);
23 }
24}
25
代码是转的。
用了之后发现,这个方法在FF下面是好用的,但是在chrome下是没有效果的。
个人经验,主要原因是图片没有加载是获取不到图片的width和height,也就是说chrome下面imgWidth和imgHeight都为0。
那我们可以在前面加上load()函数来解决这个问题。
然后呢…ie又不支持这么用load(),真是不和谐啊,之后就是做兼容了,我们都懂的。