以下一段小例子,展示了加载一个SVG图片后,分为七个基本进行缩放绘制的效果,可看出Canvas绘制SVG可保持其矢量不失真的特性
function draw(){ var img = new Image(); img.src = 'chart.svg'; document.body.appendChild(img); img.onload = function(){ var canvas = document.getElementById('canvas'); var g = canvas.getContext('2d'); var width = img.clientWidth * 1.5; var height = img.clientHeight * 1.5; var x = 2; var y = 2; for(var i=0; i<7; i++){ g.drawImage(img, x, y, width, height); x += width + 2; width /= 2; height /= 2; } }; }
提到Canvas和SVG的融合,我们将采用HT for Web的矢量功能展示一个手机电池充电进度的实例,整个手机电池的静态部分我们通过加载一个简单的SVG素材实现,而充电动态变化的部分,我们采用一个渐进色的HT矩形元素来描述,该矩形的长度通过HT矢量数据动态绑定功能,根据充电进度的百分比换算成长度信息,最后通过定时器模拟数据变化达到动态充电的效果:
ht.Default.setImage('battery', { width: 64, height: 64, comps: [ { type: 'rect', rect: { func: function(data){ return [5, 25, 50*data.a('percent'), 16] } }, background: 'red', gradient: 'spread.vertical' }, { type: 'image', name: 'battery.svg', relative: true, rect: [0, 0, 1, 1] } ] }); var node = new ht.Node(); node.setPosition(80, 150); node.setImage('battery'); node.s('image.stretch', 'uniform'); node.a('percent', 0); dataModel.add(node); graphView.setEditable(true); setInterval(function(){ percent = node.a('percent') + 0.02; if(percent > 1){ percent = 0; } node.a('percent', percent); }, 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,这样方式更容易理解,例子代码和效果如下:http://v.youku.com/v_show/id_XODg0MTU4NjEy.html