为什么在调试模式外添加谷歌地图会导致d3.js刷重绘崩溃?

Why adding google map will crash d3.js brush redraw outside debug mode?

本文关键字:js d3 崩溃 模式 调试 添加 谷歌地图 为什么      更新时间:2023-09-26

我试图结合d3.js刷和谷歌地图。我有一个地图,3个按钮来控制d3画笔(实际上是我的时间轴),和d3画笔本身。

按钮负责移动画笔,如果我不将地图添加到页面中,它们就会这样做。如果我将地图添加到页面,当js调试器(firebug或chrome调试器)启用时,播放和停止功能即可工作。但当我关闭调试器时,画笔不会重画。它的范围将被更新(我通过alert(brush_control.extent()[0])检查了它),但它仍然在它之前的动作(播放或停止)。

控制台没有异常或错误。

下面是完成这项工作的脚本:

<script>
(function(){
    var is_playing = false,
        paddingLeft = 10,
        paddingRight = 10,
        paddingBottom = 5;
        width = $(window).width() - $("#controls").width() - paddingLeft - paddingRight,
        timeline_height = 100,
        map_height = $(window).height() - timeline_height - paddingBottom,
        my_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
        brush_control = NaN;
    $("#map").height(map_height);
    // Remove the map below and everything works fine
    var map = new google.maps.Map(d3.select("#map").node(), {
      zoom: 8,
      center: new google.maps.LatLng(-14.235004,-51.92528),
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });     
    var timeline_svg = d3.select("#timeline").append("svg:svg")
                         .attr("class", "tl")
                         .attr("width", width)
                         .attr("height", timeline_height);
    brush_control = d3.svg
                      .brush()
                      .x(d3.scale
                           .linear()
                           .domain([0, my_data.length])
                           .range([0, width])
                        )
                      .extent([0,1])
                      .on("brush", brush);
    var brush_svg = timeline_svg.append("g")
                                .attr("class", "brush")
                                .call(brush_control)
                                .selectAll("rect")
                                .attr("height", timeline_height);
    $("#playbtn")[0].addEventListener("click", play_event);
    $("#pausebtn")[0].addEventListener("click", pause);
    $("#stopbtn")[0].addEventListener("click", stop);
    function play_event(){
        if(is_playing != true){
            is_playing = true;
            play();
        }
    }
    function play(){
        var delay = 100;
        setTimeout(function(){
                        var ex = brush_control.extent();
                        if(is_playing && ex[0   ] < my_data.length - 1){
                            d3.select("g").transition()
                                     .duration(delay)
                                     .call(brush_control.extent([ex[1], ex[1] + 1]));
                            ex = brush_control.extent();
                            play();
                        }
                   }, delay);
    }
    function pause(){
        is_playing = false;
    }
    function stop(){
        is_playing = false;
        d3.select("g")
          .transition()
          .duration(1000)
          .call(brush_control.extent([0, 1]))
          .call(brush_control.event);
    }
    function brush() {
        var s = d3.event.target.extent();
        data_index = Math.floor(s[0]);
        if (s[1]-s[0] != 1) {
            d3.event.target.extent([s[0], s[0] + 1]);
            d3.event.target(d3.select(this));
        }
    }
}());
</script>

问题是d3.select("g").transition()行没有选择您期望的内容,而是从谷歌地图插入的代码。如果你检查DOM元素,你会发现一些SVG代码插入,如

<svg version="1.1" overflow="hidden" width="78px" height="78px" viewBox="0 0 78 78" style="position: absolute; left: 0px; top: 0px;">
<circle cx="39" cy="39" r="35" stroke-width="3" fill-opacity="0.2" fill="#f2f4f6" stroke="#f2f4f6"></circle>
<g transform="rotate(0 39 39)"><rect x="33" y="0" rx="4" ry="4" width="12" height="11" stroke="#a6a6a6" stroke-width="1" fill="#f2f4f6"></rect><polyline points="36.5,8.5 36.5,2.5 41.5,8.5 41.5,2.5" stroke-linejoin="bevel" stroke-width="1.5" fill="#f2f4f6" stroke="#000"></polyline>
</g>
</svg>

因此,将选择范围更改为

d3.select("g.brush").transition()