【问题标题】:Decrease element size by a factor then increase by same factor to original size将元素大小减小一个因子,然后将元素大小增加相同的因子到原始大小
【发布时间】:2017-01-23 15:47:37
【问题描述】:

首先,我知道我的问题的根源在于 Javascript 中的舍入,我只是不知道如何在这种特定情况下缓解它。

我有一个元素,我希望允许用户通过单击“缩小”按钮来降低高度。高度的减少将作为元素当前高度的比例 - 例如,如果元素是 100px 高,则在缩放因子设置为 0.3 的情况下缩小一次会将其高度减少到 70px。再次缩小会将其高度降低到 49 像素,依此类推。

页面上还有一个“放大”按钮。缩小后,用户应该能够使用“放大”按钮再次增加元素的高度。至关重要的是,放大时元素高度的每个增量都应与缩小时看到的增量相匹配。例如,如果元素在缩小时的高度是:100、70、49、34.3、24.01,那么当再次放大时,元素的高度将是 24.01、34.3、49、70 100。

我创建了一个小提琴来演示此功能here。您会注意到,如果您运行它并最初连续七次单击“缩小”按钮(标记为“-”),然后连续七次单击“放大”按钮,而不是返回元素的高度到 100px,它最终为 95.7142...px,并且放大时的其他高度也不匹配缩小时的高度。

$(function() {
  var zoomAmount = 0.3;
  var $el = $("#testDiv");

  $("#zoomIn").click(function() {
    var currentHeight = $el.height();
    var newHeight = currentHeight * (1 / (1 - zoomAmount));
    //newHeight = Math.round(newHeight * 10000 / 10000);
    $el.height(newHeight);
    $el.html(newHeight);
    if (newHeight >= 100) {
        $("#zoomIn").prop("disabled", true);
    }
  });

  $("#zoomOut").click(function() {
    $("#zoomIn").prop("disabled", false);
    var currentHeight = $el.height();
    var newHeight = currentHeight * (1 - zoomAmount);
    //newHeight = Math.round(newHeight * 10000 / 10000);
    $el.height(newHeight);
    $el.html(newHeight);
  });
});

我知道这是由于用于缩小然后再缩小的计算中的舍入累积引起的,但我不知道如何避免它。您可以看到我已经注释掉了几行试图将元素的高度每次四舍五入到小数点后 2 位的行,但它们没有帮助。没有注释,元素的高度最终为 96px,这向我表明,即使我在将值设置为元素的高度之前四舍五入到 2dp,它仍然以某种方式知道完整的未四舍五入的数字并在计算时使用它下一个新高度。

我能想到的唯一解决方案是在我放大和缩小时将元素的高度值存储在一个数组中,这样当我在相反方向放大时,从数组中查找新高度而不是重新- 计算,但感觉不是很优雅。此外,在我的实际应用程序中,页面上一次有几十个元素,每个元素都有不同的高度,所以我必须在自己的数组中跟踪每个元素的高度,这似乎更不优雅。

有没有一种方法可以在我缩小和缩小时计算元素的高度(实际上你也可以先放大然后缩小,但这需要更多代码,所以我对其进行了简化),这将确保在每个“缩放增量” ' 元素的高度总是一样的?

【问题讨论】:

  • 在数组中存储各种缩放大小对我来说是个好主意。
  • 在这种情况下,存储值是唯一可靠的选择。
  • 如果你保留原来的size值,单独保留modifier,从dos 2中计算出最终值,在增加和减少modifier的时候就不会有任何四舍五入的问题。

标签: javascript rounding


【解决方案1】:

使用指数函数,并将 zoomAmount 保持为整数(更好的名称应该是 zoomLevel)。因此,您可以简单地执行 zoomAmount++zoomAmount-- ,而不是修改会累积舍入误差的浮点数,然后通过将浮点数提升到 zoomAmount (通常是数字,然后,您可以根据需要使用一些常量调整图形)。 例如:

$el.height = base_height * pow(2.7182, zoomAmount)

确保以 zoomAmount = 0 开头,因为 e^0 = 1。 由于整数不存在舍入误差,因此可以保证您具有一致的缩放级别。此解决方案的另一个优点是内存占用少,因为您只需为文档的每个元素保存一个基本高度。

【讨论】:

  • 这正是我一直在寻找的优雅解决方案。我已经为任何想要看到它的人更新了我的小提琴(我希望我理解你的解释 - 它有效,所以看起来就是这样!)。 jsfiddle.net/philipstratford/ug710caz/44
【解决方案2】:

您可以存储以前的值并在放大时弹回 (fiddle)。

$(function() {
    var values = [];

    $("#zoomIn").click(function() {
        var newHeight = values.pop();
        // ...
    });

    $("#zoomOut").click(function() {
        var currentHeight = $el.height(); // this value gets stored
        values.push(currentHeight);
        // ...
    });
});

【讨论】:

  • 实际上,你有没有注意到,如果你用这个放大,你在放大时得到 23.79999999997,但在缩小时得到 24?
  • @Snowmonkey,它采用对象var currentHeight = $el.height();的高度,而不是计算值。
  • 是的,我明白了——例如,您不一定将高度设置为 24.3 像素。当你这样做,然后读回来,它会是一个整数。
猜你喜欢
  • 2019-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2016-05-13
  • 2014-10-29
  • 1970-01-01
相关资源
最近更新 更多