view source

JavaScript

document.title = 'ルーレットで遊ぶ';

$(function(){

  var w = window.innerWidth;
  var h = window.innerHeight;

  w = Math.min(w,h) - 80;

  var c = w/2;
  var t=0;
  var deg = -90-4;
  var speed = 0;


  var se = new Audio('/mp3/pi.mp3');
  se.volume = 0.1;

  var max = 16;
  var aryOrg = [...Array(max)].map((_, i) => i);

  $demo = $('#demo');
  $svg = $('<svg>',{id:'svg',width:w,height:w,viewBox:'0 0 '+w+' '+w});
  $svg[0].id = 'svg';

  var $h1 = $('<h1>').text(document.title);
  var $input = $('<input>',{type:'number',min:2,max:27}).css({
    display:'block',
    margin:'0 auto',
    fontSize:'80px',
  }).val(max);
  $input.on('change', function(){
    max = Number($(this).val());
    colors = [];
    aryOrg = [...Array(max)].map((_, i) => i);
    aryOrg.forEach(function(v,i){
      var h = i*(360/max);
      colors.push('hsl('+h+',80%,50%)');
    });
  });
  $demo.after($input).after($h1);

  var ns = 'http://www.w3.org/2000/svg';
  var xlink = 'http://www.w3.org/1999/xlink';
  svg = document.createElementNS(ns, 'svg');
  $(svg).attr({width:w,height:w});
  $(svg).attr({'xmlns:xlink':xlink});
  $a = $('<a>');
  $i = $('<i>');
  $p = $('<p>');
  $score = $('<div>',{id:'score'});
  //$demo.append($a);
  //$demo.append($p);
  $demo.append($score);
  //$p.append($i);
  $demo.append($(svg));
  g = document.createElementNS(ns, 'g');
  //$(g).attr({id:'a'});
  $(svg).append($(g));
  circle = document.createElementNS(ns, 'circle');
  $(circle).attr({cx:w/2,cy:w/2,r:w/2-8,stroke:'#000',fill:'none'});
  $(svg).append($(circle));

  //黒▼
  var tri = document.createElementNS(ns, 'path');
  var tM = "M" + w/2 + ',' + w/20 +' ';
  var tL = 'l' + w/40 + ',' + -w/20 + ' ' + 'l' + -w/40*2 + ',' + 0 + ' ';
  var dt = tM + tL;
  $(tri).attr({d:dt,stroke:'none',fill:'#000000'});
  $(svg).append($(tri));

  var colors = [];
  aryOrg.forEach(function(v,i){
    var h = i*(360/max);
    colors.push('hsl('+h+',80%,50%)');
  });


  function drawArcPath(i,v){
    var path = document.createElementNS(ns, 'path');
    var r = w/2-8;
    var deg1 = deg+(i*(360/max));
    var deg2 = deg1+(360/max);
    var deg3 = (deg1+deg2)/2 - (deg2-deg1)/4;
    var rad1 = deg1 * Math.PI /180;
    var rad2 = deg2 * Math.PI /180;
    var rad3 = deg3 * Math.PI /180;
    var x1 = c + Math.cos(rad1) * r;
    var y1 = c + Math.sin(rad1) * r;
    var x2 = c + Math.cos(rad2) * r;
    var y2 = c + Math.sin(rad2) * r;
    var M = "M" + c + ',' + c +' ';
    var L = "L" + x1 + ',' + y1 +' ';
    var A = "A" + r + ',' + r +' ';
    var a = '0 0,1 ';
    var Z = '' + x2 + ',' + y2 + 'Z';
    d = M + L + A + a + Z;
    $(path).attr({d:d,stroke:'#000000'}).css({fill:colors[i]});
    $(g).append($(path));


    //テキスト挿入
    var r3 = w/2 - w/12;
    var x3 = c + Math.cos(rad3) * r3;
    var y3 = c + Math.sin(rad3) * r3;
    var x4 = c + Math.cos(rad2) * r3;
    var y4 = c + Math.sin(rad2) * r3;

    var path2 = document.createElementNS(ns, 'path');
    var M = "M" + x3 + ',' + y3 +' ';
    var A = "A" + r3 + ',' + r3 +' ';
    var a = '1 0,1 ';
    var L = 'L' + x4 + ',' + y4 + 'Z';
    var d2 = M + L;
    $(path2).attr({d:d2,stroke:'none',fill:'none',id:'textPath'+(i+1)});
    $(g).append($(path2));

    var text = document.createElementNS(ns, 'text');
    var textPath = document.createElementNS(ns, 'textPath');
    $(text).append($(textPath));

    var fontSize = 36;
    if(max >17){
      fontSize = 24;
    }
    if(w < 640){
      fontSize = 16;
    }
    textPath.setAttribute('text-anchor', 'middle');
    textPath.setAttribute('font-size', fontSize);
    textPath.setAttribute('font-weight', 'bol');
    textPath.setAttribute('fill', '#ffffff');
    textPath.setAttribute('href', '#textPath'+(i+1));
    textPath.textContent  = ' ' + (i+1);
    $(g).append($(text));
    
    //JavaScriptからSVGの文字列を操作/表示できない
    //代替で●数を使う
/*
    var cColor = '#000';
    if(i%2===0){cColor = '#fff';}
    var rrr = 7;
    for(j=0;j<i+1;j++){
      var rr = 2;
      if(j%5===0){rr+=2;}
      var x3 = c + Math.cos(rad3) * ( r * 9/10 - j*(rrr));
      var y3 = c + Math.sin(rad3) * ( r * 9/10 - j*(rrr));
      var circle = document.createElementNS(ns, 'circle');
      $(circle).attr({cx:x3,cy:y3,r:rr}).css({fill:cColor});
      $(g).append($(circle));
    }
*/

/*

    var path2 = document.createElementNS(ns, 'path');
    $(path2).attr({d:d2,stroke:'none'});
    $(path2).attr({'id':"t"+i,});

    var text = document.createElementNS(ns, 'text');
    var textpath = document.createElementNS(ns, 'textpath');
    $(text).attr({'font-size':'32',stroke:'#000',dy:40});
    $(textpath).attr({'xlink:href':"#t"+i,});
    $(textpath).text(i);
    $(text).append($(textpath));
    $(path2).append($(text));
    $(g).append($(path2));
*/
  }
  function role(isSlow){
    $score.text('')
    t = 0;
    pace = 7;
    if(isSlow){
      pace = 31;
    }
    timer = setInterval(function(){
      t++;
      if(isSlow){
        speed -= t/(4*1000) - Math.random()*1/9;
      } else {
        speed = Math.random()*13+3;
      }
      if(speed<0){speed=0}
      deg += speed;
      if(t%5===0){
        se.currentTime = 0;
        se.play();
      }
      draw();
    }, pace);
  }

  function fixDeg(){
    deg = Math.floor(deg%360);
    degD = deg%(360/max);//キリよくする
    deg -=degD/2;
    deg = Math.floor(deg);
  }

  function draw(){
    $(g).empty();
    aryOrg.forEach(function(v,i){
      drawArcPath(i, v);
    });
  }

  function checkValDeg(){
    deg2 = deg+90;
    if(deg2<0){
      deg2+=360;
    }
    if(deg2>360){
      deg2 = deg2 % 360;
    }
    var i = (aryOrg.length) * (360-deg2)/360;
    var i = Math.floor(i);
    var v = aryOrg[i]+1;
    //console.log(deg2);
    console.log(v);
    $score.text(v)
  }

  
  function drawScore(v){
    
  }

  aryOrg.forEach(function(v,i){
    drawArcPath(i,0);
  });

  var animateTransform = document.createElementNS(ns, 'animateTransform');
  $(animateTransform).attr({
    'xlink:href' : "#a",
    attributeName : "transform",
    type : "rotate",
    from : "0 " + c +' '+ c,
    to : "360 " + c +' '+ c,
    dur : "0.47s",
    repeatCount : "indefinite",
  })
  //$(g).append($(animateTransform).clone());
  //role();
  checkValDeg();
  $demo.addClass('stop');

  $score.on('click', function(){
    var ele = $('#demo');
    if(ele.hasClass('stop') && !ele.hasClass('slow')){
      $demo.removeClass('stop');
      role();
      //$(g).append($(animateTransform).clone());
    } else {
      //$(svg).find('animateTransform').remove();
      clearInterval(timer);
      role(true);
      var r = Math.random()*1000+400;
      setTimeout(function(){
        clearInterval(timer);
        $demo.addClass('stop');
        $demo.removeClass('slow');
        fixDeg();
        draw();
        console.log(deg);
        checkValDeg();
      }, r);
      $demo.addClass('slow');
    }
  });
  
  $a = $('<a>',{href:'/demo/-js/js-game-roulette-casino/'}).text('カジノゲームのルーレットはコチラ');
  $('#demo').after($a);
});

CSS

@font-face {
	font-family: LeagueGothic;
	src: url(/fonts/LeagueGothic-Regular.ttf);
}

#demo{
  position:relative;
  left:0;
  top:0;
  font-family: LeagueGothic, Meiryo;
  display: grid;
  place-items: center;
  user-select:none;
}
#demo a,
#demo i,
#demo p
  display:block;
  position:absolute;
  left:0;
  top:0;
}
#demo a{
  width:100%;
  height:100%;
  z-index:2;
}

#demo p{
  left:calc(50% - 20px);
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 48px 20px 0 20px;
  border-color: #000000 transparent transparent transparent;
  z-index:3;
}

#demo i{
  top:-2px;
  left:calc(50% - 0.2px);
  width:0.5px;
  height:2px;
  background-color: #ff0000;
}
svg textPath{
  text-indent:-2em;
  text-anchor:middle;
  dominant-baseline: middle;
}

#score{
  position:absolute;
  top:0;
  left:0;
  z-index:3;
  width:100%;
  height:100%;
  line-height:100vh;
  color:#fff;
  font-size:20vmin;
  font-weight:bold;
  text-align:center;
}

HTML

ページのソースを表示 : Ctrl+U , DevTools : F12

view-source:https://hi0a.com/demo/-js/js-game-roulette/

ABOUT

hi0a.com 「ひまアプリ」は無料で遊べるミニゲームや便利ツールを公開しています。

プログラミング言語の動作デモやWEBデザイン、ソースコード、フロントエンド等の開発者のための技術を公開しています。

必要な機能の関数をコピペ利用したり勉強に活用できます。

プログラムの動作サンプル結果は画面上部に出力表示されています。

環境:最新のブラウザ GoogleChrome / Windows / Android / iPhone 等の端末で動作確認しています。

画像素材や音素材は半分自作でフリー素材配布サイトも利用しています。LINK参照。

動く便利なものが好きなだけで技術自体に興味はないのでコードは汚いです。

途中放置や実験状態、仕様変更、API廃止等で動かないページもあります。