HTML5: получить позицию щелчка по дуге холста - PullRequest
1 голос
/ 20 января 2012

См. Этот jsFiddle пост для рабочего чертежа дуги; спасибо Саймону Саррису за исправление в моих предыдущих вопросах.

Я использую плагин KineticJS для создания фигур и использования обработчиков событий. Предполагая, что вы щелкнули где-то на дуге и дуга знала, где вы щелкнули (x, y), как эти две координаты можно использовать для определения процента?

Когда вы щелкаете в любом месте, общий процент всегда равен 100%.

Аддин

Чтобы сделать это проще, что я могу сделать, чтобы (x, y) фактически согнуть объект так, чтобы x перешел от 0 к максимуму x?

Ответы [ 3 ]

2 голосов
/ 20 января 2012

Простая тригонометрия. sin(angle) = opposite / adjacent. opposite - это значение y, а adjacent - это значение x. Так Math.asin((xx - x) / (yy - y)), где xx и yy - координаты центра дуги. Это дает вам угол, который вы можете затем разделить 2 * Math.PI.

С макушки головы я не могу вспомнить, что происходит с отрицательными числами. Возможно, вам придется принять значение Math.abs аргументов, а затем определить, в каком квадранте щелчка (это легко сделать с помощью < и >) и добавить Math.PI / 2 для каждого из них.

1 голос
/ 26 сентября 2013

Сюда входит проверка, находится ли мышь внутри дуги:

// Return range is 0 to Math.PI * 2
function get_mouse_circle_angle(origin_x, origin_y, mouse_x, mouse_y) {
    var mouse_angle = Math.atan2(mouse_y - origin_y, mouse_x - origin_x);
    if (mouse_angle < 0) {
        mouse_angle = (Math.PI * 2) + mouse_angle;
    }
    return mouse_angle;
}

// Return range is [0, 1)
// 0/1 is 3 oclock
function get_mouse_circle_percent(origin_x, origin_y, mouse_x, mouse_y) {
    var mouse_angle = get_mouse_circle_angle(origin_x, origin_y, mouse_x, mouse_y);
    return mouse_angle / (2 * Math.PI);
}

function get_mouse_arc_pos(origin_x, origin_y, mouse_x, mouse_y, radius, thickness) {
    var mouse_angle = Math.atan2(mouse_y - origin_y, mouse_x - origin_x);
    if (mouse_angle < 0) {
        mouse_angle = (Math.PI * 2) + mouse_angle;
    }
    var mouse_percent = mouse_angle / (2 * Math.PI);

    var circle_edge_x = origin_x + (radius + thickness / 2) * Math.cos(mouse_angle);
    var circle_edge_y = origin_y + (radius + thickness / 2) * Math.sin(mouse_angle);

    var arc_inside_x = origin_x + (radius - thickness / 2) * Math.cos(mouse_angle);
    var arc_inside_y = origin_y + (radius - thickness / 2) * Math.sin(mouse_angle);

    var is_in_circle = true;

    if (mouse_angle <= (2 * Math.PI) * 0.25) {
        if (mouse_x > circle_edge_x || mouse_y > circle_edge_y)
            is_in_circle = false;
    }
    else if (mouse_angle <= (2 * Math.PI) * 0.5) {
        if (mouse_x < circle_edge_x || mouse_y > circle_edge_y)
            is_in_circle = false;
    }
    else if (mouse_angle <= (2 * Math.PI) * 0.75) {
        if (mouse_x < circle_edge_x || mouse_y < circle_edge_y)
            is_in_circle = false;
    }
    else {
        if (mouse_x > circle_edge_x || mouse_y < circle_edge_y)
            is_in_circle = false;
    }

    var is_in_arc = is_in_circle;
    if (is_in_circle) {
        if (mouse_angle <= (2 * Math.PI) * 0.25) {
            if (mouse_x < arc_inside_x || mouse_y < arc_inside_y)
                is_in_arc = false;
        }
        else if (mouse_angle <= (2 * Math.PI) * 0.5) {
            if (mouse_x > arc_inside_x || mouse_y < arc_inside_y)
                is_in_arc = false;
        }
        else if (mouse_angle <= (2 * Math.PI) * 0.75) {
            if (mouse_x > arc_inside_x || mouse_y > arc_inside_y)
                is_in_arc = false;
        }
        else {
            if (mouse_x < arc_inside_x || mouse_y > arc_inside_y)
                is_in_arc = false;
        }
    }

    return {
        angle: mouse_angle,
        percent: mouse_percent,
        is_in_circle: is_in_circle,
        is_in_arc: is_in_arc
    };
}
0 голосов
/ 20 января 2012

На самом деле не проверял, но технически это должно работать:

// Where x1 and y1 should be the coordinates of the arc's center
function angle(x1, y1, x2, y2) {
    // Calculate a · b
    var nominator = x1 * x2 + y1 * y2;

    // Calculate ||a|| ||b||
    var denominator = Math.sqrt(x1*x1 + y1*y1) * Math.sqrt(x2*x2 + y2*y2);
    if (denominator == 0) return 0; // Indifinite angle

    // Return the angle
    return Math.acos(nominator / denominator);
}

// Returns a percent, might be negative
var percent = angle(0, 0, mouseX, mouseY) / (2*Math.PI);

Редактировать

Для отрицательных чисел вы можете попробовать добавить 1, поскольку он находится в диапазоне [-1, 1]

if (percent < 0) percent += 1;
...