如何检查用户鼠标是否在HTML Canvas元素上单击了

时间:2018-02-16 11:25:21

标签: javascript html html5-canvas

Bezier曲线公式:

二次方程式:

以下是我的代码:

function SelectBezierCurve(pos_left, pos_top) {
        for (var i = 0; i < allBezierCurves.length; i++) {
            var d = allBezierCurves[i].EndX - 3 * 
                allBezierCurves[i].ControlPoint2X +
                3 * allBezierCurves[i].ControlPoint1X - 
                allBezierCurves[i].StartX;
            var a = 3 * (allBezierCurves[i].ControlPoint2X - 2 * 
                allBezierCurves[i].ControlPoint1X
                + allBezierCurves[i].StartX) / d;
            var b = (allBezierCurves[i].ControlPoint1X - 
                allBezierCurves[i].StartX) / d;
            var c = (allBezierCurves[i].StartX - pos_left) / d;
            var p = (3 * b - a * a) / 3;
            var q = (2 * a * a * a - 9 * a * b + 27 * c) / 27;
            if (4 * p * p * p + 27 * q * q > 0) {
                var c2 = -(p * p * p / 27);
                if (q * q - 4 * c2 > 0) {
                    var sqrt = Math.sqrt(q * q - 4 * c2);
                    var z1 = (-q + sqrt) / 2;
                    var z2 = (-q - sqrt) / 2;
                    var tGivenX = -(a / 3) + Math.cbrt(z1) + Math.cbrt(z2);
                    var yOnBezierCurve = (1 - tGivenX) * (1 - tGivenX) *
                        (1 - tGivenX) * allBezierCurves[i].StartY + 3 *
                        tGivenX * (1 - tGivenX) * (1 - tGivenX) *
                        allBezierCurves[i].ControlPoint1Y + 3 * tGivenX *
                        tGivenX * (1 - tGivenX) * 
                        allBezierCurves[i].ControlPoint2Y +
                        tGivenX * tGivenX * tGivenX * 
                        allBezierCurves[i].EndY;
                    if (Math.abs(yOnBezierCurve - pos_top) < 5) {
                        if (selectedBezierCurve === i) {
                            FreeAllReferences();
                        } else {
                            selectedBezierCurve = i;
                            selectedSetOfPointsIndex = -1;
                            selectedEllipse = -1;
                            selectedCurve = -1;
                            selectedText = -1;
                        }
                        return true;
                    }
                }
            } else if (4 * p * p * p + 27 * q * q < 0) {
                var k = (Math.acos(3 * q * Math.sqrt(3 / (-p)) / (2 * p))) / 
                    3;
                var tForKEquals0 = (-a) / 3 + 2 * Math.sqrt((-p) / 3) * 
                    Math.cos(k);
                var yOnBezierCurveTForKEquals0 = (1 - tForKEquals0) * (1 - 
                    tForKEquals0) *
                    (1 - tForKEquals0) * allBezierCurves[i].StartY + 3 *
                    tForKEquals0 * (1 - tForKEquals0) * (1 - tForKEquals0) *
                    allBezierCurves[i].ControlPoint1Y + 3 * tForKEquals0 *
                    tForKEquals0 * (1 - tForKEquals0) * 
                    allBezierCurves[i].ControlPoint2Y +
                    tForKEquals0 * tForKEquals0 * tForKEquals0 * 
                    allBezierCurves[i].EndY;
                if (Math.abs(yOnBezierCurveTForKEquals0 - pos_top) < 5) {
                    if (selectedBezierCurve === i) {
                        FreeAllReferences();
                    } else {
                        selectedBezierCurve = i;
                        selectedSetOfPointsIndex = -1;
                        selectedEllipse = -1;
                        selectedCurve = -1;
                        selectedText = -1;
                    }
                    return true;
                } else {
                    k -= 2 * Math.PI / 3;
                    var tForKEquals1 = (-a) / 3 + 2 * Math.sqrt((-p) / 3) * 
                        Math.cos(k);
                    var yOnBezierCurveTForKEquals1 = (1 - tForKEquals1) * (1 
                        - tForKEquals1) *
                        (1 - tForKEquals1) * allBezierCurves[i].StartY + 3 *
                        tForKEquals1 * (1 - tForKEquals1) * (1 - 
                        tForKEquals1) *
                        allBezierCurves[i].ControlPoint1Y + 3 * tForKEquals1 
                        * tForKEquals1 * (1 - tForKEquals1) * 
                        allBezierCurves[i].ControlPoint2Y +
                        tForKEquals1 * tForKEquals1 * tForKEquals1 * 
                        allBezierCurves[i].EndY;
                    if (Math.abs(yOnBezierCurveTForKEquals1 - pos_top) < 5) {
                        if (selectedBezierCurve === i) {
                            FreeAllReferences();
                        } else {
                            selectedBezierCurve = i;
                            selectedSetOfPointsIndex = -1;
                            selectedEllipse = -1;
                            selectedCurve = -1;
                            selectedText = -1;
                        }
                        return true;
                    } else {
                        k *= 2;
                        var tForKEquals2 = (-a) / 3 + 2 * Math.sqrt((-p) / 3) 
                            * Math.cos(k);
                        var yOnBezierCurveTForKEquals2 = (1 - tForKEquals2) * 
                            (1 - tForKEquals2) *
                            (1 - tForKEquals2) * allBezierCurves[i].StartY + 
                            3 * tForKEquals2 * (1 - tForKEquals2) * (1 - 
                            tForKEquals2) *
                            allBezierCurves[i].ControlPoint1Y + 3 * 
                            tForKEquals2 *
                            tForKEquals2 * (1 - tForKEquals2) * 
                            allBezierCurves[i].ControlPoint2Y +
                            tForKEquals2 * tForKEquals2 * tForKEquals2 * 
                            allBezierCurves[i].EndY;
                        if (Math.abs(yOnBezierCurveTForKEquals2 - pos_top) < 
                            5) {
                            if (selectedBezierCurve === i) {
                                FreeAllReferences();
                            } else {
                                selectedBezierCurve = i;
                                selectedSetOfPointsIndex = -1;
                                selectedEllipse = -1;
                                selectedCurve = -1;
                                selectedText = -1;
                            }
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

在给定p1 = 67,324和p2 = 190,318以及p3 = 174,63和p4 = 292,58的情况下求解x,y = 181,188的Bezier曲线,使用下图进行公式简化我使用t表示x = 181是来到t = 1.41745。

在给定x = 181和t = 1.41745的情况下计算的y是y = 218,甚至不接近188,这是我期待的距离它不远的值。

我只对y给定x以及起始端和控制点坐标的真实根解决方案感兴趣。

  

PX = 181,P1X = 67,P2X = 190,P3X = 174,P4X = 292

     

py =试图解决这个问题

     

P1Y = 324,P2Y = 318,P3Y = 63,P4Y = 58

要提供上下文,我试图找出用户鼠标是否单击Bezier曲线。因此,我考虑使用x鼠标点击坐标的上述图片方程式求解y并检查结果y是否足够接近相应的鼠标点击y将显示用户点击了Bezier曲线。

图中的公式简化为计算机可以计算atm的位置。如果三次方程的实根不完整,请给出三次方程的所有实根的正确公式。

1 个答案:

答案 0 :(得分:0)

https://brilliant.org/wiki/cardano-method/

这回答了如何解决它的插件和突突。