创建画布的旋转克隆

时间:2016-07-18 16:17:16

标签: javascript html5 canvas

我有一个非常简单的代码,它证明了一个问题。所以,在一个页面上我有这个html:

<canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;"></canvas>

我有这段代码:

function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    return image;
}

function convertImageToCanvas(image) {
    var canvas = document.createElement("canvas");
    document.body.appendChild(canvas);
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);
    return canvas;
}

var canvas1 = document.getElementById("myCanvas");
var ctx1 = canvas1.getContext("2d");

ctx1.rotate(-30 * Math.PI / 180);
ctx1.rect(10, 60, 80, 40);
ctx1.stroke(); 

var image = convertCanvasToImage(canvas1);
var canvas2 = convertImageToCanvas(image);
document.body.appendChild(canvas2);

var ctx2 = canvas2.getContext("2d");
ctx2.rotate(30 * Math.PI / 180); // <-- This does not work

所以,正如你所看到的,我这样做了。首先,我创建一个画布,然后旋转它并绘制一个图像,然后我从这个画布创建一个图像,然后从这个图像创建一个全新的画布。最后,我将此画布添加到页面并尝试旋转它,但它不起作用。此代码(代码的最后一行)无效:

ctx2.rotate(30 * Math.PI / 180);

我尝试了很多其他角度,但仍然看不到任何影响。到底发生了什么,我该如何解决?

PS。这是我所拥有的图片:

enter image description here

1 个答案:

答案 0 :(得分:1)

使用合成来制作仅包含所需旋转矩形的画布副本。

  1. 创建主画布的副本。
  2. 在复制画布上填充旋转的矩形。
  3. 将合成设置为source-atop,这会导致任何新像素仅显示现有像素不透明的位置(==仅显示在填充的矩形中)。
  4. 将主画布绘制到复制画布上。只显示旋转矩形的内容 - 其他一切都是透明的。
  5. 示例代码和演示:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
    
    var rotationX=0;
    var rotationY=0;
    var x=10;
    var y=60;
    var w=80;
    var h=40;
    var rAngle=-30*Math.PI/180;
    
    var img=new Image();
    img.onload=start;
    img.src="https://dl.dropboxusercontent.com/u/139992952/multple/reef.jpg";
    function start(){
        cw=canvas.width=img.width;
        ch=canvas.height=img.height;
        ctx.drawImage(img,0,0);
        defineRotatedRect(ctx,rotationX,rotationY,x,y,w,h,rAngle)
        ctx.strokeStyle='red';
        ctx.stroke();
        //
        copyRotatedRectOnly(canvas,rotationX,rotationY,x,y,w,h,rAngle);
    }
    
    function copyRotatedRectOnly(canvas,rx,ry,x,y,w,h,rAngle){
        var c=canvas.cloneNode();
        var cctx=c.getContext('2d');
        document.body.appendChild(c);
        defineRotatedRect(cctx,rotationX,rotationY,x,y,w,h,rAngle)
        cctx.fill();
        cctx.globalCompositeOperation='source-atop';
        cctx.drawImage(canvas,0,0);
        return(c);
    }
    
    function defineRotatedRect(context,rx,ry,x,y,w,h,rAngle){
        context.translate(rx,ry);
        context.rotate(rAngle);
        context.beginPath();
        context.rect(x,y,w,h);
        context.rotate(-rAngle);
        context.translate(-rotationX,-rotationY);
    }
    body{ background-color:white; }
    canvas{border:1px solid red; }
    <h4>Original Canvas</h4>
    <canvas id="canvas" width=512 height=512></canvas>
    <h4>Copy containing only the rotated rectangle</h4>