|
/* jshint esversion: 6 */ |
|
/** |
|
* Draws a clockface with duration and current hour indicator |
|
* |
|
* based on code from: http://stackoverflow.com/questions/5736398/how-to-calculate-the-svg-path-for-an-arc-of-a-circle by opsb |
|
*/ |
|
|
|
const clock = {}; |
|
|
|
clock.polarToCartesian = function(centerX, centerY, radius, angleInDegrees) { |
|
var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0; |
|
return { |
|
x: centerX + (radius * Math.cos(angleInRadians)), |
|
y: centerY + (radius * Math.sin(angleInRadians)) |
|
}; |
|
}; |
|
|
|
clock.describeArc = function(x, y, radius, startAngle, endAngle){ |
|
var start = clock.polarToCartesian(x, y, radius, endAngle); |
|
var end = clock.polarToCartesian(x, y, radius, startAngle); |
|
var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1"; |
|
|
|
var d = [ |
|
"M", start.x, start.y, |
|
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y |
|
].join(" "); |
|
|
|
return d; |
|
}; |
|
|
|
/** |
|
* Draws the clock markers, usually 4 or 12 but can be any number |
|
* @method drawMarkers |
|
* @param {svg} svg SVG element to draw |
|
* @param {int} center Center coordinate (x==y) |
|
* @param {int} r_markers Radius of markers (how far from center) |
|
* @param {int} marker_size Length of marker_size |
|
* @param {int} amount Number of markers (4/12 others) |
|
* @return {null} nothing |
|
*/ |
|
clock.drawMarkers = function(svg, center,r_markers,marker_size,amount) { |
|
for (let m = 0; m < amount; m++) { |
|
let pos = 360/amount * m; |
|
let from = (pos===0 ? 359 : pos-1); |
|
|
|
svg.appendChild(clock.addPath("path", { |
|
"d": clock.describeArc(center, center, r_markers, from, pos+1), |
|
"stroke-width": marker_size |
|
})); |
|
} |
|
}; |
|
/** |
|
* Function to create SVG objects and set properties |
|
* @method addPath |
|
* @param {string} shape a valid svg shape |
|
* @param {object} props Collection of attributes to set |
|
*/ |
|
clock.addPath = function(shape, props){ |
|
let newElement = document.createElementNS('http://www.w3.org/2000/svg',shape); |
|
Object.keys(props).forEach(function(prop){ |
|
newElement.setAttribute(prop, props[prop]); |
|
}); |
|
return newElement; |
|
}; |
|
/** |
|
* Entry point, draws a clock with duration and current hour markers |
|
* It follow 12 hours clock, doesn't divide c/of into markers |
|
* @method draw |
|
* @param {svg} svg A reference or name of an svg object |
|
* @param {int} c Current hour (1 hour segment) |
|
* @param {int} of How many hours |
|
* @param {int} [markers=4] How many hour markers to put on clock |
|
* @return {null} nothing |
|
*/ |
|
clock.draw = function(svg, c=0, of=0, markers=4) { |
|
// Resize the container (and visualize) |
|
if (typeof svg !== "object") svg = document.getElementById(svg); |
|
if (!svg || svg.tagName !== "svg") throw ("Root not found or wrong type ", svg); |
|
|
|
let box = svg.getBoundingClientRect(); |
|
const w = box.width, |
|
padding = w * 0.01, /* Space to the edge of the svg */ |
|
stroke_face = w * 0.04, /* Stroke width base on image size */ |
|
r_face = (w - ((padding *2)+stroke_face )) / 2, /* radius of the face*/ |
|
|
|
r_center = w * 0.02, /* Radius of center circle*/ |
|
center = w/2, /* Center of the drawing (always square) */ |
|
|
|
r_inner = r_face - (stroke_face/2), /* radius to the inner border of the face*/ |
|
r_markers = r_face * 0.85, /* position of the markers (% from center to edge) */ |
|
marker_size = r_face * 0.10 /* How thick the markers appear */, |
|
stroke_duration = r_face * 0.35 /* How thick the duration slice shows */, |
|
r_duration = r_inner - (stroke_duration / 2) /* Radius of duration */; |
|
|
|
/* Force height to be equal to width ~ must set height and style~*/ |
|
if (box.height !== w) { |
|
svg.setAttribute("height", w); |
|
svg.setAttribute("style", "height:"+w+"px" ); |
|
} |
|
svg.appendChild(clock.addPath("path", { |
|
"d": clock.describeArc( center, center, r_inner/2, (359/12 * 0), (359/12 * of)), |
|
"stroke-width": r_inner, |
|
"class": "duration" |
|
})); |
|
|
|
/* When current is 0 don't display at all */ |
|
if (c !== 0) { |
|
svg.appendChild(clock.addPath("path", { |
|
"d": clock.describeArc( center, center, r_duration , (359/12 * (c-1)), (359/12 * c)), |
|
"stroke-width": stroke_duration, |
|
"class": "current" |
|
})); |
|
} |
|
|
|
// Draw the clock on top |
|
svg.appendChild(clock.addPath("circle", {"cx": center, "cy": center, "r": r_face, "stroke-width": stroke_face })); |
|
svg.appendChild(clock.addPath("circle", {"cx": center, "cy": center, "r": r_center, "stroke-width": stroke_face/2})); |
|
clock.drawMarkers(svg, center,r_markers,marker_size, markers); |
|
|
|
}; |
|
|
|
window.onload = function() { |
|
clock.draw("clock", 1, 3, 4); |
|
clock.draw("clocksmall", 1, 4, 12); |
|
clock.draw("clockmicro", 1, 3, 12); |
|
clock.draw("clockbig",3,3,12); |
|
}; |