确定图像偏移

时间:2013-05-09 14:46:59

标签: math canvas kineticjs

我有一个大圆圈,图像作为填充图案。圆圈旋转。

当我在圆圈内部单击时,我希望创建一个包含相同图像和相同偏移的较小圆圈。基本上它应该看起来好像较小的圆圈是透明的。

所以我的问题如下:

如何通过旋转更大的圆圈来确定较小圆圈的背景图像的偏移量?

以下是错误偏移的示例:

An example of the wrong offset

1 个答案:

答案 0 :(得分:1)

我猜你的小圆圈的源图像与大圆圈相同 - 只是没有旋转。

如果是这种情况,您需要找到未旋转的鼠标点击位置。

然后,您可以在未旋转的鼠标点击周围剪切较小的圆圈并将其旋转到位。

假设:

  • 您的原始旋转中心是cx / cy,
  • 你的旋转角度是radAngle(弧度)
  • 您的旋转的mousclick点是rx / ry。

您可以像这样计算未旋转的鼠标点击位置(preRX / preRY):

// the bigger circle's rotation point  
var cx=150;
var cy=150;

// the rotation angle in radians
var radAngle=Math.PI/6;   // 30 degrees, for example

// the rotated mouseclick point
var rx=225;
var ry=245;

// the radius of the smaller circle
var smallRadius=50;

// calculate the unrotated mouseclick point
var dx= rx-cx;
var dy= ry-cy;
var preRX= cx+ dx*Math.cos(-radAngle) - dy*Math.sin(-radAngle); 
var preRY= cy+ dy*Math.cos(-radAngle) + dx*Math.sin(-radAngle);

然后使用较小的圆圈制作剪切路径

// create a clipping path for the small circle
ctx.arc(preRX,preRY,smallRadius,0,Math.PI*2,false);
ctx.closePath();
ctx.clip();

最后翻译+旋转并将剪裁的图像绘制到位

// rotate the small circle into position
ctx.translate(cx,cy);
ctx.rotate(radAngle);
ctx.globalAlpha=1.0;
ctx.drawImage(img,-img.width/2,-img.height/2);

这是代码和小提琴:http://jsfiddle.net/m1erickson/YAt5r/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas = document.getElementById('canvas');
    var ctx=canvas.getContext("2d");

    var img=new Image();
    img.onload=function(){
        draw();
    }
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house-icon.png";


    function draw(){

        // the bigger circle's rotation point  
        var cx=150;
        var cy=150;

        // the rotation angle in radians
        var radAngle=Math.PI/6;   // 30 degrees

        // the rotated mouseclick point
        var rx=225;
        var ry=245;

        // the radius of the smaller circle
        var smallRadius=50;

        // calculate the unrotated mouseclick point
        var dx= rx-cx;
        var dy= ry-cy;
        var preRX= cx+ dx*Math.cos(-radAngle) - dy*Math.sin(-radAngle); 
        var preRY= cy+ dy*Math.cos(-radAngle) + dx*Math.sin(-radAngle);

        // test

        // rotate the original image and draw it
        ctx.save();
        ctx.translate(cx,cy);
        ctx.rotate(radAngle);
        ctx.globalAlpha=.25;
        ctx.drawImage(img,-img.width/2,-img.height/2);
        ctx.restore();

        // clip the smaller image, rotate it and draw it
        ctx.save();
        ctx.beginPath();

        // create a clipping path for the small circle
        ctx.arc(preRX,preRY,smallRadius,0,Math.PI*2,false);
        ctx.closePath();
        ctx.clip();

        // rotate the small circle into position
        ctx.translate(cx,cy);
        ctx.rotate(radAngle);
        ctx.globalAlpha=1.0;
        ctx.drawImage(img,-img.width/2,-img.height/2);

        // stroke the circle
        ctx.arc(preRX,preRY,smallRadius,0,Math.PI*2,false);
        ctx.stroke();
        ctx.restore();

    }


}); // end $(function(){});
</script>

</head>

<body>
    <p>Original image is 25% opacity</p>
    <p>Clipped overlay image is 100% opacity</p>
    <canvas id="canvas" width=350 height=350></canvas>
</body>
</html>