How to implement * object * to improve my hourly sample javascript program

The purpose of this work is to understand and play with the meaning of some kind of object concept that I heard arround.

About bounty

There are many different ways / approaches for this.

My attempts are not very clean: to add a 2nd measure with a different time zone, I have to edit 3 different places. This is not very good (see answer below).

How can I do something more useful?

At the beginning:

post-edit: the initial question was choosing between jquery and mootools, now the choice has been made; the goal is to improve it using mootools.

There are several examples / demos that I wrote to play with javascript and svg:

var cx =128; var cy =128; var slen=120; var mlen=116; var hlen= 80; var selem; var melem; var helem; function setvars() { selem=document.getElementById("seconds"); melem=document.getElementById("minutes"); helem=document.getElementById("hours"); drawtime(); }; function drawtime() { var now=new Date(); var nows=now.getTime()%60000; var nowm=now.getMinutes()*1.0+1.0*nows/60000; var nowh=now.getHours()*1.0+1.0*nowm/60; var sposx=cx + slen * Math.sin( nows / 30000 * Math.PI ); var sposy=cy - slen * Math.cos( nows / 30000 * Math.PI ); var mposx=cx + mlen * Math.sin( nowm / 30 * Math.PI ); var mposy=cy - mlen * Math.cos( nowm / 30 * Math.PI ); var hposx=cx + hlen * Math.sin( nowh / 6 * Math.PI ); var hposy=cy - hlen * Math.cos( nowh / 6 * Math.PI ); selem.setAttribute("x1",sposx); selem.setAttribute("y1",sposy); selem.setAttribute("x2",sposx); selem.setAttribute("y2",sposy); melem.setAttribute("x2",mposx); melem.setAttribute("y2",mposy); helem.setAttribute("x2",hposx); helem.setAttribute("y2",hposy); window.setTimeout(drawtime,80) }; setvars(); 
 #box1 { stroke: black; } #minutes { stroke: #2266AA; } #hours { stroke: #3388CC; } #seconds { stroke: #CCCC22; } line,circle { opacity:0.65; fill:none; stroke-width:8; stroke-linecap:round; stroke-linejoin:round; marker:none; stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1; visibility:visible; display:inline; overflow:visible; enable-background:accumulate } 
 <svg xmlns="http://www.w3.org/2000/svg" id="svg2" width="100%" height="100%" viewBox="0 0 900 256" version="1.0"> <title id="title1">Clock</title> <circle id="box1" cy="128" cx="128" r="124" /> <line id="hours" x1="128" y1="128" x2="128" y2="48" /> <line id="minutes" x1="128" y1="128" x2="244" y2="128" /> <line id="seconds" x1="128" y1="8" x2="128" y2="8" /> </svg> 

(Original published in jsfiddle ), since I am not very good at jQuery jquery and / or mootools, I would like to know if there are simpler methods, maybe writing it differently.

how to make a simple rotation around a fixed center using jquery or mootools:

 var hposx=cx + hlen * Math.sin( nowh / 6 * Math.PI ); var hposy=cy - hlen * Math.cos( nowh / 6 * Math.PI ); helem.setAttribute("x2",hposx); helem.setAttribute("y2",hposy); 

How to objectify this code? (even if that might be good) ...

All samples using object orientation, a specific library, are also welcome!

+7
source share
4 answers

Edited using the bounty: Bottom of this!

First answer

After reading the first comments from pete (thank you very much! You give me good ways to research) and SoonDead (thanks also for the first step of the conversion), I looked around a bit, jquery and mootools code, and finally I chose mootools to shorten my code, so how mootools allowed me to send an array for object.get and hash (associative array) for objet.set

 (function () { "use strict"; var Point = function(x,y) { this.x=x; this.y=y; }; var Path = function(center,length,both) { this.center = center; this.length = length; this.both = both; this.end = function(alpha) { var retx = 1.0*this.center.x + this.length*Math.sin(alpha); var rety = 1.0*this.center.y - this.length*Math.cos(alpha); if (typeof(this.both)!=='undefined') return { x1:retx, x2:retx, y1:rety, y2:rety } else return { x2:retx, y2:rety }; }; }; var Hand = function(svgline,both) { this.elem = document.id(svgline); var p = this.elem.get(['x1','y1','x2','y2']); this.path = new Path ( new Point(p.x1,p.y1),Math.sqrt( Math.pow(1.0*p.x2-1.0*p.x1,2) + Math.pow(1.0*p.y2-1.0*p.y1,2)) ,both); this.setPos = function(angle) { this.elem.set(this.path.end(angle)); }; }; var Clock = function(hour,minute,second,refresh) { this.hour = new Hand(hour); this.minute = new Hand(minute); this.second = new Hand(second,true); this.refresh = refresh; this.setTime = function(timePos) { var self= this; var tps = 1.0*timePos.getTime() % 60000; var tpm = timePos.getMinutes()*1.0 + 1.0* tps/60000; var tph = timePos.getHours()*1.0 + 1.0* tpm/60; this.second.setPos(tps / 30000 * Math.PI); this.minute.setPos(tpm / 30 * Math.PI); this.hour .setPos(tph / 6 * Math.PI); setTimeout(function() { self.setTime(new Date())},this.refresh) }; }; var clock=new Clock('hours','minutes','seconds',120); clock.setTime(new Date()); }()); 
 #box1 { stroke: black; fill:#ccc } #minutes { stroke: #2288AA; } #hours { stroke: #3388CC; } #seconds { stroke: #CCCC22; } line,circle { opacity:0.65; fill:none; stroke-width:8; stroke-linecap:round; stroke-linejoin:round; marker:none; stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1; visibility:visible; display:inline; overflow:visible; enable-background:accumulate } 
 <script src="http://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-nocompat.js" ></script> <svg xmlns="http://www.w3.org/2000/svg" id="svg2" width="100%" height="100%" viewBox="0 0 900 256" version="1.0"> <title id="title1">Clock</title> <circle id="box1" cy="128" cx="128" r="124" /> <line id="hours" x1="128" y1="128" x2="128" y2="48" /> <line id="minutes" x1="128" y1="128" x2="244" y2="128" /> <line id="seconds" x1="128" y1="128" x2="128" y2="8" /> </svg> 

Well, now my new code is 8 lines smaller and even always readable.

This is a step, but objectization means making it an object ... With goals

  • Keep it reinforced.
  • Keep it effective (do not do a useless operation or the same operation twice)
  • Make it reusable (as an object, save all fixed variables ...)

One interim personal result ,

But now the code looks like this:

 (function () { "use strict"; var Point = function(x,y) { this.x=x; this.y=y; }; var Path = function(center,length,both) { this.center = center; this.length = length; this.both = both; this.end = function(alpha) { var retx=1.0*this.center.x+this.length*Math.sin(alpha); var rety=1.0*this.center.y-this.length*Math.cos(alpha); if (typeof(this.both)!=='undefined') return { x1:retx, x2:retx, y1:rety, y2:rety } else return { x2:retx, y2:rety }; }; }; var Hand = function(svgline,both) { this.elem = document.id(svgline); var p=this.elem.get(['x1','y1','x2','y2']); this.path = new Path ( new Point(p.x1,p.y1), Math.sqrt(Math.pow(1.0*p.x2-1.0*p.x1,2)+ Math.pow(1.0*p.y2-1.0*p.y1,2)), both); this.setPos = function(angle) { this.elem.set(this.path.end(angle)); }; }; var Clock = function(hour,minute,second,refresh) { this.hour = new Hand(hour); this.minute = new Hand(minute); this.second = new Hand(second,true); this.setTime = function(timePos) { var self= this; var tps = 1.0*timePos.getTime() % 60000; var tpm = timePos.getMinutes()*1.0 + 1.0* tps/60000; var tph = timePos.getHours()*1.0 + 1.0* tpm/60; this.second.setPos(tps / 30000 * Math.PI); this.minute.setPos(tpm / 30 * Math.PI); this.hour .setPos(tph / 6 * Math.PI); }; }; var RefreshLoop = function(refresh) { var newdate=new Date(); clock1.setTime(newdate); newdate=newdate.getTime()+newdate.getTimezoneOffset()*60000; clock2.setTime(new Date(newdate)); clock3.setTime(new Date(newdate+20700000)); clock4.setTime(new Date(newdate+28800000)); }; var clock1=new Clock('hours','minutes','seconds',120); var clock2=new Clock('hours2','minutes2','seconds2',120); var clock3=new Clock('hours3','minutes3','seconds3',120); var clock4=new Clock('hours4','minutes4','seconds4',120); RefreshLoop.periodical(500); }()); 

If all parts remain small, my clock is a real reusable object (now it works 4 times).

The setTime function should calculate all hands together as each value hold part of the other, but each operation should be performed only once.

For my watch, a Path is determined by a fixed start point fixed length and a direction variable, Path.end is the calculated endpoint for the specified direction

And a Hand is a given SVG line , with its original Path and optional flag, that when setting, both the start and end points should be positioned at the same values ​​(a zero-length line, rounded to the end, gives a rounded point).

( Note (bug?): Since each element is defined in SVG, and Path.length is calculated from the distance between each end of the Path, the seconds path must be drawn first with [x1,y1] in the center of the clock ! = [x2,y2] ! )

In the hope that some want to fix / improve / discuss my objectization ...

UPDATE2

I think now this is the final version where the object is simple, mootools is used (maybe not too many, comments are welcome) and my last hours could be used many times to display different times.

 (function () { "use strict"; var Point = function(x,y) { this.x=x; this.y=y; }; var Path = function(center,length,both) { this.center = center; this.length = length; this.both = both; this.end = function(alpha) { var retx=1.0*this.center.x+this.length*Math.sin(alpha); var rety=1.0*this.center.y-this.length*Math.cos(alpha); if (typeof(this.both)!=='undefined') return { x1:retx, x2:retx, y1:rety, y2:rety } else return { x2:retx, y2:rety }; }; }; var Hand = function(svgline,both) { this.elem = document.id(svgline); var p=this.elem.get(['x1','y1','x2','y2']); this.path = new Path ( new Point(p.x1,p.y1), Math.sqrt(Math.pow(1.0*p.x2-1.0*p.x1,2)+ Math.pow(1.0*p.y2-1.0*p.y1,2)), both); this.setPos = function(angle) { this.elem.set(this.path.end(angle)); }; }; var Clock = function(hour,minute,second,refresh) { this.hour = new Hand(hour); this.minute = new Hand(minute); this.second = new Hand(second,true); this.setTime = function(timePos) { var self= this; var tps = 1.0*timePos.getTime() % 60000; var tpm = timePos.getMinutes()*1.0 + 1.0* tps/60000; var tph = timePos.getHours()*1.0 + 1.0* tpm/60; this.second.setPos(tps / 30000 * Math.PI); this.minute.setPos(tpm / 30 * Math.PI); this.hour .setPos(tph / 6 * Math.PI); }; }; var RefreshLoop = function(refresh) { var newdate=new Date(); clock1.setTime(newdate); newdate=newdate.getTime()+newdate.getTimezoneOffset()*60000; clock2.setTime(new Date(newdate)); clock3.setTime(new Date(newdate+20700000)); }; var clock1=new Clock('hours','minutes','seconds',120); var clock2=new Clock('hours2','minutes2','seconds2',120); var clock3=new Clock('hours3','minutes3','seconds3',120); RefreshLoop.periodical(500); }()); 
 circle { stroke: black; } .startbg { stop-color: #eeeeee; } .endbg { stop-color: #777777; } .box { fill:url(#grad0); } .box1 { fill:url(#grad1); } .box2 { fill:url(#grad2); } .box3 { fill:url(#grad3); } .label { stroke: #424242;fill:#eee;stroke-width:1; } .minutes { stroke: #2288AA; } .hours { stroke: #3388CC; } .seconds { stroke: #CCCC22; } line,circle,rect { opacity:0.65; fill:none; stroke-width:8; stroke-linecap:round; stroke-linejoin:round; marker:none; stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1; visibility:visible; display:inline; overflow:visible; enable-background:accumulate } text { font-size:15px; font-style:normal; font-variant:normal; font-weight:normal; font-stretch:normal; text-align:center; line-height:100%; writing-mode:lr-tb; text-anchor:middle; fill:#000000;fill-opacity:.7; stroke:none; font-family:Nimbus Sans L; } 
 <script src="http://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-nocompat.js" ></script> <svg xmlns="http://www.w3.org/2000/svg" id="svg2" width="100%" height="100%" viewBox="-1 -1 900 555" version="1.0"><defs> <linearGradient gradientUnits="userSpaceOnUse" id="g0"><stop class="startbg" /><stop class="endbg" offset="1" /></linearGradient> <linearGradient id="grad0" x1="-1" y1="-1" x2="256" y2="277" xlink:href="#g0" /> <linearGradient id="grad1" x1="256" y1="-1" x2="515" y2="277" xlink:href="#g0" /> <linearGradient id="grad2" x1="512" y1="-1" x2="771" y2="277" xlink:href="#g0" /> </defs> <circle class="box" id="box1" cy="128" cx="128" r="124" /> <line class="hours" id="hours" x1="128" y1="128" x2="128" y2="48" /> <line class="minutes" id="minutes" x1="128" y1="128" x2="244" y2="128" /> <line class="seconds" id="seconds" x1="128" y1="128" x2="128" y2="8" /> <rect class="label" x="16" y="256" width="224" height="20" /> <text x="0" y="0" xml:space="preserve"> <tspan x="128" y="271">Local time</tspan></text> <circle class="box1" id="box2" cy="128" cx="385" r="124" /> <line class="hours" id="hours2" x1="385" y1="128" x2="385" y2="48" /> <line class="minutes" id="minutes2" x1="385" y1="128" x2="501" y2="128" /> <line class="seconds" id="seconds2" x1="385" y1="128" x2="385" y2="8" /> <rect class="label" x="273" y="256" width="224" height="20" /> <text x="0" y="0" xml:space="preserve"> <tspan x="385" y="271">Universal Time Clock</tspan></text> <circle class="box2" id="box3" cy="128" cx="642" r="124" /> <line class="hours" id="hours3" x1="642" y1="128" x2="642" y2="48" /> <line class="minutes" id="minutes3" x1="642" y1="128" x2="758" y2="128" /> <line class="seconds" id="seconds3" x1="642" y1="128" x2="642" y2="8" /> <rect class="label" x="530" y="256" width="224" height="20" /> <text x="0" y="0" xml:space="preserve"> <tspan x="642" y="271">Asia/Katmandu</tspan></text> </svg> 

New attempt completely rewritten

This is using momentjs for intl infos, but no other library.

 "use strict"; var gv={ clockcount: 1, svg:'http://www.w3.org/2000/svg', xlnk:'http://www.w3.org/1999/xlink', tzlist:['Local'].concat(moment.tz.names()), vbox:document.getElementById('svg').getAttribute("viewBox").split(" ") }; function mousepos(event) { var minxy=innerWidth; if (minxy > innerHeight) minxy=innerHeight; return { x:((event.clientX-(innerWidth-minxy)/2)/minxy)*(gv.vbox[2]-gv.vbox[0]), y:((event.clientY-(innerHeight-minxy)/2)/minxy)*(gv.vbox[3]-gv.vbox[1]) }; }; function myClock(cx,cy,r,tz) { var clock=this, elem; this.cx=128; if (typeof(cx)!=='undefined') this.cx=cx; this.cy=128; if (typeof(cy)!=='undefined') this.cy=cy; this.r=100; if (typeof(r)!=='undefined') this.r=r; this.tz=new Date().getTimezoneOffset(); this.setTz=function(tz) { if (typeof(tz)!=='undefined') { this.label=tz; if (tz!=="Local") { var ndte=new Date(); var tzoff=moment(ndte).tz(tz).format('HH mm ss').split(' '); var tznow=Math.floor(ndte/1000)%86400; this.tz=(tznow-(tzoff[0]*3600+tzoff[1]*60+1*tzoff[2]))/60; } else this.tz=new Date().getTimezoneOffset(); } else this.label="Local"; }; this.setTz(tz); this.clkid=gv.clockcount++; this.floor=0; this.toggleFloor=function(e) { e.preventDefault(); clock.floor=1-clock.floor; }; this.toggleSecDraw=function(e) { e.preventDefault(); clock.secdraw=1-clock.secdraw; }; this.wheel=function(e) { e.preventDefault(); var sens=1; if (typeof(e.detail)!=='undefined') { if ( 0 > e.detail ) { sens=-1; } } else if ( 0 > e.wheelDelta ) { sens=-1; }; var cidx=gv.tzlist.indexOf(clock.label)*1+1*sens; if (cidx < 0) cidx=gv.tzlist.length-1; if (cidx >= gv.tzlist.length) cidx=0; clock.setTz(gv.tzlist[cidx]); clock.draw=0; }; this.moused = function (evt) { evt.preventDefault(); var m=mousepos(evt); if ((clock.r/2 > Math.pow(Math.pow(Math.abs(clock.cx-mx),2)+ Math.pow(Math.abs(clock.cy-my),2),.5))) { clock.box.addEventListener("mousemove", clock.mousem, true); } else { clock.box.addEventListener("mousemove", clock.mouser, true); }; clock.box.addEventListener("mouseup", clock.mouseu, true); }; this.mouseu = function(evt) { evt.preventDefault(); clock.draw=0; clock.box.removeEventListener("mousemove", clock.mouser, true); clock.box.removeEventListener("mousemove", clock.mousem, true); clock.box.removeEventListener("mouseup", clock.mouseu, true); }; this.mouser = function(evt) { evt.preventDefault(); clock.draw=0; var m=mousepos(evt); clock.r=1.25*Math.pow(Math.pow(Math.abs(clock.cx-mx),2)+ Math.pow(Math.abs(clock.cy-my),2),.5); }; this.mousem = function(evt) { evt.preventDefault(); clock.draw=0; var m=mousepos(evt); clock.cx=mx; clock.cy=my; }; this.drop = function(evt) { evt.preventDefault();clearInterval(clock.loop); clock.box.remove(); }; elem=document.createElementNS(gv.svg,'g'); elem.setAttribute('id','box'+this.clkid); document.getElementById('myClock').appendChild(elem); this.box=document.getElementById('box'+this.clkid); this.box.addEventListener("mousedown", this.moused ,true); this.box.addEventListener("click", this.toggleSecDraw,true); this.box.addEventListener("dblclick", this.toggleFloor ,true); this.box.addEventListener('mousewheel', this.wheel, true); this.box.addEventListener('DOMMouseScroll',this.wheel, true); this.box.addEventListener('contextmenu', this.drop, true); elem=document.createElementNS(gv.svg,'circle'); this.fill='fill: url(#g'+this.clkid+');'+ 'stroke: url(#gb'+this.clkid+');'; elem.setAttribute('style',this.fill); elem.setAttribute('id','crc'+this.clkid); this.box.appendChild(elem); this.crc=document.getElementById('crc'+this.clkid); this.ticks=[]; for (var i=0;i<60;i++) { elem=document.createElementNS(gv.svg,'line'); elem.setAttribute('class','ticks'); elem.setAttribute('id','t'+i+'c'+this.clkid); this.box.appendChild(elem); this.ticks.push(document.getElementById('t'+i+'c'+this.clkid)); }; elem=document.createElementNS(gv.svg,'rect'); elem.setAttribute('class','label'); elem.setAttribute('id','r'+this.clkid); this.box.appendChild(elem); this.rct=document.getElementById('r'+this.clkid); elem=document.createElementNS(gv.svg,'text'); elem.setAttribute('id','x'+this.clkid); this.box.appendChild(elem); this.tbx=document.getElementById('x'+this.clkid); elem=document.createElementNS(gv.svg,'tspan'); elem.setAttribute('id','t'+this.clkid); this.tbx.appendChild(elem); this.txt=document.getElementById('t'+this.clkid); elem=document.createElementNS(gv.svg,'line'); elem.setAttribute('id','hr'+this.clkid); elem.setAttribute('class','hours'); this.box.appendChild(elem); this.hhr=document.getElementById('hr'+this.clkid); elem=document.createElementNS(gv.svg,'line'); elem.setAttribute('id','mn'+this.clkid); elem.setAttribute('class','minutes'); this.box.appendChild(elem); this.hmn=document.getElementById('mn'+this.clkid); elem=document.createElementNS(gv.svg,'line'); elem.setAttribute('id','sc'+this.clkid); elem.setAttribute('class','seconds'); this.box.appendChild(elem); this.hsc=document.getElementById('sc'+this.clkid); elem=document.createElementNS(gv.svg,'linearGradient'); elem.setAttribute('id','g'+this.clkid); elem.setAttributeNS(gv.xlnk,'xlink:href','#g0'); document.getElementById('defs').appendChild(elem); this.deg=document.getElementById('g'+this.clkid); elem=document.createElementNS(gv.svg,'linearGradient'); elem.setAttribute('id','gb'+this.clkid); elem.setAttributeNS(gv.xlnk,'xlink:href','#g0'); document.getElementById('defs').appendChild(elem); this.dgb=document.getElementById('gb'+this.clkid); this.getTZ=function() { return this.tz; }; this.setTZ=function(tz) { this.tz=tz; }; this.draw=0; this.secdraw=1; this.adjust=function() { if (clock.draw!==1) { clock.crc.setAttribute('style','stroke-width:'+.03*clock.r+";"+ clock.fill); clock.hhr.setAttribute('style','stroke-width:'+.11*clock.r); clock.hmn.setAttribute('style','stroke-width:'+.075*clock.r); clock.hsc.setAttribute('style','stroke-width:'+ (clock.secdraw==1?.03:.09)*clock.r); clock.crc.setAttribute('cx',clock.cx); clock.crc.setAttribute('cy',clock.cy); clock.crc.setAttribute('r',clock.r); clock.rct.setAttribute('height',.2*clock.r); clock.rct.setAttribute('x',clock.cx-.9*clock.r); clock.rct.setAttribute('y',clock.cy*1+1.1*clock.r); clock.txt.innerHTML=clock.label; clock.txt.setAttribute('x',clock.cx); clock.txt.setAttribute('y',clock.cy*1+1.25*clock.r); clock.txt.setAttribute('style','font-size: '+(.15*clock.r)+"px;"); var w=clock.label.length*.1*clock.r+20.0; clock.rct.setAttribute('x',clock.cx-w/2); clock.rct.setAttribute('width',w); for (var i=0;i<60;i++) { var x=clock.cx*1+.925*clock.r*Math.sin(i/30*Math.PI); var y=clock.cy*1+.925*clock.r*Math.cos(i/30*Math.PI); clock.ticks[i].setAttribute('x1',x); clock.ticks[i].setAttribute('y1',y); clock.ticks[i].setAttribute('x2',x); clock.ticks[i].setAttribute('y2',y); clock.ticks[i].setAttribute('style','stroke-width:'+ (i%5==0?.04:.02)*clock.r); }; clock.hsc.setAttribute('x1',clock.cx); clock.hsc.setAttribute('y1',clock.cy); clock.hmn.setAttribute('x1',clock.cx); clock.hmn.setAttribute('y1',clock.cy); clock.hhr.setAttribute('x1',clock.cx); clock.hhr.setAttribute('y1',clock.cy); clock.deg.setAttribute('x1',clock.cx-1.1*clock.r); clock.deg.setAttribute('y1',clock.cy-1.1*clock.r); clock.deg.setAttribute('x2',clock.cx+1.1*clock.r); clock.deg.setAttribute('y2',clock.cy+1.1*clock.r); clock.dgb.setAttribute('x1',clock.cx+1.1*clock.r); clock.dgb.setAttribute('y1',clock.cy+1.1*clock.r); clock.dgb.setAttribute('x2',clock.cx-1.1*clock.r); clock.dgb.setAttribute('y2',clock.cy-1.1*clock.r); clock.draw=1; }; var now=new Date()/1000.0-this.tz*60; if (this.floor==1) now=Math.floor(now); var x=this.cx+(this.secdraw==1?.975:.925)* this.r*Math.sin((now % 60)/30*Math.PI); var y=this.cy-(this.secdraw==1?.975:.925)* this.r*Math.cos((now % 60)/30*Math.PI); this.hsc.setAttribute('x2',x); this.hsc.setAttribute('y2',y); if (this.secdraw==0) { this.hsc.setAttribute('x1',x); this.hsc.setAttribute('y1',y); } if (this.floor==1) now=Math.floor(now/60) else now=now/60; x=this.cx+.9*this.r*Math.sin((now %60)/30*Math.PI); y=this.cy-.9*this.r*Math.cos((now %60)/30*Math.PI); this.hmn.setAttribute('x2',x); this.hmn.setAttribute('y2',y); if (this.floor==1) now=Math.floor(now/60) else now=now/60; x=this.cx+.7*this.r*Math.sin((now % 12)/6*Math.PI); y=this.cy-.7*this.r*Math.cos((now % 12)/6*Math.PI); this.hhr.setAttribute('x2',x); this.hhr.setAttribute('y2',y); }; this.animate = function() { clock.adjust(); }; this.loop=setInterval(this.animate,66); }; document.getElementById('svg').addEventListener('dblclick', function(e){ if (e. target.id!=='svg')return;var m=mousepos(e);new myClock(mx,my,80,'Local'); }); var clocks=['UTC','Local','Asia/Kolkata']; for (var i=0;i<3;i++) { new myClock( 90+170*i,90,80,clocks[i]); }; 
 circle { stroke: black; } .startbg { stop-color: #CCC; } .endbg { stop-color: #222; } .label { stroke: #424242;fill:#eee;stroke-width:1; } .minutes { stroke: #2288AA; } .hours { stroke: #3388CC; } .seconds { stroke: #CCCC22; } .ticks { stroke: black; } line,circle,rect,point { opacity:0.65; stroke-linecap:round; stroke-linejoin:round; marker:none; stroke-miterlimit:4; stroke-dasharray:none; stroke-opacity:1; visibility:visible; display:inline; overflow:visible; enable-background:accumulate } text { font-style:normal; font-variant:normal; font-weight:normal; font-stretch:normal; text-align:center; line-height:100%; writing-mode:lr-tb; text-anchor:middle; fill:#000000;fill-opacity:.7; stroke:none; font-family:Nimbus Sans L; } 
 <?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml-stylesheet type="text/css" href="myClock2.css" ?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600" id="svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" > <defs id="defs"> <linearGradient gradientUnits="userSpaceOnUse" id="g0"><stop class="startbg" /><stop class="endbg" offset="1" /> </linearGradient></defs> <script type="text/ecmascript" xlink:href="http://momentjs.com/downloads/moment-with-locales.js" /> <script type="text/ecmascript" xlink:href="http://momentjs.com/downloads/moment-timezone-with-data.js" /> <title id="title">Clock object</title> <g id="myClock"></g> <script type="text/ecmascript" xlink:href="myClock2.js" /> <script type="text/ecmascript"> </script> </svg> 

There are 3 objects on the svg chart, with some functions:

Mouse commands:

  • when the mouse is over the clock

    • Press => switch seconds: path or point
    • Drag Center => Move Clock
    • Drag the border => resize hours
    • Double click => floor to floor mode.
    • Mouse wheel roll => change time zone
    • Right click (contextmenu) => delete clock
  • when the mouse is in the background:

    • Double click => Add New Clock

This is not ideal, as there are some errors, mainly in positioning the mouse with width="100%" height="100%" , I think this is the effect of closed fragments, but it doesn’t matter here.

You can find a fully downloadable SVG graphic on my website.

+2
source

Your code is simple and straightforward. I do not think you should try using jQuery or MooTools if your task is simple without it.

For rotation, I don't think that the built-in tools in jQuery or MooTools are created, but there are matrix transformations that you can use on svg objects, read: http://msdn.microsoft.com/en-us/library/ie/hh535760% 28v = vs. 85% 29.aspx

Or check this question: SVG rotation transformation matrix .

Regarding the creation of the object:

You can, of course, cut your code into more functions or create an object representing the current hours / minutes / seconds

 var clock = { time: { s: 0, m: 0, h: 0 }, pos: { x: 128, y: 128 }, .... anything else you might want to add }; 

First you set your properties in a set of functions

 clock.setTime = function (date) { this.time.s = date.getTime()%60000; this.time.m = date.getMinutes()*1.0+1.0*nows/60000; this.time.h = date.getHours()*1.0+1.0*nowm/60; }; 

And read them in another set of functions:

 clock.getMinPos = function () { var x = ...;// Sine is ok. var y = ...;// Cosine is ok. // I don't like matrices anyway. return [x, y]; }; 

In fact, just try breaking your code into functional tasks. One function should do only one.

+3
source

I created a D3 clock object

Plunker

enter image description here


:

  • d3Clock Can be created multiple times.

  • The constructor accepts X, Y, Width, TimeZoneOffset Object, label

:

  <script> $(document).ready(function() { var tokyoClock = new d3Clock({ clockCenterX: 140, clockCenterY: 150, clockWidth: 130, title: 'Tokyo', TZOffset: { hours: 13 } }); 

:

  • Methods are also set manually for installing TZOffsets.

:

  var iranClock = new d3Clock({ clockCenterX: 355, clockCenterY: 360, clockWidth: 180, title: 'Iran' }); iranClock.Hours(8); iranClock.Minutes(30); 

D3Clock app:

 var d3Clock = function(data) { var clockGroup, fields, formatHour, formatMinute, formatSecond, pi, render, scaleHours, scaleSecsMins, vis; width = data.clockWidth; height = data.clockWidth; offSetX = data.clockWidth / 2; offSetY = offSetX; var x = data.clockCenterX; var y = data.clockCenterY; var hourOffset = 0; var minOffset = 0; var secOffset = 0; title = data.title; var clockRadius = data.clockWidth * 0.45; formatSecond = d3.time.format("%S"); formatMinute = d3.time.format("%M"); formatHour = d3.time.format("%H"); pi = Math.PI; scaleSecsMins = d3.scale.linear().domain([0, 59 + 59 / 60]).range([0, 2 * pi]); scaleHours = d3.scale.linear().domain([0, 11 + 59 / 60]).range([0, 2 * pi]); // create Parent Div and set x, y var iDiv = document.createElement('div'); iDiv.setAttribute("style", 'background-color: transparent; height: ' + width + ' px; width: ' + width + 'px; position: absolute; top:' + y + 'px; left: ' + x + 'px; text-align: center; v-align:bottom;'); iDiv.innerHTML = '<span style="font-weight: bold;">' + title + '</span>'; document.getElementsByTagName('body')[0].appendChild(iDiv); vis = d3.select(iDiv).append("svg:svg").attr("width", width).attr("height", height); clockGroup = vis.append("svg:g").attr("transform", "translate(" + offSetX + "," + offSetY + ")"); clockGroup.append("svg:circle").attr("r", clockRadius).attr("fill", "lightgrey").attr("class", "clock outercircle").attr("stroke", "black").attr("stroke-width", 5); clockGroup.append("svg:circle").attr("r", 4).attr("fill", "black").attr("class", "clock innercircle"); // private set TZ Offset methods var setTZSeconds = function(sec) { if (sec !== undefined) secOffset = sec; } var setTZMins = function(min) { if (min !== undefined) minOffset = min; } var setTZHours = function(hr) { if (hr !== undefined) hourOffset = hr; } // exposed TimeZoneOffset this.Seconds = function(Sec) { setTZSeconds(Sec); } this.Minutes = function(Mins) { setTZMins(Mins); } this.Hours = function(Hours) { setTZHours(Hours); } if (data.TZOffset != undefined) { setTZHours(data.TZOffset.hours); setTZMins(data.TZOffset.mins); setTZSeconds(data.TZOffset.secs); } // Get time values and apply offsets fields = function() { var d, data, hour, minute, second; d = new Date(); second = d.getSeconds() + secOffset; minute = d.getMinutes() + minOffset; hour = d.getHours() + hourOffset + minute / 60; return data = [{ "unit": "seconds", "text": formatSecond(d), "numeric": second }, { "unit": "minutes", "text": formatMinute(d), "numeric": minute }, { "unit": "hours", "text": formatHour(d), "numeric": hour }]; }; render = function(data) { var hourArc, minuteArc, secondArc; clockGroup.selectAll(".clockhand").remove(); secondArc = d3.svg.arc().innerRadius(0).outerRadius(clockRadius * .9).startAngle(function(d) { return scaleSecsMins(d.numeric); }).endAngle(function(d) { return scaleSecsMins(d.numeric); }); minuteArc = d3.svg.arc().innerRadius(0).outerRadius(clockRadius * .85).startAngle(function(d) { return scaleSecsMins(d.numeric); }).endAngle(function(d) { return scaleSecsMins(d.numeric); }); hourArc = d3.svg.arc().innerRadius(0).outerRadius(clockRadius * .7).startAngle(function(d) { return scaleHours(d.numeric % 12); }).endAngle(function(d) { return scaleHours(d.numeric % 12); }); clockGroup.selectAll(".clockhand").data(data).enter().append("svg:path").attr("d", function(d) { if (d.unit === "seconds") { return secondArc(d); } else if (d.unit === "minutes") { return minuteArc(d); } else if (d.unit === "hours") { return hourArc(d); } }).attr("class", "clockhand").attr("stroke", "black").attr("style", function(d) { if (d.unit === "seconds") { return "stroke-width: 2; stroke: white" } else if (d.unit === "minutes") { return "stroke-width: 3;" } else if (d.unit === "hours") { return "stroke-width: 4;" } }).attr("fill", "none"); }; setInterval(function() { var data; data = fields(); return render(data); }, 1000); }; 

Additional methods may be available for customization.

all functions prefixed with this. published publicly for use in an instance of the object. So:

 this.Seconds = function(Sec) { setTZSeconds(Sec); } this.Minutes = function(Mins) { setTZMins(Mins); } this.Hours = function(Hours) { setTZHours(Hours); } 

setTZSeconds() , setTZMins() , setTZHours() .

, OO , . (, undefined .

  • x, y, clockObject
  • , /
+2
source

UPDATE:

jQuery MooTools, . jQuery MooTools - , DOM Manipulation AJAX, , SVG ( ), DOM AJAX.

, , ( jQuery , MooTools), $(document).ready() IIFE .

 $(document).ready(function { 'use strict'; ... }); 

instead:

 (function () { 'use strict'; ... }()); 

jQuery:

 this.element = $('#' + hand); 

/ :

 this.setPosition = function setPosition(now) { var x2 = this.element.attr('x2'), y2 = this.element.attr('y2'); this.setInterval(now); x2 = this.center.x + (this.length * Math.sin(this.interval / this.frequency * Math.PI)); y2 = this.center.y - (this.length * Math.cos(this.interval / this.frequency * Math.PI)); this.element.attr('x2', x2); this.element.attr('y2', y2); if (this.isSeconds) { //special case this.element.attr('x1', x2); this.element.attr('y1', y2); } }; 

, (, , ) .

, , , jQuery, MooTools, , , , .

ORIGINAL:

, " ", . , , :

  • .

, , ( "" ).

, "" :

 (function () { 'use strict'; var Point = function Point(x, y) { this.x = x; this.y = y; }; var Hand = function Hand(hand, center, length) { this.center = center; this.element = document.getElementById(hand); this.frequency = 0; this.isSeconds = (hand === 'seconds'); this.hand = hand; this.length = length; this.interval = 0; this.parseMilliseconds = function parseMilliseconds(now) { return now.getTime() % 60000; }; this.parseMinutes = function parseMinutes(now) { return now.getMinutes() + (this.parseMilliseconds(now) / 60000); }; this.parseHours = function parseHours(now) { return now.getHours() + (this.parseMinutes(now) / 60); }; this.setFrequency = function getFrequency() { switch (this.hand) { case 'hours': this.frequency = 6; break; case 'minutes': this.frequency = 30; break; case 'seconds': this.frequency = 30000; break; } }; this.setInterval = function setInterval(now) { switch (this.hand) { case 'hours': this.interval = this.parseHours(now); break; case 'minutes': this.interval = this.parseMinutes(now); break; case 'seconds': this.interval = this.parseMilliseconds(now); break; } }; this.setPosition = function setPosition(now) { var x2 = this.element.getAttribute('x2'), y2 = this.element.getAttribute('y2'); this.setInterval(now); x2 = this.center.x + (this.length * Math.sin(this.interval / this.frequency * Math.PI)); y2 = this.center.y - (this.length * Math.cos(this.interval / this.frequency * Math.PI)); this.element.setAttribute('x2', x2); this.element.setAttribute('y2', y2); if (this.isSeconds) { //special case this.element.setAttribute('x1', x2); this.element.setAttribute('y1', y2); } }; this.setFrequency(); }; var updateClock = function updateClock(hours, minutes, seconds) { var now = new Date(); hours.setPosition(now); minutes.setPosition(now); seconds.setPosition(now); window.setTimeout(function () { updateClock(hours, minutes, seconds); }, 80); }; var initClock = function initClock() { var center = new Point(128, 128), seconds = new Hand('seconds', center, 120), minutes = new Hand('minutes', center, 116), hours = new Hand('hours', center, 80); updateClock(hours, minutes, seconds); }; initClock(); }()); 

: http://jsfiddle.net/MbktF/19/

+1
source

All Articles