在项目中使用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的功能太多,这样的源码修改功能对其余的功能有无影响,还不能彻底肯定。待后续继续补充。