D3 v5:如何在不重新调整工具提示文字的情况下缩放图表?

我正在尝试使用d3.js v5向折线图添加缩放功能。为了显示曲线上的实际鼠标位置,有一个工具提示,带有y值(SVG元素),两条虚线和一个在交界点处的圆。工具提示元素在放大时不得更改其大小。虚线和圆圈在“焦点”组中,该组对d3.event.transform的缩放事件有反应。这些元素的行为是正确的,放大后它们不会更改其大小并正确翻译。 SVG元素位于单独的组“ focustooltip”中,该组未绑定到放大事件。放大文本时,请勿调整大小(这是正确的行为),但文本的翻译不正确(放大时,文本会远离结点,但不应如此)。

查看图像以可视化行为:

未缩放:每个元素都在正确的位置: unzoomed

缩放:文本翻译错误。 zoomed

这是我的实际代码:

<!DOCTYPE html>
<meta charset="utf-8">
<html>
    <head>
        <script type = "text/javascript" src = "https://d3js.org/d3.v5.min.js"></script>
        <style> 

            .axis path,.axis line 
            {
                fill: none;
                stroke: #000;
                shape-rendering: crispEdges;
            }

            path.line 
            {
                fill: none;
                stroke: rgb(52,101,164);
                stroke-width: 2px;
                vector-effect: non-scaling-stroke;  /* line height won't scale */
                pointer-events: none;
            }

            .overlay 
            {
                fill: none;
                pointer-events: all;
            }

            .focus circle 
            {
                fill: #F1F3F3;
                stroke: #6F257F;
                stroke-width: 2px;
            }

            text.y2
            {
                fill: rgb(239,41,41); 
            }

            line.x
            {
                stroke: blue;
                stroke-width: 2px;
                stroke-dasharray: 3,3;
                vector-effect: non-scaling-stroke; /* line height won't scale */
                pointer-events: none;
            }

            line.y
            {
                stroke: blue;
                stroke-width: 2px;
                stroke-dasharray: 3,3;
                vector-effect: non-scaling-stroke; /* line height won't scale */
                pointer-events: none;
            }

        </style>
    </head>

<body>

<div id="example"></div>
<div id="example_2"></div>

<script>

function lineChart()
{
    // set the dimensions and margins of the graph
    var margin = {top: 40,right: 20,bottom: 60,left: 50},width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom;

    // set the ranges
    var x = d3.scaleTime().range([0,width]);
    var y = d3.scaleLinear().range([height,0]);

    var formatDate = d3.timeFormat("%d-%b"),bisectDate = d3.bisector(function(d) { return d.year; }).left;

    // define the line
    var valueline = d3.line()
        .x(function(d) { return x(d.year); })
        .y(function(d) { return y(d.population); });


    function chart(selection) 
    {
        selection.each(function(data) 
        {
            var actScale=1.0;

            var zoom = d3.zoom()
                .scaleExtent([1,Infinity])
                .translateExtent([[0,0],[width,height]])
                .extent([[0,height]])
                .on("zoom",zoomed);

            // append the svg obgect to the body of the page
            // appends a 'group' element to 'svg'
            // moves the 'group' element to the top left margin
            var svg = d3.select(this)
                .append("svg")
                .attr("width",width + margin.left + margin.right)
                .attr("height",height + margin.top + margin.bottom)
                .call(zoom)
                .append("g")
                .attr("transform","translate(" + margin.left + "," + margin.top + ")");

            // Scale the range of the data
            x.domain(d3.extent(data,function(d) { return d.year; }));
            y.domain([0,d3.max(data,function(d) { return d.population; })]);

            var xAxis = d3.axisBottom(x);
            var yAxis = d3.axisLeft(y);

            svg.append("defs").append("clipPath")
                .attr("id","clip")
                .append("rect")
                .attr("width",width)
                .attr("height",height);

            var clipping = svg.append("g")
                .attr("clip-path","url(#clip)");

            var path = clipping.append("path")
                .data([data])
                .attr("class","line")
                .attr("d",valueline);

            var focus = clipping.append("g")
                .style("display","none");

            var focustooltip = clipping.append("g")
                .style("display","none");

            // append the x line
            focus.append("line")
                .attr("class","x")
                .style("stroke","blue")
                .style("stroke-dasharray","3,3")
                // .style("stroke-width","2px")
                .style("opacity",0.5)
                .attr("y1",0)
                .attr("y2",height);

            // append the y line
            focus.append("line")
                .attr("class","y")
                .style("stroke",3")
                .style("opacity",0.5)
                .attr("x1",width)
                .attr("x2",width);

            focustooltip.append("text")
                .attr("class","y2")
                .attr("dx",8)
                .attr("dy","-.3em");

            // append the circle at the intersection
            var circle = focus.append("circle")
                .attr("class","y")
                .style("fill","none")
                .style("stroke","blue")
                .attr("r",4);

            // append the rectangle to capture mouse
            var rect = clipping.append("rect")
                .attr("width",height)
                .style("fill","none")
                .style("pointer-events","all")
                .on("mouseover",function() { focus.style("display",null); focustooltip.style("display",null);})
                .on("mouseout","none"); focustooltip.style("display",null);})
                .on("mousemove",mousemove);

            function mousemove() 
            {
                var x0 = x.invert(d3.mouse(this)[0]),i = bisectDate(data,x0,1),d0 = data[i - 1],d1 = data[i],d = x0 - d0.year > d1.year - x0 ? d1 : d0;

                focus.select("circle.y")
                    .attr("transform","translate(" + x(d.year) + "," + y(d.population) + ")");

                focus.select(".x")
                    .attr("transform"," + y(d.population) + ")")
                    .attr("y2",height - y(d.population));

                focus.select(".y")
                    .attr("transform","translate(" + width * -1 + "," + y(d.population) + 1 + ")")
                    .attr("x2",width + width);

                focustooltip.select("text.y2")
                    .attr("transform"," + y(d.population) + ")")
                    .text(d.population);
            }

            var gX = svg.append("g")
                .attr("class","axis axis--x")
                .attr("transform","translate(0," + height + ")")
                .call(xAxis);

            var gY = svg.append("g")
                .attr("class","axis axis--y")
                .call(yAxis);

            //Create title 
            var title = svg.append("text")
                .attr("x",(width / 2))             
                .attr("y",0 - (margin.top / 2))
                .attr("text-anchor","middle")  
                .style("font-size","16px") 
                .text("x vs y");

            // text label for the x axis
            svg.append("text")             
                .attr("transform","translate(" + (width/2) + "," + (height + margin.top) + ")")
                .style("text-anchor","middle")
                .text("x-axis");

            // text label for the y axis
            svg.append("text")
                .attr("transform","rotate(-90)")
                .attr("y",0 - margin.left)
                .attr("x",0 - (height / 2))
                .attr("dy","1em")
                .style("text-anchor","middle")
                // .text(yaxis_lable);
                .text("y-axis");

            function zoomed() 
            {
                path.attr("transform",d3.event.transform);

                focus.attr("transform",d3.event.transform);
                // focustooltip.attr("transform",0)scale(1)");

                focus.select("circle").attr("r",4 / d3.event.transform.k);
                focus.select("circle").attr("stroke-width",2 / d3.event.transform.k);

                rect.attr("transform",d3.event.transform);

                gX.call(xAxis.scale(d3.event.transform.rescaleX(x)));
                gY.call(yAxis.scale(d3.event.transform.rescaleY(y)));
            }

        });

    }   

    return chart;
}

var chart = lineChart();

// Get the data
d3.csv("data_graph.csv")
    .then(function(data)
    {
        // format the data
        data.forEach(function(d) 
        {
            d.year = d.year;
            d.population = +d.population;
        })
        d3.select("#example")
            .datum(data)
            .call(chart);
    });


// Get the data
d3.csv("data_graph.csv")
    .then(function(data)
    {
        // format the data
        data.forEach(function(d) 
        {
            d.year = d.year;
            d.population = +d.population;
        })
        d3.select("#example_2")
            .datum(data)
            .call(chart);
    });

</script>
</body>
</html>
liuchongjun217 回答:D3 v5:如何在不重新调整工具提示文字的情况下缩放图表?

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3059765.html

大家都在问