Рафаэль SVG VML Внедрение нескольких точек разворота для вращения - PullRequest
2 голосов
/ 14 января 2011

За последние два дня я эффективно понял, как НЕ вращать элементы Рафаэля.

В основном я пытаюсь реализовать несколько точек поворота для элемента, чтобы вращать его мышью.

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

Когда мышь нажата и движется, ее достаточно просто вращать вокруг оси, используя Raphael elements.rotate (градусов,x, y) и вычисление градусов на основе положений мыши и atan2 до точки поворота.

Проблема возникает после того, как я повернул элемент, bbox и другие повороты.Там х, у позиции одинаковые, только там видовой экран другой.

В браузере с поддержкой SVG я могу создавать новые точки разворота на основе matrixTransformation и getCTM .Однако после создания первого набора новых опорных точек каждый поворот после опорных точек все дальше удаляется от преобразованного bbox из-за ошибок округления.

rotate errors

Выше даже не вариант в IE, так как в основе VML и не может учитывать преобразование.

Это единственный эффективный способПоворот элемента навесного оборудования осуществляется с помощью абсолютного поворота или вращения вокруг центра ограничительной рамки?

Возможно ли вообще создавать точки множественного поворота для объекта и обновлять их после наведения мыши, чтобы они оставались в углах и центрепреобразованный bbox?

ОБНОВЛЕНИЕ: Я пытался использовать смещение jQuery, чтобы найти стержень после его поворота и использовать это местоположение смещениякак опорная точка.

Демонстрационный сайт ... http://weather.speedfetishperformance.com/dev/raphael/rotation.html

1 Ответ

1 голос
/ 17 января 2011

Лучший кроссбраузерный способ, который я могу придумать, чтобы сделать то, что вы хотите, - это выполнить ротацию самостоятельно, а не позволить SVG делать это.Поворот координат x, y довольно прост, и я использую этот код (tcl) всякий раз, когда мне нужно сделать двухмерное вращение: Поворот холста .

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

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

Вот частичная реализация этого кода Tcl в javascript:

сначала мынам нужно регулярное выражение для токенизации путей SVG:

var svg_path_regexp = (function(){
  var number = '-?[0-9.]+';
  var comma = '\s*[, \t]\s*';
  var space = '\s+';
  var xy = number + comma + number;
  var standard_paths = '[mlcsqt]';
  var horiz_vert = '[hv]\s*' + number;
  var arc = 'a\s*' + xy + space + number + space + xy + space + xy;
  var OR = '\s*|';

  return new RegExp(
    standard_paths +OR+
    xy +OR+
    horiz_vert +OR+
    arc,

    'ig'
  );
})();

теперь мы можем реализовать функцию поворота:

function rotate_SVG_path (path, Ox, Oy, angle) {
  angle = angle * Math.atan(1) * 4 / 180.0; // degrees to radians

  var tokens = path.match(svg_path_regexp);

  for (var i=0; i<tokens.length; i++) {
    var token = tokens[i].replace(/^\s+|\s+$/g,''); // trim string

    if (token.match(/\d/)) { // assume it's a coordinate
      var xy = token.split(/[, \t]+/);
      var x = parseFloat(xy[0]);
      var y = parseFloat(xy[1]);
      x = x - Ox;  // Shift to origin
      y = y - Oy;
      var xx = x * Math.cos(angle) - y * Math.sin(angle); // Rotate
      var yy = x * Math.sin(angle) + y * Math.cos(angle);
      x = xx + Ox; // Shift back
      y = yy + Oy;

      token = x + ',' + y;
    }
    else if (token.match(/^[hv]/)) {
      // handle horizontal/vertical line here
    }
    else if (token.match(/^a/)) {
      // handle arcs here
    }

    tokens[i] = token;
  }
  return tokens.join('');
}

Вышеуказанная функция поворота реализует все, кромегоризонтальные / вертикальные линии (необходимо отслеживать предыдущее значение xy) и дуги.Ни один из них не должен быть слишком сложным для реализации.

...