你可以控制SVG的笔画宽度是如何绘制的?

目前正在构build基于浏览器的SVG应用程序。 在这个应用程序,各种形状可以由用户,包括矩形风格和定位。

当我将一个stroke-width应用到1px的SVG rect元素时,笔划被应用于rect的偏移量,并由不同的浏览器以不同的方式插入。 这被certificate是麻烦的, 特别是当我尝试计算矩形的外部宽度和可视位置并将其放置在其他元素旁边时。

例如:

  • Firefox添加了1px插图(底部和左侧)和1px的偏移量(顶部和右侧)
  • Chrome添加了1px的插入(上和左)和1px的偏移(下和右)

到目前为止,我唯一的解决scheme是自己绘制实际边框(可能使用path工具),并将边框放在描边元素后面。 但是这个解决scheme是一个令人不快的解决办法,如果可能的话,我宁愿不要走这条路。

所以我的问题是,你能控制如何在元素上绘制SVG的stroke-width吗?

不,您不能指定描边是在内部还是外部绘制。 我在2003年向SVG工作组提出了这个function的build议 ,但没有得到任何支持(或讨论)。

SVG提出的stroke-location示例,来自phrogz.net/SVG/stroke-location.svg

正如我在提案中指出的那样,

  • 您可以通过加倍笔画宽度,然后使用剪切path将对象剪贴到自身来获得与“内部”相同的视觉效果,
  • 您可以通过将笔画宽度加倍,然后将对象的无笔画拷贝叠加在其自身之上来实现与“外部”相同的视觉效果。

编辑 :这个答案将来可能是错的。 应该可以通过将veStrokePathveIntersect (用于'inside')或者veExclude (用于'outside')结合使用SVGvector效果来实现这些结果。 然而,vector效果仍然是一个工作草案模块,没有我可以find的实现。

编辑2 :SVG 2草案规范包含stroke-alignment属性(具有中间可能值)。 这个属性最终可能会成为UA。

编辑3 :SVG工作组有趣并且令人沮丧地从SVG 2中删除了stroke-alignment 。您可以在这里看到一些关于散文的描述。

更新: stroke-alignment属性是在4月1日移动到一个全新的规格,称为SVG笔画 。

截至2015年2月26日的SVG 2.0编辑草案(可能自2月13日起), stroke-alignment属性存在 与值innercenter (默认)outer

它似乎以@Phrogz提出的stroke-location属性和后来的stroke-positionbuild议的方式工作 。 这个属性至less从2011年开始计划,但除了注释说

SVG 2应包含指定笔划位置的方法

,它从来没有在规范中详细描述,因为它被推迟 – 直到现在看来。

没有浏览器支持这个属性,或者,据我所知,任何新的SVG 2function,但希望他们会尽快规范成熟。 这是我个人一直敦促拥有的财产,我真的很高兴,它终于在规范中。

似乎有一些问题,如何该属性应该在开放path以及循环行为。 这些问题很可能会延长浏览器的实现时间。 但是,当浏览器开始支持这个属性时,我将用新的信息更新这个答案。

我find了一个简单的方法,有几个限制,但为我工作:

  • 在defs中定义形状
  • 定义一个引用该形状的剪辑path
  • 使用它,并与外部剪辑一起中风

这里有个工作的例子:

 <defs> <path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z"/> <clipPath id="clip"> <use xlink:href="#ld"/> </clipPath> </defs> <g> <use xlink:href="#ld" stroke="#0081C6" stroke-width="160" fill="#00D2B8" clip-path="url(#clip)"/> </g> 

这里有一个函数可以根据浏览器计算你需要添加多less个像素(使用给定的笔划)到顶部,右侧,底部和左侧:

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

正如上面的人已经注意到,你要么必须重新计算笔画path坐标的偏移量,要么将其宽度加倍,然后遮住一侧或另一侧,因为SVG不仅不能本地支持Illustrator的笔画alignment,而且PostScript也不会。

Adobe PostScript手册第二版中的笔画规范规定:“ 4.5.1 笔画 笔画操作符沿当前path绘制一些厚度的线条,对于path中的每个直线段或曲线段, 笔划绘制一条居中的线侧面平行于线段的线段“。 (强调他们的)

规范的其余部分没有偏移线的位置的属性。 当Illustrator允许您在内部或外部alignment时,它将重新计算实际path的偏移量(因为它仍然比套印和遮罩在计算上便宜)。 .ai文档中的path坐标是引用,而不是被格式化或导出为最终格式的path。

因为Inkscape的原生格式是spec SVG,所以它不能提供spec所缺less的function。

这里是使用symboluse 内部有界 rect的工作。

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

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> 

注意:确保更换? 在真正的价值use

背景 :为什么这个工作原因是因为符号通过用svgreplacesymbol和在阴影DOM中创build一个元素来build立一个新的视口。 然后将这个影子DOM的svg链接到当前的SVG元素中。 请注意, svg s可以嵌套,并且每个svg都会创build一个新的视口,该视口svg重叠的所有内容,包括重叠的边框。 想了解更多详情,请阅读Sara Soueidan撰写的精彩文章 。

(脏)可能的解决scheme是通过使用模式,

这里是一个内部描边三angular形的例子:

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> 

我不知道会有多大的帮助,但在我的情况下,我只是创build了另一个只有边框的圆形,并将其放在另一个形状的“内部”。