野生技术-图片合成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);
});
});
});
});