Более элегантный способ изменения размера сектора с использованием Raphaël JS и SVG?

Я использую Raphaël в первый раз с небольшим опытом svg, и мне нужен кто-то, кто действительно хорошо разбирается в этих двух, чтобы помочь мне.

Я создал круговую диаграмму с динамическими секторами. Секторы можно изменить, перетащив круглые кнопки. См. эту скрипту. Я тестировал только в Chrome и Safari, которые являются единственными требуемыми браузерами.

Круговая диаграмма еще не завершена. Секторы могут перекрываться. Пожалуйста, проигнорируйте это сейчас.

У меня возникли проблемы, когда начальный угол сектора был больше угла окончания. Это тот случай, когда конечный угол проходит отметку 0/360 °. Чтобы решить эту проблему, я использовал параметр path rotation. Я двигал сектор вперед, двигая углы назад, пока конечный угол не достиг 360. Вы можете видеть это в скрипке в этой функции:

function sector_update(cx, cy, r, startAngle, endAngle, sec) {
    var x1 = cx + r * Math.cos(-startAngle * rad),
        x2 = cx + r * Math.cos(-endAngle * rad),
        y1 = cy + r * Math.sin(-startAngle * rad),
        y2 = cy + r * Math.sin(-endAngle * rad);


    var rotation = 0;

    // This is the part that I have the feeling could be improved.
    // Remove the entire if-clause and let "rotation" equal 0 to see what happens
    if (startAngle > endAngle) {
        rotation = endAngle;
        startAngle = startAngle - endAngle;
        endAngle = 360;
    }

    sec.attr('path', ["M", cx, cy, "L", x1, y1, "A", r, r, rotation, 
    +(endAngle - startAngle > 180), 0, x2, y2, "z"]);
}

Хотя это работает красиво, я немного скептически настроен. Можно ли это решить без поворота пути? Я ценю любую помощь или указатели.

Ответы

Ответ 1

Can this be solved without the rotation of the path?

Ответ: Да, это возможно. Вам вообще не нужно менять поворот пути. Если я что-то не упустил, следующий код, похоже, будет работать так же, как и в скрипте:

function sector_update(cx, cy, r, startAngle, endAngle, sec) {
    var x1 = cx + r * Math.cos(-startAngle * rad),
        x2 = cx + r * Math.cos(-endAngle * rad),
        y1 = cy + r * Math.sin(-startAngle * rad),
        y2 = cy + r * Math.sin(-endAngle * rad);

    //notice there is no "roation" variable
    if (startAngle > endAngle) {
        startAngle -= endAngle;
        endAngle = 360;
    }

    sec.attr('path', ["M", cx, cy, "L", x1, y1, "A", r, r, 0, 
    +(endAngle - startAngle > 180), 0, x2, y2, "z"]);
}

Объяснение:. Для моего объяснения я буду использовать терминологию SVG в W3 Spec и Справочная библиотека Raphael. То есть, в то время как вы используете cx, cy и rotation, они используют rx, ry и x-axis-rotation соответственно.

Короче говоря, всякий раз, когда rx равно ry, тогда x-axis-rotation не имеет смысла.

Посмотрите этот SVG. Используйте инструменты разработки вашего браузера или сохраните SVG на свой компьютер и используйте редактор файлов для его редактирования. В частности, посмотрите на последний элемент path, в котором есть четыре дуги. Попробуйте изменить значение x-axis-rotation для каждой дуги. Вы заметите, что первая дуга (где rx и ry равны "25" ) никогда не изменяется при обновлении значения x-axis-rotation.

Почему? Это потому, что у вас есть дуга окружности. Независимо от того, насколько вы вращаете круг, он все равно будет тем же кругом. Например, подержите стакан перед собой, чтобы стекло было горизонтально к земле, и вы смотрите прямо вниз по стеклу. Теперь поверните/скрутите стекло с запястьем. Вы видите, как круглая форма, которую вы видите, остается в той же круглой форме? Теперь установите стекло на стол в обычном порядке (так оно вертикально и может содержать жидкость). Теперь переверните стакан. Вы можете увидеть очевидное изменение перспективы; он указывал вверх, но теперь он лежит ровно. Это то, что делает x-axis-rotation.

Возможно, лучший пример - просто поиграть с вышеупомянутым SVG файлом. Играйте с x-axis-rotation по дугам в последнем элементе path. Вы увидите, что дуги вращаются вокруг. Это то, что делает x-axis-rotation.

Вернуться к вашему коду:. Поскольку вы имеете дело только с круглыми объектами, x-axis-rotation не будет иметь никакого значения для конечного вывода. Пока вы имеете дело только с круговыми объектами, вы можете жестко закодировать его значение до нуля без каких-либо забот. Все, что вам действительно нужно сделать, это изменить углы, которые вы сделали правильно.

Производительность:. Я пробовал использовать JavaScript во время вашей функции sector_update как с изменением переменной x-axis-rotation, так и без нее. Результат? Я не видел разницы в производительности. Большая часть времени, затраченного на фактическое рисование SVG, а не на математику, которая определяет ее значения. Фактически, все, что вы действительно делаете в JavaScript, - это обновление кода для установки значения в элементе path. В этот момент браузер берет на себя механизм рендеринга, чтобы на самом деле нарисовать объект SVG. Я полагаю, что это проблема для браузера, так как каждый браузер имеет разную производительность рендеринга. Но что касается того, имеет ли значение x-axis-rotation какое-либо влияние, я думаю, что нет. Если есть падение производительности (поскольку браузер, возможно, придется сделать дополнительную операцию с плавающей точкой), это так невероятно спорный вопрос, потому что подавляющее большинство времени тратится на рисование объекта, а не расчета его значения. Поэтому я бы сказал, чтобы не беспокоиться об этом.

Я надеюсь, что это поможет, дайте мне знать, если я что-то пропустил или не объяснил что-то достаточно хорошо.