I'm trying to build an analogue clock SP feature, but before anything else, I've put it in an HTML file to provide proof of concept.
In an HTML file, separate from SharePoint, the code runs perfectly fine, no problem (in IE, Chrome and Firefox).
However, if I point a Content Editor web part to this file, the canvas draws but the setInterval doesn't fire because I get this:
Uncaught TypeError:
ctx.beginPathis not a function
How do I resolve that?
<canvas id="abcdef" width="400" height="400"></canvas>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
(function() {
var canvas = document.getElementById("abcdef");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
drawClock(ctx);
setInterval(drawClock, 1000);
function drawClock(context) {
drawFace(context);
drawNumbers(context);
drawTime(context);
}
function drawFace(ctx) {
var grad;
console.info(ctx);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fillStyle = "lightgrey";
ctx.fill()
grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius * 0.1;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = 'black';
ctx.fill();
}
function drawNumbers(ctx) {
var ang;
var num;
ctx.font = radius * 0.15 + "px arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
for (num = 1; num < 13; num++) {
ang = num * Math.PI / 6;
ctx.rotate(ang);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, radius * 0.85);
ctx.rotate(-ang);
}
}
function drawTime(ctx) {
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
//hour
hour = hour % 12;
hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60));
drawHand(hour, radius * 0.5, radius * 0.07, "grey");
//minute
minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60));
drawHand(minute, radius * 0.8, radius * 0.07, "black");
// second
second = (second * Math.PI / 30);
drawHand(second, radius * 0.9, radius * 0.02, "red");
}
function drawHand(pos, length, width, colour) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.strokeStyle = colour;
ctx.moveTo(0, 0);
ctx.rotate(pos);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.rotate(-pos);
}
}());
</script>
The error you're getting suggests that the global variable, ctx, is being used elsewhere in the page you're embedded inside, and is being overridden after your code has executed. The easiest solution to this, if your code otherwise works elsewhere, is to simply wrap it all in an IIFE, so all your variables are then locally scoped:
(function() {
var canvas = document.getElementById("abcdef");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
/* etc - include all your functions here too */
}());
This way none of your variables will conflict with any others that share the same name at the global scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With