zoukankan      html  css  js  c++  java
  • D3.js从源码分析到精通(一)

    npm install d3 -S
    npm install @types/d3 -D
    
    import * as d3 from 'd3'
    

    d3-selection

    select 方法

    selectAll 方法

    // 第一个
    d3.select('.box').style('background','red')
    // 多个
    d3.selectAll('.box').style('background','red')
    

    下面两种是操作dom的

    d3-selectorAll

    // 这个函数最优价值的点是把类数组包含到里面去啦
    function array$1(x) {
      return typeof x === "object" && "length" in x
        ? x 
        // Array, TypedArray, NodeList, array-like
        // 数组   类型化数组   节点列表   类数组       
        : Array.from(x); // Map, Set, iterable, string, 或者其他的
    }
    

    TypedArray 看源码的时候蒙蔽这是啥,在mdn查查下

    类型化数组对象描述一个底层二进制数据缓冲区的一个类数组视图

    跟数组的通用方法类型

    const typedArray1=new Int8Array(2)
    typedArray1[0]=11;
    console.log(typedArray1);
    // Int8Array(2) [ 11, 0 ]
    
    function selectorAll(selector) {
      return selector == null ? [] : function() {
        return this.querySelectorAll(selector);
      };
    }
    

    简单的分析,selectorAll就是方法querySelectorAll

    selector

    function selector(selector) {
      return selector == null ? none : function() {
        return this.querySelector(selector);
      };
    }
    

    本质就是 document.querySelector 方法

    slection.filter

    过滤器

    d3.selectAll("tr").filter(":nth-child(even)");
    下面也是可以的
    d3.selectAll(".aaa:nth-child(even)").style('background','red')
    函数的写法
    d3.selectAll(".aaa").filter((v,i)=>i%2)
    

    attr

    selection_attr

    因为设计到SVG的判断有点复杂,我在mdn实现的时候发现无效,就去掉SVG这部分代码

    function selection_attr(name, value) {
      if (arguments.length < 3) {
        // 获取dom节点
        let node=this.node()
        return node.getActiveAttrib(name)
      }
      return this.each(
        // 如果为null/undefined 就删除这个属性
        value==null?attrRemove:
        typeof value==='function'?attrFunction:
          attrConstant
      )(name,value)
    }
    // 删除这个属性
    function attrRemove(name) {
      return function() {
        this.removeAttribute(name);
      };
    }
    // 设置属性和值
    function attrConstant(name, value) {
      return function() {
        this.setAttribute(name, value);
      };
    }
    // 如果是函数
    function attrFunction(name, value) {
      return function() {
        var v = value.apply(this, arguments);
        if (v == null) this.removeAttribute(name);
        else this.setAttribute(name, v);
      };
    }
    this.each 的含义是算多个节点的操作
    function node_each(callback, that) {
      let index = -1;
      for (const node of this) {
        callback.call(that, node, ++index, this);
      }
      return this;
    }
    

    深入理解其中的用法

    // 添加
    d3.select('#ccc').attr('name','333')  
    // 函数添加
    d3.select('#ccc').attr('name',()=>{
        return 'eee'
    })  
    // 多个添加,起到作用的是 this.each
    d3.selectAll('.ccc').attr('name','333')
    // 删除  null/undefined
    d3.selectAll('.ccc').attr('name',null)
    

    classed()

    classList 相关操作

    function classArray(string) {
      return string.trim().split(/^|s+/);
    }
    // classArray('aaa bbb  ccc')
    // => ['aaa','bbb','ccc']
    // 查看dom的classList
    function classList(node) {
      return node.classList || new ClassList(node);
    }
    // 如果没有classList 方法,就创建classList方法
    function ClassList(node) {
      this._node = node;
      this._names = classArray(node.getAttribute("class") || "");
    }
    
    ClassList.prototype = {
      add: function(name) {
         // 查找原来是否有 ,如果有这不添加,没有就添加
        var i = this._names.indexOf(name);
        if (i < 0) {
          this._names.push(name);
          this._node.setAttribute("class", this._names.join(" "));
        }
      },
      remove: function(name) {
          //查找原来是否有,有则删除
        var i = this._names.indexOf(name);
        if (i >= 0) {
          this._names.splice(i, 1);
          this._node.setAttribute("class", this._names.join(" "));
        }
      },
      contains: function(name) {
    //	 判断是否有这个属性
        return this._names.indexOf(name) >= 0;
      }
    };
    // 查找所有属性,遍历添加
    function classedAdd(node, names) {
      var list = classList(node), i = -1, n = names.length;
      while (++i < n) list.add(names[i]);
    }
    // 查找所有属性,遍历删除
    function classedRemove(node, names) {
      var list = classList(node), i = -1, n = names.length;
      while (++i < n) list.remove(names[i]);
    }
    

    理解源码后

    单个参数
    类型 contains 查询是否有这个属性有true 否则false
    d3.selectr('.aaa').classed('bbb') // true/false
    多个参数
    d3.selectr('.aaa').classed('bbb',ture) //添加(没有添加,有就不变)
    d3.selectr('.aaa').classed('bbb',false)// 删除 (有则删除,没有则不变)
    // 批量添加和删除
    d3.selectAll('.aaa').classed('bbb',true)
    // 函数的方式
    <div class="aaa"></div>
    <div class="aaa"></div>
    <div class="aaa">
      <div class="ccc"></div>
    </div>
    
     console.log(d3.selectAll('.aaa').classed('bbb',(v,i)=>{
          // 子dom   索引
          console.log(v,i);
          return true
        }));
    

    style

    getPropertyPriority

    判断是否设置important 优先级

    如果有!important 就表示为important 否则为'', 记得是内联的样式

        <div class="aaa" id="box" style="background: #00230b!important;"></div>
    	//  记得比如你们跟我一样喜欢用ts,记得加上别名限制
    	//let a = document.querySelector('#box') as HTMLElement;
    
    	let a = document.querySelector('#box');
        console.log(a.style.getPropertyPriority('background'));
    	// important
    

    getPropertyValue

    查询单个值

      <div class="aaa" id="box" style="background: #00230b"></div>
    
    	let a = document.querySelector('#box') as HTMLElement;
        // 第一种
        let b = a.style.getPropertyValue('background');
        console.log(b);
    	// rgb(0, 35, 11)
        // 第二种
        console.log(getComputedStyle(a).getPropertyValue('background'));
        //rgb(0, 35, 11) none repeat scroll 0% 0% / auto padding-box border-box
    

    源码

    1602行
    function styleValue(node, name) {
      return node.style.getPropertyValue(name)
          || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
    }
    

    删除

      <div class="aaa" id="box" style="background: #00230b"></div>
    
        let a=document.querySelector('.aaa')
        a.style.removeProperty('background')
    	// 返回''
    
    function styleRemove(name) {
      return function() {
        this.style.removeProperty(name);
      };
    }
    

    设置

    setProperty 参数

    ​ 属性,值, 优先级
    优先级(important) 默认为''

    let a=document.querySelector('.aaa')
    a.style.setProperty('border','3px solid red','important')
    

    源码

    function styleConstant(name, value, priority) {
      return function() {
        this.style.setProperty(name, value, priority);
      };
    }
    

    value 为函数

    function styleFunction(name, value, priority) {
      return function() {
        var v = value.apply(this, arguments);
        if (v == null) this.style.removeProperty(name);
        else this.style.setProperty(name, v, priority);
      };
    }
    

    从源码上看我们可以删除或者设置默认属性

    实际操作的代码可以是
    // 删除默认内置css
      d3.select('.aaa').style('margin',()=>{
          return null // undefined
        })
    如果有值
       d3.select('.aaa').style('margin',()=>{
          return '30px'
        },'important')
    // important 是可以默认写入的
    

    最后我们看看默认整合的代码

    export default function(name, value, priority) {
      return arguments.length > 1
          ? this.each((value == null
                ? styleRemove : typeof value === "function"
                ? styleFunction
                : styleConstant)(name, value, priority == null ? "" : priority))
          : styleValue(this.node(), name);
    }
    

    我们可以整合全部完整的实例

    arguments的长度为1 执行styleValue方法
    也就是查询功能
        console.log(d3.select('.aaa').style('font-size'));
    this.each 是一个进行多个赋值的操作
    当第二个参数是==null就是删除操作 还是undefined也是
    d3.select('.aaa').style('font-size',null)
    当第二个参数是函数
       d3.select('.aaa').style('margin',()=>{
          return '30px'
        },'important')
    否则就是最简单的复制操作
        console.log(d3.select('.aaa').style('font-size','40px'));
    
  • 相关阅读:
    CR, LF, CR/LF区别与关系
    利用 jQuery 克隆 Object
    【2015】网易前端面经
    前端架构:Angular与requirejs集成实践
    高质量代码之HTML、CSS篇
    【转】requirejs简单入门
    2014搜狗前端面经【B事业部】
    2014小型公司前端面经
    【转】对象创建模式
    2014搜狗前端面经【A事业部】
  • 原文地址:https://www.cnblogs.com/fangdongdemao/p/13690183.html
Copyright © 2011-2022 走看看