Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

javascript - Trying to rotate canvas, something is going wrong

So I'm trying to make a nice interactive map of my office in HTML5 for documentation purposes(tracking phone extensions, port numbers, etc), and since a lot of our offices and cubicles are the same, I figure I should have just one of each type of office, then just duplicate it for all of the offices it matches. My only issue is, I can't rotate the canvas properly. I've followed all the tutorials, but for some reason, my image keeps getting cut off. I can't seem to locate the source of the problem.

Any ideas?

Here is my code so far:

http://jsfiddle.net/pmcDw/1/

<!DOCTYPE HTML>

<head>
    <title>Test Interactive Office Schematic</title>
    <style>
        html, body {
            margin: 0px;
            padding: 0px;
        }
    </style>
</head>

<body>
    <script>
        function addOffice(type, id, occupentName) { 

            var canvas = document.createElement('canvas');
            canvas.id = id;
            canvas.style.position = "absolute";
            canvas.style.left = "20px";
            canvas.style.class = "office";
            var context = canvas.getContext('2d');
            context.beginPath();
            context.moveTo(0, 0);
            if (type == 1) {
                canvas.width = 80;
                canvas.height = 80;
                context.lineTo(2, 0);
                context.lineTo(2, 20);
                context.quadraticCurveTo(22, 20, 22, 0);
                context.lineTo(60, 0);
                context.lineTo(60, 80);
                context.lineTo(0, 80);
                context.lineTo(0, 0);
            }
            context.lineWidth = 2;
            context.strokeStyle = 'black';
            context.stroke();
            context.textBaseline = "Alphabetic";
            context.textAlign = "center";
            context.fillText(occupentName, canvas.width / 2, canvas.height / 2);
            document.body.appendChild(canvas);
            canvas = document.getElementById("1");
            context = canvas.getContext('2d');
            var tempCanvas = document.createElement("canvas"),
                tempCtx = tempCanvas.getContext("2d");
            tempCanvas.width = canvas.width;
            tempCanvas.height = canvas.height;
            tempCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height);
            context.clearRect(0, 0, canvas.width, canvas.height);
            context.save();
            context.translate(canvas.width / 2, canvas.height / 2);
            context.rotate(180 * Math.PI / 180);
            context.drawImage(tempCanvas, 0, 0, 80, 80, 40, 40, 80, 80);
            context.restore();
        }
        addOffice(1, 1, "test");
    </script>
</body>

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After you have translated and rotated the context you need to translate back:

context.translate(canvas.width / 2, canvas.height / 2);
context.rotate(180 * Math.PI / 180);

/// here, translate back:
context.translate(-canvas.width / 2, -canvas.height / 2);

context.drawImage(tempCanvas, 0, 0);

(you don't need to clip and/or specify width and height if destination size is the same as source size).

But if you simply want to flip the image or rotate it 180 you can instead use scale the canvas instead using a negative value - just remember to reverse the coordinates (here's a demo of this technique):

context.scale(-1, -1);
context.drawImage(tempCanvas, -tempCanvas.width, -tempCanvas.height);

More in-depth on transformation in general (update)

To better explain how transformations works lets go through the various stages.

Origo (see definition here) is always point [0, 0] in a coordinate system (or more accurately the point where the axis crosses). When you use transformations this is the point that gets translated in a context for a canvas.

This is also the reason why you manipulate the context an not the canvas directly as the transformations are applied to context and not the element (otherwise the element would be rotated itself when you applied a rotate transformation to it - which you can do by CSS).

Initially the coordinate system looks like this (white blended is non-visible areas of the canvas, the center square is canvas and the blue grid is the context and the current coordinate system):

(Note: ignore the negative Y axis - I somehow managed to overlook that detail when making the graphics - the y axis is of course positive vertically down).

Inital

If we now translate the canvas 3.5 by 3.5 points to get origo at center the context and coordinate system will now look like this:

translated

If we now wanted to apply rotation that will happen at the origo point. This is why we need to translate before rotate as when rotate is applied we get this result:

rotated

If we now just draw the image it will not be centered cause drawImage draws an image from the image's upper left corner. Which means it would look like this:

drawImage non translated

This is why we need to translate back origo so that we compensate for the image corner.

However, since we also have rotation applied the origo will be moved relative to the current systems orientation as well.

We translate back (half the size of the image to get the image's center point at the previous origo point) - the rotation remains the same:

translated back

Now we can call the drawImage as now you can see the origo seem to be in the correct position for this operation:

final transform


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...