0

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>

There are several probable causes of this:

  1. Cellular data networks are not "always-on". Depending on the underlying technology, there can be a substantial delay between when a first packet is sent and when IP connectivity is actually established. This will be most noticeable after IP networking has been idle for some time.

  2. Your receiver may not be correctly checking the socket for readability. Regardless of what high-level APIs you may be using, underneath there needs to be a call to select() to check whether the socket is readable. When a datagram arrives, select() should unblock and signal that the socket descriptor is readable. Alternatively, but less efficiently, you could set the socket to non-blocking and poll it with a read. Polling wastes CPU time when there is no data and delays detection of arrival for up to the polling interval, but can be useful if for some reason you can't spare a thread to wait on select().

  3. I said above that select() should signal readability on a watched socket when data arrives, but this behavior can be modified by the socket's "Receive low-water mark". The default value is usually 1, meaning any data will signal readability. But if SO_RCVLOWAT is set higher (via setsockopt() or a higher-level equivalent), then readability will be not be signaled until more than the specified amount of data has arrived. You can check the value with getsockopt() or whatever API is equivalent in your environment.

Item 1 would cause the first datagram to actually be delayed, but only when the IP network has been idle for a while and not once it comes up active. Items 2 and 3 would only make it appear to your program that the first datagram was delayed: a packet sniffer at the receiver would show the first datagram arriving on time.

4

1 回答 1

0

您的画布可以在两个方向上调整:增长和缩小。

我经常这样做,但我发现唯一始终有效的方法(尤其是在涉及表格时)是为宽度和高度提供 100% 的尺寸,并以经典方式调整容器(无论是 atd还是 a div)。

为了避免视口尺寸与画布尺寸不同的问题,我总是为调整大小事件添加一个侦听器。

使用 jquery,我通常会得到这种类,其中为每个画布创建一个 Grapher 实例:

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;
};

在你的情况下,我会创建例如new Grapher({canvasId:'#wf1'}).

于 2012-05-14T19:41:30.793 回答