简体   繁体   中英

Include Countdown Timer multiple times

I found this countdown timer that I would like to include in one of my modules. Unfortunately I can't figure out how to use the timer multiple times on one page (the classic one - only the last timer is running) - I also know that probably (?) the go function should be the reason - but currently I can't figure out how to instantiate the timer.

What I have so far (but it does not work):

Codepen Original: https://codepen.io/l422y/pen/cdwhm

I have in-depth JS basic knowledge but this is still beyond my horizon.

 var ringer = { //countdown_to: "10/31/2014", //countdown_to: targetdaytime, rings: { 'DAYS': { s: 86400000, // mseconds in a day, max: 365 }, 'HOURS': { s: 3600000, // mseconds per hour, max: 24 }, 'MINUTES': { s: 60000, // mseconds per minute max: 60 }, 'SECONDS': { s: 1000, max: 60 }, 'MICROSEC': { s: 10, max: 100 } }, r_count: 5, r_spacing: 10, // px r_size: 100, // px r_thickness: 2, // px update_interval: 11, // ms init: function(container, targetdaytime) { $r = ringer; $r.cvs = document.createElement('canvas'); $r.size = { w: ($r.r_size + $r.r_thickness) * $r.r_count + ($r.r_spacing * ($r.r_count - 1)), h: ($r.r_size + $r.r_thickness) }; $r.cvs.setAttribute('width', $r.size.w); $r.cvs.setAttribute('height', $r.size.h); $r.ctx = $r.cvs.getContext('2d'); $(container).append($r.cvs); $r.cvs = $($r.cvs); $r.ctx.textAlign = 'center'; $r.actual_size = $r.r_size + $r.r_thickness; $r.countdown_to_time = new Date(targetdaytime).getTime(); $r.cvs.css({ width: $r.size.w + "px", height: $r.size.h + "px" }); $r.go(); }, ctx: null, go: function() { var idx = 0; $r.time = (new Date().getTime()) - $r.countdown_to_time; for (var r_key in $r.rings) $r.unit(idx++, r_key, $r.rings[r_key]); setTimeout($r.go, $r.update_interval); }, unit: function(idx, label, ring) { var x, y, value, ring_secs = ring.s; value = parseFloat($r.time / ring_secs); $r.time -= Math.round(parseInt(value)) * ring_secs; value = Math.abs(value); x = ($r.r_size * .5 + $r.r_thickness * .5); x += +(idx * ($r.r_size + $r.r_spacing + $r.r_thickness)); y = $r.r_size * .5; y += $r.r_thickness * .5; // calculate arc end angle var degrees = 360 - (value / ring.max) * 360.0; var endAngle = degrees * (Math.PI / 180); $r.ctx.save(); $r.ctx.translate(x, y); $r.ctx.clearRect($r.actual_size * -0.5, $r.actual_size * -0.5, $r.actual_size, $r.actual_size); // first circle $r.ctx.strokeStyle = "rgba(128,128,128,0.2)"; $r.ctx.beginPath(); $r.ctx.arc(0, 0, $r.r_size / 2, 0, 2 * Math.PI, 2); $r.ctx.lineWidth = $r.r_thickness; $r.ctx.stroke(); // second circle $r.ctx.strokeStyle = "rgba(253, 128, 1, 0.9)"; $r.ctx.beginPath(); $r.ctx.arc(0, 0, $r.r_size / 2, 0, endAngle, 1); $r.ctx.lineWidth = $r.r_thickness; $r.ctx.stroke(); // label $r.ctx.fillStyle = "#ffffff"; $r.ctx.font = '12px Helvetica'; $r.ctx.fillText(label, 0, 23); $r.ctx.fillText(label, 0, 23); $r.ctx.font = 'bold 40px Helvetica'; $r.ctx.fillText(Math.floor(value), 0, 10); $r.ctx.restore(); } } jQuery(document).ready(function($) { new ringer.init('#cd-container-1', '12/24/2020'); new ringer.init('#cd-container-2', '10/31/2020'); });
 body, html { width: 100%; height: 100%; margin: 0; } html { display: table; } canvas { width: 900px; height: 200px; display: block; position: relative; background: transparent; margin: 40px auto; } body { background: #000000; background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/12399/free-pumpkin-wallpaper-25771-26455-hd-wallpapers.jpg"); background-position: top center; background-size: cover; color: #fff; margin: 0; padding: 0; overflow: hidden; display: table-cell; vertical-align: middle; text-align: center; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="cd-container-1"></div> <div id="cd-container-2"></div>

It is because your object is not a JS class, therefore it is not possible to create instances of it. Its basically a single instance of a class.

I transformed it to a class for you, so now you can initialize multiple instances of it:

 class Ringer { // <-- make class from it rings = { // <-- object properties to class fields 'DAYS': { s: 86400000, // mseconds in a day, max: 365 }, 'HOURS': { s: 3600000, // mseconds per hour, max: 24 }, 'MINUTES': { s: 60000, // mseconds per minute max: 60 }, 'SECONDS': { s: 1000, max: 60 }, 'MICROSEC': { s: 10, max: 100 } }; r_count = 5; r_spacing = 10; // px r_size = 100; // px r_thickness = 2; // px update_interval = 11; // ms ctx = null; init (container, targetdaytime) { // <-- functions to class methods this.cvs = document.createElement('canvas'); // <-- just access this instead of reference to the object this.size = { w: (this.r_size + this.r_thickness) * this.r_count + (this.r_spacing * (this.r_count - 1)), h: (this.r_size + this.r_thickness) }; this.cvs.setAttribute('width', this.size.w); this.cvs.setAttribute('height', this.size.h); this.ctx = this.cvs.getContext('2d'); $(container).append(this.cvs); this.cvs = $(this.cvs); this.ctx.textAlign = 'center'; this.actual_size = this.r_size + this.r_thickness; this.countdown_to_time = new Date(targetdaytime).getTime(); this.cvs.css({ width: this.size.w + "px", height: this.size.h + "px" }); this.go(); } go() { var idx = 0; this.time = (new Date().getTime()) - this.countdown_to_time; for (var r_key in this.rings) this.unit(idx++, r_key, this.rings[r_key]); setTimeout(() => this.go(), this.update_interval); // () => this.go() instead of $r.go } unit(idx, label, ring) { var x, y, value, ring_secs = ring.s; value = parseFloat(this.time / ring_secs); this.time -= Math.round(parseInt(value)) * ring_secs; value = Math.abs(value); x = (this.r_size * .5 + this.r_thickness * .5); x += +(idx * (this.r_size + this.r_spacing + this.r_thickness)); y = this.r_size * .5; y += this.r_thickness * .5; // calculate arc end angle var degrees = 360 - (value / ring.max) * 360.0; var endAngle = degrees * (Math.PI / 180); this.ctx.save(); this.ctx.translate(x, y); this.ctx.clearRect(this.actual_size * -0.5, this.actual_size * -0.5, this.actual_size, this.actual_size); // first circle this.ctx.strokeStyle = "rgba(128,128,128,0.2)"; this.ctx.beginPath(); this.ctx.arc(0, 0, this.r_size / 2, 0, 2 * Math.PI, 2); this.ctx.lineWidth = this.r_thickness; this.ctx.stroke(); // second circle this.ctx.strokeStyle = "rgba(253, 128, 1, 0.9)"; this.ctx.beginPath(); this.ctx.arc(0, 0, this.r_size / 2, 0, endAngle, 1); this.ctx.lineWidth = this.r_thickness; this.ctx.stroke(); // label this.ctx.fillStyle = "#ffffff"; this.ctx.font = '12px Helvetica'; this.ctx.fillText(label, 0, 23); this.ctx.fillText(label, 0, 23); this.ctx.font = 'bold 40px Helvetica'; this.ctx.fillText(Math.floor(value), 0, 10); this.ctx.restore(); } } jQuery(document).ready(function($) { (new Ringer()).init('#cd-container-1', '12/24/2020'); // <-- init new instance with new Ringer() and call init() on that instance (new Ringer()).init('#cd-container-2', '10/31/2020'); });
 body, html { width: 100%; height: 100%; margin: 0; } html { display: table; } canvas { width: 900px; height: 200px; display: block; position: relative; background: transparent; margin: 40px auto; } body { background: #000000; background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/12399/free-pumpkin-wallpaper-25771-26455-hd-wallpapers.jpg"); background-position: top center; background-size: cover; color: #fff; margin: 0; padding: 0; overflow: hidden; display: table-cell; vertical-align: middle; text-align: center; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="cd-container-1"></div> <div id="cd-container-2"></div>

If you want to read more into classes and how they work, I found a cool little summary here: https://www.digitalocean.com/community/tutorials/js-objects-prototypes-classes

Simple: wrap it in a function.

function createRinger() {
    const ringer = { ... }
    return ringer
}

const ringer1 = createRinger()
const ringer2 = createRinger()

ringer1.init(target1, targetDateTime1)
ringer2.init(target2, targetDateTime2)

There are other ways that improve efficiency of memory use (eg use the prototype chain), but unless you have lots of timers on a page, these approaches are moot.

谁能告诉我如何在标签后面的戒指内侧添加背景颜色?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM