• d3代码如何改造成update结构(恰当处理enter和exit)


    d3的enter和exit

    网上有很多blog讲解。说的还凑合的见:https://blog.csdn.net/nicolecc/article/details/50786661

    如何把自己的rude绘图代码,进行精致化(update)

     不多比比,上代码示例:

    d3.selectAll('.circle_group').children().remove();
    var circle_group = d3.selectAll('.circle_group')
        .data(circleData)
        .enter().append('g')
        .attr('class', 'circle_group brushNode')
        .attr('transform',
            function (d) {
                return 'translate(' + d.x + ',' + d.y + ')';
            })
        .on('click', function (d) {
            if (shiftKey) {
                //标记当前点
                d3.select(this).classed("selected", function (d) {
    
                    d.selected = !d.selected;
                    d.previouslySelected = !d.selected;
                    return d.selected;
                })
    
                //阻止事件冒泡
                d3.event.stopPropagation();
            }
        })
        .on("contextmenu", function (node) {
            contextmenu("Rmenu");
        })
    
    circle_group.append('circle')
        .attr('r', function (d) {
            return d.r;
        })
        .style("fill", function (d) {
            return color20(d.index);
        })
    
    ;
    circle_group.append('text')
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")//在圆圈中加上数据
        .style('fill', function (node) {
            return '#555';
        })
        .attr("y", -7)
        .text(d => d.text);
    
    circle_group.call(d3.drag()
    //定义了元素拖拽行为的原点,设置为圆的圆心位置可以避免明显的元素跳动, 与d3v3中的origin方法类似。
        .subject(function () {
            var thisData = d3.select(this);
            return {
                x: thisData.datum().x,
                y: thisData.datum().y
            };
        })
        .on("start", dragstarted)
        .on("drag", dragmove)
        .on("end", dragended));

     很明显,新手图省事都是这么绘图的。就绘图结果来看,如果你不加动画一点问题都没有,只要一加动画过渡动画,所有的图形都是从无到有的过程,而我们想看的是,如果点更新的话,能看到他从哪(位置)更新到哪(位置)。(这里就不加动画过渡了,就一行代码的事.transition().duration(300) )。

    改造如下:

        //这部分代码是有则改之,无则添加的功能
    const circle_data=d3.selectAll('.circle_group').data(circleData)  //更新部分,如果你数据的数目没变,那circle_data.size()=你数据内容改变的数目,你可以把circle_data考虑成update部分就行,这样编代码准没错
        .attr('transform',             //首次运行的时候,因为没有元素circle_data.size()=0, 所以这个transform不会运行到
            function (d) {
                return 'translate(' + d.x + ',' + d.y + ')';
            });
    const circle_enter=circle_data.enter().append('g')  //add 部分,首次运行的时候,circle_enter.size()=全部元素,所以在circle_enter进行所有的初始化设置操作
        .attr('class', 'circle_group brushNode')
        .attr('transform',
            function (d) {
                return 'translate(' + d.x + ',' + d.y + ')';
            });
    circle_data.exit().remove();  // 当你删一些数据的时候, .exit().size()>0
    
    
    
    circle_enter.on('click', function (d) {
        if (shiftKey) {
            //标记当前点
            d3.select(this).classed("selected", function (d) {
    
                d.selected = !d.selected;
                d.previouslySelected = !d.selected;
                return d.selected;
            })
    
            //阻止事件冒泡
            d3.event.stopPropagation();
        }
    })
        .on("contextmenu", function (node) {
            contextmenu("Rmenu");
        })
    
    circle_enter.append('circle')     //add
        .attr('r', d=>d.r)
        .style("fill", function (d) {
            return color20(d.index);
        });
    circle_data.select('circle')  //update,这里不要append ,因为元素已经在那了(enter().append()过了)。当然首次运行(视图首次显示)的时候,这几句代码是运行不到的。
        .attr('r', d=>d.r)
        .style("fill", function (d) {
            return color20(d.index);
        });
    
    circle_enter.append('text')  //add
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")//在圆圈中加上数据
        .style('fill', function (node) {
            return '#555';
        })
        .attr("y", -7)
        .text(d => d.text);
    circle_data.select('text')  //update  不要append 
        .text(d => d.text);
    
    const drag=d3.drag()
    //定义了元素拖拽行为的原点,设置为圆的圆心位置可以避免明显的元素跳动, 与d3v3中的origin方法类似。
        .subject(function () {
            var thisData = d3.select(this);
            return {
                x: thisData.datum().x,
                y: thisData.datum().y
            };
        })
        .on("start", dragstarted)
        .on("drag", dragmove)
        .on("end", dragended);
    circle_enter.call(drag);
    circle_data.call(drag);   //update 注意,这里一定要重新绑定一下,这里涉及到drag的初始化(subject用于初始化drag拖动点的初始位置)

    敲黑板

    1、更新部分的所有与位置有关的事件(比如d3.drag()的初始位置)要重新绑定,否则会出现不可预料的结果。

    2、update部分与数据有关的attr,style要重新设置,这时就不用append了。(因为这个元素既然有了,你已经在之前的.enter().append().append(其他元素)添加过了,这里只需要更新一下即可。)。一些固定的attr,style就不用重复设置了(之前enter已经绑定过了)

  • 相关阅读:
    Java中的基本数据类型以及自增特性总结
    mysql菜鸟
    Typora使用教程
    net core下链路追踪skywalking安装和简单使用
    netcore5下ocelot网关简单使用
    netcore热插拔dll
    快速排序
    netcore5下js请求跨域
    SpringBoot接口防刷
    EL 表达式
  • 原文地址:https://www.cnblogs.com/xunhanliu/p/10995687.html
Copyright © 2020-2023  润新知