支持可变粗细笔划
Support for variable thickness stroke
是否有支持可变粗细路径/笔画的矢量图形标准,例如来自手写笔输入:
一定程度的平滑可能是可以接受的。我假设最好的存储方式是将其存储为常规路径(例如 ),然后在路径中的各个点处逐点稀疏厚度信息,它们之间具有梯度。
我看过SVG,但似乎没有支持它的元素。是否有任何矢量图形标准可以?
不幸的是,这已经被提议但没有进一步发展为 SVG 标准:
https://www.w3.org/Graphics/SVG/WG/wiki/Proposals/Variable_width_stroke
最好的办法是根据所需的内部曲线和描边宽度生成自己的轮廓曲线。
Adobe Illustrator 在使用宽度工具时会执行此操作,Inkscape 也有一个 feature 会执行此操作。
所以从技术上回答你的问题,.ai 文件格式确实保存了笔画宽度信息,但当导出到 SVG 时,它是一个带填充的封闭路径。
当前实现的单一路径不允许可变厚度。有一个 W3.org proposal for SVG standard,但目前还没有在纯 SVG 中实现。
“厚度可变的路径”有多种实现方式,但它依赖于 svg 对象(例如,多路径)和 C++ 或 javascript 函数。
- PowerStroke is an implementation of such idea of a variable thickness stroke in Inkscape. A good entry to the source in c++ is here.
SVG还有其他实现javascript,依赖多路径:
Tubefy,一组很少的js函数,原理是基于线性插值。 Tubefy有几种实现方式,最简单的是:
$ = function (id) { return typeof id=='string'?document.getElementById(id):id };
var root = document.rootElement;
function lerp(p, a, b) { return Number(a)+(b-a)*p; }
function lerpA(p, a, b) { var c=[];
for(var i=0; i<a.length; i++) c[i]=lerp(p, a[i], b[i]);
return c;
}
function toCss(a){
for(var i=0; i<a.length; i++) a[i]=Math.round(a[i]);
return "rgb(" + a.join() + ")";
}
Variable Stroke-Width,基于多个路径,这可能是满足您需求的最佳答案。
其中一个例子,js函数使用了Tubefy,直接在svg文件中实现:
<script>//<![CDATA[
var op=1, op1=1;
function vsw0(p0, n, g){ p0=$(p0);
var SW=p0.getAttribute('stroke-widths').replace(/ /g,'').split(',');
var T=p0.getTotalLength();
var n_1=n-1, dt=T/n, dash=(dt+1)+','+T;
p0.setAttribute('stroke-dasharray', dash);
for(var i=0; i<n; i++){ p=i/n_1;
var sw=lerp(p, SW[0], SW[1]); // current stroke width
var off=-i*dt; // current dash offset
var c=toCss(lerpA(p, [255,0,0], [255,255,0])); // curr color
var newP=p0.cloneNode(true);
newP.setAttribute('style', 'stroke-width:'+sw+';stroke-dashoffset:'+off+';stroke:'+c);
$(g).appendChild(newP);
}
}
function f(){ $('abg').setAttribute('stroke', $('bg').getAttribute('fill')) }
//]]></script>
</svg>
是否有支持可变粗细路径/笔画的矢量图形标准,例如来自手写笔输入:
一定程度的平滑可能是可以接受的。我假设最好的存储方式是将其存储为常规路径(例如
我看过SVG,但似乎没有支持它的元素。是否有任何矢量图形标准可以?
不幸的是,这已经被提议但没有进一步发展为 SVG 标准:
https://www.w3.org/Graphics/SVG/WG/wiki/Proposals/Variable_width_stroke
最好的办法是根据所需的内部曲线和描边宽度生成自己的轮廓曲线。
Adobe Illustrator 在使用宽度工具时会执行此操作,Inkscape 也有一个 feature 会执行此操作。
所以从技术上回答你的问题,.ai 文件格式确实保存了笔画宽度信息,但当导出到 SVG 时,它是一个带填充的封闭路径。
当前实现的单一路径不允许可变厚度。有一个 W3.org proposal for SVG standard,但目前还没有在纯 SVG 中实现。
“厚度可变的路径”有多种实现方式,但它依赖于 svg 对象(例如,多路径)和 C++ 或 javascript 函数。
- PowerStroke is an implementation of such idea of a variable thickness stroke in Inkscape. A good entry to the source in c++ is here.
SVG还有其他实现javascript,依赖多路径:
Tubefy,一组很少的js函数,原理是基于线性插值。 Tubefy有几种实现方式,最简单的是:
$ = function (id) { return typeof id=='string'?document.getElementById(id):id }; var root = document.rootElement; function lerp(p, a, b) { return Number(a)+(b-a)*p; } function lerpA(p, a, b) { var c=[]; for(var i=0; i<a.length; i++) c[i]=lerp(p, a[i], b[i]); return c; } function toCss(a){ for(var i=0; i<a.length; i++) a[i]=Math.round(a[i]); return "rgb(" + a.join() + ")"; }
Variable Stroke-Width,基于多个路径,这可能是满足您需求的最佳答案。
其中一个例子,js函数使用了Tubefy,直接在svg文件中实现:
<script>//<![CDATA[
var op=1, op1=1;
function vsw0(p0, n, g){ p0=$(p0);
var SW=p0.getAttribute('stroke-widths').replace(/ /g,'').split(',');
var T=p0.getTotalLength();
var n_1=n-1, dt=T/n, dash=(dt+1)+','+T;
p0.setAttribute('stroke-dasharray', dash);
for(var i=0; i<n; i++){ p=i/n_1;
var sw=lerp(p, SW[0], SW[1]); // current stroke width
var off=-i*dt; // current dash offset
var c=toCss(lerpA(p, [255,0,0], [255,255,0])); // curr color
var newP=p0.cloneNode(true);
newP.setAttribute('style', 'stroke-width:'+sw+';stroke-dashoffset:'+off+';stroke:'+c);
$(g).appendChild(newP);
}
}
function f(){ $('abg').setAttribute('stroke', $('bg').getAttribute('fill')) }
//]]></script>
</svg>