Chinaunix首页 | 论坛 | 博客
  • 博客访问: 485448
  • 博文数量: 226
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2111
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-20 09:02
个人简介

web web web

文章分类

全部博文(226)

文章存档

2020年(2)

2019年(1)

2018年(3)

2017年(26)

2016年(57)

2015年(60)

2014年(77)

我的朋友

分类: HTML5

2015-04-22 13:30:46

SVG与Canvas是HTML5上绘制图形应用的两种完全不同模式的技术,两种绘制图形方式各有优缺点,但两者并非水火不容,尤其是SVG内容可直接绘制在Canvas上的功能,使得两者可以完美的融合在一起,让Canvas可享用到现有丰富的SVG素材,并不失SVG矢量无级缩放的特点。

基于HTML5的Drag and Drop生成图片Base64信息》这篇虽然展示的是拖拽普通栅格图片的效果,但你也可以直接拖拽SVG格式的图片进行显示,只不过普通图片的格式数据为data:image/png类型,而SVG格式的数据类型为data:image/svg+xml的类型,下图为该拓扑图拖拽入SVG格式图片的运行效果:

Screen Shot 2015-02-01 at 2.20.40 PM

以下一段小例子,展示了加载一个SVG图片后,分为七个基本进行缩放绘制的效果,可看出Canvas绘制SVG可保持其矢量不失真的特性

点击(此处)折叠或打开

  1. function draw(){
  2.     var img = new Image();
  3.     img.src = 'chart.svg';
  4.     document.body.appendChild(img);
  5.     img.onload = function(){
  6.         var canvas = document.getElementById('canvas');
  7.         var g = canvas.getContext('2d');
  8.         var width = img.clientWidth * 1.5;
  9.         var height = img.clientHeight * 1.5;
  10.         var x = 2;
  11.         var y = 2;
  12.         for(var i=0; i<7; i++){
  13.             g.drawImage(img, x, y, width, height);
  14.             x += width + 2;
  15.             width /= 2;
  16.             height /= 2;
  17.         }
  18.     };
  19. }

Screen Shot 2015-02-01 at 2.21.39 PM

提到Canvas和SVG的融合,我们将采用的矢量功能展示一个手机电池充电进度的实例,整个手机电池的静态部分我们通过加载一个简单的SVG素材实现,而充电动态变化的部分,我们采用一个渐进色的矩形元素来描述,该矩形的长度通过矢量数据动态绑定功能,根据充电进度的百分比换算成长度信息,最后通过定时器模拟数据变化达到动态充电的效果:

Screen Shot 2015-02-01 at 2.21.21 PM

点击(此处)折叠或打开

  1. ht.Default.setImage('battery', {
  2.     width: 64,
  3.     height: 64,
  4.     comps: [
  5.         {
  6.             type: 'rect',
  7.             rect: {
  8.                 func: function(data){
  9.                     return [5, 25, 50*data.a('percent'), 16]
  10.                 }
  11.             },
  12.             background: 'red',
  13.             gradient: 'spread.vertical'
  14.         },
  15.         {
  16.             type: 'image',
  17.             name: 'battery.svg',
  18.             relative: true,
  19.             rect: [0, 0, 1, 1]
  20.         }
  21.     ]
  22. });

  23. var node = new ht.Node();
  24. node.setPosition(80, 150);
  25. node.setImage('battery');
  26. node.s('image.stretch', 'uniform');
  27. node.a('percent', 0);
  28. dataModel.add(node);

  29. graphView.setEditable(true);

  30. setInterval(function(){
  31.     percent = node.a('percent') + 0.02;
  32.     if(percent > 1){
  33.         percent = 0;
  34.     }
  35.     node.a('percent', percent);
  36. }, 16);

SVG绘制到Canvas还有一种特殊的应用场景,就是将HTML元素通过SVG的foreignObject特性描述在SVG中,然后Canvas绘制SVG时,即可把foreignObject描述的HTML内容绘制到Canvas上,可参见https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas 的实例,其中采用了Blob的方式设置img的src作为URL是比较怪异的技术点,但从上文提到其实我们可以将整个SVG内容转换成data:image/svg+xml;的base64内容即可作为src的url传入,因此我对该例子做了改造,采用btoa(data)把svg内容转换成base64的方式设置img.src,这样方式更容易理解,例子代码和效果如下:

Screen Shot 2015-02-01 at 2.21.56 PM


点击(此处)折叠或打开

  1. function draw(){
  2.     var canvas = document.getElementById('canvas');
  3.     var ctx = canvas.getContext('2d');
  4.     var data = 。。。;
  5.     var img = new Image();
  6.     img.onload = function () {
  7.         ctx.drawImage(img, 0, 0);
  8.     };
  9.     img.src = 'data:image/svg+xml;base64,' + btoa(data);
  10. }


阅读(1097) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~