原文来源:https://css-tricks.com/lots-of-ways-to-use-math-random-in-javascript/
Math.random()
是JavaScript中的一个API。能够为您提供一个随机数的功能。 返回的数字将介于0(包括0)和1(不包括1)之间。
Math.random()//返回一个小于1的随机数(不包含1)
Math.random()
函数对于游戏,动画,随机数据,艺术效果,随机文本生成等许多方面非常有用! 它可以用于Web开发,移动应用程序,计算机程序和视频游戏。
每当我们在工作中需要使用随机数据时,就可以使用此功能! 让我们看一下我们使用它的八种不同方式。 这些示例均来自不同的作者,利用这一API进行了一些有趣的创作。
<canvas id=c>canvas>
canvas {
position: absolute;
top: 0;
left: 0;
}
var w = c.width = window.innerWidth,
h = c.height = window.innerHeight,
ctx = c.getContext( '2d' ),
opts = {
len: 20,
count: 50,
baseTime: 10,
addedTime: 10,
dieChance: .05,
spawnChance: 1,
sparkChance: .1,
sparkDist: 10,
sparkSize: 2,
color: 'hsl(hue,100%,light%)',
baseLight: 50,
addedLight: 10, // [50-10,50+10]
shadowToTimePropMult: 6,
baseLightInputMultiplier: .01,
addedLightInputMultiplier: .02,
cx: w / 2,
cy: h / 2,
repaintAlpha: .04,
hueChange: .1
},
tick = 0,
lines = [],
dieX = w / 2 / opts.len,
dieY = h / 2 / opts.len,
baseRad = Math.PI * 2 / 6;
ctx.fillStyle = 'black';
ctx.fillRect( 0, 0, w, h );
function loop() {
window.requestAnimationFrame( loop );
++tick;
ctx.globalCompositeOperation = 'source-over';
ctx.shadowBlur = 0;
ctx.fillStyle = 'rgba(0,0,0,alp)'.replace( 'alp', opts.repaintAlpha );
ctx.fillRect( 0, 0, w, h );
ctx.globalCompositeOperation = 'lighter';
if( lines.length < opts.count && Math.random() < opts.spawnChance )
lines.push( new Line );
lines.map( function( line ){ line.step(); } );
}
function Line(){
this.reset();
}
Line.prototype.reset = function(){
this.x = 0;
this.y = 0;
this.addedX = 0;
this.addedY = 0;
this.rad = 0;
this.lightInputMultiplier = opts.baseLightInputMultiplier + opts.addedLightInputMultiplier * Math.random();
this.color = opts.color.replace( 'hue', tick * opts.hueChange );
this.cumulativeTime = 0;
this.beginPhase();
}
Line.prototype.beginPhase = function(){
this.x += this.addedX;
this.y += this.addedY;
this.time = 0;
this.targetTime = ( opts.baseTime + opts.addedTime * Math.random() ) |0;
this.rad += baseRad * ( Math.random() < .5 ? 1 : -1 );
this.addedX = Math.cos( this.rad );
this.addedY = Math.sin( this.rad );
if( Math.random() < opts.dieChance || this.x > dieX || this.x < -dieX || this.y > dieY || this.y < -dieY )
this.reset();
}
Line.prototype.step = function(){
++this.time;
++this.cumulativeTime;
if( this.time >= this.targetTime )
this.beginPhase();
var prop = this.time / this.targetTime,
wave = Math.sin( prop * Math.PI / 2 ),
x = this.addedX * wave,
y = this.addedY * wave;
ctx.shadowBlur = prop * opts.shadowToTimePropMult;
ctx.fillStyle = ctx.shadowColor = this.color.replace( 'light', opts.baseLight + opts.addedLight * Math.sin( this.cumulativeTime * this.lightInputMultiplier ) );
ctx.fillRect( opts.cx + ( this.x + x ) * opts.len, opts.cy + ( this.y + y ) * opts.len, 2, 2 );
if( Math.random() < opts.sparkChance )
ctx.fillRect( opts.cx + ( this.x + x ) * opts.len + Math.random() * opts.sparkDist * ( Math.random() < .5 ? 1 : -1 ) - opts.sparkSize / 2, opts.cy + ( this.y + y ) * opts.len + Math.random() * opts.sparkDist * ( Math.random() < .5 ? 1 : -1 ) - opts.sparkSize / 2, opts.sparkSize, opts.sparkSize )
}
loop();
window.addEventListener( 'resize', function(){
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
ctx.fillStyle = 'black';
ctx.fillRect( 0, 0, w, h );
opts.cx = w / 2;
opts.cy = h / 2;
dieX = w / 2 / opts.len;
dieY = h / 2 / opts.len;
});
生成一个对象并使其动画化,我们使用Math.random
。霓虹灯线形成自发的六边形,同时利用随机化产生火花效果。
<header>
<h1>Random Musich1>
<p>Using the characteristics of <em>Auld Lang Syneem>p>
header>
<section id="staff">
section>
<div class="triggers">
<a id="play">
<span class="play">span>
<span class="stop">span>
a>
<a id="new">New Songa>
div>
import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic|Inconsolata);
$c-primary: #545454;
$c-dark: darken($c-primary,10%);
$c-black: darken($c-dark,20%);
$c-med: lighten($c-primary,10%);
$c-gray: #c0c0c0;
$c-light: #f0f0f0;
$c-white: #ffffff;
$c-off-white: transparentize($c-white, 0.8);
$c-barely-white: transparentize($c-white, 0.9);
$clef_h: 100px;
#staff {
height: $clef_h * 2;
width: 95%;
margin: 4em auto;
position: relative;
.clef {
height: $clef_h;
width: 100%;
position: relative;
margin-bottom: 24px;
.beat {
display: block;
position: absolute;
top: 0; bottom: 0;
transition: background 200ms;
&.sus {
z-index: 1;
}
&.chord {
z-index: 2;
font-size: 10px;
$note-di: 4px;
.note {
transition: transform 500ms, background 100ms;
position: absolute;
left: 50%;
transform: translate3d(-50%, -50%, 0) scale(1);
background-color: $c-white;
width: $note-di;
height: $note-di;
border-radius: 50%;
@for $i from 0 through 36 {
&.note-#{$i} {
$ratio: $i / 36;
top: $ratio * 100%;
background-color: hsl($ratio * 360, 50%, 40%);
}
}
}
}
&.active {
transition-duration: 50ms;
/* background: $c-barely-white; */
z-index: 9;
.note {
transform: translate3d(-50%, -50%, 0) scale(2);
@for $i from 0 through 36 {
&.note-#{$i} {
$ratio: $i / 36;
background-color: hsl($ratio * 360, 100%, 60%);
}
}
}
}
}
}
}
.triggers {
width: 100%;
text-align: center;
$button-di: 40px;
a {
color: $c-white;
font-weight: 100;
cursor: pointer;
display: block;
margin: 0 auto;
text-transform: uppercase;
opacity: 0.8;
width: 100px;
transition: opacity 200ms;
font-size: 2em;
&.inactive {
opacity: 0.3;
pointer-events: none;
}
&:hover, &:active {
opacity: 1;
}
play {
width: $button-di;
height: $button-di;
line-height: $button-di;
border-radius: 50%;
background-color: $c-off-white;
margin-bottom: 12px;
position: relative;
.play, .stop {
display: block;
position: absolute;
top: 50%;
left: 50%;
}
.play {
border-left: 8px solid $c-white;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
transform: translate3d(-40%, -50%, 0);
}
.stop {
background-color: $c-white;
height: 10px;
width: 10px;
transform: translate3d(-50%, -50%, 0);
display: none;
}
&.playing {
.play { display: none;}
.stop { display: block;}
}
}
new {
font-size: 0.875em;
}
}
}
body {
background-color: $c-black;
font-family: 'Source Sans Pro';
font-weight: 300;
color: $c-white;
header, article, #staff {
transition: opacity 300ms;
}
#staff {
opacity: 0.5;
}
&.playing {
header, article {
opacity: 0.4;
}
#staff {
opacity: 1;
}
}
}
pre {
font-family: 'Inconsolata';
font-size: 0.9em;
background-color: $c-barely-white;
box-sizing: border-box;
padding: 12px;
em {
font-style: normal;
color: darken($c-white,70%);
}
}
code {
font-family: 'Inconsolata';
font-size: 0.9em;
padding: 6px;
white-space: nowrap;
background-color: $c-off-white;
}
h1, h2, h3 {
font-weight: 300;
text-transform: uppercase;
letter-spacing: 0.125em;
}
h1 {
margin-bottom: 0.25em;
}
h1 { font-size: 1.4em; }
h2 { font-size: 1.1em; }
h3 { font-size: 0.9em; }
h1, h2 {
text-align: center;
}
header {
text-align: center;
margin-top: 4em;
h1, p {
margin: 0;
}
p {
margin-top: 0.5em;
color: $c-light;
}
}
article {
width: 90%;
max-width: 600px;
margin: 8em auto;
line-height: 1.8;
text-align: justify;
text-justify: inter-word;
h1,h2 {
margin-top: 1em;
}
h1, h2, h3 {
margin-bottom: 0;
& + p {
margin-top: 0;
}
}
a {
color: $c-white;
}
}
###
///
random music generator
jake albaugh
///
###
###
# globals
###
# generate a package of chances and values based on an object containing multiple possible zero values
ChancePkg = (vals) ->
# generating vals and their chances of occuring
new_vals = []
# get total number of vals
vals_count = 0
for value of vals
if vals.hasOwnProperty(value) && vals[value] > 0
vals_count += vals[value]
new_vals.push [value, vals[value]]
# go through new vals and generate chance for each value
new_vals_chances = []
total = 0
for val, i in new_vals
# relative amount for random selection
amount = total + ( (val[1] / vals_count ) * 100000)
# push amount into chances array
new_vals_chances.push amount
# set value to be the value, no longer an array of data
new_vals[i] = parseInt(val[0])
# increase base total
total = amount
# return package which has array for both non-zero vals and their corrosponding chance
return {chances: new_vals_chances, vals: new_vals}
# get the sound to silence ratio at the smallest scale
getSoundRatio = (measures, beats, values) ->
# generating vals and their chances of occuring
new_values = []
# get total number of vals
values_count = 0
for value of values
if values.hasOwnProperty(value) && values[value] > 0
values_count += values[value]
new_values.push [value, values[value]]
# resolution is the smallest sized note
resolution = (beats * (new_values[new_values.length - 1][1] / 4))
# possible is how many resolution sized notes are in the piece
possible = measures * (beats * (resolution / 4))
# usage to be used in the loop
usage = 0
for value in new_values
# how many resolution values are in a single value? (ie. how many sixteenth notes are in a quarter note)
res_value = (1 / value[0]) * resolution
# use resolution value * occurances
usage += res_value * value[1]
return usage / possible
# generate clef values based on data
Piece = (piece) ->
{measures, beats, treble_clef, bass_clef, composition} = piece
this.treble_clef = {
# sound ratio is the presence of sound divided by the presenece of silence in the analyzed piece
sound_ratio: getSoundRatio(measures, beats, treble_clef.values)
# value package has array for both non-zero values and their corrosponding chance
values_pkg: new ChancePkg(treble_clef.values)
# interval package has array for both non-zero intervals and their corrosponding chance
intervals_pkg: new ChancePkg(treble_clef.intervals)
# octaves package has array for both non-zero octaves and their corrosponding chance
octaves_pkg: new ChancePkg(treble_clef.octaves)
# chords package has array for both non-zero chords and their corrosponding chance
chords_pkg: new ChancePkg(treble_clef.chords)
# setting the base octave
base_octave: 5
# tone
wave: 'sine'
# gain
gain: 0.3
}
this.bass_clef = {
# sound ratio is the presence of sound divided by the presenece of silence in the analyzed piece
sound_ratio: getSoundRatio(measures, beats, bass_clef.values)
# value package has array for both non-zero values and their corrosponding chance
values_pkg: new ChancePkg(bass_clef.values)
# interval package has array for both non-zero intervals and their corrosponding chance
intervals_pkg: new ChancePkg(bass_clef.intervals)
# octaves package has array for both non-zero octaves and their corrosponding chance
octaves_pkg: new ChancePkg(bass_clef.octaves)
# chords package has array for both non-zero chords and their corrosponding chance
chords_pkg: new ChancePkg(bass_clef.chords)
# setting the base octave
base_octave: 3
# tone
wave: 'sine'
# gain
gain: 0.3
}
this.composition = composition
return
# initiate audio context
audio_context = undefined
(init = (g) ->
try
# "crossbrowser" audio context.
audio_context = new (g.AudioContext or g.webkitAudioContext)
catch e
console.log "No web audio oscillator support in this browser"
return
) window
# oscillator prototype
Oscillator = (tone) ->
max_gain = tone.gain
this.tone = tone
this.play = () ->
# capturing current time for play start and stop
current_time = audio_context.currentTime
# create oscillator
o = audio_context.createOscillator()
# create gain
gn = audio_context.createGain()
# set waveform
o.type = this.tone.wave
# set frequency
if this.tone.frequency
o.frequency.value = this.tone.frequency
# connect oscillator to gain
o.connect gn
# connect gain to output
gn.connect audio_context.destination
# set gain amount
gn.gain.value = (max_gain / this.tone.vol) / 1
# play it
o.start(current_time)
# stop after sustain
o.stop(current_time + this.tone.sustain)
return this
# note frequencies array of octave arrays that start on c (our root note)
freqs = [
[16.351, 17.324, 18.354, 19.445, 20.601, 21.827, 23.124, 24.499, 25.956, 27.5, 29.135, 30.868]
[32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735]
[65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471]
[130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942]
[261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883]
[523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767]
[1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533]
[2093.005, 2217.461, 2349.318, 2489.016, 2637.021, 2793.826, 2959.955, 3135.964, 3322.438, 3520, 3729.31, 3951.066]
[4186.009, 4434.922, 4698.636, 4978.032, 5274.042, 5587.652, 5919.91, 6271.928, 6644.876, 7040, 7458.62, 7902.132]
[8372.018, 8869.844, 9397.272, 9956.064, 10548.084, 11175.304, 11839.82, 12543.856, 13289.752, 14080, 14917.24, 15804.264]
]
# get random val from chance package
randomVal = (chance_pkg) ->
random = Math.random() * 100000
for chance, i in chance_pkg.chances
return chance_pkg.vals[i] if random < chance
return
# get sequence function
getSequence = (clef, composition) ->
# get the duration in smallest resolution amount
duration = composition.measures * (composition.beats * (composition.resolution / 4))
# note sequence
sequence = []
# while there is still duration
while duration > 0
# random hit
random = Math.random()
# if a hit
if random < clef.sound_ratio
# random chord note count
chord = randomVal(clef.chords_pkg)
# random length for the chord
value = randomVal(clef.values_pkg)
# if there isnt enough space
if ((1 / value) / (1 / composition.resolution)) >= duration
# make it the length of remaining
value = ((1 / duration) / (1 / composition.resolution))
# the new chord
new_chord = {length: (1 / value), notes: []}
# for each note in the chord
for note in [1..chord]
# get a random interval
interval = randomVal(clef.intervals_pkg)
# get the random octave
octave = randomVal(clef.octaves_pkg)
# make intervale relative to key
interval += composition.root
# if key pushes interval into new octave
if interval > 12
interval -= 12
# make the octave relative to the clef's octave
new_octave = clef.base_octave + ((2 - octave) * -1)
# the frequency of the note
note = freqs[new_octave - 1][interval]
# if note doesnt already exist in chord
if new_chord.notes.indexOf(note) == -1
# push the frequency into the chord's notes
new_chord.notes.push {freq: note, int: interval, octave: octave}
else
# duplicate note in chord, ignoring it for now.
console.log 'duplicate note in chord, ignoring it for now.'
# push the chord into the sequence
sequence.push new_chord
# get values resolution-relative value
res_value = Math.floor((1 / value) / (1 / composition.resolution))
# if we need to add sustain notes
if res_value > 1
# add blank values
for blank in [1..res_value - 1]
sequence.push 'sus'
# subtract from the duration
duration -= res_value
else
# it was a miss, add a zero to the sequence
sequence.push 0
# subtract tick from duration
duration--
return sequence
Note = (tone) ->
this.osc = () ->
return new Oscillator(tone)
returns
###
# data (to be derived from an analyzed piece of music)
###
piece = {
# piece data (auld lang syne)
measures: 16 # measures in analyzed piece
beats: 4 # beats per measure in analyzed piece
# all our analysis will be relative to each clef
treble_clef: {
# note values are the duration of the note / chord.
# this is a map of how many times each value appears in the analyzed data
values: {
1: 0 # whole
1.5: 4 # dotted half
2: 5 # half
3: 12 # dotted quarter
4: 28 # quarter
6: 0 # dotted eighth
8: 12 # eighth
12: 0 # dotted sixteenth
16: 0 # sixteenth
32: 0 # thirty-second
}
# relative to the key, the intervals are steps between notes and the root (no octaves)
# this includes all single notes and instances of a note in a chord
# this is a map of how many times each interval appears in the analyzed data
intervals: {
0: 32 # root / perfect unison (F)
1: 0 # minor second (F#)
2: 9 # major second (G)
3: 0 # minor third (G#)
4: 13 # major third (A)
5: 0 # perfect fourth (A#)
6: 6 # tritone (B)
7: 13 # perfect fifth (C)
8: 0 # minor sixth (C#)
9: 15 # major sixth (D)
10: 0 # minor seventh (D#)
11: 12 # major seventh (E)
}
# octaves are how many times a note appears in each octave (relative to the key)
octaves: {
1: 37 # clef - 1
2: 67 # clef
3: 1 # clef + 1
}
# instead of using proper chords (dyad, triad, 7th, 9th, and 11th), we only analyze how many notes are in the chord
# this is a map of how many times each chord size appears in the analyzed data
chords: {
1: 9 # 1 note
2: 47 # 2 notes
3: 0 # 3 notes
4: 0 # 4 notes
5: 0 # 5 notes
}
}
bass_clef: {
# note values are the duration of the note / chord.
# this is a map of how many times each value appears in the analyzed data
values: {
1: 0 # whole
1.5: 4 # dotted half
2: 5 # half
3: 12 # dotted quarter
4: 28 # quarter
6: 0 # dotted eighth
8: 12 # eighth
12: 0 # dotted sixteenth
16: 0 # sixteenth
32: 0 # thirty-second
}
# relative to the key, the intervals are steps between notes and the root (no octaves)
# this includes all single notes and instances of a note in a chord
# this is a map of how many times each interval appears in the analyzed data
intervals: {
0: 25 # root / perfect unison (F)
1: 0 # minor second (F#)
2: 1 # major second (G)
3: 0 # minor third (G#)
4: 17 # major third (A)
5: 2 # perfect fourth (A#)
6: 0 # tritone (B)
7: 38 # perfect fifth (C)
8: 1 # minor sixth (C#)
9: 4 # major sixth (D)
10: 0 # minor seventh (D#)
11: 2 # major seventh (E)
}
# octaves are how many times a note appears in each octave (relative to the key)
octaves: {
1: 2 # clef - 1
2: 53 # clef
3: 50 # clef + 1
}
# instead of using proper chords (dyad, triad, 7th, 9th, and 11th), we only analyze how many notes are in the chord
# this is a map of how many times each chord size appears in the analyzed data
chords: {
1: 9 # 1 note
2: 46 # 2 notes
3: 0 # 3 notes
4: 0 # 4 notes
5: 0 # 5 notes
}
}
# defining the desired output composition data
composition: {
measures: 32 # bars to generate
beats: 4 # beats per measure
tempo: 120 # tempo
resolution: 16 # resolution scale of piece
root: 5 # root of key (0-11), 0 is 'C'
}
}
# lets analyze our piece data!
p = new Piece(piece)
# sequence stores
trebleSequence = undefined
bassSequence = undefined
# get sequences
getSequences = () ->
# creating our treble clef
trebleSequence = getSequence(p.treble_clef, p.composition)
bassSequence = getSequence(p.bass_clef, p.composition)
draw_sequences()
getSequenceHtml = (name, composition, sequence) ->
$seq_html = $('+ name + ' clef">')
beats = composition.measures * (composition.beats * (composition.resolution / 4))
width_increment = 1 / beats * 100
left = 0
for chord in sequence
if typeof chord == "object"
width = width_increment * (chord.length / (1 / composition.resolution))
width = width_increment
classname = 'chord value-' + Math.round( (1 / chord.length) * 100) / 100
classname = classname.replace('.', '-')
notes = ''
for note in chord.notes
out_of_36 = 36 - (note.int + ((note.octave - 1) * 12))
notes += '+ out_of_36 + '">'
else if chord == 'sus'
classname = 'sus'
width = width_increment
notes = ''
else
width = width_increment
classname = 'blank'
notes = ''
$seq_html.append '+ classname + '" style="width: ' + width + '%; left: ' + left + '%">' + notes + ''
left += width
return $seq_html
draw_sequences = () ->
composition = p.composition
$staffs = $('')
$staffs.append getSequenceHtml('treble', composition, trebleSequence)
$staffs.append getSequenceHtml('bass', composition, bassSequence)
$('#staff').html $staffs
return
performance_interval = undefined
# play sequences
playSequences = () ->
composition = p.composition
sequences = [trebleSequence, bassSequence]
waves = [p.treble_clef.wave, p.bass_clef.wave]
gains = [p.treble_clef.gain, p.bass_clef.gain]
# total beat count
beats = composition.measures * (composition.beats * (composition.resolution / 4))
# css width of beat
beat_width = 100 / beats
# relative index
index = 0
# tempo to ms
tempo_time = 60000 / composition.tempo
# single beat instance
next_beat = () ->
for sequence, i in sequences
chord = sequence[index]
# if beat in any rhythm array has value
if typeof chord == "object"
# beats per second
bps = composition.tempo / 60
# how much of a beat is the length
beat_count = chord.length / 0.25
# sustain of the note in seconds
chord_length_secs = beat_count * bps / 2
sustain = (chord_length_secs / bps) - 0.1
for note in chord.notes
# new note
n = new Note({frequency: note.freq, sustain: sustain, wave: waves[i], gain: gains[i], vol: chord.notes.length})
# new oscillator
o = n.osc()
# play oscillator
o.play()
if i == 0 then clef = 'treble' else clef = 'bass'
if typeof chord == "object"
$('.' + clef + ' .beat.active').removeClass 'active'
$('.' + clef + ' .beat.go').removeClass clef + '-go'
$('.' + clef + ' .beat:nth-child(' + (index + 1) + ')').addClass clef + '-go'
else if chord != 'sus'
$('.' + clef + ' .beat.active').removeClass 'active'
$('.' + clef + ' .beat.go').removeClass clef + '-go'
$('.beat:nth-child(' + (index + 1) + ')').addClass 'active'
# update index
index = (index + 1) % beats
# first call of next beat
next_beat()
# ms to relative speed (based on resolution)
time = tempo_time / (composition.resolution / 4)
# set interval for next beat to occur at approriate time
performance_interval = window.setInterval(next_beat, time)
# stop button
stopSequences = () ->
window.clearInterval(performance_interval)
# get sequences
getSequences()
playing = false
play_handler = (p) ->
if p == true
playSequences()
else
stopSequences()
playing = p
$('#play').click () ->
$(this).toggleClass 'playing'
$('body').toggleClass 'playing'
$('#new').toggleClass 'inactive'
play_handler(!playing)
$('#new').click () ->
getSequences()
该程序采用传统的“ Auld Lang Syne”旋律,并在钢琴中弹奏随机音符。 根据计数数据创建一个更改包,并生成一个随机数来选择一个值。 八度音阶也是随机选择的。
<html>
<head>
<title>Random Picture Generatortitle>
<link rel="stylesheet" href="assets/stylesheets/app.css">
head>
<body>
<header class="flex">
<h1>Random Picture Generatorh1>
<button>Generate Random Picturebutton>
header>
<section class="flex">
<img src="">
section>
<script src="assets/scripts/app.js">script>
body>
html>
html, body {
margin: 0;
height: 100%;
width: 100%;
}
header {
width: 100%;
padding-bottom: 25px;
flex-direction: column;
}
img {
width: 70%;
}
.flex {
display: flex;
justify-content: center;
align-items: center;
}
const imageArray = [
"https://images.unsplash.com/photo-1508185159346-bb1c5e93ebb4?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=55cf14db6ed80a0410e229368963e9d8&auto=format&fit=crop&w=1900&q=80",
"https://images.unsplash.com/photo-1495480393121-409eb65c7fbe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=05ea43dbe96aba57d48b792c93752068&auto=format&fit=crop&w=1351&q=80",
"https://images.unsplash.com/photo-1501611724492-c09bebdba1ac?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ebdb0480ffed49bd075fd85c54dd3317&auto=format&fit=crop&w=1491&q=80",
"https://images.unsplash.com/photo-1417106338293-88a3c25ea0be?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=d1565ecb73a2b38784db60c3b68ab3b8&auto=format&fit=crop&w=1352&q=80",
"https://images.unsplash.com/photo-1500520198921-6d4704f98092?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ac4bc726064d0be43ba92476ccae1a75&auto=format&fit=crop&w=1225&q=80",
"https://images.unsplash.com/photo-1504966981333-1ac8809be1ca?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=9a1325446cbf9b56f6ee549623a50696&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1437075130536-230e17c888b5?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ff573beba18e5bf45eb0cccaa2c862b3&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1515002246390-7bf7e8f87b54?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1eac0f70640261e09152340f13b79144&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1506057278219-795838d4c2dd?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=f68d8d7b0223cd906ea8cac13421881d&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1488402410361-05152fa654d3?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5266aadc96d5b5b23996e7120d3190a8&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1475598322381-f1b499717dda?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=cb49f991ce8dd947b45ccd1bd905ec8c&auto=format&fit=crop&w=1355&q=80",
"https://images.unsplash.com/photo-1501949997128-2fdb9f6428f1?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=951ee200e732c9b8c4ea0a7372ca9d27&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1494783367193-149034c05e8f?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a98c0f9a6c602e964e6533de413d59ba&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1476547362848-ed2a9f99cd29?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5b4647c9e25267c25866936c916e4aa8&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1506017669510-0bcbe8003d70?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=9403f5d4ac23a5726bfc3c8308b31c01&auto=format&fit=crop&w=1350&q=80",
"https://images.unsplash.com/photo-1489447068241-b3490214e879?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=a85cb0d68de38ae2aa00d8a9663a320a&auto=format&fit=crop&w=1350&q=80"
];
const image = document.querySelector("img");
const button = document.querySelector("button");
window.onload = () => generateRandomPicture(imageArray);
button.addEventListener("click", () => generateRandomPicture(imageArray));
function generateRandomPicture(array){
let randomNum = Math.floor(Math.random() * array.length);
image.setAttribute("src", array[randomNum]);
}
图像存储在一个数组中。通过array.length
生成一个数字并乘以数组中的图像数量。然后,将Math.floor
将值四舍五入为整数,并在加载页面或单击按钮时在HTML中设置图像src
。
#app.wrap
.bg
.colors()
button.refresh(v-on:click="newColors").
button.expand(v-on:click="newColors").
color(v-for="(c, i) in colors", v-bind:name="names[i]" v-bind:color="c")
a.fulllink(href="https://farbvelo.elastiq.ch/", target="_blank")
strong
span F
span u
span l
span l
span
span V
span e
span r
span s
span i
span o
span n
@import url('https://fonts.googleapis.com/css?family=Space+Mono');
button {
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
background: transparent;
/* inherit font & color from ancestor */
color: inherit;
font: inherit;
/* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */
line-height: normal;
/* Corrects font smoothing for webkit */
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;
/* Corrects inability to style clickable `input` types in iOS */
-webkit-appearance: none;
}
html {
font-size: calc(.75rem + 1.15vh);
font-family: 'Space Mono', monospace;
}
body {
height: 100vh;
background: #212121;
overflow: hidden;
}
input {
position: absolute;
z-index: 2;
}
.wrap, .bg {
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
.bg {
//opacity: .9;
//clip-path: inset(12vmin 26% 12vmin 26%);
}
.colors {
position: absolute;
left: 50%;
bottom: 10vmin; top: 10vmin;
display: flex;
flex-direction: column;
cursor: pointer;
transform: translateX(-50%);
width: 52%;
@media (max-width: 700px){
width: 75%;
}
}
.colors .color {
position: relative;
display: flex;
@media (max-width: 700px){
display: block;
padding: 1rem;
}
align-items: center;
padding: 0 1rem;
flex-grow: 1;
&::after {
opacity: .5;
content: '';
position: absolute;
left: 0; right: 0; bottom: 0; top: 0;
box-shadow: 0 0 10rem currentColor;
}
/*
border: solid currentColor;
border-width: 0 2px;
*/
transition: 200ms color linear, 200ms background-color linear, 300ms padding-bottom cubic-bezier(.7, .3, .3, 1) 100ms;
min-height: 0.1vmax;
&:last-child {
padding-bottom: #{1.61803 * 4rem};
}
&:hover {
padding-bottom: #{1.61803 * 4rem};
}
}
.colors:hover .color {
&:last-child {
padding-bottom: 1rem;
}
&:hover {
padding-bottom: #{1.61803 * 4rem};
}
}
.label {
flex-grow: 1;
padding-right: 1rem;
font-size: .75em;
@media (max-width: 700px) {
font-size: .6em;
margin-bottom: .15em;
}
}
.name {
font-size: .8em;
text-align: right;
@media (max-width: 700px){
text-align: left;
}
}
.refresh, .expand {
z-index: 1;
position: absolute;
top: 100%; left: 100%;
margin: 0;
padding: 0;
transform: translate(-60%,-60%);
font-size: 2em;
width: 1.2em; height: 1.2em;
background: #000;
color: #fff;
border-radius: 50%;
outline: 0;
box-shadow: 0 0 2rem rgba(#000, .2);
cursor: pointer;
svg {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%,-50%);
animation-name: rotate;
animation-duration: 3s;
width: .6em; height: .6em;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: paused;
line-height: 1;
fill: #fff;
}
&:hover {
svg {
animation-play-state: running;
}
}
}
.expand {
display: none;
margin-left: -1.4em;
svg {
fill: none;
stroke: #fff;
stroke-width: 1.5;
animation: none;
width: .75em; height: .75em;
}
}
@keyframes rotate {
from {transform: translate(-50%,-50%) rotate(0deg);}
to {transform: translate(-50%,-50%) rotate(360deg);}
}
.fulllink {
position: fixed;
top: 0;
right: 0;
font-size: .65em;
text-decoration: none;
padding: 1.2em 3.5em;
width: 10ex;
text-align: center;
transform: translateX(30%) rotate(45deg);
span {
position: relative;
animation: .5s ease-in 1s infinite alternate jumpup;
animation-duration: 1s;
@for $i from 1 through 20 {
&:nth-child(#{$i}) {
animation-delay: 1000ms + $i * 100ms;
}
}
}
}
@keyframes jumpup {
100% {
opacity: .1;
}
}
// full version: https://farbvelo.elastiq.ch/
// color-names: https://github.com/meodai/color-nameshttps://github.com/meodai/color-names
const shuffleArray = arr => arr
.map(a => [Math.random(), a])
.sort((a, b) => a[0] - b[0])
.map(a => a[1]);
const random = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var generateRandomColors = (total, mode = 'lab', padding = .175, parts = 4) => {
let colors = [];
const part = Math.floor(total / parts);
const reminder = total % parts;
// hues to pick from
const baseHue = random(0, 360);
const hues = [0, 60, 120, 180, 240, 300].map(offset => {
return (baseHue + offset) % 360;
});
// low saturated color
const baseSaturation = random(5, 40);
const baseLightness = random(0, 20);
const rangeLightness = 90 - baseLightness;
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
baseLightness * random(.25, .75)
) );
for (let i = 0; i < (part - 1); i++) {
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
baseLightness + (rangeLightness * Math.pow(i/(part - 1), 1.5))
) );
}
// random shades
const minSat = random(50, 70);
const maxSat = minSat + 30;
const minLight = random(45, 80);
const maxLight = Math.min(minLight + 40, 95);
for (let i = 0; i < (part + reminder - 1); i++) {
colors.push( HUSL.toHex(
hues[random(0, hues.length - 1)],
random(minSat, maxSat),
random(minLight, maxLight)
) )
}
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
rangeLightness
) );
//colors = shuffleArray(colors);
return chroma.scale(colors).padding(padding).mode(mode).colors(total);
}
function getContrastColor(color) {
let currentColor = chroma( color );
let lum = currentColor.luminance();
let contrastColor;
if ( lum < 0.15 ) {
contrastColor = currentColor.set('hsl.l', '+.25');
} else {
contrastColor = currentColor.set('hsl.l', '-.35');
}
return contrastColor;
}
Vue.component('color', {
props: ['color', 'name'],
template: `
{{ color }}
{{ name.name }}
`,
computed: {
/*name: function () {
console.log(name)
return getClosestNamedColor( this.color ).name;
},*/
textColor: function () {
return getContrastColor(this.color);
}
}
});
let colors = new Vue({
el: '#app',
data: () => {
return {
colors: [],
names: [],
amount: 6,
}
},
methods: {
getNames: function () {
fetch(`https://api.color.pizza/v1/${this.colors.join().replace(/#/g, '')}?noduplicates=true&goodnamesonly=true`)
.then(data => data.json())
.then(data => {
this.names = data.colors;
});
},
newColors: function () {
let colorArr = generateRandomColors(this.amount)
this.colors = colorArr;
this.getNames();
let gradient = [...colorArr];
gradient[0] += ' 12vmin'
gradient[gradient.length - 1] += ' 69%'
//url("https://www.transparenttextures.com/patterns/concrete-wall.png"),
document.querySelector('.bg').style['background-image'] = `
linear-gradient(to bottom, ${gradient.join(',')})
`;
document.querySelector('.refresh').style.background = this.colors[this.colors.length - 1];
document.querySelector('.expand').style.background = this.colors[this.colors.length - 1];
document.querySelector('.fulllink').style.background = this.colors[1];
document.querySelector('.fulllink').style.color = getContrastColor(this.colors[1]);
}
},
mounted: function () {
this.newColors();
}
});
这就是奇迹发生的地方:
const random = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
代码的第一行随机打乱数组,第二行返回0到10之间的随机数字。在随机颜色背景的示例中,可以设置颜色和特定范围,例如色相,饱和度和阴影。
有关生成随机十六进制颜色的另一种方法,请查看Chris Coyer的这篇文章
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML5 Canvas Generative Arttitle>
<style type="text/css">
style>
head>
<body>
<div id="container">
<canvas id="displayCanvas" width="1024px" height="576px">
Your browser does not support HTML5 canvas.
canvas>
<form>
<p id="caption">
HTML5 Canvas - Morphing Fractal Curves, version 2.
<br><a href="http://www.rectangleworld.com">rectangleworld.coma>
p>
form>
div>
body>
html>
body {background-color:#000000; color:#333333;}
h4 {font-family: sans-serif; color:#333333; font-size:16px;}
h3 {font-family: sans-serif; color:#333333;}
p {font-family: sans-serif; color:#333333; font-size:14px;}
#caption {position:absolute; width:1024px; text-align:center; top:520px; z-index:1}
a {font-family: sans-serif; color:#d15423; text-decoration:none;}
canvas {}
#displayCanvas {position:absolute; top:10px; z-index:0;}
div {}
#container {width:1024px; height:576px; margin:auto;}
indow.addEventListener("load", windowLoadHandler, false);
//for debug messages while testing code
var Debugger = function() { };
Debugger.log = function(message) {
try {
console.log(message);
}
catch (exception) {
return;
}
}
function windowLoadHandler() {
canvasApp();
}
function canvasSupport() {
return Modernizr.canvas;
}
function canvasApp() {
if (!canvasSupport()) {
return;
}
var displayCanvas = document.getElementById("displayCanvas");
var context = displayCanvas.getContext("2d");
var displayWidth = displayCanvas.width;
var displayHeight = displayCanvas.height;
//off screen canvas used only when exporting image
var exportCanvas = document.createElement('canvas');
exportCanvas.width = displayWidth;
exportCanvas.height = displayHeight;
var exportCanvasContext = exportCanvas.getContext("2d");
//var exportImage = document.createElement('img');
//buttons
var btnExport = document.getElementById("btnExport");
btnExport.addEventListener("click", exportPressed, false);
var btnRegenerate = document.getElementById("btnRegenerate");
btnRegenerate.addEventListener("click", regeneratePressed, false);
var numCircles;
var maxMaxRad;
var minMaxRad;
var minRadFactor;
var circles;
var iterations;
var numPoints;
var timer;
var drawsPerFrame;
var drawCount;
var bgColor,urlColor;
var lineWidth;
var colorParamArray;
var colorArray;
var dataLists;
var minX, maxX, minY, maxY;
var xSpace, ySpace;
var lineNumber;
var twistAmount;
var fullTurn;
var lineAlpha;
var maxColorValue;
var minColorValue;
init();
function init() {
numCircles = 15; //35
maxMaxRad = 200;
minMaxRad = 200;
minRadFactor = 0;
iterations = 11;
numPoints = Math.pow(2,iterations)+1;
drawsPerFrame = 4;
fullTurn = Math.PI*2*numPoints/(1+numPoints);
minX = -maxMaxRad;
maxX = displayWidth + maxMaxRad;
minY = displayHeight/2-50;
maxY = displayHeight/2+50;
twistAmount = 0.67*Math.PI*2;
stepsPerSegment = Math.floor(800/numCircles);
maxColorValue = 100;
minColorValue = 20;
lineAlpha = 0.10;
bgColor = "#000000";
urlColor = "#333333";
lineWidth = 1.01;
startGenerate();
}
function startGenerate() {
drawCount = 0;
context.setTransform(1,0,0,1,0,0);
context.clearRect(0,0,displayWidth,displayHeight);
setCircles();
colorArray = setColorList(iterations);
lineNumber = 0;
if(timer) {clearInterval(timer);}
timer = setInterval(onTimer,1000/60);
}
function setColorList(iter) {
var r0,g0,b0;
var r1,g1,b1;
var r2,g2,b2;
var param;
var colorArray;
var lastColorObject;
var i, len;
var maxComponentDistance = 32;
var maxComponentFactor = 0.5;
r0 = minColorValue + Math.random()*(maxColorValue-minColorValue);
g0 = minColorValue + Math.random()*(maxColorValue-minColorValue);
b0 = minColorValue + Math.random()*(maxColorValue-minColorValue);;
r1 = minColorValue + Math.random()*(maxColorValue-minColorValue);
g1 = minColorValue + Math.random()*(maxColorValue-minColorValue);
b1 = minColorValue + Math.random()*(maxColorValue-minColorValue);
/*
//can also set colors explicitly here if you like.
r1 = 90;
g1 = 60;
b1 = 20;
r0 = 30;
g0 = 77;
b0 = 66;
*/
a = lineAlpha;
var colorParamArray = setLinePoints(iter);
colorArray = [];
len = colorParamArray.length;
for (i = 0; i < len; i++) {
param = colorParamArray[i];
r = Math.floor(r0 + param*(r1 - r0));
g = Math.floor(g0 + param*(g1 - g0));
b = Math.floor(b0 + param*(b1 - b0));
var newColor = "rgba("+r+","+g+","+b+","+a+")";
colorArray.push(newColor);
}
return colorArray;
}
function setCircles() {
var i;
var r,g,b,a;
var grad;
circles = [];
for (i = 0; i < numCircles; i++) {
maxR = minMaxRad+Math.random()*(maxMaxRad-minMaxRad);
minR = minRadFactor*maxR;
var newCircle = {
centerX: minX + i/(numCircles-1)*(maxX - minX),
centerY: minY + i/(numCircles-1)*(maxY - minY),
//centerY: minY + Math.random()*(maxY - minY),
maxRad : maxR,
minRad : minR,
phase : i/(numCircles-1)*twistAmount,
pointArray : setLinePoints(iterations)
};
circles.push(newCircle);
}
}
function onTimer() {
var i;
var cosTheta, sinTheta;
var theta;
var numCircles = circles.length;
var linParam;
var cosParam;
var centerX, centerY;
var xSqueeze = 0.75;
var x0,y0;
var rad, rad0, rad1;
var phase, phase0, phase1;
for (var k = 0; k < drawsPerFrame; k++) {
theta = lineNumber/(numPoints-1)*fullTurn;
context.globalCompositeOperation = "lighter";
context.lineJoin = "miter";
context.strokeStyle = colorArray[lineNumber];
context.lineWidth = lineWidth;
context.beginPath();
//move to first point
centerX = circles[0].centerX;
centerY = circles[0].centerY;
rad = circles[0].minRad + circles[0].pointArray[lineNumber]*(circles[0].maxRad - circles[0].minRad);
phase = circles[0].phase;
x0 = centerX + xSqueeze*rad*Math.cos(theta + phase);
y0 = centerY + rad*Math.sin(theta + phase);
context.moveTo(x0,y0);
for (i=0; i< numCircles-1; i++) {
//draw between i and i+1 circle
rad0 = circles[i].minRad + circles[i].pointArray[lineNumber]*(circles[i].maxRad - circles[i].minRad);
rad1 = circles[i+1].minRad + circles[i+1].pointArray[lineNumber]*(circles[i+1].maxRad - circles[i+1].minRad);
phase0 = circles[i].phase;
phase1 = circles[i+1].phase;
for (j = 0; j < stepsPerSegment; j++) {
linParam = j/(stepsPerSegment-1);
cosParam = 0.5-0.5*Math.cos(linParam*Math.PI);
//interpolate center
centerX = circles[i].centerX + linParam*(circles[i+1].centerX - circles[i].centerX);
centerY = circles[i].centerY + cosParam*(circles[i+1].centerY - circles[i].centerY);
//interpolate radius
rad = rad0 + cosParam*(rad1 - rad0);
//interpolate phase
phase = phase0 + cosParam*(phase1 - phase0);
x0 = centerX + xSqueeze*rad*Math.cos(theta + phase);
y0 = centerY + rad*Math.sin(theta + phase);
context.lineTo(x0,y0);
}
}
context.stroke();
lineNumber++;
if (lineNumber > numPoints-1) {
clearInterval(timer);
timer = null;
break;
}
}
}
//Here is the function that defines a noisy (but not wildly varying) data set which we will use to draw the curves.
//We first define the points in a linked list, but then store the values in an array.
function setLinePoints(iterations) {
var pointList = {};
var pointArray = [];
pointList.first = {x:0, y:1};
var lastPoint = {x:1, y:1}
var minY = 1;
var maxY = 1;
var point;
var nextPoint;
var dx, newX, newY;
var ratio;
var minRatio = 0.5;
pointList.first.next = lastPoint;
for (var i = 0; i < iterations; i++) {
point = pointList.first;
while (point.next != null) {
nextPoint = point.next;
dx = nextPoint.x - point.x;
newX = 0.5*(point.x + nextPoint.x);
newY = 0.5*(point.y + nextPoint.y);
newY += dx*(Math.random()*2 - 1);
var newPoint = {x:newX, y:newY};
//min, max
if (newY < minY) {
minY = newY;
}
else if (newY > maxY) {
maxY = newY;
}
//put between points
newPoint.next = nextPoint;
point.next = newPoint;
point = nextPoint;
}
}
//normalize to values between 0 and 1
//Also store y values in array here.
if (maxY != minY) {
var normalizeRate = 1/(maxY - minY);
point = pointList.first;
while (point != null) {
point.y = normalizeRate*(point.y - minY);
pointArray.push(point.y);
point = point.next;
}
}
//unlikely that max = min, but could happen if using zero iterations. In this case, set all points equal to 1.
else {
point = pointList.first;
while (point != null) {
point.y = 1;
pointArray.push(point.y);
point = point.next;
}
}
return pointArray;
}
function exportPressed(evt) {
//background - otherwise background will be transparent.
exportCanvasContext.fillStyle = bgColor;
exportCanvasContext.fillRect(0,0,displayWidth,displayHeight);
//draw
exportCanvasContext.drawImage(displayCanvas, 0,0,displayWidth,displayHeight,0,0,displayWidth,displayHeight);
//add printed url to image
exportCanvasContext.fillStyle = urlColor;
exportCanvasContext.font = 'bold italic 16px Helvetica, Arial, sans-serif';
exportCanvasContext.textBaseline = "top";
var metrics = exportCanvasContext.measureText("rectangleworld.com");
exportCanvasContext.fillText("rectangleworld.com", displayWidth - metrics.width - 10, 5);
//we will open a new window with the image contained within:
//retrieve canvas image as data URL:
var dataURL = exportCanvas.toDataURL("image/png");
//open a new window of appropriate size to hold the image:
var imageWindow = window.open("", "fractalLineImage", "left=0,top=0,width="+displayWidth+",height="+displayHeight+",toolbar=0,resizable=0");
//write some html into the new window, creating an empty image:
imageWindow.document.write("Export Image ")
imageWindow.document.write("
+ " alt=''"
+ " height='" + displayHeight + "'"
+ " width='" + displayWidth + "'"
+ " style='position:absolute;left:0;top:0'/>");
imageWindow.document.close();
//copy the image into the empty img in the newly opened window:
var exportImage = imageWindow.document.getElementById("exportImage");
exportImage.src = dataURL;
}
function regeneratePressed(evt) {
startGenerate();
}
}
在此变形分形曲线中,Math.random
两次用于设置渐变的颜色,一次用于设置曲线的最大半径。 这是在每次迭代中构建全新外观的好方法!
h1
svg role="img"
title.title Random Words!
text.word x="50%" y="50%" text-anchor="middle" fill="#222" stroke="#222" stroke-width="1.5%" dominant-baseline="central" stroke-linecap="round" Random Words!
text.word x="50%" y="50%" text-anchor="middle" fill="white" dominant-baseline="central" Random Words!
p Made with <b>♥b> by <a href="https://twitter.com/LandonSchropp">Landon Schroppa>
html, body, h1
height: 100%
width: 100%
body
transition: background-color 0.3s ease-in
font-family: 'Open Sans', sans-serif
background-color: hsl(350, 100%, 50%)
// in firefox, a transformed element causes a scroll when it extends beyond the element's size, so we'll disable it
overflow: hidden
font-size: 12px
@media (min-width: 480px)
font-size: 14px
@media (min-width: 640px)
font-size: 16px
.word
font-family: 'Bangers', cursive
svg
height: 100%
width: 100%
position: relative
top: -1rem
animation: pop-out 2s ease-in-out infinite
.word
font-family: 'Bangers', cursive
letter-spacing: 0.05em
color: white
padding: 0.5em
font-size: 28px
@media (min-width: 480px)
font-size: 36px
@media (min-width: 640px)
font-size: 48px
@media (min-width: 960px)
font-size: 64px
@media (min-width: 1280px)
font-size: 84px
p
position: fixed
bottom: 0
left: 0
right: 0
line-height: 2rem
text-align: center
color: transparentize(white, 0.25)
background-color: transparentize(#222, 0.0)
@keyframes pop-out
0%
transform: scale3d(0, 0, 1)
opacity: 1
25%
transform: scale3d(1, 1, 1)
opacity: 1
100%
transform: scale3d(1.5, 1.5, 1)
opacity: 0
a, a:visited
color: inherit
V
$(document).ready(function () {
// set the background to a random color
var hue = 350;
// cache the jquery elements to prevent dom queries during the animation events
var $body = $("body");
var $svg = $("svg");
var $word = $(".word");
// when the animation iterates
$("h1").on(
"webkitAnimationIteration oanimationiteration msAnimationIteration animationiteration ",
function () {
// replace the header with a random word
var word = words[Math.floor(Math.random() * words.length)] + "!";
$word.text(word);
// update the background color
hue += 47;
$body.css("background-color", "hsl(" + hue + ", 100%, 50%)");
}
);
});
// the 10,000 most comment words, taken from https://goo.gl/hfjFkz
words = [
"the",
"of",
"and",
];
我们使用Math.random
将标题替换为数组中随机选择的单词:
var word = words[Math.floor(Math.random() * words.length)] + "!";
这很像随机图像示例-对于初学者来说是一种完美的练习!
<div class="wrapper">
<button class="form-control" id="keygen">Generate API Keybutton>
<input class="form-control" id="apikey" type="text" value="" placeholder="Click on the button to generate a new API key ..." />
div>
body {
text-align: center;
background: #f1f1f1;
}
.wrapper {
padding-top:60px;
}
button.form-control {
background: #f7f7f7 none repeat scroll 0 0;
border-color: #ccc;
box-shadow: 0 1px 0 #ccc;
color: #555;
vertical-align: top;
border-radius: 3px;
border-style: solid;
border-width: 1px;
box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-size: 13px;
height: 28px;
line-height: 26px;
margin: 0;
padding: 0 10px 1px;
text-decoration: none;
white-space: nowrap;
}
input.form-control {
background-color: #fff;
border: 1px solid #ddd;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07) inset;
color: #32373c;
outline: 0 none;
transition: border-color 50ms ease-in-out 0s;
margin: 1px;
padding: 3px 5px;
border-radius: 0;
font-size: 14px;
font-family: inherit;
font-weight: inherit;
box-sizing: border-box;
color: #444;
font-family: "Open Sans",sans-serif;
line-height: 1.4em;
width: 310px;
}
function generateUUID()
{
var d = new Date().getTime();
if( window.performance && typeof window.performance.now === "function" )
{
d += performance.now();
}
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)
{
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x3|0x8)).toString(16);
});
return uuid;
}
/**
* Generate new key and insert into input value
*/
$( '#keygen' ).on('click',function(){
$( '#apikey' ).val( generateUUID() );
});
这是一个随机数的超级现实应用案例! 该演示会生成16个随机数,以创建一个通用唯一标识符(UUID),该标识符可用作提供对API的访问的密钥。
<div class="container">
<div class="text">div>
div>
@import 'https://fonts.googleapis.com/css?family=Roboto+Mono:100'
html, body
font-family 'Roboto Mono', monospace
background #212121
height 100%
.container
height 100%
width 100%
justify-content center
align-items center
display flex
.text
font-weight 100
font-size 28px
color #FAFAFA
.dud
color #757575
class TextScramble {
constructor(el) {
this.el = el
this.chars = '!<>-_\\/[]{}—=+*^?#________'
this.update = this.update.bind(this)
}
setText(newText) {
const oldText = this.el.innerText
const length = Math.max(oldText.length, newText.length)
const promise = new Promise((resolve) => this.resolve = resolve)
this.queue = []
for (let i = 0; i < length; i++) {
const from = oldText[i] || ''
const to = newText[i] || ''
const start = Math.floor(Math.random() * 40)
const end = start + Math.floor(Math.random() * 40)
this.queue.push({ from, to, start, end })
}
cancelAnimationFrame(this.frameRequest)
this.frame = 0
this.update()
return promise
}
update() {
let output = ''
let complete = 0
for (let i = 0, n = this.queue.length; i < n; i++) {
let { from, to, start, end, char } = this.queue[i]
if (this.frame >= end) {
complete++
output += to
} else if (this.frame >= start) {
if (!char || Math.random() < 0.28) {
char = this.randomChar()
this.queue[i].char = char
}
output += `${char}`
} else {
output += from
}
}
this.el.innerHTML = output
if (complete === this.queue.length) {
this.resolve()
} else {
this.frameRequest = requestAnimationFrame(this.update)
this.frame++
}
}
randomChar() {
return this.chars[Math.floor(Math.random() * this.chars.length)]
}
}
// ——————————————————————————————————————————————————
// Example
// ——————————————————————————————————————————————————
const phrases = [
'Neo,',
'sooner or later',
'you\'re going to realize',
'just as I did',
'that there\'s a difference',
'between knowing the path',
'and walking the path'
]
const el = document.querySelector('.text')
const fx = new TextScramble(el)
let counter = 0
const next = () => {
fx.setText(phrases[counter]).then(() => {
setTimeout(next, 800)
})
counter = (counter + 1) % phrases.length
}
next()
依次存储和显示一些短语,并由一个动画隔开,该动画看起来像是用Math.random
选择的短语之间的随机字符来扰乱字母。
<ul id="moves">
<li data-move="rock">
<span class="fa fa-fw fa-hand-rock-o">span>
<span class="text">Rockspan>
li>
<li data-move="paper">
<span class="fa fa-fw fa-hand-paper-o">span>
<span class="text">Paperspan>
li>
<li data-move="scissors">
<span class="fa fa-fw fa-hand-scissors-o">span>
<span class="text">Scissorsspan>
li>
ul>
<div class="scoreboard">
<table>
<thead>
<td>Playertd>
<td>Computertd>
thead>
<tbody>
<tr>
<td class="Player-count">0td>
<td class="Computer-count">0td>
tr>
tbody>
table>
div>
// Observify Colours
$light-blue: #edf0f9;
$dark-blue: #151e28;
$blue: #019cdf;
$green: #35b197;
$red: #e94d5a;
$orange: #f66e3a;
$pink: #f583b6;
$purple: #7e4894;
$black: #000000;
$white: #ffffff;
// Variables
$body-bg: $dark-blue;
$color: $light-blue;
$font: 'Open Sans', sans-serif;
$font-size: 16px;
@keyframes icon-animation {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.4); }
60% { opacity: 0;}
80% { transform: scale(0.5); }
90% { opacity: 0; }
}
body {
background-color: $body-bg;
color: $color;
font-family: $font;
font-size: $font-size;
}
// Put your prototype code here
#moves {
list-style: none;
width: 100%;
padding: 0;
display: flex;
li {
background: $green;
width: 33.33%;
margin: 1em;
&:hover {
background: lighten($green, 10);
}
&:active {
background: $orange;
}
.fa {
display: block;
font-size: 48px;
text-align: center;
width: 100%;
padding: 1em;
box-sizing: border-box;
&.animating {
animation: icon-animation 2s 1;
}
}
.text {
text-align: center;
width: 100%;
display: block;
padding-bottom: 2em;
text-transform: uppercase;
letter-spacing: 0.2em;
font-weight: 600;
font-size: 11px;
}
}
}
.scoreboard {
width: 100%;
table {
width: 100%;
background: lighten($body-bg, 3);
td {
padding: .5em;
box-sizing: border-box;
text-align: center;
text-transform: uppercase;
}
thead {
font-size: 12px;
font-weight: 700;
letter-spacing: 0.2em;
td {
padding-top: 2em;
}
}
tbody {
td {
font-size: 96px;
font-weight: 900;
line-height: 1em;
}
}
}
}
$(window).load(function() {
var movesContainer = $('#moves'),
playerCount = $('.Player-count'),
computerCount = $('.Computer-count');
$('#moves li').on("click", function() {
var yourMove = $(this).data('move');
processMoves(yourMove);
var icon = $(this).find('.fa');
icon.addClass('animating');
var s = setTimeout(function(icon) {
$('#moves li .fa').removeClass('animating');
clearTimeout();
}, 5000);
});
});
function processMoves(yourMove) {
var opponentMove = generateRandomOpponentMove();
calculateWinner(yourMove,opponentMove);
}
function generateRandomOpponentMove() {
var availableMoves = ['rock','paper','scissors'],
randomNumber = Math.floor(Math.random() * availableMoves.length),
opponentMove = availableMoves[randomNumber];
return opponentMove;
}
function calculateWinner(yourMove, opponentMove) {
switch(yourMove) {
case 'rock':
if(opponentMove === 'rock') {
return 'draw';
} else if (opponentMove === 'scissors') {
youWin();
} else {
youLose();
}
break;
case 'paper':
if(opponentMove === 'paper') {
return 'draw';
} else if (opponentMove === 'rock') {
youWin();
} else {
youLose();
}
break;
case 'scissors':
if(opponentMove === 'scissors') {
return 'draw';
} else if (opponentMove === 'paper') {
youWin();
} else {
youLose();
}
break;
}
}
function youWin() {
var playerScore = $('.Player-count');
var playerScoreUpdated = parseInt(playerScore.text()) + 1;
playerScore.text(playerScoreUpdated);
}
function youLose() {
var computerScore = $('.Computer-count');
var computerScoreUpdated = parseInt(computerScore.text()) + 1;
computerScore.text(computerScoreUpdated);
}
在这个童年时代的经典剪刀石头布游戏中,Math.random
作为对手的计算机生成随机移动。 它从三个可用的招式中进行选择。
div id="app">
<section class="wrapper">
<h1>The Password Genieh1>
<div class="password-box">
<span id="password" class="password" v-on:click="copyToClipboard">{{ password }}span>
<span class="regenerate-password" v-on:click="generatePassword">span>
<span class="copy-password" v-on:click="copyToClipboard">span>
<span class="tooltip" v-if="copied">Password copied successfuly!span>
div>
<form @keydown.enter.prevent="">
<div class="field-wrap">
<label>Strengthlabel>
<span class="range-value">{{strength.text}}span>
<div class="range-slider_wrapper slider-strength" v-bind:class="strength.text">
<span class="slider-bar" v-bind:style="{ width: strength.score + '%' }">span>
<input type="range" class="range-slider" min="0" max="100" v-model="strength.score" disabled>
div>
div>
<div class="seperator">div>
<div class="field-wrap">
<label>Lengthlabel>
<span class="range-value">{{settings.length}}span>
<div class="range-slider_wrapper">
<span class="slider-bar" v-bind:style="{ width: lengthThumbPosition + '%' }">span>
<input type="range" class="range-slider" min="6" v-bind:max="settings.maxLength" v-model="settings.length">
div>
div>
<div class="field-wrap">
<label>Digitslabel>
<span class="range-value">{{settings.digits}}span>
<div class="range-slider_wrapper">
<span class="slider-bar" v-bind:style="{ width: digitsThumbPosition + '%' }">span>
<input type="range" class="range-slider" min="0" v-bind:max="settings.maxDigits" v-model="settings.digits">
div>
div>
<div class="field-wrap">
<label>Symbolslabel>
<span class="range-value">{{settings.symbols}}span>
<div class="range-slider_wrapper">
<span class="slider-bar" v-bind:style="{ width: symbolsThumbPosition + '%' }">span>
<input type="range" class="range-slider" min="0" v-bind:max="settings.maxSymbols" v-model="settings.symbols">
div>
div>
form>
section>
div>
$blue: #3fa4f4;
$purple: #6e77f7;
$peach: #fc8680;
$pink: #ef5081;
$green: #8BC34A;
$dark-green: #4caf50;
$red: #ff6666;
$orange: #ff9800;
$wrapper-bg: #f4f7fc;
$wrapper-width: 400px;
*{
box-sizing: border-box;
}
body{
font-size: 15px;
font-family: Tahoma,Verdana,Segoe,sans-serif;
color: #444;
background-color: #fefefe;
background-image: linear-gradient(-45deg, #018bfd 0%, #3F51B5 100%);
background-repeat: no-repeat;
background-size: cover;
padding: 0 20px;
margin: 0;
min-height: 100vh;
position: relative;
}
.header{
padding: 2em 0;
text-align: center;
.title{
font-size: 1.2em;
font-weight: bold;
color: #fff;
img{
width: 12px;
margin: 0 2px 2px;
vertical-align: bottom;
}
}
}
.wrapper{
width: $wrapper-width;
max-width: 100%;
min-height: 400px;
margin: 40px auto;
position: relative;
border: 1px solid #eee;
border-radius: 3px;
padding: 40px 20px;
font-size: 0.85em;
-webkit-box-shadow: 0 0 15px 0 rgba(0,0,0,0.05);
box-shadow: 0 0 15px 0 rgba(0,0,0,0.05);
background-color: $wrapper-bg;
position: relative;
transition: all ease-in 0.25s;
}
h1{
text-align: center;
margin: 0 0 40px;
}
.field-wrap{
margin-bottom: 20px;
}
form{
overflow: overlay;
margin-top: 30px;
}
label{
display: inline-block;
min-width: 20%;
}
.range-slider_wrapper{
position: relative;
width: 100%;
margin: 10px 0 30px;
}
.range-slider{
-webkit-appearance: none;
appearance: none;
background: lighten($blue, 20%);
width: 100%;
border-radius: 3px;
vertical-align: bottom;
margin: 0;
height: 6px;
cursor: pointer;
transition: all ease-in 0.25s;
}
.range-slider::-webkit-slider-thumb{
-webkit-appearance: none;
appearance: none;
border-radius: 0;
border: 0;
position:relative;
width: 4px;
height: 15px;
background-color: darken($blue, 5%);
}
.range-slider::-moz-range-thumb{
-moz-appearance: none;
appearance: none;
border-radius: 0;
border: 0;
position:relative;
width: 4px;
height: 15px;
background-color: darken($blue, 5%);
}
.range-slider{
&:focus{
outline: none;
}
&:hover, &:active{
&::-webkit-slider-thumb{
top: 0px;
}
}
}
::-moz-range-track {
background: transparent;
border: 0;
}
input::-moz-focus-inner,
input::-moz-focus-outer {
border: 0;
}
.range-value{
text-transform: capitalize;
float: right;
vertical-align: bottom;
min-width: 30px;
display: inline-block;
text-align: center;
border-radius: 3px;
font-size: 0.9em;
}
.slider-bar{
position: absolute;
height: 6px;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
background: $blue;
left: 0;
bottom: 0;
pointer-events: none;
}
.slider{
&-strength{
.range-slider{
cursor: default;
}
.slider-bar{
border-radius: 3px;
transition: all ease-in 0.25s;
}
.range-slider::-webkit-slider-thumb{
background-color: transparent;
}
.range-slider::-moz-range-thumb{
background-color: transparent;
}
&.weak{
.range-slider{
background-color: lighten($red, 30%);
}
.slider-bar, .slider-bar:after{
background-color: $red;
}
}
&.average{
.range-slider{
background-color: lighten($orange, 30%);
}
.slider-bar, .slider-bar:after{
background-color: $orange;
}
}
&.strong{
.range-slider{
background-color: lighten($green, 30%);
}
.slider-bar, .slider-bar:after{
background-color: $green;
}
}
&.secure{
.range-slider{
background-color: lighten($green, 30%);
}
.slider-bar, .slider-bar:after{
background-color: $green;
}
}
}
}
.password-box{
width: 100%;
min-height: 80px;
margin-bottom: 40px;
position: relative;
text-align: center;
border-radius: 3px;
background: #fff;
letter-spacing: 2px;
transition: all ease-in 0.3s;
border: 1px solid rgb(189, 204, 230);
.password{
width: 70%;
padding: 1.5em 1em;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
word-wrap: break-word;
}
}
.regenerate-password, .copy-password{
width: 44px;
height: 50%;
position: absolute;
right: 0;
transition: all ease-in 0.25s;
&:hover{
opacity: 0.8;
}
}
.regenerate-password{
top: 0;
background-color: #fff;
background-image: url('https://nourabusoud.github.io/password-genie/images/regenerate.svg');
background-size: 40%;
background-position: center center;
background-repeat: no-repeat;
transition: all ease-in 0.25s;
cursor: pointer;
&:hover{
background-color: #fff;
}
}
.copy-password{
bottom: 0;
background-color: #fff;
background-image: url('https://nourabusoud.github.io/password-genie/images/copy-full.svg');
background-size: 50%;
background-position: center center;
background-repeat: no-repeat;
transition: all ease-in 0.25s;
cursor: pointer;
&:hover{
background-color: #fff;
}
}
.tooltip{
font-size: 0.8em;
display: block;
text-align: center;
padding: 0.5em;
border-radius: 3px;
position: absolute;
bottom: -35px;
left: 50%;
transform: translateX(-50%);
}
.seperator{
width: 100%;
height: 3px;
background-color: #fff;
margin: 60px 0 40px;
}
/* Footer */
footer{
width: 100%;
text-align: center;
color: #fff;
}
footer a{
color: #fff;
}
.github-links{
margin-bottom: 30px;
}
// fix for copy text
textarea, textarea:focus{
font-size: 16px;
}
new Vue({
el: '#app',
data() {
return {
password: '',
copied: false,
settings: {
maxLength: 64,
maxDigits: 10,
maxSymbols: 10,
length: 12,
digits: 4,
symbols: 2,
ambiguous: true,
}
};
},
computed: {
lengthThumbPosition: function() {
return (( (this.settings.length - 6) / (this.settings.maxLength - 6)) * 100);
},
digitsThumbPosition: function() {
return (( (this.settings.digits - 0) / (this.settings.maxDigits - 0)) * 100);
},
symbolsThumbPosition: function() {
return (( (this.settings.symbols - 0) / (this.settings.maxSymbols - 0)) * 100);
},
strength: function() {
var count = {
excess: 0,
upperCase: 0,
numbers: 0,
symbols: 0
};
var weight = {
excess: 3,
upperCase: 4,
numbers: 5,
symbols: 5,
combo: 0,
flatLower: 0,
flatNumber: 0
};
var strength = {
text: '',
score: 0
};
var baseScore = 30;
for (i=0; i < this.password.length;i++){
if (this.password.charAt(i).match(/[A-Z]/g)) {count.upperCase++;}
if (this.password.charAt(i).match(/[0-9]/g)) {count.numbers++;}
if (this.password.charAt(i).match(/(.*[!,@,#,$,%,^,&,*,?,_,~])/)) {count.symbols++;}
}
count.excess = this.password.length - 6;
if (count.upperCase && count.numbers && count.symbols){
weight.combo = 25;
}
else if ((count.upperCase && count.numbers) || (count.upperCase && count.symbols) || (count.numbers && count.symbols)){
weight.combo = 15;
}
if (this.password.match(/^[\sa-z]+$/))
{
weight.flatLower = -30;
}
if (this.password.match(/^[\s0-9]+$/))
{
weight.flatNumber = -50;
}
var score =
baseScore +
(count.excess * weight.excess) +
(count.upperCase * weight.upperCase) +
(count.numbers * weight.numbers) +
(count.symbols * weight.symbols) +
weight.combo + weight.flatLower +
weight.flatNumber;
if(score < 30 ) {
strength.text = "weak";
strength.score = 10;
return strength;
} else if (score >= 30 && score < 75 ){
strength.text = "average";
strength.score = 40;
return strength;
} else if (score >= 75 && score < 150 ){
strength.text = "strong";
strength.score = 75;
return strength;
} else {
strength.text = "secure";
strength.score = 100;
return strength;
}
},
},
mounted() {
this.generatePassword();
},
watch: {
settings: {
handler: function() {
this.generatePassword();
},
deep: true
}
},
methods: {
// copy password to clipboard
copyToClipboard(){
// we should create a textarea, put the password inside it, select it and finally copy it
var copyElement = document.createElement("textarea");
copyElement.style.opacity = '0';
copyElement.style.position = 'fixed';
copyElement.textContent = this.password;
var body = document.getElementsByTagName('body')[0];
body.appendChild(copyElement);
copyElement.select();
document.execCommand('copy');
body.removeChild(copyElement);
this.copied = true;
// reset this.copied
setTimeout(() => {
this.copied = false;
}, 750);
},
// generate the password
generatePassword() {
var lettersSetArray = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
var symbolsSetArray = [ "=","+","-","^","?","!","%","&","*","$","#","^","@","|"];
//var ambiguousSetArray = ["(",")","{","}","[","]","(",")","/","~",";",":",".","<",">"];
var passwordArray = [];
var digitsArray = [];
var digitsPositionArray = [];
// first, fill the password array with letters, uppercase and lowecase
for (var i = 0; i < this.settings.length; i++) {
// get an array for all indexes of the password array
digitsPositionArray.push(i);
var upperCase = Math.round(Math.random() * 1);
if (upperCase === 0) {
passwordArray[i] = lettersSetArray[Math.floor(Math.random()*lettersSetArray.length)].toUpperCase();
}
else {
passwordArray[i] = lettersSetArray[Math.floor(Math.random()*lettersSetArray.length)];
}
}
// Add digits to password
for (i = 0; i < this.settings.digits; i++) {
digit = Math.round(Math.random() * 9);
numberIndex = digitsPositionArray[Math.floor(Math.random()*digitsPositionArray.length)];
passwordArray[numberIndex] = digit;
/* remove position from digitsPositionArray so we make sure to the have the exact number of digits in our password
since without this step, numbers may override other numbers */
var j = digitsPositionArray.indexOf(numberIndex);
if(i != -1) {
digitsPositionArray.splice(j, 1);
}
}
// add special charachters "symbols"
for (i = 0; i < this.settings.symbols; i++) {
var symbol = symbolsSetArray[Math.floor(Math.random()*symbolsSetArray.length)];
var symbolIndex = digitsPositionArray[Math.floor(Math.random()*digitsPositionArray.length)];
passwordArray[symbolIndex] = symbol;
/* remove position from digitsPositionArray so we make sure to the have the exact number of digits in our password
since without this step, numbers may override other numbers */
var j = digitsPositionArray.indexOf(symbolIndex);
if(i != -1) {
digitsPositionArray.splice(j, 1);
}
}
this.password = passwordArray.join("");
},
},
});
这个密码生成器使用Math.random
,获取包含大写和小写字母的密码数组,然后将随机数字添加到生成的密码中。这是另一个很实用的例子
不完全是。 Math.random()
返回一个伪随机数
。 该算法称为伪随机数生成器(或PRNG)。 这意味着在某些情况下能够控制其随机性。
这一随机化是基于xorshift128 +算法,该算法可能在您的浏览器上运行。
所以,它是随机的。
有许多方法可以在不重复的情况下获得独特的值。Fisher-Yates
是一种通过改变数组序列来防止两次获得相同数字的好方法。 Math.random
将从有限序列的变化数组中选择一个值,如下面的代码片段所示。
function shuffle (array) {
var i = 0
, j = 0
, temp = null
for (i = array.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1))
temp = array[i]
array[i] = array[j]
array[j] = temp
}
}
如您在本文中所见,Math.random()
非常棒!但是,如果您要处理敏感的应用程序,并且需要一种更安全的随机方法,则建议您使用WebCrypto
。 您可能要使用WebCrypto
的原因包括临时验证码,随机密码生成,随机彩票号码等。
如果出于网络安全、密码学或统计的目的需要随机化,请使用window.crypto.getRandomValues
函数,相关内容请查看Mozilla关于WebCrypto API的文档。