Поворот расположения элемента группы SVG в JavaScript без поворота всего изображения - PullRequest
2 голосов
/ 20 июня 2011

У меня есть карта, нарисованная в SVG, в которой я использую матричные преобразования для поворота на основе определенных событий мыши. Когда я нажимаю на части карты, у меня появляются аннотации, которые нарисованы (в элементе группы, отдельном от повернутого изображения).

Прямо сейчас я могу переместить эти аннотации с картой, когда перетаскиваю ее, просто отправив событие в функцию JavaScript, чтобы выполнить этот сдвиг как отдельное действие. Я хотел бы сделать то же самое, когда я поворачиваю и масштабирую основную карту, но не уверен, как поступить - очевидно, я не хочу поворачивать все изображение аннотации; Я просто хочу сдвинуть его, чтобы он соответствовал обновленной карте. Возможно, мне нужно выяснить, как рассчитать влияние преобразования карты на координаты X / Y отдельной точки, а затем применить этот расчет к местоположению аннотации. Кажется, я не могу найти никаких ресурсов, которые могли бы помочь выяснить, как это сделать.

Вот статья в блоге, в которой я писал о том, как я манипулирую базовой картой: http://justindthomas.wordpress.com/category/flower-nfa/

Живой пример из этой статьи сейчас не работает (я переместил расположение файлов JavaScript), но он должен дать некоторый полезный контекст для моего вопроса.

1 Ответ

1 голос
/ 25 июня 2011

Я закончил просто делать математику от руки. Вот функция, которую я использовал для потомков:

getRadiusAngle: function(referenceX, referenceY, centerX, centerY) {                
    var width = centerX - referenceX;
    var height = centerY - referenceY;
    var angle, radius;

    if(centerY > referenceY) {
        if(centerX > referenceX) {
            angle = Math.PI - Math.atan(Math.abs(height/width));
            radius = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
        } else if (centerX < referenceX) {
            angle = Math.atan(Math.abs(height/width));
            radius = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
        } else if (centerX == referenceX) {
            angle = Math.PI / 2;
            radius = height;
        }
    } else if(centerY < referenceY) {
        if(centerX > referenceX) {
            angle = Math.PI + Math.atan(Math.abs(height/width));
            radius = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
        } else if (centerX < referenceX) {
            angle = (2 * Math.PI) - Math.atan(Math.abs(height/width));
            radius = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
        } else if (centerX == referenceX) {
            angle = Math.PI * 1.5;
            radius = Math.abs(height);
        }
    } else if(centerY == referenceY) {
        if(centerX > referenceX) {
            angle = Math.PI;
            radius = width;
        } else if (centerX < referenceX) {
            angle = 0;
            radius = Math.abs(width);
        } else if(centerX == referenceX) {
            angle = 0;
            radius = 0;
        }
    }

    return({
        "radius": radius, 
        "angle": angle
    })
},

Для операций поворота я тогда использовал:

var calcwidth = annotations[i].getAttribute("calcwidth");
var matrix = annotations[i].getCTM();

var referenceX = (matrix.e + (calcwidth/2));
var referenceY = (matrix.f + 32);

var ra = this.getRadiusAngle(referenceX, referenceY, pointerX, pointerY);

var current_angle = ra.angle;
var radius = ra.radius

var newX, newY;
if(radius == 0) {
    newX = matrix.e;
    newY = matrix.f;
} else {      
    var new_angle = current_angle + -radians;  

    newX = (pointerX + (radius * Math.cos(new_angle))) - (calcwidth/2);
    newY = (pointerY + -(radius * Math.sin(new_angle))) - 32;
}

annotations[i].setAttribute("transform", "translate(" 
    + newX + " " + newY + ")");

Для масштабирования я использовал похожую стратегию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...