野生技术-图片合成phantomjs
公司有这样一个需求,在地图上绘制轨迹点并生成图片。拿到这么个需求乍一看很简单,其实挺复杂的,没有5年工作经验,基本无能为力。具体细节请听我细细道来。
坑1:轨迹是有一套算法的,gps的点里会出现少量漂移。就是说现在还在这,下一秒可能是100公里之外了,这个需要写算法过滤。通过几个点的时间距离计算速度,超过一定速度的就是不合理的点,需要过滤掉。
坑2:坐标系不同。需要转换,这个不可能依赖于线上的接口转换,量太大了,需要自己想办法本地实现。
坑3:缩放比例。这个是后面制作过程中才发现的大坑。有的人在全国范围内活动,这个生成的图应该是全国地图;有的人在几个省内活动,这个图应该就是在这几个省;有的人只在镇内活动,这个图只应该是个镇。也是个复杂的算法,要分析一下经纬度的规则,不同经纬度用不同的比例。适当取样就可以了。
坑4:如何画图。想来想去只能百度地图了,那么就需要一个工具把网页上的百度地图变成图片。这里我选了个工具:phantomjs(nodejs库名是phantom)。用虚拟浏览器进行网页截图,今天来聊一下这个。
phantom一般用于做爬虫,但是其截图功能也是可以用于生成图片的。尤其是生成复杂的图片,可以用html5技术制作。非常的nice。虽然单个图片处理有点慢, 但是结合多线程技术,效率还是可以的。主要是可以做复杂的图,渐变效果,旋转效果,文字描边、阴影等等能够用html5简单实现。
这是一项很实用的野生技术,我相信能转换思路把phantom用于处理图片的人不多。其实我已经成功用在很多项目里了,非常nice
[部分代码]
app.get('/getPic.action', function(req, res) { var screen_width=req.query.screen_width; if(!screen_width) { var screen_width=1920; } var screen_height=req.query.screen_height; if(!screen_height) { var screen_height=10; } console.log("screen"); var phantom = require('phantom'); var savename=req.query.savename; if(!savename) { res.end(JSON.stringify({success:false,msg:'savename不得为空'})); return false; } var fromurl=req.query.fromurl; if(!fromurl) { res.end(JSON.stringify({success:false,msg:'fromurl不得为空'})); return false; }else{ fromurl=decodeURI(fromurl); } var pcormob=req.query.pcormob; if(!pcormob || pcormob=="pc") { var this_userAgent="Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36 LBBROWSER"; }else{ var this_userAgent="Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36"; } console.log(this_userAgent); var delay=req.query.delay; if(!delay) { var delay=10; } phantom.create().then(function(ph) { ph.createPage().then(function(page) { page.property('settings', { javascriptEnabled: true, loadImages: true, webSecurityEnabled: false, userAgent: this_userAgent //要指定谷歌ua,我用火狐无法浏览 }); page.property('viewportSize', { width: screen_width, height: screen_height }); page.property('clipRect', { top:0 ,left:0 ,width:screen_width ,height:screen_height }); page.open(fromurl).then(function(status) { page.evaluate(function () { //操作页面事件 $("body").css("over-flow","hidden"); console.log($("body").css("over-flow")); }); setTimeout(function(){ page.render(savename).then(function() { console.log('Page rendered'); ph.exit(); res.end(JSON.stringify({success:true})); }); },delay); }); }); }); });