【问题标题】:How to calculate correct position offsets for rotated image?如何计算旋转图像的正确位置偏移?
【发布时间】:2012-03-31 04:13:31
【问题描述】:

我正在尝试创建一个小型仪表控制,有点像汽车中的速度计,只是它只跨越 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 );
}

感谢所有帮助和建议!

【问题讨论】:

    标签: c# javascript css math


    【解决方案1】:

    看看this example。说明:

    旋转插件不允许你指定锚点——它总是围绕中心旋转。我只是将箭头的大小翻了一番,使其横跨仪表的宽度。旋转此箭头可为您提供所需的效果。添加了对 CSS 的细微调整以控制箭头的溢出部分。

    【讨论】:

    • 我也看过这个,你显然有一些工作(+1),但我无法将它翻译成对我有用的东西。
    【解决方案2】:

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

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

    【讨论】:

    • 我尝试添加一个包装器 div,但我无法想出任何可行的方法,所以我返回计算偏移量。如果我做对了事情,它看起来应该会起作用,所以 +1 :)
    【解决方案3】:

    我没有详细查看你的问题的具体数字(底部的箭头是朝上还是反之?),但你可能会发现箭头的尖端向左或向右移动图像中心由(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)

    【讨论】:

    • 起初我无法完成这项工作,直到我制作了一个工作/预期输出值表并将其与计算结果进行比较。 TopShift 值以某种方式移动(最小值出现在预期最大值的位置),但是一旦发现问题就很容易补偿。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 2022-01-07
    • 1970-01-01
    相关资源
    最近更新 更多