2012-03-14 607 views
2

我想创建一个小型控制器,有点像汽车里的车速表,只是它只能跨越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> 

但是我怎么计算重新定位旋转的图像正确的偏移,使得箭头总是从背景图像的确切中心底点?

更新 - 解

基于埃里克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); 
} 

感谢所有帮助和建议!

回答

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)

+0

起初,我无法完成这项工作,直到我创建了工作/预期输出值表并将其与计算结果进行比较。 TopShift值会以某种方式发生变化(最小值出现在最大值出现的位置),但一旦发现问题很容易进行补偿。谢谢! – 2012-03-15 00:06:16

1

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

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

+0

我尝试添加一个包装div,但是我无法想出任何有效的工作,所以我回去计算偏移量。它看起来应该工作,如果我做了正确的事情,所以+1) – 2012-03-15 00:12:15

1

看一看this example。说明:

rotate插件不允许您指定锚点 - 它总是围绕中心旋转。我简单地将箭头的大小加倍,以便在仪表宽度上延伸。旋转此箭头可以获得所需的效果。对CSS进行微小的调整以保持控制中的箭头溢出部分。

+0

我也看了这个,你显然有一些工作(+1),但我无法将其转化为一些东西为我工作。 – 2012-03-15 00:13:32