Bill Balloni
Bill Balloni

Reputation: 21

Can't get <canvas> in a <table> to shrink in width

I am having a problem getting the desired layout of canvas elements on a page. I am using a table to do the layout. The desired layout is to have one canvas to the left that is full height and two other canvases to the right, one on top of the other, with a combined height of the left canvas. The two right canvases are of fixed width and height. When the browser window is resized I want the left canvas to resize to take up all the width available (up to the width of the right canvases). I am using window.onresize event to catch the resize events and to resize the left canvas.

The problem I see is that the left cavas will resize correctly when the browser window width gets bigger, but fails to shrink when the browser window width gets smaller! The code is below. What gives? Is there something inherent in canvas that doesn't allow flexible resizing?

I have searched for a answer to this issue with no luck. Hopefully someone here has conquered this and can give me a hand.

Here is sample code:

<!DOCTYPE html>
<html>
    <head>
        <title>SO Example</title>
        <script type="text/javascript">
            window.onload = function ()
            {
                var canvas = document.getElementById("wf1");
                canvas.width = canvas.parentNode.clientWidth;
                canvas.height = canvas.parentNode.clientHeight;
            }
            window.onresize = function ()
            {
                var canvas = document.getElementById("wf1");
                canvas.width = canvas.parentNode.clientWidth;
                canvas.height = canvas.parentNode.clientHeight;
            }
        </script>

        <style type="text/css">
            table
            {
                border-collapse: collapse;
                background-color: #ccc;
            }
            tr, td
            {
                padding: 0;
                line-height: 0;
                width: 100%;
            }
        </style>
    </head>

    <body>
        <table>
            <tr class="slot">
                <td>
                    <canvas id="wf1" class="wfblock" style="background-color:red;"></canvas>
                </td>
                <td>
                    <canvas id="pm1" style="background-color: green; width: 200px; height: 84px;"></canvas>
                    <canvas id="pm2" style="background-color: blue;  width: 200px; height: 84px;"></canvas>
                </td>
            </tr>
        </table>
    </body>
</html>

Upvotes: 0

Views: 2818

Answers (1)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382454

Your canvas can be adjusted in both directions : growing and shrinking.

I do that frequently but I found that the only thing that always works (especially when tables are involved) is giving 100% dimensions for both width and height and adjust the container (be it a td or a div) in a classical way.

To avoid problem with viewport dimensions being different from the ones of the canvas, I always add a listener for the resize event.

Using jquery, I usually end up with this kind of class, where an instance of Grapher is created for each canvas :

function Grapher(options) {
    this.graphId = options.canvasId;
    this.dimChanged = true; // you may remove that if you want (see above)
};

Grapher.prototype.draw = function() {
    if (!this._ensureInit()) return;

    // makes all the drawing, depending on the state of the application's model

    // uses dimChanged to know if the positions and dimensions of drawed objects have
    //  to be recomputed due to a change in canvas dimensions

}

Grapher.prototype._ensureInit = function() {
    if (this.canvas) return true;
    var canvas = document.getElementById(this.graphId);
    if (!canvas) {
        return false;
    }
    if (!$('#'+this.graphId).is(':visible')) return false;
    this.canvas = canvas;
    this.context = this.canvas.getContext("2d");
    var _this = this;
    var setDim = function() {
        _this.w = _this.canvas.clientWidth;
        _this.h = _this.canvas.clientHeight;
        _this.canvas.width = _this.w;
        _this.canvas.height = _this.h;
        _this.dimChanged = true;
        _this.draw(); // calls the function that draws the content
    };
    setDim();
    $(window).resize(setDim);
    // other inits (mouse hover, mouse click, etc.)
    return true;
};

In your case I would create for example new Grapher({canvasId:'#wf1'}).

Upvotes: 0

Related Questions