在項目中使用highcharts是很容易的,移動端也適配的不錯,按照官網教程便可。可是在移動端,因爲手機端屏幕過小,需求方但願能夠弄一個全屏圖,把手機橫過來觀察曲線。git
正常:npm
豎過來:json
很容易想到的一種實現方法:設置曲線container的寬爲屏幕的高,高爲屏幕的寬,而後給曲線的container加一個transform:rotate(90deg)
,就可以實現豎屏了。canvas
這樣看起來沒問題,可是當須要展示tooltip的時候,會發現tooltip很差使了。表現出來的現象是:當用戶用手指延着曲線的x軸移動時,tooltip並不會跟着手指移動。
仔細觀察會發現,tooltip的移動,仍是根據手指在屏幕上移動時的【橫座標】來的。api
通過查閱highcharts文檔,發現chart.inverted
能夠實現x軸和y軸的反轉。試了一下這個配置,發現並非想象中那麼理想,主要緣由爲:
一、y軸在屏幕下方,但咱們須要的是y軸在屏幕上方。而y軸的位置不那麼好調整。
二、tooltip也須要咱們單獨進行旋轉。可是旋轉後,手指touchmove時,tooltip適配會出問題,有時候會跑到曲線外面去,沒法控制。而且因爲是svg畫圖,tooltip自己的transform-origin
的選擇就是一個比較蛋疼的問題。瀏覽器
查閱了highcharts其餘的api,而且上git搜了搜issue,可是並無這個問題的解決方法。原本想放棄highcharts, 轉投echarts的, 但在echarts的issue裏發現不少人遇到了這個問題,但官方直接給列爲了bug, 還不知道何時能夠修復。最後仍是考慮使用highcharts。echarts
因爲大概知道問題產生的緣由:圖表豎過來後,應該用觸摸事件的縱座標而不是橫座標來做爲表格內的橫座標。改源碼應該挺快的。less
項目是用經過npm安裝的highcharts, 首先根據highcharts的package.json能夠看到,引用的入口文件爲:highcharts.js
這個文件是壓縮過的,它對應的源代碼文件爲:highcharts.src.jside
結合源代碼文件和瀏覽器調試,發如今用戶滑動手指是,進入了下面的邏輯:svg
onContainerTouchStart: function(e) { this.zoomOption(e); this.touch(e, true); }, onContainerTouchMove: function(e) { this.touch(e); },
一切都在這個touch函數裏。繼續往下看:
/** * General touch handler shared by touchstart and touchmove. */ touch: function(e, start) { var chart = this.chart, hasMoved, pinchDown, isInside; if (chart.index !== H.hoverChartIndex) { this.onContainerMouseLeave({ relatedTarget: true }); } H.hoverChartIndex = chart.index; // 這裏判斷是是不是單觸 if (e.touches.length === 1) { // e爲js的觸摸事件 e = this.normalize(e); // e.chartX ,e.chartY應該就是觸摸時,在表格內部的橫座標和縱座標,這裏的normalize應該是對事件進行了擴展。 isInside = chart.isInsidePlot( e.chartX - chart.plotLeft, e.chartY - chart.plotTop ); if (isInside && !chart.openMenu) { // Run mouse events and display tooltip etc if (start) { this.runPointActions(e); } // Android fires touchmove events after the touchstart even if the // finger hasn't moved, or moved only a pixel or two. In iOS however, // the touchmove doesn't fire unless the finger moves more than ~4px. // So we emulate this behaviour in Android by checking how much it // moved, and cancelling on small distances. #3450. if (e.type === 'touchmove') { pinchDown = this.pinchDown; hasMoved = pinchDown[0] ? Math.sqrt( // #5266 Math.pow(pinchDown[0].chartX - e.chartX, 2) + Math.pow(pinchDown[0].chartY - e.chartY, 2) ) >= 4 : false; } if (pick(hasMoved, true)) { this.pinch(e); } } else if (start) { // Hide the tooltip on touching outside the plot area (#1203) this.reset(); } } else if (e.touches.length === 2) { this.pinch(e); } },
這裏的normalize
比較關鍵,由於產生tooltip表現不符合預期的緣由應該就是:旋轉時,因爲圖被豎過來了,須要使用觸摸事件的縱座標來表示觸摸的【橫座標】,但highcharts依然採用了事件的橫座標。繼續看看normalize
的內容。
/** * Takes a browser event object and extends it with custom Highcharts * properties `chartX` and `chartY` in order to work on the internal * coordinate system. * * @param {Object} e * The event object in standard browsers. * * @return {PointerEvent} * A browser event with extended properties `chartX` and `chartY`. */ normalize: function(e, chartPosition) { var chartX, chartY, ePos; // IE normalizing e = e || win.event; if (!e.target) { e.target = e.srcElement; } // iOS (#2757) ePos = e.touches ? (e.touches.length ? e.touches.item(0) : e.changedTouches[0]) : e; // Get mouse position if (!chartPosition) { this.chartPosition = chartPosition = offset(this.chart.container); } // chartX and chartY // 這裏是計算chartX和chartY,計算方法是用當前觸摸(點擊)事件的橫座標減去圖表的橫座標,縱座標減去圖表的縱座標。 if (ePos.pageX === undefined) { // IE < 9. #886. chartX = Math.max(e.x, e.clientX - chartPosition.left); // #2005, #2129: the second case is // for IE10 quirks mode within framesets chartY = e.y; } else { chartX = ePos.pageX - chartPosition.left; chartY = ePos.pageY - chartPosition.top; } // 這裏的chartX和chartY已是在表格內部的座標了,後續的邏輯都是根據這個chartX和chartY來的,若是當圖表被豎過來時,人爲把這兩個值交換一下,是否就解決了tooltip的問題呢。 if(豎屏) { // 【豎屏】能夠經過在配置表格的時候增長變量來判斷 return extend(e, { chartX: Math.round(chartY), chartY: Math.round(chartX) }); } return extend(e, { chartX: Math.round(chartX), chartY: Math.round(chartY) }); },
按照這個思路,找到入口文件highcharts.js裏對應部分的代碼,進行修改。修改完成後,發現tooltip的表現符合預期了。
通過測試, 圖表的其餘基本功能正常。以前還擔憂這樣會不會影響lengends的點擊等。後來想了一下,因爲是svg畫圖,全部點擊事件應該都是直接綁定在元素上的,而不是像canvas同樣強依賴座標,因此不會影響。這也是爲何在echarts下進行rotate, lengends的交互也會受影響的緣由。
因爲highcharts的功能太多,這樣的源碼修改功能對其餘的功能有無影響,還不能徹底肯定。待後續繼續補充。