440

<canvas>ページに合わせて HTML5 要素を自動的にスケーリングするにはどうすればよいですか?

たとえば、とプロパティを 100% に<div>設定することで をスケーリングできますが、はスケーリングしませんか?heightwidth<canvas>

4

17 に答える 17

397

これに対するエレガントな解決策を見つけたと思います:

JavaScript

/* important! for alignment, you should make things
 * relative to the canvas' current width/height.
 */
function draw() {
  var ctx = (a canvas context);
  ctx.canvas.width  = window.innerWidth;
  ctx.canvas.height = window.innerHeight;
  //...drawing code...
}

CSS

html, body {
  width:  100%;
  height: 100%;
  margin: 0;
}

これまでのところ、パフォーマンスに大きなマイナスの影響はありません。

于 2010-06-20T06:43:09.743 に答える
73

次の解決策が私にとって最も効果的でした。私はコーディングに比較的慣れていないので、何かが期待どおりに機能していることを視覚的に確認するのが好きです。次のサイトで見つけました: http://htmlcheats.com/html/resize-the-html5-canvas-dyamically/

コードは次のとおりです。

(function() {
  var
    // Obtain a reference to the canvas element using its id.
    htmlCanvas = document.getElementById('c'),
    // Obtain a graphics context on the canvas element for drawing.
    context = htmlCanvas.getContext('2d');

  // Start listening to resize events and draw canvas.
  initialize();

  function initialize() {
    // Register an event listener to call the resizeCanvas() function 
    // each time the window is resized.
    window.addEventListener('resize', resizeCanvas, false);
    // Draw canvas border for the first time.
    resizeCanvas();
  }

  // Display custom canvas. In this case it's a blue, 5 pixel 
  // border that resizes along with the browser window.
  function redraw() {
    context.strokeStyle = 'blue';
    context.lineWidth = '5';
    context.strokeRect(0, 0, window.innerWidth, window.innerHeight);
  }

  // Runs each time the DOM window resize event fires.
  // Resets the canvas dimensions to match window,
  // then draws the new borders accordingly.
  function resizeCanvas() {
    htmlCanvas.width = window.innerWidth;
    htmlCanvas.height = window.innerHeight;
    redraw();
  }
})();
html,
body {
  width: 100%;
  height: 100%;
  margin: 0px;
  border: 0;
  overflow: hidden;
  /*  Disable scrollbars */
  display: block;
  /* No floating content on sides */
}
<canvas id='c' style='position:absolute; left:0px; top:0px;'></canvas>

青い境界線は、サイズ変更キャンバスの端を示しており、常にウィンドウの端に沿っており、4 つの側面すべてに表示されています。これは、上記の他の回答の一部には当てはまりませんでした。それが役に立てば幸い。

于 2015-03-06T14:05:20.023 に答える
22

基本的に、onresize イベントをボディにバインドする必要があります。イベントをキャッチしたら、window.innerWidth と window.innerHeight を使用してキャンバスのサイズを変更するだけです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Canvas Resize</title>

    <script type="text/javascript">
        function resize_canvas(){
            canvas = document.getElementById("canvas");
            if (canvas.width  < window.innerWidth)
            {
                canvas.width  = window.innerWidth;
            }

            if (canvas.height < window.innerHeight)
            {
                canvas.height = window.innerHeight;
            }
        }
    </script>
</head>

<body onresize="resize_canvas()">
        <canvas id="canvas">Your browser doesn't support canvas</canvas>
</body>
</html>
于 2011-09-08T22:18:59.180 に答える
19

ブラウザー クライアントのサイズに基づいてキャンバス座標空間の幅と高さを設定すると、ブラウザーのサイズが変更されるたびに、サイズ変更と再描画が必要になります。

それほど複雑でない解決策は、描画可能なサイズを Javascript 変数で維持することですが、キャンバスのサイズは screen.width、screen.height のサイズに基づいて設定します。CSS を使用して適合させる:

#containingDiv { 
  overflow: hidden;
}
#myCanvas {
  position: absolute; 
  top: 0px;
  left: 0px;
} 

通常、ブラウザー ウィンドウが画面自体よりも大きくなることはありません (デュアル モニターが一致しない場合など、画面の解像度が誤って報告される場合を除きます)。そのため、背景が表示されず、ピクセルの比率が変化しません。CSS を使用してキャンバスをスケーリングしない限り、キャンバスのピクセルは画面の解像度に正比例します。

于 2011-10-23T01:17:51.797 に答える
18

上記の @jerseyboy のソリューションに追加する純粋な CSSアプローチ。
Firefox (v29 でテスト済み)、Chrome (v34 でテスト済み)、Internet Explorer (v11 でテスト済み) で動作します。

<!DOCTYPE html>
<html>
    <head>
    <style>
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
        }
        canvas {
            background-color: #ccc;
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="500" height="500"></canvas>
    <script>
        var canvas = document.getElementById('canvas');
        if (canvas.getContext) {
            var ctx = canvas.getContext('2d');
            ctx.fillRect(25,25,100,100);
            ctx.clearRect(45,45,60,60);
            ctx.strokeRect(50,50,50,50);
        }
    </script>
</body>
</html>

例へのリンク: http://temporaer.net/open/so/140502_canvas-fit-to-window.html

ただし、@jerseyboy がコメントで述べているように、注意してください。

CSS でキャンバスをリスケールするのは面倒です。少なくとも Chrome と Safari では、マウス/タッチ イベントの位置はキャンバスのピクセル位置と 1:1 で対応しないため、座標系を変換する必要があります。

于 2014-05-02T18:51:41.903 に答える
14
function resize() {

    var canvas = document.getElementById('game');
    var canvasRatio = canvas.height / canvas.width;
    var windowRatio = window.innerHeight / window.innerWidth;
    var width;
    var height;

    if (windowRatio < canvasRatio) {
        height = window.innerHeight;
        width = height / canvasRatio;
    } else {
        width = window.innerWidth;
        height = width * canvasRatio;
    }

    canvas.style.width = width + 'px';
    canvas.style.height = height + 'px';
};

window.addEventListener('resize', resize, false);
于 2013-10-16T09:59:10.190 に答える
8

キャンバスで画像データを自動的にアップスケールしたい場合を除き (これは James Black の回答で説明されていますが、見栄えがよくありません)、自分でサイズを変更して画像を再描画する必要があります。キャンバスのセンタリング

于 2009-11-04T13:52:23.207 に答える
4

div が Web ページを完全に埋め尽くした場合、その div を埋めて、div を埋め尽くすキャンバスを作成できます。

パーセンテージを使用するにはcssを使用する必要があるかもしれないので、これは興味深いかもしれませんが、使用しているブラウザーと、仕様にどれだけ一致しているかによって異なります: http://www.whatwg.org/ specs/web-apps/current-work/multipage/the-canvas-element.html#the-canvas-element

canvas 要素の固有の寸法は座標空間のサイズに等しく、数値は CSS ピクセルで解釈されます。ただし、要素はスタイル シートによって任意のサイズにすることができます。レンダリング中、イメージはこのレイアウト サイズに合わせてスケーリングされます。

div の offsetWidth と高さを取得するか、ウィンドウの高さ/幅を取得してピクセル値として設定する必要がある場合があります。

于 2009-11-03T02:29:18.073 に答える
3

CSS

body { margin: 0; } 
canvas { display: block; } 

JavaScript

window.addEventListener("load", function()
{
    var canvas = document.createElement('canvas'); document.body.appendChild(canvas);
    var context = canvas.getContext('2d');

    function draw()
    {
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.beginPath();
        context.moveTo(0, 0); context.lineTo(canvas.width, canvas.height); 
        context.moveTo(canvas.width, 0); context.lineTo(0, canvas.height); 
        context.stroke();
    }
    function resize()
    {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        draw();
    }
    window.addEventListener("resize", resize);
    resize();
});
于 2014-11-28T16:39:05.970 に答える
3

縦横比を保持し、純粋な CSS で (縦横比を指定して) 実行することに関心がある場合は、以下のようにすることができます。キーは、padding-bottom要素::contentのサイズを設定するcontainer要素にあります。これは100%、デフォルトの親の幅を基準にしてサイズ変更されます。ここで指定する比率は、canvas要素のサイズの比率と一致する必要があります。

// Javascript

var canvas = document.querySelector('canvas'),
    context = canvas.getContext('2d');

context.fillStyle = '#ff0000';
context.fillRect(500, 200, 200, 200);

context.fillStyle = '#000000';
context.font = '30px serif';
context.fillText('This is some text that should not be distorted, just scaled', 10, 40);
/*CSS*/

.container {
  position: relative; 
  background-color: green;
}

.container::after {
  content: ' ';
  display: block;
  padding: 0 0 50%;
}

.wrapper {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
}

canvas {
  width: 100%;
  height: 100%;
}
<!-- HTML -->

<div class=container>
  <div class=wrapper>
    <canvas width=1200 height=600></canvas>  
  </div>
</div>

于 2015-05-31T17:34:26.477 に答える
1

すべての答えを組み合わせた小さな完全なコード スニペットを次に示します。[コード スニペットを実行] を押してから [フル ページ] を押し、ウィンドウのサイズを変更して実際の動作を確認します。

function refresh(referenceWidth, referenceHeight, drawFunction) {
  const myCanvas = document.getElementById("myCanvas");
  myCanvas.width = myCanvas.clientWidth;
  myCanvas.height = myCanvas.clientHeight;

  const ratio = Math.min(
    myCanvas.width / referenceWidth,
    myCanvas.height / referenceHeight
  );
  const ctx = myCanvas.getContext("2d");
  ctx.scale(ratio, ratio);

  drawFunction(ctx, ratio);
  window.requestAnimationFrame(() => {
    refresh(referenceWidth, referenceHeight, drawFunction);
  });
}

//100, 100 is the "reference" size. Choose whatever you want.
refresh(100, 100, (ctx, ratio) => {
  //Custom drawing code! Draw whatever you want here.
  const referenceLineWidth = 1;
  ctx.lineWidth = referenceLineWidth / ratio;
  ctx.beginPath();
  ctx.strokeStyle = "blue";
  ctx.arc(50, 50, 49, 0, 2 * Math.PI);
  ctx.stroke();
});
div {
  width: 90vw;
  height: 90vh;
}

canvas {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
<div>
  <canvas id="myCanvas"></canvas>
</div>

このスニペットは、window.innerWidth と window.innerHeight ではなく canvas.clientWidth と canvas.clientHeight を使用して、複雑なレイアウト内でスニペットを正しく実行します。ただし、フル ウィンドウを使用する div に配置するだけで、フル ウィンドウでも機能します。この方法はより柔軟です。

このスニペットは、新しい window.requestAnimationFrame を使用して、フレームごとにキャンバスのサイズを繰り返し変更します。これを使用できない場合は、代わりに setTimeout を使用してください。また、これは非効率的です。より効率的にするには、clientWidth と clientHeight を保存し、clientWidth と clientHeight が変更された場合にのみ再計算して再描画します。

「参照」解像度の考え方により、1 つの解像度を使用してすべての描画コマンドを記述できます。描画コードを変更しなくても、クライアントのサイズに自動的に調整されます。

スニペットは自明ですが、英語で説明したい場合: https://medium.com/@doomgoober/resizing-canvas-vector-graphics-without-aliasing-7a1f9e684e4d

于 2020-08-28T23:36:14.327 に答える
0

これがまさに私たちがすべきことだと思います:http://www.html5rocks.com/en/tutorials/casestudies/gopherwoord-studios-resizing-html5-games/

function resizeGame() {
    var gameArea = document.getElementById('gameArea');
    var widthToHeight = 4 / 3;
    var newWidth = window.innerWidth;
    var newHeight = window.innerHeight;
    var newWidthToHeight = newWidth / newHeight;

    if (newWidthToHeight > widthToHeight) {
        newWidth = newHeight * widthToHeight;
        gameArea.style.height = newHeight + 'px';
        gameArea.style.width = newWidth + 'px';
    } else {
        newHeight = newWidth / widthToHeight;
        gameArea.style.width = newWidth + 'px';
        gameArea.style.height = newHeight + 'px';
    }

    gameArea.style.marginTop = (-newHeight / 2) + 'px';
    gameArea.style.marginLeft = (-newWidth / 2) + 'px';

    var gameCanvas = document.getElementById('gameCanvas');
    gameCanvas.width = newWidth;
    gameCanvas.height = newHeight;
}

window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);
于 2014-01-04T04:31:11.993 に答える
-2

私は sketch.js を使用しているので、キャンバスの init コマンドを実行した後、jquery で幅と高さを変更します。親要素に基づく寸法です。

$('#DrawCanvas').sketch().attr('height',$('#DrawCanvas').parent().height()).attr('width',$('#DrawCanvas').parent ()。幅());

于 2015-01-06T05:43:04.267 に答える