view source

JavaScript

document.title = 'ルーレット ゲーム JavaScript SVG';

$(function(){
  var w = 600;
  var c = w/2;
  var t=0;
  var deg = 0;
  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 512 512"});
  $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:'120px',
  }).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>');
  $demo.append($a);
  $demo.append($p);
  $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 colors = [];
  aryOrg.forEach(function(v,i){
    var h = i*(360/max);
    colors.push('hsl('+h+',80%,50%)');
  });


  function drawArcPath(i, deg){
    deg = deg || 0;
    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;
    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 - 48;
    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 = 32;
    if(max >17){
      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){
    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;
      $(g).empty();
      aryOrg.forEach(function(v,i){
        drawArcPath(i,deg);
      });
      if(t%5===0){
        se.currentTime = 0;
        se.play();
      }
    }, pace);
  }

  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();
  $demo.on('click', function(){
    var ele = $(this);
    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');
      }, r);
      $demo.addClass('slow');
    }
  });
  
});

CSS

#demo{
  position:relative;
  left:0;
  top:0;
}
#demo a,
#demo i,
#demo p,
#demo svg{
  display:block;
  position:absolute;
  left:0;
  top:0;
}
#demo a{
  width:100%;
  height:100%;
  z-index:2;
}
#demo svg{
  top:20px;
  left:calc(50% - 300px);
}
#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;
}

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廃止等で動かないページもあります。ご了承下さい。