目前正在构建一个基于浏览器的SVG应用程序。在这个应用程序中,用户可以设置各种形状的样式和位置,包括矩形。

当我将笔画宽度应用到SVG矩形元素(比如1px)时,不同的浏览器会以不同的方式将笔画应用到矩形的偏移和插入。这被证明是很麻烦的,特别是当我试图计算一个矩形的外部宽度和视觉位置,并将其放置在其他元素旁边时。

例如:

Firefox添加了1px的插入(底部和左侧)和1px的偏移(顶部和右侧) Chrome添加了1px的插入(顶部和左侧),和1px的偏移(底部和右侧)

到目前为止,我唯一的解决方案是自己绘制实际的边界(可能是用路径工具),并将边界定位在描边元素的后面。但这种解决方案是一种令人不快的变通方法,如果可能的话,我宁愿不走这条路。

所以我的问题是,你能控制SVG的笔画宽度如何在元素上绘制吗?


当前回答

您可以使用CSS样式的笔画和填充顺序。即先描边,后填充,得到想要的效果。

MDN油漆订购:https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-order

CSS代码:

paint-order: stroke;

其他回答

这里是一个关于内边框矩形使用符号和使用的工作。

例如:https://jsbin.com/yopemiwame/edit?html,输出

SVG:

<svg>
  <symbol id="inner-border-rect">
    <rect class="inner-border" width="100%" height="100%" style="fill:rgb(0,255,255);stroke-width:10;stroke:rgb(0,0,0)">
  </symbol>
  ...
  <use xlink:href="#inner-border-rect" x="?" y="?" width="?" height="?">
</svg>

注意:一定要替换?用真正的价值。

背景:这样工作的原因是因为symbol通过用svg替换symbol并在shadow DOM中创建一个元素来建立一个新的视口。阴影DOM的svg随后链接到当前svg元素。注意,svg可以嵌套,并且每个svg都会创建一个新的视口,它会剪辑所有重叠的部分,包括重叠的边界。要想更详细地了解正在发生的事情,请阅读Sara Soueidan的这篇精彩文章。

下面是一个函数,它将计算你需要添加多少像素-使用给定的笔画-到顶部,右侧,底部和左侧,所有这些都基于浏览器:

var getStrokeOffsets = function(stroke){

        var strokeFloor =       Math.floor(stroke / 2),                                                                 // max offset
            strokeCeil =        Math.ceil(stroke / 2);                                                                  // min offset

        if($.browser.mozilla){                                                                                          // Mozilla offsets

            return {
                bottom:     strokeFloor,
                left:       strokeFloor,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }else if($.browser.webkit){                                                                                     // WebKit offsets

            return {
                bottom:     strokeCeil,
                left:       strokeFloor,
                top:        strokeFloor,
                right:      strokeCeil
            };

        }else{                                                                                                          // default offsets

            return {
                bottom:     strokeCeil,
                left:       strokeCeil,
                top:        strokeCeil,
                right:      strokeCeil
            };

        }

    };

如上所述,你必须重新计算笔画路径坐标的偏移量,或者将其宽度翻倍,然后掩码一侧或另一侧,因为不仅SVG本身不支持Illustrator的笔画对齐,而且PostScript也不支持。

Adobe PostScript手册第二版中的笔画规范规定: 4.5.1抚摸: 描边操作符沿着当前路径绘制一条一定粗细的线。对于路径中的每个直线或曲线段,笔画一条以该段为中心,两侧平行于该段的直线。”(并强调了这一点)

规范的其余部分没有用于偏移行的位置的属性。当Illustrator让你在内部或外部对齐时,它会重新计算实际路径的偏移量(因为它仍然比套印然后掩蔽计算更便宜)。.ai文档中的路径坐标是引用,而不是被光栅化或导出为最终格式的内容。

因为Inkscape的原生格式是规范SVG,所以它不能提供规范所缺乏的特性。

这招对我很管用:

.btn {
 border: 1px solid black;
 box-shadow: inset 0 0 0 1px black;
}

一个(肮脏的)可能的解决方案是使用模式,

下面是一个内描边三角形的例子:

https://jsfiddle.net/qr3p7php/5/

<style>
#triangle1{
  fill: #0F0;
  fill-opacity: 0.3;
  stroke: #000;
  stroke-opacity: 0.5;
  stroke-width: 20;
}
#triangle2{
  stroke: #f00;
  stroke-opacity: 1;
  stroke-width: 1;
}    
</style>

<svg height="210" width="400" >
    <pattern id="fagl" patternUnits="objectBoundingBox" width="2" height="1" x="-50%">
        <path id="triangle1" d="M150 0 L75 200 L225 200 Z">
    </pattern>    
    <path id="triangle2" d="M150 0 L75 200 L225 200 Z" fill="url(#fagl)"/>
</svg>