簡體   English   中英

Raphael SVG VML實現旋轉的多個樞軸點

[英]Raphael SVG VML Implement Multi Pivot Points for Rotation

在過去的兩天內,我有效地弄清楚了如何不旋轉Raphael Elements。

基本上,我試圖在元素上實現多個樞軸點以通過鼠標旋轉它。

當用戶進入旋轉模式時,將創建5個樞軸。 一個用於邊界框的每個角,另一個用於邊界框的中心。

當鼠標向下移動時,使用Raphael elements.rotate(degrees,x,y)繞樞軸旋轉非常簡單並根據鼠標位置和樞軸點atan2計算度數。

在旋轉元素,bbox和其他樞軸之后,就會出現問題。 只有相同的視口中的x,y位置不同。

在啟用SVG的瀏覽器中,我可以基於matrixTransformation和getCTM創建新的樞軸點。 但是,在創建了第一組新的樞軸之后,由於舍入誤差,樞軸之后的每個旋轉都離轉換后的bbox更遠。

旋轉誤差

上面的內容甚至不是IE中的選項,因為in是基於VML的,無法說明轉換。

實現元素旋轉的唯一有效方法是使用絕對旋轉還是圍繞邊界框的中心旋轉?

是否可以在一個對象上創建多個樞軸點並在mouseup之后對其進行更新以保留在變換后的bbox的角和中心?

更新:我試圖使用jQuery offset來旋轉旋轉后找到樞軸,並將該偏移位置用作樞軸點。

演示站點... http://weather.speedfetishperformance.com/dev/raphael/rotation.html

我能想到的最好的跨瀏覽器方式是自己實現旋轉,而不是讓SVG做到。 旋轉x,y坐標非常簡單,每當我需要進行2D旋轉時,我就一直在使用此(tcl)代碼: Canvas Rotation

這樣做的好處是您可以最大程度地控制旋轉,因為您需要手動進行旋轉。 這解決了您試圖旋轉后猜測最終坐標的問題。 另外,這應該與跨瀏覽器兼容。

缺點是您必須使用路徑。 因此,沒有矩形(盡管將其轉換為路徑應該很容易)或橢圓形(將其轉換為路徑更難但可行)。 另外,由於您是手動進行操作,因此它比讓SVG為您完成操作要慢。

這是javascript中Tcl代碼的部分實現:

首先,我們需要一個正則表達式來標記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值)和圓弧以外的所有內容。 兩者都不應該太難實施。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM