<div id="contents">
  <button id="startBtn">Start</button>
  <button id="resetBtn">Reset</button>
</div>
body {
  margin: 0;
  padding: 0;
}

#contents {
  position: relative;
  width: 100vw;
  height: 100vh;
}

#contents button {
  position: absolute;
  top: 10px;
  width: 100px;
  height: 50px;
  border-radius: 3px;
  border: none;
  cursor: pointer;
}

#startBtn {
  left: 120px;
}

#resetBtn {
  left: 10px;
}
// Canvas追加
const target = document.getElementById('contents')      // 追加先
const CreateCanvas = document.createElement('canvas')   // canvas element作成
CreateCanvas.setAttribute('id', 'canvas')               // canvas に id 付与
target.appendChild(CreateCanvas)                        // 追加

let AnimateID         // ID

let canvas
let ctx
let Cwidth
let Cheight

let ArcPath = [[Math.floor(Math.random() * Cwidth) + 1, Math.floor(Math.random() * Cheight) + 1]]  // 背景円の出現位置
let ArcSize = [Math.floor(Math.random() * 80) + 20]                                          // 背景円のサイズ

function draw() {
  // 追加先のサイズ取得
  Cwidth = target.clientWidth
  Cheight = target.clientHeight

  // Canvas サイズ設定
  CreateCanvas.width = Cwidth
  CreateCanvas.height = Cheight               

  // Canvas・コンテキスト取得
  canvas = document.getElementById('canvas')
  ctx = canvas.getContext('2d')

  // Canvasの中央取得
  let CenterW = Cwidth/2
  let CenterH = Cheight/2
  
  // 描画リセット
  ctx.clearRect(0, 0, Cwidth, Cheight) 

  // 円描画
  ArcPath.map((value, index) => {

    // 左右色分け
    if (value[0] >= CenterW) {
      ctx.strokeStyle = 'rgba(232, 74, 95, 1)'
      ctx.fillStyle = 'rgba(42, 54, 59, 1)'  
    } else {
      ctx.strokeStyle = 'rgba(42, 54, 59, 1)'  
      ctx.fillStyle = 'rgba(232, 74, 95, 1)'
    }

    ctx.beginPath()
    ctx.arc(value[0], value[1], ArcSize[index], 0, Math.PI * 2, true)

    // 線描画と塗りつぶし分け
    if (index % 2 ===  0) {
      ctx.stroke()
    } else {
      ctx.fill()
      ctx.stroke()
    }
  })
  
  ArcPath.push([Math.floor(Math.random() * Cwidth) + 1, Math.floor(Math.random() * Cheight) + 1])
  ArcSize.push([Math.floor(Math.random() * 80) + 20] )
  
  // 円描画
  ctx.fillStyle = 'rgba(42, 54, 59, 1)'
  ctx.strokeStyle = 'rgba(232, 74, 95, 1)'
  
  ctx.beginPath()
  ctx.arc(CenterW + Math.floor(Math.random() * 6) - 3, CenterH + Math.floor(Math.random() * 6) - 3, 120, 0, Math.PI * 2, true)
  ctx.fill()
  
  ctx.beginPath()
  ctx.arc(CenterW + Math.floor(Math.random() * 6) - 3, CenterH + Math.floor(Math.random() * 6) - 3, 120, 0, Math.PI * 2, true)
  ctx.stroke()
  
  // テキスト描画
  ctx.fillStyle = 'rgba(232, 74, 95, 1)'
  ctx.strokeStyle = 'rgba(255,255,255, 1)'
  ctx.font = '42px serif'
  
  // テキストサイズ取得
  let textSize = ctx.measureText('Text Test')  
  
  // テキスト塗りつぶし 
  ctx.fillText('Test Text', CenterW - (textSize.width / 2) + Math.floor(Math.random() * 6) - 3, CenterH + Math.floor(Math.random() * 6) - 3)
  
  // テキストアウトライン  
  ctx.strokeText('Test Text', CenterW - (textSize.width / 2) + Math.floor(Math.random() * 6) - 3, CenterH + Math.floor(Math.random() * 6) - 3)
  
  if (ArcSize.length <= 1000) {
    AnimateID = requestAnimationFrame(draw)
  } 
}

// スタートボタン
document.querySelector('#startBtn').addEventListener('click', () => {
  if (!AnimateID) {
    AnimateID = requestAnimationFrame(draw)
  }
})

// リセットボタン
document.querySelector('#resetBtn').addEventListener('click', () => {
  cancelAnimationFrame(AnimateID)
  AnimateID = null
  
  ArcPath = [[Math.floor(Math.random() * Cwidth) + 1, Math.floor(Math.random() * Cheight) + 1]]
  ArcSize = [Math.floor(Math.random() * 80) + 20] 

  Cwidth = target.clientWidth
  Cheight = target.clientHeight
  
  canvas = document.getElementById('canvas')
  ctx = canvas.getContext('2d')
  ctx.clearRect(0, 0, Cwidth, Cheight)
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.