Skip to content

Instantly share code, notes, and snippets.

@stugoo
Last active December 16, 2015 06:58
Show Gist options
  • Save stugoo/5395159 to your computer and use it in GitHub Desktop.
Save stugoo/5395159 to your computer and use it in GitHub Desktop.
SVG Arc drawing, pass in a CFG and allow it to draw an arc
Display the source blob
Display the rendered blob
Raw
<svg xmlns="http://www.w3.org/2000/svg" class="avatar__svg" viewBox="0 0 100 100">
<circle class="circle circle--outer" cx="50" cy="50" r="50"/>
<circle class="circle circle--knockout" cx="50" cy="50" r="40"/>
<circle class="circle circle--inner" cx="50" cy="50" r="33"/>
<path class="path path--percentage" d="M0,0"/>
</svg>
/*
example usage
config = {},
config.percentage = 360 * (percentage/100); // circle % in degress;
config.el = document.querySelector('.svg_container'); // container
config.svg = config.el.querySelector('svg');
config.avatarid = svgID; // UID of SVG
drawArc(config);
*/
drawArc = function(config){
var self = this,
path = config.svg.querySelector('path'),
animating = false,
// base options (could be calculated on the fly)
options = {
centerX : 50,
centerY : 50,
startDegrees : -90,
endDegrees : config.freshness -90,
innerRadius : 33,
thickness : 7,
nextDegree : 0.6,
maxEnd : config.freshness -90
},
tick,
/*
Options:
- centerX, centerY: coordinates for the center of the circle
- startDegrees, endDegrees: fill between these angles, clockwise
- innerRadius, outerRadius: distance from the center
- thickness: distance between innerRadius and outerRadius
You should only specify two out of three of the radii and thickness
*/
annularSector = function(path,options){
var opts = optionsWithDefaults(options);
var p = [ // points
[opts.cx + opts.r2*Math.cos(opts.startRadians),
opts.cy + opts.r2*Math.sin(opts.startRadians)],
[opts.cx + opts.r2*Math.cos(opts.closeRadians),
opts.cy + opts.r2*Math.sin(opts.closeRadians)],
[opts.cx + opts.r1*Math.cos(opts.closeRadians),
opts.cy + opts.r1*Math.sin(opts.closeRadians)],
[opts.cx + opts.r1*Math.cos(opts.startRadians),
opts.cy + opts.r1*Math.sin(opts.startRadians)]
];
var angleDiff = opts.closeRadians - opts.startRadians;
var largeArc = (angleDiff % (Math.PI*2)) > Math.PI ? 1 : 0;
var cmds = [];
cmds.push("M"+p[0].join()); // Move to P0
cmds.push("A"+[opts.r2,opts.r2,0,largeArc,1,p[1]].join()); // Arc to P1
cmds.push("L"+p[2].join()); // Line to P2
cmds.push("A"+[opts.r1,opts.r1,0,largeArc,0,p[3]].join()); // Arc to P3
cmds.push("z"); // Close path (Line to P0)
path.setAttribute('d',cmds.join(' '));
function optionsWithDefaults(o){
// Create a new object so that we don't mutate the original
var o2 = {
cx : o.centerX || 0,
cy : o.centerY || 0,
startRadians : (o.startDegrees || 0) * Math.PI/180,
closeRadians : (o.endDegrees || 0) * Math.PI/180
};
var t = o.thickness!==undefined ? o.thickness : 100;
if (o.innerRadius!==undefined) o2.r1 = o.innerRadius;
else if (o.outerRadius!==undefined) o2.r1 = o.outerRadius - t;
else o2.r1 = 200 - t;
if (o.outerRadius!==undefined) o2.r2 = o.outerRadius;
else o2.r2 = o2.r1 + t;
if (o2.r1<0) o2.r1 = 0;
if (o2.r2<0) o2.r2 = 0;
return o2;
}
},
initialise = function(){
annularSector(path,options);
};
initialise();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment