Are there any vector graphics standards that support variable-thickness paths / strokes, e.g. from a stylus input:
Some amount of smoothing may be acceptable. I'd assume that the best way to store it would be as a regular path (e.g. this) and then point-wise sparse thickness information at various points in the path, with gradients between them.
I have looked at SVG but there doesn't seem to be an element that can support it. Are there any vector graphics standards that can?
A single path as currently implemented does not allow variable thickness. There is a W3.org proposal for SVG standard, but no implementation so far in pure SVG.
There are several implementation of a "path with variable thickness", but that relies on svg objects (eg., multiple paths) and a c++ or javascript functions.
There are other implementations in SVG and javascript, relying on multiple paths:
Tubefy, a set of few js functions, the principle is based on a linear interpolation. There are several implementation of Tubefy, the simplest is:
$ = 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, based on multiple path, which could be the best answer to your needs.
In one of the examples, the js function uses Tubefy and is directly implemented in the svg file:
<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>