javascript-在d3js styleTween中使用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进行警告的注释,并且在过渡结束时确实有效.

我希望先计算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%”插值到“ calc(80%-3rem)”.当然,插值器不知道如何处理,实际上是从“ calc(20%-3rem)”插值到“ calc(80%-3rem)”.

让我们来看看:

const interpolator = d3.interpolate("20%","calc(80% - 3rem)");
d3.range(0,1.1,0.1).forEach(d => {
  console.log(interpolator(d))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

最简单的解决方案是评估calc()的结果并在插值器中使用该值.有几种方法可以做到这一点,例如使用this library.

因此,假设评估后我们有一些值,例如150px和430px.现在插值很简单:

const interpolator = d3.interpolate("150px","430px");
d3.range(0,0.1).forEach(d => {
  console.log(interpolator(d))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

相关文章

Css3如何实现鼠标移上变长特效?(图文+视频)
css3怎么实现鼠标悬停图片时缓慢变大效果?(图文+视频)
jquery如何实现点击网页回到顶部效果?(图文+视频)
css3边框阴影效果怎么做?(图文+视频)
css怎么实现圆角边框和圆形效果?(图文+视频教程)
Css3如何实现旋转移动动画特效