Javascript 当适合flex容器大小时,画布会增大

Javascript 当适合flex容器大小时,画布会增大,javascript,html,css,canvas,Javascript,Html,Css,Canvas,我想要实现的布局是(无需阅读,是不言自明的。请尝试调整大小): #内容应该是屏幕/视口的100%高度,既不高也不低 两行,#内容标题和#面板。#panels行应填充垂直空间 #面板应包含div,其中一些是包裹的画布。画布应该是一个正方形,大小与包装的最小宽度和高度相同 我有两个问题: 调整窗口的大小会使画布的大小无限增长。(尝试调整JSFIDLE框架的大小) 我从最初的resize调用猜测,内容已经垂直溢出 我试图使示例尽可能简单,并对大部分代码进行了注释,希望足够了 test.html &

我想要实现的布局是(无需阅读,是不言自明的。请尝试调整大小):

  • #内容应该是屏幕/视口的100%高度,既不高也不低
  • 两行,#内容标题和#面板。#panels行应填充垂直空间
  • #面板应包含div,其中一些是包裹的画布。画布应该是一个正方形,大小与包装的最小宽度和高度相同
我有两个问题:

  • 调整窗口的大小会使画布的大小无限增长。(尝试调整JSFIDLE框架的大小)
  • 我从最初的resize调用猜测,内容已经垂直溢出
  • 我试图使示例尽可能简单,并对大部分代码进行了注释,希望足够了

    test.html

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width,initial-scale=1">
            <title>Test</title>
            <link rel="stylesheet" href="normalize.css">
            <link rel="stylesheet" href="test.css">
            <script src="test.js"></script>
        </head>
        <body>
            <div id="content">
                <div id="content-header">HEADER</div>
                <div id="panels">
                    <div class="canvas-wrapper">
                        <canvas id="test-canvas"></canvas>
                    </div>
                </div>
            </div>
        </body>
    </html>
    
    test.js

    /* Border box */
    
    html {
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
                box-sizing: border-box;
    }
    
    *,
    *::before,
    *::after {
        -webkit-box-sizing: inherit;
            -moz-box-sizing: inherit;
                box-sizing: inherit;
    }
    
    /* Full height #content */
    
    html, body, #content {
        height: 100%;
    }
    
    /* #panels fills verical space */
    
    #content {
        display: flex;
        flex-direction: column;
    }
    
    #content-header {
        flex: 0 1 0;
    }
    
    #panels {
        flex: 1 0 0;
    }
    
    /* #panels is flex row container */
    
    #panels {
        display: flex;
        flex-direction: row;
    }
    
    /* Wrapping canvas to calculate size from flex container */
    
    .canvas-wrapper {
        display: block;
    
        /* Can grow and can shrink */
        flex: 1 1 auto;
    
        background-color: rgba(0, 0, 255, 0.2);
    }
    
    canvas {
        display: block;
        
        /* Center horizontally */
        margin: 0 auto;
    
        border: 1px solid red;
    }
    
    // width X height -> size X size, size is min(parentWidth, parentHeight)
    function fitToParent(element) {
        // parent element is the .canvas-wrapper
        const parentWidth = element.parentElement.clientWidth;
        const parentHeight = element.parentElement.clientHeight;
    
        const size = Math.min(parentWidth, parentHeight);
    
        // for debug
        console.log('Wrapper size = ' + parentWidth + 'x' + parentHeight + ' Canvas size = ' + size + 'x' + size);
    
        element.width = size;
        element.height = size;
    }
    
    window.addEventListener('load', function() {
        const canvas = document.getElementById('test-canvas');
        const ctx = canvas.getContext('2d');
    
        function resize() {
            fitToParent(canvas);
    
            // random draw operation, doesn't matter
            ctx.fillStyle = 'green';
            ctx.fillRect(10, 10, 150, 100);
        }
    
        window.addEventListener('resize', resize);
    
        resize();
    });
    

    通过进一步的测试,问题似乎是由于#panels flex容器(或任何其他显示样式)将画布的大小视为最小而导致的

    我发现的一个解决方法是,在调整画布大小之前,首先将画布的宽度和高度设置为0。 但我不确定这是否正常,它会导致一些我希望避免的不稳定动画。在接受这个答案之前,我会等待,以防有人能想到别的东西

    此外,第二个问题(垂直溢出)仍然存在

    // width X height -> size X size, size is min(parentWidth, parentHeight)
    function fitToParent(element) {
        // WORKAROUND
        element.width = 0;
        element.height = 0;
        
        // parent element is the .canvas-wrapper
        const parentWidth = element.parentElement.clientWidth;
        const parentHeight = element.parentElement.clientHeight;
    
        const size = Math.min(parentWidth, parentHeight);
    
        // for debug
        console.log('Wrapper size = ' + parentWidth + 'x' + parentHeight + ' Canvas size = ' + size + 'x' + size);
    
        element.width = size;
        element.height = size;
    }
    
    解决办法

    编辑

    显然,画布宽度和高度属性不考虑框大小,因此边界溢出。通过将css属性设置为与元素属性相同的值(宽度、高度->style.width、style.height)进行修复

    所以,我认为第二个问题已经解决了

    // width X height -> size X size, size is min(parentWidth, parentHeight)
    function fitToParent(element) {
        // WORKAROUND
        element.width = 0;
        element.height = 0;
        element.style.width = 0;
        element.style.height = 0;
        
        // parent element is the .canvas-wrapper
        const parentWidth = element.parentElement.clientWidth;
        const parentHeight = element.parentElement.clientHeight;
    
        const size = Math.min(parentWidth, parentHeight);
    
        // for debug
        console.log('Wrapper size = ' + parentWidth + 'x' + parentHeight + ' Canvas size = ' + size + 'x' + size);
    
        element.width = size;
        element.height = size;
        element.style.width = size + 'px';
        element.style.height = size + 'px';
    }
    

    这是否回答了您的问题?我用在particular@MattEllen不幸的是,没有。我实际上从实际代码中删除了去抖动功能,以使问题更加明显。使用去抖动,结果是相同的,但速度较慢,因为调用resize函数的次数要少得多。