【问题标题】:SVG path with stroke fills the svg element带有描边的 SVG 路径填充 svg 元素
【发布时间】:2021-06-07 06:32:25
【问题描述】:

我有一组可用于在谷歌地图中创建多边形的坐标。我使用 mercantor-projection formula described in this answer 将其转换为可在 svg 中使用的一组点 (x,y)。转换成功并正确渲染。

元素中没有设置 stroke 属性的情况下,下面的 sn-p 渲染效果很好。如果您取消注释第 29 行将 stroke 属性设置为红色的位置,它将填充整个 svg 元素,而不是用红色勾勒元素,这突出了本文的主要问题。

const COORDINATES = [[-86.917595,32.664169],[-86.918817,32.644278],[-86.898304,32.567687],[-86.90675,32.537298],[-86.890829,32.513742],[-86.878989,32.487323],[-86.885203,32.482438],[-86.870212,32.468974],[-86.860056,32.450861],[-86.86709,32.439188],[-86.849898,32.438325],[-86.824394,32.424725],[-86.845448,32.415416],[-86.843758,32.400416],[-86.827244,32.378816],[-86.815399,32.370821],[-86.807378,32.354356],[-86.814912,32.340803],[-86.820921,32.33324],[-86.816107,32.30997],[-86.798268,32.308632],[-86.773163,32.340728],[-86.780447,32.3686],[-86.778365,32.394601],[-86.749981,32.389105],[-86.727181,32.404497],[-86.717897,32.402814],[-86.719028,32.372059],[-86.711337,32.360767],[-86.683537,32.353395],[-86.655597,32.376147],[-86.653419,32.397247],[-86.618,32.405717],[-86.613453,32.398584],[-86.614841,32.374266],[-86.595335,32.361345],[-86.581873,32.375019],[-86.570551,32.375006],[-86.542537,32.363517],[-86.532531,32.338775],[-86.496774,32.344437],[-86.491902,32.364327],[-86.463564,32.377288],[-86.461277,32.403473],[-86.456273,32.405837],[-86.444721,32.399841],[-86.411172,32.409937],[-86.412229,32.528746],[-86.412446,32.579324],[-86.413116,32.707386],[-86.524434,32.707058],[-86.714219,32.705694],[-86.71339,32.661732],[-86.771532,32.660717],[-86.816574,32.660117],[-86.917595,32.664169]];

const getPoint = ([x, y]) => {
    return {
        x: (x + 180) * (256 / 360),
        y: (256 / 2) - (256 * Math.log(Math.tan((Math.PI / 4) + ((y * Math.PI / 180) / 2))) / (2 * Math.PI))
    };
};

const svg = document.querySelector('svg');
const points = [];
let minX = 256;
let minY = 256;
let maxX = 0;
let maxY = 0;

for(const coordinate of COORDINATES) {
  const point = getPoint(coordinate);
  minX = Math.min(minX, point.x);
  minY = Math.min(minY, point.y);
  maxX = Math.max(maxX, point.x);
  maxY = Math.max(maxY, point.y);
  points.push(`${point.x},${point.y}`);
}

const g = document
  .createElementNS("http://www.w3.org/2000/svg", 'g');

const path = document
  .createElementNS("http://www.w3.org/2000/svg", 'path');

svg.setAttribute(
  'viewBox', 
  [minX, minY, maxX - minX, maxY - minY].join(' ')
);

path.setAttribute('d', 'M' + points.join(' ') + 'z');
path.setAttribute('fill', 'blue');
//path.setAttribute('stroke', 'red');
  
g.appendChild(path);
svg.appendChild(g);
<svg height="400" width="400" preserveAspectRatio="xMinYMin meet"></svg>

为什么设置 stroke 属性会用指定的笔触颜色填充 SVG 元素?

如果有人能指出如何解决上述sn-p的问题,那就太好了。

【问题讨论】:

    标签: javascript html svg


    【解决方案1】:

    问题与 SVG 的缩放有关。将笔画宽度设置为 0.0025 之类的小值可以解决此问题。

    const COORDINATES = [[-86.917595,32.664169],[-86.918817,32.644278],[-86.898304,32.567687],[-86.90675,32.537298],[-86.890829,32.513742],[-86.878989,32.487323],[-86.885203,32.482438],[-86.870212,32.468974],[-86.860056,32.450861],[-86.86709,32.439188],[-86.849898,32.438325],[-86.824394,32.424725],[-86.845448,32.415416],[-86.843758,32.400416],[-86.827244,32.378816],[-86.815399,32.370821],[-86.807378,32.354356],[-86.814912,32.340803],[-86.820921,32.33324],[-86.816107,32.30997],[-86.798268,32.308632],[-86.773163,32.340728],[-86.780447,32.3686],[-86.778365,32.394601],[-86.749981,32.389105],[-86.727181,32.404497],[-86.717897,32.402814],[-86.719028,32.372059],[-86.711337,32.360767],[-86.683537,32.353395],[-86.655597,32.376147],[-86.653419,32.397247],[-86.618,32.405717],[-86.613453,32.398584],[-86.614841,32.374266],[-86.595335,32.361345],[-86.581873,32.375019],[-86.570551,32.375006],[-86.542537,32.363517],[-86.532531,32.338775],[-86.496774,32.344437],[-86.491902,32.364327],[-86.463564,32.377288],[-86.461277,32.403473],[-86.456273,32.405837],[-86.444721,32.399841],[-86.411172,32.409937],[-86.412229,32.528746],[-86.412446,32.579324],[-86.413116,32.707386],[-86.524434,32.707058],[-86.714219,32.705694],[-86.71339,32.661732],[-86.771532,32.660717],[-86.816574,32.660117],[-86.917595,32.664169]];
    
    const getPoint = ([x, y]) => {
        return {
            x: (x + 180) * (256 / 360),
            y: (256 / 2) - (256 * Math.log(Math.tan((Math.PI / 4) + ((y * Math.PI / 180) / 2))) / (2 * Math.PI))
        };
    };
    
    const svg = document.querySelector('svg');
    const points = [];
    let minX = 256;
    let minY = 256;
    let maxX = 0;
    let maxY = 0;
    
    for(const coordinate of COORDINATES) {
      const point = getPoint(coordinate);
      minX = Math.min(minX, point.x);
      minY = Math.min(minY, point.y);
      maxX = Math.max(maxX, point.x);
      maxY = Math.max(maxY, point.y);
      points.push(`${point.x},${point.y}`);
    }
    
    const g = document
      .createElementNS("http://www.w3.org/2000/svg", 'g');
    
    const path = document
      .createElementNS("http://www.w3.org/2000/svg", 'path');
    
    svg.setAttribute(
      'viewBox', 
      [minX, minY, maxX - minX, maxY - minY].join(' ')
    );
    
    path.setAttribute('d', 'M' + points.join(' ') + 'z');
    path.setAttribute('fill', 'blue');
    path.setAttribute('stroke', 'red');
    path.setAttribute('stroke-width', '.0025');
      
    g.appendChild(path);
    svg.appendChild(g);
    <svg height="400" width="400" preserveAspectRatio="xMinYMin meet"></svg>

    【讨论】:

    • 非常感谢!我已经为这个问题苦苦挣扎了几个小时了。
    • 也可以使用vector-effect: non-scaling-stroke;,但最好的办法是将坐标缩放到更自然的值,像这样玩极端会使它更容易出现舍入错误和奇怪的错误。
    • @Kaiido vector-effect: non-scaling-stroke 也可以。不幸的是,它不适用于我们公司仍然支持的 IE11。关于将其放大到自然值,乘以 x,y 是否指向更高的百分比有效?还是有其他更简单的转换方式?
    • 是的,将您的坐标乘以一个设定因子会起作用,您必须计算所述因子,我个人没有时间彻底查看您的代码以更好地指导您如何做所以,对不起。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2015-02-03
    • 1970-01-01
    相关资源
    最近更新 更多