Javascript 在d3js styleTween中使用CSS calc时发生意外转换

Javascript 在d3js styleTween中使用CSS calc时发生意外转换,javascript,css,d3.js,css-calc,Javascript,Css,D3.js,Css Calc,我想使用CSS calc来计算div的left属性的开始值和/或结束值,我想使用d3js styleTween平滑地移动该属性。但在开始过渡到正确的端点之前,div会向相反的方向跳跃 我用Chromium版本73.0.3683.75和Firefox 60.7.0esr 64位测试了代码。两者都会产生相同的意外行为 使用this.style.left作为d3.interpolate中的第一个参数不会更改结果 我在d3js styleTween文档中找不到警告不要使用calc的注释,它在转换结束时确

我想使用CSS calc来计算div的left属性的开始值和/或结束值,我想使用d3js styleTween平滑地移动该属性。但在开始过渡到正确的端点之前,div会向相反的方向跳跃

我用Chromium版本73.0.3683.75和Firefox 60.7.0esr 64位测试了代码。两者都会产生相同的意外行为

使用this.style.left作为d3.interpolate中的第一个参数不会更改结果

我在d3js styleTween文档中找不到警告不要使用calc的注释,它在转换结束时确实有效

我希望先计算calc值,然后将结果传递给插值函数,这样可以解决这个问题。但我不确定这是否可行

<!DOCTYPE html>
<html>
    <head>
        <title>Odd interpolation with CSS calc and d3 styleTween</title>

        <style>
        html {height: 100%;}
        body {height: 100%; margin:0; }

        div.button {
        position: absolute;
        left: 20%;
        width: 3rem;
        height: 100%;
        background-color: #0af;
        }
        </style>
    </head>

    <body>
        <div class="button" id="menu_toggle"></div>
    </body>

    <script src="https://d3js.org/d3.v4.min.js" />
    <script>
        menu = function()
        {
            var div = d3.select('div.button');
            var is_left = true;
            function toggle_menu()
        {
            var left = "20%"
            var right = "calc(80% - 3rem)"
            if (is_left)
            {
                is_left = false;
                div.transition().duration(2000)
                                .styleTween('left', function() { return d3.interpolate(left, right); });
            }
            else
            {
                is_left = true;
                div.transition().duration(2000)
                                .styleTween('left', function() { return d3.interpolate(right, left); });
            }
        }
        return {toggle_menu:toggle_menu}
        }()

        d3.select('#menu_toggle').on("click", menu.toggle_menu)
    </script>
</html>
我希望在20%和80%-3rem这两个位置之间平稳过渡


相反,当div从左侧开始时,它先向左跳3rem,然后再向右移动。类似地,如果div位于右侧,它首先向右跳转3rem,然后再向左移动。

问题很简单:您是在插值字符串,而不是它们的计算值

当您在CSS中执行此操作时

calc(80% - 3rem)
。。。它将被评估为像素值。到目前为止,一切顺利。然而,D3插值器实际上是双关语,用于从20%插值到calc80%-3rem。当然,插值器不知道如何处理这个问题,它实际上是从calc20%-3rem插值到calc80%-3rem

让我们看看:

常量插值器=d3。插值20%,计算80%-3rem; d3.range0、1.1、0.1.forEachd=>{ console.LoginInterpolatord }
由于d3s字符串插值使用第二个输入结果字符串作为模板,并使用与第一个输入的索引匹配的对应数字对其找到的任何数字进行插值,因此可以通过插值两个值来避免手动计算css计算:

calc(20% - 0rem)