如何实现*对象*为提高我的时钟采样JavaScript程序(How to implement *ob

2019-08-02 06:16发布

这项工作的目的是了解并与一些对象的概念我听说角落找寻的意义发挥。

关于赏金

有很多不同的方法/办法做到这一点。

我的尝试是不是真的干净:用于添加2ST时钟,与另一个时区,我不得不编辑3个不同的地方。 这不是很好(见答案的底部)。

我怎么能这样做更有用的东西?

一开始:

编辑后:最初的问题是关于jQuery和MooTools的,现在的选择,因为已经取得之间进行选择; 我们的目标是改善这一点,与使用的mootools的。

有一个小样品/演示中,我写道:使用JavaScript和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> 

(渊源张贴在的jsfiddle ),因为我不太了解JavaScript jQuery和/或MooTools的经历,我想知道,如果一些simplier方法存在,也许在以不同的方式书面方式这一点。

如何做简单的绕固定中心,使用jQuery或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);

如何对象化这个代码? (如果连这可能是一件好事)...

使用面向对象,特定的库,否则所有样品都欢迎!

Answer 1:

你的代码是简单明了。 我不认为你应该尝试使用jQuery或MooTools的,如果你的任务是没有简单。

对于旋转,我不认为有建于jQuery的或MooTools的工具,但也有矩阵变换,你可以使用SVG对象,阅读: http://msdn.microsoft.com/en-us/library/ie/hh535760 %28V = vs.85%29.aspx

或检查这个问题: SVG旋转转换Matrix 。

作为用于制造物体:

当然,你可以切片你的代码,以更多的功能,或者您作出这样的表示当前时/分/秒的对象

var clock = {
    time: {
        s: 0,
        m: 0,
        h: 0    
    },
    pos: {
        x: 128,
        y: 128
    },

   .... anything else you might want to add
};

您在一组函数首先设置其属性

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;
};

而在另一组的功能阅读:

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

真的只是尝试你的代码划分为功能性任务。 一个功能应该只做一两件事。



Answer 2:

从赏金编辑:进入这个底部!

第一个答案

皮特阅读第一评论后(非常感谢!你给我的研究提供了很好的方式)和SoonDead(感谢过转换的第一步),我周围已经稍微留意一下,jQuerymootools的代码,最终我选择的mootools减少我的代码,如mootools的让我提交array用于object.gethash的(关联数组) 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> 

好了,现在我的新代码是8行较小,甚至送花儿给人可读。

这是一个进步,但objectization是指使其作为一个对象 ......随着目标

  1. 保持reabable
  2. 保持有效(不作无用的操作或相同的操作两个时间)
  3. 让它可重复使用(作为对象,让所有固定变量了...)

一个中介的个人成绩 ,

但现在的代码如下所示:

(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);
}());

当所有的部分留小,我的clock是一个真正的可重复使用的对象(现在的工作的4倍)。

该功能setTime需要计算所有的手在一起,每个价值持有之外的部分,但每个操作必须只做过一次。

对于我的时钟,一个Path通过一个固定的定义start point的固定length和可变direction的Path.end是所计算的结束点指定的direction

Hand是一个给定的SVG line ,与他原来的Path ,和一个可选标志speficying上设定中,起点和终点都在相同的值(零长度线,以圆终止给圆点)被positionned。

备注(错误):由于每个元件在SVG中定义和Path.length从路径的每一端之间的距离计算,该seconds路径必须被首先用绘制[x1,y1]在的中心时钟, ! = [x2,y2]

希望一些要纠正/改善/讨论我的objectization ...

UPDATE2

我认为,这是现在的最终版本 ,其中目标很简单,MooTools是使用(也许不是太多,言论的欢迎)和我最后的时钟可用于许多时间来显示不同timezome。

 (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> 

新的尝试彻底改写

这种使用momentjs对国际的相关信息,但没有其他库。

 "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> 

有3 对象时钟上的SVG图 ,与一些特点:

鼠标命令:

  • 当鼠标在一个时钟

    • 点击=>切换秒:路径或点
    • 拖动中心=>移动时钟
    • 拖动边框=>调整时钟
    • 双击=>切换地面模式
    • 滚动鼠标滚轮=>改变时区
    • 右键单击(文本菜单)=>删除时钟
  • 当鼠标在背景:

    • 双击=>添加一个新的时钟

这是不完美的,因为有一些缺陷,主要是在与鼠标positionning width="100%" height="100%" ,我认为这是封闭的片段的效果,但”这里无关紧要。

你可以找到一个完整的可用在我的网站SVG图片



Answer 3:

我创建了一个D3时钟对象

Plunker


  • d3Clock可以多次实例化。

  • 构造函数采用X,Y,宽度,timezoneoffset的对象,标签

  <script>
    $(document).ready(function() {

      var tokyoClock = new d3Clock({
        clockCenterX: 140,
        clockCenterY: 150,
        clockWidth: 130,
        title: 'Tokyo',
        TZOffset: {
          hours: 13
        }
      });

  • 方法也暴露手动设置TZOffsets

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

      iranClock.Hours(8);
      iranClock.Minutes(30);

该d3Clock附件:

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);
};

更多的方法可以被暴露,以允许定制

与前缀的所有功能this. 将被实例化的对象所使用的暴露公开。 所以:

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

暴露访问私有setTZSeconds() setTZMins() setTZHours()

它被认为是良好的面向对象表格的公共方法调用私有方法应该做的工作。 公共方法可以限制或过滤的结果(像我检查没有undefined的私有方法。

公共方法可以接触到

  • 改变X,Y所以clockObjects可以在屏幕上实例化之后移动
  • 改变大小
  • 更改时钟指针样式,标题位置/造型


Answer 4:

更新:

你可以使用jQuery或MooTools的,但我没有看到这样的地步。 jQuery和MooTools的一些库,使DOM操作还是AJAX更简单,你与SVG做什么(在这种情况下)并没有做太多的DOM操作,而且也没有参与AJAX的主要目的。

也就是说,如果你有你的心脏上使用其中的一个(我会使用jQuery在这个答案,因为我不是精通与MooTools的还)设置,我会在一个包装函数调用启动$(document).ready()函数来代替IIFE 。

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

代替:

(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的助阵,但在这种情况下,我不认为任何将增加足够的价值是值得的。

原版的:

我被“对象化这个代码”假设,你的意思是让更多的抽象。 既然这样,你的代码有:

  • 做工作
  • 是相当紧凑
  • 是相当可读

并且因此不太可能有任何的缩小(或一定“更好”)。

这就是说,你可以抽象的“手”对象是这样的:

(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/



文章来源: How to implement *object* for improve my clock sample javascript program