Ext 4图表:当鼠标悬停线不仅仅在标记上方时突出显示线条?

时间:2014-12-11 16:57:59

标签: extjs charts

我有一个带有系列的图表,配置了高亮显示,标记未显示。

对于某些数据,标记相距足够远,当鼠标悬停在线上时,它可能会突出显示,也可能不突出显示,具体取决于鼠标光标与(隐藏)标记的接近程度。因为没有显示标记,所以这给出了当鼠标悬停在线上时高度随机且断裂的外观;有时它会突出显示,有时却没有。

我尝试增加selectionTolerance,但这是不可接受的,因为它基本上是标记周围的半径,这样当鼠标光标甚至不接近时,将鼠标悬停在距标记越来越远的位置会导致线条突出显示线。

所以,我想要一个小的selectionTolerance,所以鼠标必须接近该线,但我希望当鼠标接近线时应用高光,而不是当它是接近(隐藏)标记

如何做到这一点?

感谢。

编辑:进一步观察,我相信答案是让我重载Ext.chart.series.Line的 isItemInPoint 函数。就我而言,当showMarkers为false时,我只希望线条突出显示在线上。当ShowMarkers为true时,当前行为是可接受的。所以,它应该是一个非常干净的覆盖。还是要弄清楚如何确定一个点是否在线上,以及返回哪个项目,但这可能仅仅是一些数学问题。

1 个答案:

答案 0 :(得分:0)

所以,这就是我最终做的事情,它可以按照需要运作。我将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;
    }
});