如何计算旋转图像的正确位置偏移?

时间:2012-03-14 16:56:05

标签: c# javascript css math

我正在尝试制造一个小型仪表控制装置,有点像车内的车速表,除了它只能跨越180度。

要渲染控件,我使用的是两个图像文件。第一个是仪表的背景,显示了一个半圆,从0度的绿色到180度的红色。第二幅图像是一个垂直箭头,与半圆的半径大致相同,略小于背景图像的高度。

我使用以下标记来呈现控件:

<div class="gauge" id="@Model.ClientID">
    <img class="gauge" alt="" src="@Url.Content( "~/images/icons/gauge-bg.png" )" />
    <img class="arrow" alt="" src="@Url.Content( "~/images/icons/gauge-arrow.png" )" />
</div>

图像位于div的相对内部,以便它们重叠。背景图像为120x63像素,箭头图像为12x58像素(WxH),但如果能够更轻松地解决问题,则可以进行调整。在应用任何旋转之前,箭头图像会直指向上。

我有一个百分比(从0到100)我转换为箭头图像的旋转角度(从-90到90),如下所示:

// input value for the offset calculations (see below)
public double ArrowRotationDegrees 
{
    // 0 for 0%, 90 for 50% and 180 for 100%
    get { return 180.0 * Percent / 100; }
}

// input value for the jquery rotate plugin as our base arrow points vertically up
public double ArrowRotationDegreesRelative // -90 for 0%, 0 for 50% and 90 for 100%
{
    // -90 for 0%, 0 for 50% and 90 for 100%
    get { return ArrowRotationDegrees - 90; }
}

要执行旋转我正在使用jquery-rotate,它似乎总是围绕图像的中心旋转。

<script type="text/javascript">
    $(document).ready(function () {
        var arrow = $('#@Model.ClientID').find('img.arrow');
        arrow.rotate(@Model.ArrowRotationDegreesRelative);
        arrow.css({left: @Model.ArrowLeftShiftPixels, top: @Model.ArrowTopShiftPixels});
    });
</script>

但是,如何计算重新定位旋转图像的正确偏移量,以使箭头始终指向背景图像的正中心底部?

更新 - 解决方案

根据Eric J.的回答,我能够调整代码并获得工作结果,而无需更改标记:

public int ArrowLeftShiftPixels // used to position rotated image correctly horizontally
{
    // default offset (no rotation) is left:55
    get { return 55 - GetArrowLeftShift( ArrowRotationDegrees ); }
}

public int ArrowTopShiftPixels // used to position rotated image correctly vertically
{
    // default offset (no rotation) is top:5
    // formula output is shifted (max appears where min should be); add 29 to reverse this effect
    get { return 34 - GetArrowTopShift( ArrowRotationDegrees ); }
}

public int GetArrowLeftShift( double degrees )
{
    var result = (58.0 / 2) * Math.Cos( degrees * Math.PI / 180 );
    return (int) Math.Round( result, 0 );
}

public int GetArrowTopShift( double degrees )
{
    var result = (58.0 / 2) * Math.Sin( degrees * Math.PI / 180 );
    return (int) Math.Round( result, 0 );
}

感谢所有的帮助和建议!

3 个答案:

答案 0 :(得分:1)

我没有详细查看你问题的具体数字(根据底部的箭头是反对的,反之亦然?),但你可能会发现箭头的左侧或右侧移动了图像的中心位于(half it's length) * cos(Angle),而它们向上或向下移动(half it's length) * sin (Angle)。确保在指定角度时使用弧度或度数,以适合用于计算sin和cos的trig库。

如果您在C#中计算sincos服务器端,请使用弧度。

Here's an explanation如何旋转任意角度(匹配我刚才解释的,但图表可能会有所帮助)。请注意,在您的情况下,初始角度为0,因此初始公式为

  

x = 0(因为cos(0)= 0)   y = r(因为r * sin(0)= r)

答案 1 :(得分:1)

您可以在两个维度中生成大小为图像大小两倍的div。然后你绝对会把你的图像放在那个div中,所以图像的枢轴点(箭头的底部)是div的半高和宽。然后,您可以将div转换为正确的区域(因此图像的关键点位于正确的区域中),然后在div上执行旋转。

编辑:这是一个解释它的jsfiddle http://jsfiddle.net/pVpE7/

答案 2 :(得分:1)

看看this example。说明:

旋转插件不允许您指定锚点 - 它始终围绕中心旋转。我只是将箭头的大小加倍,使其横跨量规的宽度。旋转此箭头可以获得所需的效果。对CSS进行了一些小调整,以保持箭头的溢出部分处于控制状态。