得益於echarts和其他多種數據可視化框架的流行,現在做出各種美觀大氣炫酷的圖形化報表已經是信手拈來的事情,接踵而來的就是各種新鮮的奇葩需求。最近我們就遇到一個,要能夠將多張熱力圖合成為一張動圖,展現出過去一段時間的變化趨勢,然后再通過qq/微信分享出去。用戶爸爸的腦洞開得不錯,仔細一想也有道理,畢竟不是每個人都裝了我們的app啊。
解決的思路也中規中矩,第一步,echart頁面先發起數據請求,得到應該生成圖片的起始時間和數量;第二步,由echart頁面的js畫出圖表,通過js上傳到服務端(java),循環這個過程,直到所有圖片上傳成功;第三步,在服務端將多張圖片合成為gif,保存起來。這一步偷懶沒有自己寫,github上面找了一個很輕量的庫(https://github.com/rtyley/animated-gif-lib-for-java),實測效果還不錯。
整體來講很簡單,但是這里面有個坑就是第一步echarts頁面發起請求,需要用戶訪問這個頁面才行。由於里面有大量的js執行,curl顯然是不行的。必須要通過瀏覽器訪問。Windows用戶可以很愉快的寫個計划任務調用chrome每天運行一次就搞定了,沒有圖形化界面的linux用戶就要hard一點點了。一開始嘗試的是網上普遍流行的方法:selenium+chrome headless+chromedriver。這種方法的起源其實是自動化測試,但是我們的需求是一個瀏覽器,把頁面上所有js給我跑一遍。最后這個方式是失敗了,原因是chromedriver的局限——它可以渲染整個頁面,也可以調用某個js方法(By JavaScriptExecutor.executeScript()),但是它不能把頁面上的js和導入的js全部跑一遍,就像一個普通的瀏覽器那樣。成功的方法其實更簡單,就是讓chrome運載在虛擬的X Window-Xvfb。注意Xvfb安裝之后需要安裝中文字庫和圖表需要用到的字體(從windows復制過來即可)。
Xvfb -ac :1 -screen 0 1280x1024x16 export DISPLAY=:1 google-chrome-stable --disable-gpu http://xxx.html