d3绘制地图(放大显示2 3级行政单位)

1、使用d3绘制地图,希望随着地图的放大缩小显示不同级别的行政单位,默认1级行政单位是各个省和直辖市。

实现思路:

1)改造地图json文件,给各个行政单位进行区域划分

2)绘制地图的时候默认只显示一级行政单位。将2级及以上行政单位默认隐藏(通过class样式)

3)地图放大缩小(zoom函数中)时,在相应的倍数中去查找对应的级别样式,把display:none的样式移除。

/**
   * @函数名称:zoomed
   * @param dom  'g' element
   * @param transform {
   *                    x: 100,
   *                    y:100,
   *                    k:0.1,
   *                    changeCenter:boolean 是否需要改变中心点
   *                  }
   * @作用:定位并且放大缩小函数 相似功能使用函数处理
   * @date 2018/7/9
   */
  zoomed(dom, transform, changeCenter) {
    const me = this;
    // TODO 此处有个bug 拖拽原点设置有问题  需要处理
    const d = dom || d3.select('g');
    d.attr(
      'transform',
      transform
        ? 'translate(' +
          transform.x +
          ',' +
          transform.y +
          ') scale(' +
          transform.k +
          ')'
        : d3.event.transform,
    );
    // 处理字体
    const k = d3.event.transform.k;
    const tfont = TEXTFONT / k;
    d3.selectAll('.text').attr('font-size', tfont + 'px');
    // 处理线条变化
    let pathW = 1 / k;
    pathW = pathW > 1 ? 1 : pathW;
    d3.selectAll('path').attr('stroke-width', pathW);
    /**
     *  地图是否支持分层显示
     */
    if (LAYERED) {
      // 处理气泡的大小
      for (let i = 0; i < 5; i++) {
        const rm = BASER / k;
        const rt = (BASER + i * 5) / k;
        i === 0 ? d3.selectAll('.bubbledata').attr('r', rm + 'px')
          : d3.selectAll('.bubbledata' + i)
            .attr('from', rm)
            .attr('to', rt);
      }
    }
    // 处理相应级别的字体显示和隐藏  循环浪费资源 使用if else判断
    setLayered();
  }
let BASER = 10; // 默认的数据圈半径
let LAYERED = 0; // 是否支持下钻
const TEXTFONT = 12; // 字体大小
//   修Modify改样式集合 重复样式不修改dom
const MODFIYSTYLE = {};
const GENERAL_LEVEL = 4;
/**
 * 对于当前 ZOOK操作的集合 只修改其中变量
 * @type {{value: number; level: number; level4: number; level3: number; level2: number; level1: number}}
 */
const ZOOMK = {
  value: 0,
  level: 0,
  level4: 6,
  level3: 3,
  level2: 2,
  level1: 1,
};
/**
 * 拿到当前的层级
 * @param key
 * @returns {number}
 */
const getlevel = function (key) {
  return key > ZOOMK.level4
    ? GENERAL_LEVEL
    : (key > ZOOMK.level3
      ? GENERAL_LEVEL - 1
      : (key > ZOOMK.level2
        ? GENERAL_LEVEL - 2
        : GENERAL_LEVEL - 3));
};

/**
 *
 * @param {string} className
 * @param {number} level  循环的次数
 * @param {number} changeLevel  需要改变的级别
 * @param {boolean} status  更改的状态
 * @param {string} operator  更改的状态  允许为 '>=' '=='
 */
const setLevelStatus = function(className: string, level: number, changeLevel: number, status: boolean, operator: string) {
  if (operator === '<=') {
    for (let i = level; i > 0; i--) {
      const itemClassName = className + i;
      i <= changeLevel
        ? setLayeredStyle(itemClassName, status)
        : setLayeredStyle(itemClassName, !status);
    }
  } else {
    for (let i = level; i > 0; i--) {
      const itemClassName = className + i;
      i === changeLevel
        ? setLayeredStyle(itemClassName, status)
        : setLayeredStyle(itemClassName, !status);
    }
  }
};
/**
 * setLayeredStyle
 * MODFIYSTYLE 利用缓存机制 减少对dom的操作  提升性能
 * 使用class赋值 来优化性能
 * @param key  获取样式dom的值 目前是样式
 * @param val  要设置的样式 true为显示 false为隐藏
 */
const setLayeredStyle = function (key, val) {
  if (MODFIYSTYLE[key] !== val) {
    d3.selectAll(key).classed('d3Chart-dom-show', val);
    MODFIYSTYLE[key] = val;
  }
};
/**
 * 处理分层 根据层次来处理各个阶段是否需要分层显示
 */
const setLayered = function () {
  const k = d3.event.transform.k;
  const Le = getlevel(k); // 获取当前的级别
  if (k === ZOOMK.value || Le === ZOOMK.level) {
    return;
  }
  // 目前默认有4个层级 所以此处默认循环4次
  setLevelStatus('.citylevel', GENERAL_LEVEL, Le, true, '<=');
  ZOOMK.level = Le;
  if (LAYERED) {
    // 当前逻辑  默认分层为0 此处循环需要 +1
    // 获取需要改变的层  当当前层次大于配置的层次 则默认配置+1层需要改变 否则就是当前层次的状态需要改变
    const ly = LAYERED + 1;
    const changeLe = Le > ly ? ly : Le;
    setLevelStatus('.baselevel', ly, changeLe, true, '==');
  }
  ZOOMK.value = k;
};

猜你喜欢

转载自blog.csdn.net/ligaoming_123/article/details/82843439
D3