10

私は、SVGを使用して線を描画するJavascriptでマップを開発しています。

道路を検索できる機能を追加したいのですが、道路が見つかると地図上に円が表示されます。

SVGで円を描くことができることは知っていますが、私の問題は、ズームレベルに応じて円のサイズが変わらないことです。言い換えれば、円は常に同じサイズでなければなりません。私の地図上の道路にはこの機能があり、私がしなければならなかったのは追加することだけでした

vector-effect="non-scaling-stroke"

行属性に。

線はこんな感じ。

<line vector-effect="non-scaling-stroke" stroke-width="3" id = 'line1' x1 = '0' y1 = '0' x2 = '0' y2 = '0' style = 'stroke:rgb(255,215,0);'/> 

円はこんな感じ。

<circle id = "pointCircle" cx="0" cy="0" r="10" stroke="red" stroke-width="1" fill = "red"/>

どういうわけか、円を「非スケーリング」として定義することは可能ですか?

4

4 に答える 4

7

少し時間がかかりましたが、ようやく数学をきれいにできました。このソリューションには、次の 3 つのことが必要です。

  1. このスクリプトを ( SVGPan.jsスクリプトと共に) ページに含めます。
    <script xlink:href="SVGPanUnscale.js"></script>
  2. 拡大縮小したくない項目を特定し (例: それらを特別なクラスまたは ID を持つグループに配置する、または各要素に特定のクラスを配置する)、スクリプトにそれらの項目を見つける方法を指示します。
    unscaleEach("g.non-scaling > *, circle.non-scaling");
  3. ではなくtransform="translate(…,…)"、図に各要素を配置するために使用します。 cx="…" cy="…"

これらの手順だけで、SVGPan を使用したズームとパンは、マークされた要素のスケール (または回転、または傾斜) に影響しません。

デモ: http://phrogz.net/svg/scale-independent-elements.svg

としょうかん

// Copyright 2012 © Gavin Kistner, !@phrogz.net
// License: http://phrogz.net/JS/_ReuseLicense.txt

// Undo the scaling to selected elements inside an SVGPan viewport
function unscaleEach(selector){
  if (!selector) selector = "g.non-scaling > *";
  window.addEventListener('mousewheel',     unzoom, false);
  window.addEventListener('DOMMouseScroll', unzoom, false);
  function unzoom(evt){
    // getRoot is a global function exposed by SVGPan
    var r = getRoot(evt.target.ownerDocument);
    [].forEach.call(r.querySelectorAll(selector), unscale);
  }
}

// Counteract all transforms applied above an element.
// Apply a translation to the element to have it remain at a local position
function unscale(el){
  var svg = el.ownerSVGElement;
  var xf = el.scaleIndependentXForm;
  if (!xf){
    // Keep a single transform matrix in the stack for fighting transformations
    // Be sure to apply this transform after existing transforms (translate)
    xf = el.scaleIndependentXForm = svg.createSVGTransform();
    el.transform.baseVal.appendItem(xf);
  }
  var m = svg.getTransformToElement(el.parentNode);
  m.e = m.f = 0; // Ignore (preserve) any translations done up to this point
  xf.setMatrix(m);
}

デモコード

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Scale-Independent Elements</title>
  <style>
    polyline { fill:none; stroke:#000; vector-effect:non-scaling-stroke; }
    circle, polygon { fill:#ff9; stroke:#f00; opacity:0.5 }
  </style>
  <g id="viewport" transform="translate(500,300)">
    <polyline points="-100,-50 50,75 100,50" />
    <g class="non-scaling">
      <circle  transform="translate(-100,-50)" r="10" />
      <polygon transform="translate(100,50)" points="0,-10 10,0 0,10 -10,0" />
    </g>
    <circle class="non-scaling" transform="translate(50,75)" r="10" />
  </g>
  <script xlink:href="SVGPan.js"></script>
  <script xlink:href="SVGPanUnscale.js"></script>
  <script>
    unscaleEach("g.non-scaling > *, circle.non-scaling");
  </script>
</svg>
于 2012-05-23T05:02:08.393 に答える
3

これを行う完全に静的な方法を探している場合は、非スケーリング ストロークとマーカーを組み合わせてこれを取得できる可能性があります。これは、マーカーがストローク幅に関連している可能性があるためです。

つまり、円を <marker> 要素で囲み、必要な場所でそれらのマーカーを使用できます。

<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000">
    <marker id="Triangle"
      viewBox="0 0 10 10" refX="0" refY="5" 
      markerUnits="strokeWidth"
      markerWidth="4" markerHeight="3"
      orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </marker>
        <path d="M 100 100 l 200 0" vector-effect="non-scaling-stroke"
        fill="none" stroke="black" stroke-width="10" 
        marker-end="url(#Triangle)"  />
        <path d="M 100 200 l 200 0" 
        fill="none" stroke="black" stroke-width="10" 
        marker-end="url(#Triangle)"  />
</svg>

同じものをここで表示して微調整することもできます。svg 仕様は、この場合に何が起こるべきかについて完全に明示的ではありません (マーカーは SVG Tiny 1.2 になく、ベクトル効果は SVG 1.1 にはないため)。私の現在の考えでは、おそらくマーカーのサイズに影響を与えるはずですが、現時点ではそれを行うビューアはないようです (Opera や Chrome などのベクトル効果をサポートするビューアで試してください)。

于 2012-05-07T08:07:35.043 に答える