我有一个带有系列的图表,配置了一个高亮显示,标记没有显示。
对于一些数据,标记彼此足够远,当鼠标悬停在线上时,它可能会突出显示,也可能不突出显示,具体取决于鼠标光标与(隐藏)标记的接近程度。 因为没有显示标记,所以这给出了当鼠标悬停在线上时高度随机且断裂的外观; 有时它突出显示,有时它不突出。
我尝试增加selectionTolerance,但这是不可接受的,因为它基本上是标记周围的半径,因此当鼠标光标甚至不接近线时,将鼠标悬停在距离标记越来越远的位置会导致线条突出显示。
所以,我想要一个小的selectionTolerance,所以鼠标必须接近线,但我希望当鼠标接近线时应用高光 ,而不是当它接近(隐藏) 标记时 。
怎么做到这一点?
谢谢。
编辑:进一步观察,我相信答案是我为Ext.chart.series.Line重载isItemInPoint函数。 就我而言,当showMarkers为false时,我只希望线条突出显示在线上。 当ShowMarkers为true时,当前行为是可接受的。 所以,它应该是一个非常干净的覆盖。 仍然必须弄清楚如何确定一个点是否在线上,以及返回哪个项目,但这可能仅仅是一些数学问题。
I have a chart with a line series, with a highlight configured, markers are not shown.
With some data, the markers are far enough apart from each other that when mousing over the line it may or may not highlight depending on how close the mouse cursor is to a (hidden) marker. Because markers are not shown, this gives the appearance that the highlghting when hovering the mouse over the line is random and broken; sometimes it highlights, sometimes it doesn't.
I tried increasing selectionTolerance, but this isn't acceptable as that is essentially a radius around the marker, such that hovering farther and farther away from the marker causes the line to highlight when the mouse cursor isn't even close to the line.
So, I want a small selectionTolerance so the mouse has to be close to the line, but I want the highlight to be applied when the mouse is close to the line, not just when it is close to a (hidden) marker.
How to accomplish this?
Thanks.
Edit: upon looking further, I believe the answer is for me to overload the isItemInPoint function for Ext.chart.series.Line. In my case, I only want the line to highlight when hovering over the line when showMarkers is false. When ShowMarkers is true, the current behavior is acceptable. So, it should be a pretty clean override. Still have to figure out how to determine if a point is on the line, and which item to return, but that's probably just a matter of some maths.
最满意答案
所以,这就是我最终做的事情,并且它可以按照需要运行。 我将chart.series.line扩展为betterline。 然后我将我的系列类型设置为“betterline”并在配置中设置lineSelectionTolerance。
Ext.define('MyExtends.SeriesLine', { extend: 'Ext.chart.series.Line', alias: ['series.betterline', 'Ext.chart.series.BetterLine'], type: 'betterline', isItemInPoint: function (x, y, item, i) { var me = this, items = me.items, ln = items.length, tolerance = me.selectionTolerance, prevItem, nextItem, prevPoint, nextPoint, x1, x2, y1, y2, dist1, dist2, dist, sqrt = Math.sqrt; nextItem = items[i]; prevItem = i && items[i - 1]; if (i >= ln) { prevItem = items[ln - 1]; } prevPoint = prevItem && prevItem.point; nextPoint = nextItem && nextItem.point; x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance; y1 = prevItem ? prevPoint[1] : nextPoint[1]; x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance; y2 = nextItem ? nextPoint[1] : prevPoint[1]; dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)); dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); dist = Math.min(dist1, dist2); if (dist <= tolerance) { return dist == dist1 ? prevItem : nextItem; } if (me.lineSelectionTolerance) { if (prevItem && nextItem && prevItem != nextItem) { tolerance = me.lineSelectionTolerance; x1 = parseFloat(prevPoint[0]); y1 = parseFloat(prevPoint[1]); x2 = parseFloat(nextPoint[0]); y2 = parseFloat(nextPoint[1]); if (x > x1 && x < x2) { var slope = (y2 - y1) / (x2 - x1); var slopePerp = -1 / slope; var xIntercept = (x2 * (x * slopePerp - y + y1) + x1 * (x * -slopePerp + y - y2)) / (slopePerp * (x2 - x1) + y1 - y2); var yIntercept = slopePerp * xIntercept - slopePerp * x + y; if (!(y2 - y1)) // Horizontal line { xIntercept = x; yIntercept = y1; } var a = (x - xIntercept); var b = (y - yIntercept); var distPointToIntercept = sqrt(a * a + b * b); // Pythagorean if (distPointToIntercept < tolerance) { dist1 = sqrt((xIntercept - x1) * (xIntercept - x1) + (yIntercept - y1) * (yIntercept - y1)); dist2 = sqrt((xIntercept - x2) * (xIntercept - x2) + (yIntercept - y2) * (yIntercept - y2)); dist = Math.min(dist1, dist2); return dist == dist1 ? prevItem : nextItem; } } } } return false; } });So, here's what I ended up doing, and it works as desired. I extended chart.series.line into betterline. Then I make my series type "betterline" and set lineSelectionTolerance in the config as well.
Ext.define('MyExtends.SeriesLine', { extend: 'Ext.chart.series.Line', alias: ['series.betterline', 'Ext.chart.series.BetterLine'], type: 'betterline', isItemInPoint: function (x, y, item, i) { var me = this, items = me.items, ln = items.length, tolerance = me.selectionTolerance, prevItem, nextItem, prevPoint, nextPoint, x1, x2, y1, y2, dist1, dist2, dist, sqrt = Math.sqrt; nextItem = items[i]; prevItem = i && items[i - 1]; if (i >= ln) { prevItem = items[ln - 1]; } prevPoint = prevItem && prevItem.point; nextPoint = nextItem && nextItem.point; x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance; y1 = prevItem ? prevPoint[1] : nextPoint[1]; x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance; y2 = nextItem ? nextPoint[1] : prevPoint[1]; dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)); dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); dist = Math.min(dist1, dist2); if (dist <= tolerance) { return dist == dist1 ? prevItem : nextItem; } if (me.lineSelectionTolerance) { if (prevItem && nextItem && prevItem != nextItem) { tolerance = me.lineSelectionTolerance; x1 = parseFloat(prevPoint[0]); y1 = parseFloat(prevPoint[1]); x2 = parseFloat(nextPoint[0]); y2 = parseFloat(nextPoint[1]); if (x > x1 && x < x2) { var slope = (y2 - y1) / (x2 - x1); var slopePerp = -1 / slope; var xIntercept = (x2 * (x * slopePerp - y + y1) + x1 * (x * -slopePerp + y - y2)) / (slopePerp * (x2 - x1) + y1 - y2); var yIntercept = slopePerp * xIntercept - slopePerp * x + y; if (!(y2 - y1)) // Horizontal line { xIntercept = x; yIntercept = y1; } var a = (x - xIntercept); var b = (y - yIntercept); var distPointToIntercept = sqrt(a * a + b * b); // Pythagorean if (distPointToIntercept < tolerance) { dist1 = sqrt((xIntercept - x1) * (xIntercept - x1) + (yIntercept - y1) * (yIntercept - y1)); dist2 = sqrt((xIntercept - x2) * (xIntercept - x2) + (yIntercept - y2) * (yIntercept - y2)); dist = Math.min(dist1, dist2); return dist == dist1 ? prevItem : nextItem; } } } } return false; } });更多推荐
发布评论