株価指数

株価指数 | ひまあそび-ミニゲーム hi0a.com

view source

JavaScript

document.title = '株価指数';

let { canvas, ctx, cx, cy, w, h, min, demo } = readyCanvas();

var style = document.createElement('style');
style.innerText = 'html,body{overflow:hidden;cursor:none;user-select:none;}';
document.getElementsByTagName('head').item(0).appendChild(style);


canvas.style.backgroundColor = '#000000';

let search = location.search.slice(1);
let params = new URLSearchParams(search);
let q = params.get('q');
if(q){
  img.src = q;
}

var t = 0;
var bgcolor = '#000';
var color = '#0f0';











const candleWidth = 8;
const totalCandles = 300;
let offset = 0;

// 固定スケール範囲(Y軸の価格範囲)
const PRICE_MIN = 16000;
const PRICE_MAX = 24000;

let candles = [];

function getRandomCandle(prevClose) {
  const maxMove = 500; // ボラティリティ

  // open を生成
  let open = prevClose + (Math.random() - 0.5) * 100;

  // close を open ± maxMove に制限
  let close = open + (Math.random() - 0.5) * maxMove * 2;

  // high/low を close/open の範囲から上下に追加
  let high = Math.max(open, close) + Math.random() * (maxMove / 2);
  let low = Math.min(open, close) - Math.random() * (maxMove / 2);

  // === 固定スケールに収まるように制限 ===
  high = Math.min(high, PRICE_MAX);
  low = Math.max(low, PRICE_MIN);
  open = Math.min(Math.max(open, PRICE_MIN), PRICE_MAX);
  close = Math.min(Math.max(close, PRICE_MIN), PRICE_MAX);

  return { open, close, high, low };
}

function generateInitialCandles() {
  let prevClose = 20000;
  for (let i = 0; i < totalCandles; i++) {
    const candle = getRandomCandle(prevClose);
    candles.push(candle);
    prevClose = candle.close;
  }
}

function addNewCandle() {
  const prevClose = candles[candles.length - 1].close;
  candles.push(getRandomCandle(prevClose));
  if (candles.length > totalCandles) {
    candles.shift();
  }
}

// 固定スケールでY座標に変換
function priceToY(price) {
  const marginRatio = 0.05; // 上下5%マージン
  const range = PRICE_MAX - PRICE_MIN;
  const extendedMin = PRICE_MIN - range * marginRatio;
  const extendedMax = PRICE_MAX + range * marginRatio;
  const extendedRange = extendedMax - extendedMin;
  return canvas.height - ((price - extendedMin) / extendedRange) * canvas.height;
}

function drawCandle(x, candle) {
  const { open, close, high, low } = candle;
  const yOpen = priceToY(open);
  const yClose = priceToY(close);
  const yHigh = priceToY(high);
  const yLow = priceToY(low);

  const color = close >= open ? '#00FF00' : '#FF3333';

  // wick
  ctx.strokeStyle = color;
  ctx.beginPath();
  ctx.moveTo(x + candleWidth / 2, yHigh);
  ctx.lineTo(x + candleWidth / 2, yLow);
  ctx.stroke();

  // body
  ctx.fillStyle = color;
  const top = Math.min(yOpen, yClose);
  const height = Math.abs(yClose - yOpen);
  ctx.fillRect(x, top, candleWidth, height || 1);
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const visibleCount = Math.ceil(canvas.width / candleWidth);

  for (let i = 0; i < visibleCount; i++) {
    const idx = candles.length - visibleCount + i;
    const x = i * candleWidth - (offset % candleWidth);
    if (idx >= 0 && candles[idx]) {
      drawCandle(x, candles[idx]);
    }
  }
}

function animate() {
  requestAnimationFrame(animate);
  offset += 1;

  if (offset % candleWidth === 0) {
    addNewCandle();
  }

  draw();
}

generateInitialCandles();
animate();


document.oncontextmenu = function () {return false;}

CSS

HTML

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

view-source:https://hi0a.com/game/canvas-stock-index/

ABOUT

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

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

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

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

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

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

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