English 中文(简体)
• 如何在印瓦特的SVG中抽取非消耗性循环
原标题:How to draw non-scalable circle in SVG with Javascript

我在Javascript利用SVG绘制地图。

我要补充说,你可以寻找一条道路,如果找到道路,地图上就有一个圈子。

I know i can draw a circle in SVG, but my problem is that, the size of the circle should not change depending on the zoom-level. In other words the circle must have the same size at all times. The roads on my map have this feature, all i had to do was add

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"/>

可否将这个圈子定义为“非扩展性”?

问题回答

当时我去了,但我最后去做的是数学清洗。 这一解决办法需要三个方面:

  1. Include this script in your page (along with the SVGPan.js script), e.g.
    <script xlink:href="SVGPanUnscale.js"></script>
  2. Identify the items you want not to scale (e.g. place them in a group with a special class or ID, or put a particular class on each element) and then tell the script how to find those items, e.g.
    unscaleEach("g.non-scaling > *, circle.non-scaling");
  3. Use transform="translate(…,…)" to place each element on the diagram, not cx="…" cy="…".

仅仅采取这些步骤,使用SVGPan进行集聚和种植不会影响标记要素的规模(或轮换或sk)。

Demo: http://phrogz.net/svg/scale-independent-elements.svg

Library

// Copyright 2012 © Gavin Kistner, [email protected]
// 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);
}

Demo Code

<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>

如果你寻找完全静态的方式,你可能能够将非中风与标记相结合,以达到这一目的,因为标识可能与中风。

换言之,你可以把圈子划入一个带;标记和组件,然后在需要时使用这些标识。

<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>

The same can also be viewed and tweaked here. The svg spec isn t fully explicit about what should happen in this case (since markers are not in SVG Tiny 1.2, and vector-effect isn t in SVG 1.1). My current line of thinking was that it should probably affect the size of the marker, but it seems no viewers do that at the moment (try in a viewer that supports vector-effect, e.g Opera or Chrome).

类似一些工作是在网上进行的(可能与这一ug子有关:320635 <);以及新变式的贴在仅仅照此附上时的 t。

transform.baseVal.appendItem

This seems to work better. Even works in IE 10.

EDIT: 规定在前线进行多种翻译的更一般情况下的代码,以及其后可能出现的其他变化。 所有的翻译之后,首先进行矩阵转换,但必须予以保留。

<代码>translate(1718.07 839.711) 翻译(0)矩阵(0.287175 0 0.287175 0 0 0 0 0) 轮值(45 100)

function unscale()
{
    var xf = this.ownerSVGElement.createSVGTransform();
    var m = this.ownerSVGElement.getTransformToElement(this.parentNode);
    m.e = m.f = 0; // Ignore (preserve) any translations done up to this point
    xf.setMatrix(m);

    // Keep a single transform matrix in the stack for fighting transformations
    // Be sure to apply this transform after existing transforms (translate)
    var SVG_TRANSFORM_MATRIX = 1;
    var SVG_TRANSFORM_TRANSLATE = 2;
    var baseVal = this.transform.baseVal;
    if(baseVal.numberOfItems == 0)
        baseVal.appendItem(xf);
    else
    {
        for(var i = 0; i < baseVal.numberOfItems; ++i)
        {
            if(baseVal.getItem(i).type == SVG_TRANSFORM_TRANSLATE && i == baseVal.numberOfItems - 1)
        {
                baseVal.appendItem(xf);
            }

            if(baseVal.getItem(i).type != SVG_TRANSFORM_TRANSLATE)
            {
                if(baseVal.getItem(i).type == SVG_TRANSFORM_MATRIX)
                    baseVal.replaceItem(xf, i);
                else
                    baseVal.insertItemBefore(xf, i);
                break;
            }
        }
    }
}

EDIT2: Chrome killed getTransformToElement for some reason, so the matrix needs to be retrieved manually:

var m = this.parentNode.getScreenCTM().inverse().multiply(this.ownerSVGElement.getScreenCTM());




相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签