web-dev-qa-db-ja.com

SVGで変換元を設定する方法

Javascriptを使用して、SVGドキュメント内の特定の要素のサイズを変更して回転する必要があります。問題は、デフォルトでは、(0, 0) –左上のOriginの周りに常に変換を適用することです。

この変換アンカーポイントを再定義するにはどうすればよいですか?

transform-Origin属性を使用してみましたが、何の影響もありません。

これは私がそれをやった方法です:

svg.getDocumentById('someId').setAttribute('transform-Origin', '75 240');

Firefoxで属性が正しく設定されていることがわかりますが、ピボットポイントは指定したポイントに設定されていないようです。 center bottom50% 100%のようなものをかっこありとなしで試しました。今のところ何も機能していません。

誰でも助けることができますか?

83
Charlemagne

回転するにはtransform="rotate(deg, cx, cy)"を使用します。ここで、degは回転する角度で、(cx、cy)は回転の中心を定義します。

スケーリング/サイズ変更を行うには、(-cx、-cy)で変換し、スケーリングしてから(cx、cy)に戻す必要があります。 マトリックス変換 でこれを行うことができます:

transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"

ここで、sxはx軸の倍率、syはy軸の倍率です。

132

固定値(「center」または「50%」ではない)を使用できる場合は、代わりにCSSを使用できます。

-moz-transform-Origin: 25px 25px;
-ms-transform-Origin:  25px 25px;
-o-transform-Origin: 25px 25px;
-webkit-transform-Origin:  25px 25px;
transform-Origin: 25px 25px;

一部のブラウザ(Firefoxなど)は、相対値を正しく処理しません。

19
Hafenkranich

あなたが私のような人で、transform-Originでパンしてズームしたい場合は、もう少し必要になります。

// <g id="view"></g>
var view = document.getElementById("view");

var state = {
  x: 0,
  y: 0,
  scale: 1
};

// Origin of transform, set to mouse position or pinch center
var oX = window.innerWidth/2;
var oY = window.innerHeight/2;

var changeScale = function (scale) {
  // Limit the scale here if you want
  // Zoom and pan transform-Origin equivalent
  var scaleD = scale / state.scale;
  var currentX = state.x;
  var currentY = state.y;
  // The magic
  var x = scaleD * (currentX - oX) + oX;
  var y = scaleD * (currentY - oY) + oY;

  state.scale = scale;
  state.x = x;
  state.y = y;

  var transform = "matrix("+scale+",0,0,"+scale+","+x+","+y+")";
  //var transform = "translate("+x+","+y+") scale("+scale+")"; //same
  view.setAttributeNS(null, "transform", transform);
};

ここでは動作しています: http://forresto.github.io/dataflow-prototyping/react/

11
forresto

matrix変換を使用せずにスケーリングする場合:

transform="translate(cx, cy) scale(sx sy) translate(-cx, -cy)"

そして、これはCSSにあります:

transform: translate(cxpx, cypx) scale(sx, sy) translate(-cxpx, -cypx)
10
cmititiuc

同様の問題がありました。しかし、私はDを使用して要素を配置し、CSSでtransformおよびtransitionを処理することを望んでいました。これは私の元のコードで、Chrome 65:

_//...
this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('circle')
  .attr('transform-Origin', (d,i)=> `${valueScale(d.value) * Math.sin( sliceSize * i)} 
                                     ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)}`)
//... etc (set the cx, cy and r below) ...
_

これにより、同じデータを使用してcxcy、および_transform-Origin_の値をjavascriptに設定できました。

ただし、これはFirefoxでは機能しませんでした!私がしなければならなかったのは、circleタグでgをラップし、同じものを使用してtranslateでした上からの位置決め式。次に、circleタグにgを追加し、cxおよびcyの値を_0_に設定しました。そこから、transform: scale(2)は期待どおりに中心から拡大縮小します。最終的なコードは次のようになりました。

_this.layerGroups.selectAll('.dot')
  .data(data)
  .enter()
  .append('g')
  .attrs({
    class: d => `dot ${d.metric}`,
    transform: (d,i) => `translate(${valueScale(d.value) * Math.sin( sliceSize * i)} ${valueScale(d.value) * Math.cos( sliceSize * i + Math.PI)})`
  })
  .append('circle')
  .attrs({
    r: this.opts.dotRadius,
    cx: 0,
    cy: 0,
  })
_

この変更を行った後、transform: scale(2)を追加するために、_.dot_ではなくcircleをターゲットとするようにCSSを変更しました。 _transform-Origin_を使用する必要さえありませんでした。

注:

  1. 2番目の例では_d3-selection-multi_を使用しています。これにより、属性ごとに_.attrs_を繰り返す代わりに、オブジェクトを_.attr_に渡すことができます。

  2. 文字列テンプレートリテラルを使用する場合、最初の例に示すように改行に注意してください。これにより、出力に改行が含まれ、コードが破損する場合があります。

0
Jamie S