A plugin to display the time of various timezones as analog clocks
<?php
/*
Plugin Name: Analog Clocks
Description: A plugin to display the time of various timezones as analog clocks.
Version: 3.1.0
Author: Mike Vahldieck
Plugin URI: http://it-breeze.info
Author URI: http://it-breeze.info
License: GPL2
*/
<?php
/*
Plugin Name: Analog Clocks
Description: A plugin to display the time of various timezones as analog clocks.
Version: 3.1.0
Author: Mike Vahldieck
Plugin URI: http://it-breeze.info
Author URI: http://it-breeze.info
License: GPL2
*/
function display_analog_digital_clocks($atts) {
static $instance_id = 0; // Ensure unique instance per shortcode
$instance_id++;
// Get the time zones from the shortcode attributes
$zones = shortcode_atts(array(
'locations' => 'GMT,Europe/Berlin,America/New_York,Asia/Bangkok,Asia/Makassar',
), $atts);
$locations = explode(',', $zones['locations']);
// Generate unique JavaScript variable name for this instance
$unique_var = 'clockData_' . $instance_id;
// Generate dynamic HTML for the specified locations
$output = '<div id="analog-clocks-' . $instance_id . '" class="analog-clocks">';
foreach ($locations as $location) {
$id = strtolower(str_replace(['/', ' '], '-', $location)) . '-' . $instance_id; // Create a unique ID
$output .= '
<div class="city-clock">
<canvas id="' . $id . '-clock" width="150" height="150"></canvas>
<div syle="text-align: center;"><span id="' . $id . '-digital" class="digital-time"></span> <br>' . htmlspecialchars($location) . '</div>
</div>';
}
$output .= '</div>';
// Enqueue JavaScript and CSS
wp_enqueue_script('clock-script', plugins_url('clock.js', __FILE__), array(), false, true);
wp_enqueue_style('clock-style', plugins_url('clock.css', __FILE__));
// Pass unique data to the script for this instance
wp_localize_script('clock-script', $unique_var, $locations);
// Add a script to initialize this specific instance
$output .= "<script>
document.addEventListener('DOMContentLoaded', function() {
initializeClocks('$unique_var', '$instance_id');
});
</script>";
return $output;
}
add_shortcode('display_clocks', 'display_analog_digital_clocks');
clock.js
JAVASCRIPT
function initializeClocks(clockDataVar, instanceId) {
const clockData = window[clockDataVar]; // Get the unique clock data for this instance
function drawClock(canvasId, digitalId, timeZone) {
const canvas = document.getElementById(canvasId);
const digital = document.getElementById(digitalId);
if (!canvas || !digital) {
console.error(`Canvas or digital time element for "${timeZone}" not found.`);
return;
}
function initializeClocks(clockDataVar, instanceId) {
const clockData = window[clockDataVar]; // Get the unique clock data for this instance
function drawClock(canvasId, digitalId, timeZone) {
const canvas = document.getElementById(canvasId);
const digital = document.getElementById(digitalId);
if (!canvas || !digital) {
console.error(`Canvas or digital time element for "${timeZone}" not found.`);
return;
}
const ctx = canvas.getContext("2d");
const radius = canvas.height / 2;
ctx.translate(radius, radius);
const clockRadius = radius * 0.9;
function drawFace() {
ctx.beginPath();
ctx.arc(0, 0, clockRadius, 0, 2 * Math.PI);
ctx.fillStyle = "#fff";
ctx.fill();
ctx.strokeStyle = "#000";
ctx.lineWidth = 5;
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 5, 0, 2 * Math.PI);
ctx.fillStyle = "#000";
ctx.fill();
}
function drawNumbers() {
ctx.font = `${clockRadius * 0.15}px Arial`;
ctx.textBaseline = "middle";
ctx.textAlign = "center";
for (let num = 1; num <= 12; num++) {
const ang = (num * Math.PI) / 6;
ctx.rotate(ang);
ctx.translate(0, -clockRadius * 0.85);
ctx.rotate(-ang);
ctx.fillText(num.toString(), 0, 0);
ctx.rotate(ang);
ctx.translate(0, clockRadius * 0.85);
ctx.rotate(-ang);
}
}
function drawTime() {
const now = new Date();
const localTime = new Date(now.toLocaleString("en-US", { timeZone }));
const hour = localTime.getHours();
const minute = localTime.getMinutes();
const second = localTime.getSeconds();
// Update digital time
const digitalTime = `${hour.toString().padStart(2, "0")}:${minute.toString().padStart(2, "0")}:${second.toString().padStart(2, "0")}`;
digital.textContent = digitalTime;
// Analog clock hands
const hourAngle = ((hour % 12) + minute / 60) * Math.PI / 6;
const minuteAngle = (minute + second / 60) * Math.PI / 30;
const secondAngle = second * Math.PI / 30;
// Hour hand
ctx.beginPath();
ctx.lineWidth = 8;
ctx.lineCap = "round";
ctx.moveTo(0, 0);
ctx.rotate(hourAngle);
ctx.lineTo(0, -clockRadius * 0.5);
ctx.stroke();
ctx.rotate(-hourAngle);
// Minute hand
ctx.beginPath();
ctx.lineWidth = 6;
ctx.moveTo(0, 0);
ctx.rotate(minuteAngle);
ctx.lineTo(0, -clockRadius * 0.7);
ctx.stroke();
ctx.rotate(-minuteAngle);
// Second hand
ctx.beginPath();
ctx.strokeStyle = "#ff0000";
ctx.lineWidth = 2;
ctx.moveTo(0, 0);
ctx.rotate(secondAngle);
ctx.lineTo(0, -clockRadius * 0.9);
ctx.stroke();
ctx.rotate(-secondAngle);
}
function updateClock() {
ctx.clearRect(-radius, -radius, canvas.width, canvas.height);
drawFace();
drawNumbers();
drawTime();
}
setInterval(updateClock, 1000);
updateClock();
}
// Initialize clocks for this instance
clockData.forEach((location) => {
const id = location.toLowerCase().replace(/[/\s]/g, "-") + "-" + instanceId;
drawClock(`${id}-clock`, `${id}-digital`, location);
});
}