use*_*613 9 javascript jquery html5
我正在使用这个JSFiddle中的代码来创建一个财富类型的游戏.我想要做的是让用户选择自己的颜色而不是生成随机颜色.
我将此添加到HTML代码中:
<select id="colour" name="colour" class="colour">
<option value=""></option>
<option value="db0000">Red</option>
<option value="171515">Black</option>
<option value="008c0a">Green</option>
</select>
Run Code Online (Sandbox Code Playgroud)
我只编辑了这部分Javascript:
for (i = 0; i < 1; i++) {
digit[i] = colors[Math.round(Math.random() * 1)];
//color = color+digit[i];
color = document.getElementById("colour").value;
//color = color+digit[i];
}
Run Code Online (Sandbox Code Playgroud)
我补充道color = document.getElementById("colour").value;.
问题是颜色不能正常工作.它将正确地创建具有所选颜色的第一和第二段,但是从第三段开始,它将在车轮中添加额外的黑色段.
我几乎改变了Javascript中的每个数字来查明问题,但仍然无法解决这个问题.
编辑:
为了确保我没有引起任何混淆,我想要做的是为每个添加到方向盘的新段,我需要选择一种新颜色.
这段代码是一个很好的例子,说明了为什么原型模式比功能模式要好得多。该插件被定义为事实上的工厂函数,它声明了各种各样的函数本地状态变量(startAngle、arc、pplArray等),这些变量由实现该插件的各种方法封闭,最重要的是,其中一些方法methods使用对象字面量语法在函数本地 ( ) 上定义为表达式化函数字面量,一种方法被定义为表达式化函数字面量并分配给一次性函数本地 ( var rotateWheel),该函数被提升到作用域的顶部,并且由各种其他方法关闭,其余部分(genHex()、stopRotateWheel()等)被定义为函数语句,这些语句被提升到作用域的顶部并由各种其他方法关闭。真是一团糟!
此外,并非所有闭包变量都真正需要是闭包,因为它们实际上不需要在方法调用之间维护状态;arc就是一个很好的例子。
这里可以提出的另一个批评是,某些状态实际上存储在 DOM 树中,这是荒谬且不必要的。我特意指的是params.participants,它是一个 jQuery 选择器,它在 DOM 中的某个位置定位一个<ul>元素(在哪里并不重要),它的子<li>元素被迭代以从其内部 HTML 构建轮子段文本。这些数据不需要存储在 DOM 上;它可以轻松地存储在类实例的数组中。
当然,还有对函数式模式的经典批评,它会导致为每次调用构造函数/工厂函数($.fn.spinwheel()在本例中)定义新的函数对象,而原型模式将涉及每个函数的单个定义定义类时在类原型上调用函数。
不管怎样,我使用原型模式重写了整个插件。该小部件现在被定义为全局构造函数window.SpinWheel(当然,如果需要,可以将其移动到命名空间中)。所有实例方法都是使用统一语法通过将表达式化函数文字分配给类原型来定义的SpinWheel.prototype。
就状态数据而言,在构造函数上静态定义了一些默认配置数据(基本上我$.fn.spinwheel.default_options在原始代码中获取了对象并将其分配给SpinWheel.config,但修复了拼写错误并删除了params.participants),然后是配置对象作为参数传递给构造函数并$canvas在实例本身上捕获(以及画布节点的 jQuery 包装器及其上下文对象)作为this.config. 最后,实际的可变实例状态作为属性存储在实例上,例如this.segmentTexts(每个段的文本)、this.colors(当前选定的段颜色)和this.curAngle(滚轮的当前角度)。就是这样,实际上只有三种数据:静态默认(后备)配置、实例配置和实例属性。所有方法的定义风格都是统一的,并且对所有对象数据具有相同的访问权限。
jQuery 插件现在只是该类的一个薄包装SpinWheel;基本上,它会实例化它,将其附加到目标画布(并不是真正必要的,除非外部代码想要在创建后访问它),然后初始化它。插件接口与原始代码相同,但是使用新代码,SpinWheel如果您愿意,您还可以独立于 jQuery 插件框架进行实例化(尽管,当然,应该说,实现仍然依赖于 jQuery正在加载)。
另外,只是为了好玩,我添加了Delete、Clear、 和Reset按钮来演示对方向盘的更多控制。您现在可以通过正则表达式与文本匹配来删除段,清除整个轮子,以便您可以从头开始构建它,并将其重置为初始配置(尽管如果您没有通过初始配置配置颜色,它们将再次随机生成,这肯定会与初始显示中的有所不同;但如果需要,您可以配置初始颜色)。
这是新的 HTML:
\n\n<div id="main">\n\n <div id="left-column">\n <form class="iform" action="#" method="get">\n <label for="joiner"></label>\n <input id="joiner" name="joiner" class="joiner" placeholder="Please Enter your name" />\n <select id="colorer" name="colorer" class="colorer">\n <option value="">auto</option>\n <option value="db0000">Red</option>\n <option value="171515">Black</option>\n <option value="008c0a">Green</option>\n </select>\n <button class="add">Add</button>\n <button class="delete">Delete</button>\n <button class="spin-trigger">Spin</button>\n <button class="clear">Clear</button>\n <button class="reset">Reset</button>\n </form>\n <canvas class="canvas" width="500" height="500"></canvas>\n </div>\n\n <div id="right-column">\n <p class="winner">The Winner is ... <span> </span></p>\n </div>\n\n <div style="clear:both"></div>\n\n</div>\nRun Code Online (Sandbox Code Playgroud)\n\n这是定义该类的新 IIFE SpinWheel:
(function($) {\n\n // define main SpinWheel constructor function\n var SpinWheel = function($canvas, config ) {\n\n // validate config\n // 1: reject invalids\n for (configKey in config) {\n if (!config.hasOwnProperty(configKey)) continue;\n if (!SpinWheel.config.hasOwnProperty(configKey)) throw \'error: invalid config key "\'+configKey+\'" in SpinWheel instantiation.\';\n } // end for\n // 2: check for requireds\n var requiredParams = [\'segmentTexts\'];\n for (var i = 0; i < requiredParams.length; ++i) {\n var requiredParam = requiredParams[i];\n if (!config.hasOwnProperty(requiredParam)) throw \'error: missing required config key \\\'\'+requiredParam+\'\\\' in SpinWheel instantiation.\';\n } // end for\n\n // store the per-instance config on the "this" object\n this.config = config;\n\n // capture the canvas jQuery object and init the canvas context\n // note: there should only ever be one SpinWheel instantiated per canvas, and there\'s only one canvas manipulated by a single SpinWheel instance\n this.$canvas = $canvas;\n this.canvasCtx = this.$canvas[0].getContext("2d");\n\n // initialize the segments, colors, and curAngle -- wrap this in a function for reusability\n this.reset();\n\n }; // end SpinWheel()\n\n // SpinWheel statics\n /* --- please look at the index.html source in order to understand what they do ---\n * outerRadius : the big circle border\n * innerRadius : the inner circle border\n * textRadius : How far the the text on the wheel locate from the center point\n * spinTrigger : the element that trigger the spin action\n * wheelBorderColor : what is the wheel border color\n * wheelBorderWidth : what is the "thickness" of the border of the wheel\n * wheelTextFont : what is the style of the text on the wheel\n * wheelTextColor : what is the color of the tet on the wheel\n * wheelTextShadow : what is the shadow for the text on the wheel\n * resultTextFont : it is not being used currently\n * arrowColor : what is the color of the arrow on the top\n * joiner : usually a form input where user can put in their name\n * addTrigger : what element will trigger the add participant\n * winnerDiv : the element you want to display the winner\n */\n SpinWheel.config = {\n \'segmentTexts\':[\'1\',\'2\',\'3\',\'4\',\'5\',\'6\'],\n \'colors\':[], // we\'ll allow omitted config colors; will just generate unspecifieds randomly on-the-fly whenever the wheel is reset\n \'outerRadius\':200,\n \'innerRadius\':3,\n \'textRadius\':160,\n \'spinTrigger\':\'.spin-trigger\',\n \'wheelBorderColor\':\'black\',\n \'wheelBorderWidth\':3,\n \'wheelTextFont\': \'bold 15px sans-serif\',\n \'wheelTextColor\':\'black\',\n \'wheelTextShadowColor\':\'rgb(220,220,220)\',\n \'resultTextFont\':\'bold 30px sans-serif\',\n \'arrowColor\':\'black\',\n \'addTrigger\':\'.add\',\n \'deleteTrigger\':\'.delete\',\n \'clearTrigger\':\'.clear\',\n \'resetTrigger\':\'.reset\',\n \'joiner\':\'.joiner\',\n \'colorer\':\'.colorer\',\n \'winnerDiv\':\'.winner\'\n };\n\n // SpinWheel instance methods\n SpinWheel.prototype.getConfig = function(key) {\n if (this.config.hasOwnProperty(key)) return this.config[key]; // per-instance config\n if (SpinWheel.config.hasOwnProperty(key)) return SpinWheel.config[key]; // default static config\n throw \'error: invalid config key "\'+key+\'" requested from SpinWheel::getConfig().\';\n } // end SpinWheel::getConfig()\n\n SpinWheel.prototype.init = function() {\n this.setup();\n this.drawWheel();\n }; // end SpinWheel::init()\n\n SpinWheel.prototype.setup = function() {\n\n var thisClosure = this; // necessary to allow callback functions to access the SpinWheel instance\n\n $(this.getConfig(\'spinTrigger\')).bind(\'click\', function(ev) { (function(ev, target ) {\n ev.preventDefault();\n this.spin();\n }).call(thisClosure, ev, this ); } );\n\n $(this.getConfig(\'addTrigger\')).bind(\'click\', function(ev) { (function(ev, target ) {\n ev.preventDefault();\n //var item = $(\'<li/>\').append($(this.getConfig(\'joiner\')).val());\n //$(params.paricipants).append(item);\n var $joiner = $(this.getConfig(\'joiner\'));\n var text = $joiner.val();\n if (text) { // don\'t add a segment with empty text\n var $color = $(this.getConfig(\'colorer\'));\n var color = $color.find(\'option:selected\').text();\n this.add(text, color );\n this.drawWheel();\n } // end if\n }).call(thisClosure, ev, this ); } );\n\n $(this.getConfig(\'deleteTrigger\')).bind(\'click\', function(ev) { (function(ev, target ) {\n ev.preventDefault();\n var $joiner = $(this.getConfig(\'joiner\')); // reuse joiner input box\n var text = $joiner.val();\n if (text) { // don\'t delete with empty pattern\n this.del(new RegExp(text));\n this.drawWheel();\n } // end if\n }).call(thisClosure, ev, this ); } );\n\n $(this.getConfig(\'clearTrigger\')).bind(\'click\', function(ev) { (function(ev, target ) {\n ev.preventDefault();\n this.clear();\n this.drawWheel();\n }).call(thisClosure, ev, this ); } );\n\n $(this.getConfig(\'resetTrigger\')).bind(\'click\', function(ev) { (function(ev, target ) {\n ev.preventDefault();\n this.reset();\n this.drawWheel();\n }).call(thisClosure, ev, this ); } );\n\n }; // end SpinWheel::setup()\n\n SpinWheel.prototype.clear = function() {\n\n // clear primary wheel state data\n this.segmentTexts = [];\n this.colors = [];\n this.curAngle = 0;\n\n // also, in case there was a spin in-progress, stop it\n this.stopRotateWheel();\n\n }; // end SpinWheel::clear()\n\n SpinWheel.prototype.reset = function() {\n\n // precomputations\n var segmentTexts = this.getConfig(\'segmentTexts\');\n var colors = this.getConfig(\'colors\');\n\n // copy the configured segment texts to an instance attribute; this distinction is necessary, since we allow the user to manipulate the segments after initial configuration / resetting\n this.segmentTexts = segmentTexts.slice();\n\n // generate initial colors\n this.colors = [];\n for (var i = 0; i < this.segmentTexts.length; ++i)\n this.colors.push(colors.length > i ? colors[i] : this.genHexColor());\n\n // initialize curAngle, which must always exist and track the current angle of the wheel\n this.curAngle = 0;\n\n // also, in case there was a spin in-progress, stop it\n this.stopRotateWheel();\n\n }; // end SpinWheel::reset()\n\n SpinWheel.prototype.add = function(text, color ) {\n // translate color \'auto\' to a generated color\n // also take anything invalid as auto\n if (!color || color === \'auto\')\n color = this.genHexColor();\n // we just store the text of each segment on the segmentTexts array\n this.segmentTexts.push(text);\n this.colors.push(color);\n }; // end SpinWheel::add()\n\n SpinWheel.prototype.del = function(pattern) {\n for (var i = 0; i < this.segmentTexts.length; ++i) {\n if (this.segmentTexts[i].match(pattern)) {\n this.segmentTexts.splice(i, 1 );\n if (this.colors.length > i) this.colors.splice(i, 1 ); // colors array can be short\n --i;\n } // end if\n } // end for\n }; // end SpinWheel::del()\n\n SpinWheel.prototype.spin = function() {\n // the following are per-spin ad hoc state vars that are initialized for each spin, thus there\'s no point in storing values for them on the config struct\n this.spinAngleStart = Math.random()*10 + 10;\n this.spinTimeTotal = Math.random()*3 + 4*1000;\n this.spinTime = 0;\n this.rotateWheel();\n }; // end SpinWheel::spin()\n\n SpinWheel.prototype.genHexColor = function() {\n\n var hexDigits = [\'0\',\'1\',\'2\',\'3\',\'4\',\'5\',\'6\',\'7\',\'8\',\'9\',\'a\',\'b\',\'c\',\'d\',\'e\',\'f\'];\n\n // 6 digits in a hex color spec\n var hexColor = \'#\';\n for (var i = 0; i < 6; ++i)\n hexColor = hexColor+hexDigits[Math.round(Math.random()*15)];\n\n return hexColor;\n\n }; // end SpinWheel::genHexColor()\n\n SpinWheel.prototype.rotateWheel = function() {\n\n // advance time\n this.spinTime += 30;\n\n // check for completion\n if (this.spinTime >= this.spinTimeTotal) {\n this.finishSpin();\n return;\n } // end if\n\n // advance angle\n var x = this.spinAngleStart - this.easeOut(this.spinTime, 0, this.spinAngleStart, this.spinTimeTotal );\n this.curAngle += (x*Math.PI/180);\n\n // redraw\n this.drawWheel();\n\n // schedule next rotation\n this.spinTimeout = setTimeout(this.rotateWheel.bind(this), 30 );\n\n }; // end SpinWheel::rotateWheel()\n\n SpinWheel.prototype.finishSpin = function() {\n\n // stop the rotation timeout chain\n this.stopRotateWheel();\n\n // precomputations\n var segmentNum = this.segmentTexts.length;\n var arc = 2*Math.PI/segmentNum;\n\n // hit segment calc\n var degrees = this.curAngle*180/Math.PI + 90;\n var arcd = arc*180/Math.PI;\n var index = Math.floor((360 - degrees%360)/arcd);\n\n // update the display\n this.canvasCtx.save();\n this.canvasCtx.font = this.getConfig(\'resultTextFont\');\n var text = this.segmentTexts[index];\n $(this.getConfig(\'winnerDiv\')).html(text).show();\n //canvasCtx.fillText(text, 250 - canvasCtx.measureText(text).width / 2, 250 + 10);\n this.canvasCtx.restore();\n\n }; // end SpinWheel::finishSpin()\n\n SpinWheel.prototype.stopRotateWheel = function() {\n\n // clear any existing timeout\n if (this.spinTimeout) {\n clearTimeout(this.spinTimeout);\n this.spinTimeout = null;\n } // end if\n\n }; // end SpinWheel::stopRotateWheel()\n\n SpinWheel.prototype.drawArrow = function() {\n this.canvasCtx.fillStyle = this.getConfig(\'arrowColor\');\n var outerRadius = this.getConfig(\'outerRadius\');\n this.canvasCtx.beginPath();\n this.canvasCtx.moveTo(250-4, 250-(outerRadius+15) );\n this.canvasCtx.lineTo(250+4, 250-(outerRadius+15) );\n this.canvasCtx.lineTo(250+4, 250-(outerRadius-15) );\n this.canvasCtx.lineTo(250+9, 250-(outerRadius-15) );\n this.canvasCtx.lineTo(250+0, 250-(outerRadius-23) );\n this.canvasCtx.lineTo(250-9, 250-(outerRadius-15) );\n this.canvasCtx.lineTo(250-4, 250-(outerRadius-15) );\n this.canvasCtx.lineTo(250-4, 250-(outerRadius+15) );\n this.canvasCtx.fill();\n }; // end SpinWheel::drawArrow()\n\n SpinWheel.prototype.drawWheel = function() {\n\n // precomputations\n var outerRadius = this.getConfig(\'outerRadius\');\n var innerRadius = this.getConfig(\'innerRadius\');\n var textRadius = this.getConfig(\'textRadius\');\n var segmentNum = this.segmentTexts.length;\n var arc = 2*Math.PI/segmentNum;\n\n // init canvas\n this.canvasCtx.strokeStyle = this.getConfig(\'wheelBorderColor\');\n this.canvasCtx.lineWidth = this.getConfig(\'wheelBorderWidth\');\n this.canvasCtx.font = this.getConfig(\'wheelTextFont\');\n this.canvasCtx.clearRect(0,0,500,500);\n\n // draw each segment\n for (var i = 0; i < segmentNum; ++i) {\n var text = this.segmentTexts[i];\n var angle = this.curAngle + i*arc;\n this.canvasCtx.fillStyle = this.colors[i];\n this.canvasCtx.beginPath();\n // ** arc(centerX, centerY, radius, startingAngle, endingAngle, antiClockwise);\n this.canvasCtx.arc(250, 250, outerRadius, angle, angle + arc, false );\n this.canvasCtx.arc(250, 250, innerRadius, angle + arc, angle, true );\n this.canvasCtx.stroke();\n this.canvasCtx.fill();\n this.canvasCtx.save();\n this.canvasCtx.shadowOffsetX = -1;\n this.canvasCtx.shadowOffsetY = -1;\n this.canvasCtx.shadowBlur = 1;\n this.canvasCtx.shadowColor = this.getConfig(\'wheelTextShadowColor\');\n this.canvasCtx.fillStyle = this.getConfig(\'wheelTextColor\');\n this.canvasCtx.translate(250 + Math.cos(angle + arc/2)*textRadius, 250 + Math.sin(angle + arc/2)*textRadius );\n this.canvasCtx.rotate(angle + arc/2 + Math.PI/2);\n this.canvasCtx.fillText(text, -this.canvasCtx.measureText(text).width/2, 0 );\n this.canvasCtx.restore();\n this.canvasCtx.closePath();\n } // end for\n\n this.drawArrow();\n\n }; // end SpinWheel::drawWheel()\n\n SpinWheel.prototype.easeOut = function(t,b,c,d) {\n var ts = (t/=d)*t;\n var tc = ts*t;\n return b+c*(tc + -3*ts + 3*t);\n }; // end SpinWheel::easeOut()\n\n // export the class\n window.SpinWheel = SpinWheel;\n\n})(jQuery);\nRun Code Online (Sandbox Code Playgroud)\n\n这是提供 jQuery 插件接口的薄包装器:
\n\n(function($) {\n\n // spinwheel() jQuery plugin loader\n $.fn.spinwheel = function(config) {\n\n var $canvas = this; // the "this" object is the jQuery object that wraps the canvas HTML DOM object\n\n // create a new SpinWheel instance and store it on the canvas DOM object, which is attached to the DOM tree, so it will be accessible by external code\n var spinWheel = new SpinWheel($canvas, config );\n $canvas[0].spinWheel = spinWheel;\n\n // initialize it\n spinWheel.init();\n\n }; // end $.fn.spinwheel()\n\n})(jQuery);\nRun Code Online (Sandbox Code Playgroud)\n\njQuery 插件实例化代码不会改变(除了我重命名了主配置参数):
\n\n$(document).ready(function() {\n $(\'.canvas\').spinwheel({\'segmentTexts\':[\'\xe2\x99\x88\',\'\xe2\x99\x89\',\'\xe2\x99\x8a\',\'\xe2\x99\x8b\',\'\xe2\x99\x8c\',\'\xe2\x99\x8d\',\'\xe2\x99\x8e\',\'\xe2\x99\x8f\',\'\xe2\x99\x90\',\'\xe2\x99\x91\',\'\xe2\x99\x92\',\'\xe2\x99\x93\']});\n});\nRun Code Online (Sandbox Code Playgroud)\n\n演示:
\n\nhttp://jsfiddle.net/kYvzd/212/
\n\n如果您有任何疑问,请告诉我。
\n| 归档时间: |
|
| 查看次数: |
390 次 |
| 最近记录: |