2014-11-29 10 views
9

Sto utilizzando il codice in questo JSFiddle per creare un gioco di tipo Ruota della fortuna. Quello che sto cercando di fare è lasciare che gli utenti scelgano i propri colori invece di generare colori casuali.Colore segmento HTML5?

ho aggiunto questo al codice 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> 

ho curato solo questa parte del 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];  
} 

ho aggiunto color = document.getElementById("colour").value;.

Il problema è che i colori non funzionano correttamente. Creerà correttamente il primo e il secondo segmento con il colore scelto, ma dal terzo segmento aggiungerà un segmento extra nero nella ruota.

Ho quasi cambiato ogni numero nel Javascript per individuare il problema e ancora non riesco a capirlo.

EDIT:

Per assicurarsi che non sto facendo alcuna confusione, quello che sto cercando di fare è per ogni nuovo segmento aggiunto alla ruota, ho bisogno di scegliere un nuovo colore.

+0

Hey Ho aggiornato alcuni di essi fammi sapere se vuoi collaborare a questo http://jsfiddle.net/kYvzd/173/ – Rafael

+0

@Rafael, ciò che hai fatto cambia il colore dell'intera ruota! ma ho bisogno di cambiare il colore dei segmenti/colonne .. quindi per ogni nuovo segmento aggiunto alla ruota, ho bisogno di scegliere un nuovo colore. – user3806613

+0

Capisco ma non sono riuscito a identificare dove era definito il colore del segmento della ruota. Per favore mostrami dov'è. – Rafael

risposta

4

Questo codice è un eccellente esempio del motivo per cui il modello di prototipo è molto più meglio del modello funzionale. Questo plugin è definito come una funzione di fabbrica de facto che dichiara un assortimento eterogeneo di vars di stato locale (startAngle, arc, pplArray, ecc.) Che vengono chiusi dai vari metodi che implementano il plug-in e, per di più, alcuni dei metodi sono definiti come valori letterali delle funzioni espressionati su una funzione locale (methods) utilizzando la sintassi letterale dell'oggetto, un metodo è definito come una funzione letterale espressionizzata e assegnato a una funzione singola locale (var rotateWheel) che viene issato in cima allo scope e chiuso da vari altri metodi, mentre il resto (genHex(), stopRotateWheel(), ecc.) viene definito come istruzioni di funzione che vengono issate in cima allo scope e chiuse da vari ot anche i suoi metodi. Che casino!

Inoltre, non tutte le chiusure di chiusura devono effettivamente essere chiuse, in quanto non devono effettivamente mantenere lo stato tra le chiamate di metodo; arc è un buon esempio di questo.

Ancora un'altra critica che può essere fatta qui è che qualche stato è effettivamente memorizzato nell'albero DOM, che è assurdo e non necessario. Mi riferisco specificamente a params.participants, che è un selettore jQuery che individua un elemento <ul> da qualche parte nel DOM (non importa dove), i cui figli <li> elementi vengono iterati per creare il testo del segmento di ruota dal loro innerHTML. Questi dati non devono essere memorizzati sul DOM; potrebbe essere memorizzato facilmente in un array su un'istanza di classe.

E poi ovviamente c'è la critica classica del modello funzionale che causa la definizione di nuovi oggetti funzione per ogni invocazione della funzione costruttore/fabbrica ($.fn.spinwheel() in questo caso), mentre il modello prototipo implicherebbe una singola definizione di ogni funzione sul prototipo di classe quando viene definita la classe.

In ogni caso, ho riscritto l'intero plug-in utilizzando il modello del prototipo.Il widget è ora definito come una funzione di costruzione globale su window.SpinWheel (ovviamente, potrebbe essere spostato in uno spazio dei nomi se lo si desidera). Tutti i metodi di istanza sono definiti utilizzando una sintassi uniforme assegnando valori letterali delle funzioni espressionati al prototipo di classe, SpinWheel.prototype.

In termini di dati di stato, c'è un po 'di dati di configurazione di default definiti staticamente sulla funzione di costruzione (fondamentalmente ho preso l'oggetto $.fn.spinwheel.default_options nel codice originale ed assegnato al SpinWheel.config, ma fissato un errore di ortografia e rimosso params.participants), quindi l'oggetto di configurazione passato come argomento alla funzione di costruzione viene acquisito (insieme al wrapper jQuery del nodo dell'area di disegno e al relativo oggetto di contesto) sull'istanza stessa come this.config. Infine, lo stato dell'istanza mutabile effettiva viene memorizzato come proprietà nell'istanza, ad esempio this.segmentTexts (il testo per ogni segmento), this.colors (i colori del segmento attualmente selezionati) e this.curAngle (l'angolo corrente della ruota). Ecco, in realtà solo tre tipi di dati: configurazione predefinita di default (fallback), configurazione di istanza e attributi di istanza. Tutti i metodi sono uniformi nel loro stile di definizione e hanno accesso identico a tutti i dati dell'oggetto.

Il plug-in jQuery è ora solo un involucro sottile attorno alla classe SpinWheel; in pratica, lo istanzia, lo collega alla tela di destinazione (non è veramente necessario a meno che il codice esterno non voglia accedervi dopo la creazione) e lo inizializzi. L'interfaccia del plugin è la stessa del codice originale, ma con il nuovo codice è anche possibile creare un'istanza dello SpinWheel indipendentemente dal framework del plugin jQuery, se lo si desidera (sebbene, ovviamente, si debba dire che l'implementazione dipende ancora da jQuery in fase di caricamento).

Inoltre, solo per il gusto di farlo, ho aggiunto Delete, Clear, e Reset pulsanti per dimostrare un maggiore controllo sul volante. Ora puoi cancellare segmenti con la corrispondenza regolare rispetto al testo, cancellare l'intera ruota in modo da poterla creare da zero e reimpostarla nella configurazione iniziale (anche se se non hai configurato i colori tramite la configurazione iniziale, verranno generati di nuovo in modo casuale, che sarà sicuramente diverso da quello che erano nella visualizzazione iniziale, ma è possibile configurare i colori iniziali se lo si desidera).

Ecco il nuovo HTML:

<div id="main"> 

    <div id="left-column"> 
     <form class="iform" action="#" method="get"> 
      <label for="joiner"></label> 
      <input id="joiner" name="joiner" class="joiner" placeholder="Please Enter your name" /> 
      <select id="colorer" name="colorer" class="colorer"> 
       <option value="">auto</option> 
       <option value="db0000">Red</option> 
       <option value="171515">Black</option> 
       <option value="008c0a">Green</option> 
      </select> 
      <button class="add">Add</button> 
      <button class="delete">Delete</button> 
      <button class="spin-trigger">Spin</button> 
      <button class="clear">Clear</button> 
      <button class="reset">Reset</button> 
     </form> 
     <canvas class="canvas" width="500" height="500"></canvas> 
    </div> 

    <div id="right-column"> 
     <p class="winner">The Winner is ... <span>&nbsp;</span></p> 
    </div> 

    <div style="clear:both"></div> 

</div> 

Ecco il nuovo IIFE che definisce la classe SpinWheel:

(function($) { 

    // define main SpinWheel constructor function 
    var SpinWheel = function($canvas, config) { 

     // validate config 
     // 1: reject invalids 
     for (configKey in config) { 
      if (!config.hasOwnProperty(configKey)) continue; 
      if (!SpinWheel.config.hasOwnProperty(configKey)) throw 'error: invalid config key "'+configKey+'" in SpinWheel instantiation.'; 
     } // end for 
     // 2: check for requireds 
     var requiredParams = ['segmentTexts']; 
     for (var i = 0; i < requiredParams.length; ++i) { 
      var requiredParam = requiredParams[i]; 
      if (!config.hasOwnProperty(requiredParam)) throw 'error: missing required config key \''+requiredParam+'\' in SpinWheel instantiation.'; 
     } // end for 

     // store the per-instance config on the "this" object 
     this.config = config; 

     // capture the canvas jQuery object and init the canvas context 
     // note: there should only ever be one SpinWheel instantiated per canvas, and there's only one canvas manipulated by a single SpinWheel instance 
     this.$canvas = $canvas; 
     this.canvasCtx = this.$canvas[0].getContext("2d"); 

     // initialize the segments, colors, and curAngle -- wrap this in a function for reusability 
     this.reset(); 

    }; // end SpinWheel() 

    // SpinWheel statics 
    /* --- please look at the index.html source in order to understand what they do --- 
     * outerRadius : the big circle border 
     * innerRadius : the inner circle border 
     * textRadius : How far the the text on the wheel locate from the center point 
     * spinTrigger : the element that trigger the spin action 
     * wheelBorderColor : what is the wheel border color 
     * wheelBorderWidth : what is the "thickness" of the border of the wheel 
     * wheelTextFont : what is the style of the text on the wheel 
     * wheelTextColor : what is the color of the tet on the wheel 
     * wheelTextShadow : what is the shadow for the text on the wheel 
     * resultTextFont : it is not being used currently 
     * arrowColor : what is the color of the arrow on the top 
     * joiner : usually a form input where user can put in their name 
     * addTrigger : what element will trigger the add participant 
     * winnerDiv : the element you want to display the winner 
     */ 
    SpinWheel.config = { 
     'segmentTexts':['1','2','3','4','5','6'], 
     'colors':[], // we'll allow omitted config colors; will just generate unspecifieds randomly on-the-fly whenever the wheel is reset 
     'outerRadius':200, 
     'innerRadius':3, 
     'textRadius':160, 
     'spinTrigger':'.spin-trigger', 
     'wheelBorderColor':'black', 
     'wheelBorderWidth':3, 
     'wheelTextFont': 'bold 15px sans-serif', 
     'wheelTextColor':'black', 
     'wheelTextShadowColor':'rgb(220,220,220)', 
     'resultTextFont':'bold 30px sans-serif', 
     'arrowColor':'black', 
     'addTrigger':'.add', 
     'deleteTrigger':'.delete', 
     'clearTrigger':'.clear', 
     'resetTrigger':'.reset', 
     'joiner':'.joiner', 
     'colorer':'.colorer', 
     'winnerDiv':'.winner' 
    }; 

    // SpinWheel instance methods 
    SpinWheel.prototype.getConfig = function(key) { 
     if (this.config.hasOwnProperty(key)) return this.config[key]; // per-instance config 
     if (SpinWheel.config.hasOwnProperty(key)) return SpinWheel.config[key]; // default static config 
     throw 'error: invalid config key "'+key+'" requested from SpinWheel::getConfig().'; 
    } // end SpinWheel::getConfig() 

    SpinWheel.prototype.init = function() { 
     this.setup(); 
     this.drawWheel(); 
    }; // end SpinWheel::init() 

    SpinWheel.prototype.setup = function() { 

     var thisClosure = this; // necessary to allow callback functions to access the SpinWheel instance 

     $(this.getConfig('spinTrigger')).bind('click', function(ev) { (function(ev, target) { 
      ev.preventDefault(); 
      this.spin(); 
     }).call(thisClosure, ev, this); }); 

     $(this.getConfig('addTrigger')).bind('click', function(ev) { (function(ev, target) { 
      ev.preventDefault(); 
      //var item = $('<li/>').append($(this.getConfig('joiner')).val()); 
      //$(params.paricipants).append(item); 
      var $joiner = $(this.getConfig('joiner')); 
      var text = $joiner.val(); 
      if (text) { // don't add a segment with empty text 
       var $color = $(this.getConfig('colorer')); 
       var color = $color.find('option:selected').text(); 
       this.add(text, color); 
       this.drawWheel(); 
      } // end if 
     }).call(thisClosure, ev, this); }); 

     $(this.getConfig('deleteTrigger')).bind('click', function(ev) { (function(ev, target) { 
      ev.preventDefault(); 
      var $joiner = $(this.getConfig('joiner')); // reuse joiner input box 
      var text = $joiner.val(); 
      if (text) { // don't delete with empty pattern 
       this.del(new RegExp(text)); 
       this.drawWheel(); 
      } // end if 
     }).call(thisClosure, ev, this); }); 

     $(this.getConfig('clearTrigger')).bind('click', function(ev) { (function(ev, target) { 
      ev.preventDefault(); 
      this.clear(); 
      this.drawWheel(); 
     }).call(thisClosure, ev, this); }); 

     $(this.getConfig('resetTrigger')).bind('click', function(ev) { (function(ev, target) { 
      ev.preventDefault(); 
      this.reset(); 
      this.drawWheel(); 
     }).call(thisClosure, ev, this); }); 

    }; // end SpinWheel::setup() 

    SpinWheel.prototype.clear = function() { 

     // clear primary wheel state data 
     this.segmentTexts = []; 
     this.colors = []; 
     this.curAngle = 0; 

     // also, in case there was a spin in-progress, stop it 
     this.stopRotateWheel(); 

    }; // end SpinWheel::clear() 

    SpinWheel.prototype.reset = function() { 

     // precomputations 
     var segmentTexts = this.getConfig('segmentTexts'); 
     var colors = this.getConfig('colors'); 

     // 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 
     this.segmentTexts = segmentTexts.slice(); 

     // generate initial colors 
     this.colors = []; 
     for (var i = 0; i < this.segmentTexts.length; ++i) 
      this.colors.push(colors.length > i ? colors[i] : this.genHexColor()); 

     // initialize curAngle, which must always exist and track the current angle of the wheel 
     this.curAngle = 0; 

     // also, in case there was a spin in-progress, stop it 
     this.stopRotateWheel(); 

    }; // end SpinWheel::reset() 

    SpinWheel.prototype.add = function(text, color) { 
     // translate color 'auto' to a generated color 
     // also take anything invalid as auto 
     if (!color || color === 'auto') 
      color = this.genHexColor(); 
     // we just store the text of each segment on the segmentTexts array 
     this.segmentTexts.push(text); 
     this.colors.push(color); 
    }; // end SpinWheel::add() 

    SpinWheel.prototype.del = function(pattern) { 
     for (var i = 0; i < this.segmentTexts.length; ++i) { 
      if (this.segmentTexts[i].match(pattern)) { 
       this.segmentTexts.splice(i, 1); 
       if (this.colors.length > i) this.colors.splice(i, 1); // colors array can be short 
       --i; 
      } // end if 
     } // end for 
    }; // end SpinWheel::del() 

    SpinWheel.prototype.spin = function() { 
     // 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 
     this.spinAngleStart = Math.random()*10 + 10; 
     this.spinTimeTotal = Math.random()*3 + 4*1000; 
     this.spinTime = 0; 
     this.rotateWheel(); 
    }; // end SpinWheel::spin() 

    SpinWheel.prototype.genHexColor = function() { 

     var hexDigits = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']; 

     // 6 digits in a hex color spec 
     var hexColor = '#'; 
     for (var i = 0; i < 6; ++i) 
      hexColor = hexColor+hexDigits[Math.round(Math.random()*15)]; 

     return hexColor; 

    }; // end SpinWheel::genHexColor() 

    SpinWheel.prototype.rotateWheel = function() { 

     // advance time 
     this.spinTime += 30; 

     // check for completion 
     if (this.spinTime >= this.spinTimeTotal) { 
      this.finishSpin(); 
      return; 
     } // end if 

     // advance angle 
     var x = this.spinAngleStart - this.easeOut(this.spinTime, 0, this.spinAngleStart, this.spinTimeTotal); 
     this.curAngle += (x*Math.PI/180); 

     // redraw 
     this.drawWheel(); 

     // schedule next rotation 
     this.spinTimeout = setTimeout(this.rotateWheel.bind(this), 30); 

    }; // end SpinWheel::rotateWheel() 

    SpinWheel.prototype.finishSpin = function() { 

     // stop the rotation timeout chain 
     this.stopRotateWheel(); 

     // precomputations 
     var segmentNum = this.segmentTexts.length; 
     var arc = 2*Math.PI/segmentNum; 

     // hit segment calc 
     var degrees = this.curAngle*180/Math.PI + 90; 
     var arcd = arc*180/Math.PI; 
     var index = Math.floor((360 - degrees%360)/arcd); 

     // update the display 
     this.canvasCtx.save(); 
     this.canvasCtx.font = this.getConfig('resultTextFont'); 
     var text = this.segmentTexts[index]; 
     $(this.getConfig('winnerDiv')).html(text).show(); 
     //canvasCtx.fillText(text, 250 - canvasCtx.measureText(text).width/2, 250 + 10); 
     this.canvasCtx.restore(); 

    }; // end SpinWheel::finishSpin() 

    SpinWheel.prototype.stopRotateWheel = function() { 

     // clear any existing timeout 
     if (this.spinTimeout) { 
      clearTimeout(this.spinTimeout); 
      this.spinTimeout = null; 
     } // end if 

    }; // end SpinWheel::stopRotateWheel() 

    SpinWheel.prototype.drawArrow = function() { 
     this.canvasCtx.fillStyle = this.getConfig('arrowColor'); 
     var outerRadius = this.getConfig('outerRadius'); 
     this.canvasCtx.beginPath(); 
     this.canvasCtx.moveTo(250-4, 250-(outerRadius+15)); 
     this.canvasCtx.lineTo(250+4, 250-(outerRadius+15)); 
     this.canvasCtx.lineTo(250+4, 250-(outerRadius-15)); 
     this.canvasCtx.lineTo(250+9, 250-(outerRadius-15)); 
     this.canvasCtx.lineTo(250+0, 250-(outerRadius-23)); 
     this.canvasCtx.lineTo(250-9, 250-(outerRadius-15)); 
     this.canvasCtx.lineTo(250-4, 250-(outerRadius-15)); 
     this.canvasCtx.lineTo(250-4, 250-(outerRadius+15)); 
     this.canvasCtx.fill(); 
    }; // end SpinWheel::drawArrow() 

    SpinWheel.prototype.drawWheel = function() { 

     // precomputations 
     var outerRadius = this.getConfig('outerRadius'); 
     var innerRadius = this.getConfig('innerRadius'); 
     var textRadius = this.getConfig('textRadius'); 
     var segmentNum = this.segmentTexts.length; 
     var arc = 2*Math.PI/segmentNum; 

     // init canvas 
     this.canvasCtx.strokeStyle = this.getConfig('wheelBorderColor'); 
     this.canvasCtx.lineWidth = this.getConfig('wheelBorderWidth'); 
     this.canvasCtx.font = this.getConfig('wheelTextFont'); 
     this.canvasCtx.clearRect(0,0,500,500); 

     // draw each segment 
     for (var i = 0; i < segmentNum; ++i) { 
      var text = this.segmentTexts[i]; 
      var angle = this.curAngle + i*arc; 
      this.canvasCtx.fillStyle = this.colors[i]; 
      this.canvasCtx.beginPath(); 
      // ** arc(centerX, centerY, radius, startingAngle, endingAngle, antiClockwise); 
      this.canvasCtx.arc(250, 250, outerRadius, angle, angle + arc, false); 
      this.canvasCtx.arc(250, 250, innerRadius, angle + arc, angle, true); 
      this.canvasCtx.stroke(); 
      this.canvasCtx.fill(); 
      this.canvasCtx.save(); 
      this.canvasCtx.shadowOffsetX = -1; 
      this.canvasCtx.shadowOffsetY = -1; 
      this.canvasCtx.shadowBlur = 1; 
      this.canvasCtx.shadowColor = this.getConfig('wheelTextShadowColor'); 
      this.canvasCtx.fillStyle  = this.getConfig('wheelTextColor'); 
      this.canvasCtx.translate(250 + Math.cos(angle + arc/2)*textRadius, 250 + Math.sin(angle + arc/2)*textRadius); 
      this.canvasCtx.rotate(angle + arc/2 + Math.PI/2); 
      this.canvasCtx.fillText(text, -this.canvasCtx.measureText(text).width/2, 0); 
      this.canvasCtx.restore(); 
      this.canvasCtx.closePath(); 
     } // end for 

     this.drawArrow(); 

    }; // end SpinWheel::drawWheel() 

    SpinWheel.prototype.easeOut = function(t,b,c,d) { 
     var ts = (t/=d)*t; 
     var tc = ts*t; 
     return b+c*(tc + -3*ts + 3*t); 
    }; // end SpinWheel::easeOut() 

    // export the class 
    window.SpinWheel = SpinWheel; 

})(jQuery); 

Ed ecco l'involucro sottile che fornisce l'interfaccia plugin per jQuery:

(function($) { 

    // spinwheel() jQuery plugin loader 
    $.fn.spinwheel = function(config) { 

     var $canvas = this; // the "this" object is the jQuery object that wraps the canvas HTML DOM object 

     // 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 
     var spinWheel = new SpinWheel($canvas, config); 
     $canvas[0].spinWheel = spinWheel; 

     // initialize it 
     spinWheel.init(); 

    }; // end $.fn.spinwheel() 

})(jQuery); 

Il codice di istanziazione per jQuery-plugin non cambia (eccetto Ho rinominato il parametro di configurazione primario):

$(document).ready(function() { 
    $('.canvas').spinwheel({'segmentTexts':['♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓']}); 
}); 

Demo:

http://jsfiddle.net/kYvzd/212/

fatemi sapere se avete domande.

0

Prova ad aggiungere qualcosa di simile alla Colorwheel Raffaello e associarlo a un campo di input forma (forse anche un nascosto uno)

Poi hanno il codice di colore in questo modo:

function genHex(){ 
     // change #colorcode to the id of your input field 
     var value = $('#colorcode').val(); 
     // if no code has been selected by user return a generated colour code 
     if(value === '') { 
      var colors=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"], color = "", digit = [], i; 

      for (i=0;i<6;i++){ 
       digit[i]=colors[Math.round(Math.random()*14)];    
       color = color+digit[i];  
      } 

      if($.inArray(color, colorCache) > -1){ 
       genHex(); 
      } else { 
       colorCache.push('#'+color); 
       return '#'+color; 
      } 
     } 
     else { 
      return value; 
     } 
Problemi correlati