d3.js制作条形时间范围选择器


效果如上图所示。
本项目使用主要d3.js v4制作,可以用来选择两年的时间范围,两端按钮切换年,在时间轴上标注可以选择的时间范围和关键时间点。时间数据可以在前端配置,也可以从后端请求。
此程序相对比较简单,主要涉及d3的比例尺和拖动处理。

1)d3的比例尺其实就是把一个范围的数据映射到另一个范围的数据上

此处,我们使用线性比例尺:d3.scaleLinear()
它可以把一段连续的值域映射到另一段连续的值域,比如:

var scale = d3.scaleLinear()
    .domain([0, 730])
   // startPos是时间横条的开始x坐标,endPos是结束x坐标
   .range([startPos, endPos]);

如果我们想知道两年中的具体某天在时间横条上对应点的x坐标,就可以把天数作为参数传给scale(),返回值就是对应的x坐标。
当然,d3.js中还有很多其他比例尺,详细信息可以查询API文档:https://github.com/d3/d3-scale#scaleLinear

2)我们这里的拖动主要分两部分,首先是单独拖动滑块,然后是两个滑块一起拖动。

单独拖动滑块的逻辑:
a.如果两个滑块被同时拖动过,则移除两个滑块间的黄线。
b.使用class名称来判断拖动的是哪个滑块。
c.计算鼠标x坐标,然后用比例尺反向求出对应的天数位置。

// xPos为x轴坐标
var index = scale().invert(xPos);

d.移动对应滑块到鼠标位置。

var dragFun = function () {
      // 移除拖拽连线元素
      if (stickDragLine) {
        stickDragLine.remove();
        stickDragLine = null;
      }
      // 获得被点击元素class
      var className = d3.select(this).attr('class');
      // 计算鼠标x坐标,要减去滑块宽度的二分之一
      var pos = d3.event.x - slipBlockWidth / 2;
      // 计算鼠标index,
      var index = getIndex(pos);
      var blockIndex;

      // 当前块位置,可以配置默认位置,也可从后端请求
      if (className === 'slip-left') {
        blockIndex = splitBlockIndex.left;
      }
      if (className === 'slip-right') {
        blockIndex = splitBlockIndex.right;
      }
      // 滑块只能在0到maxIndex之间滑动,即上层横条内
      if (blockIndex >= 0 && blockIndex <= maxIndex) {
        if (className === 'slip-left') {
            // 移动左滑块和相关背景和文字到鼠标位置
            changeLeftBlock(index);
        }
        if (className === 'slip-right') {
            // 移动左滑块和相关背景和文字到鼠标位置
            changeRightBlock(index);
        }
}
// 滑块拖动
var slipBlockDrag = d3.drag()
      .on('drag', dragFun);
// 滑块元素调用拖拽方法
slipBlockLeft.call(slipBlockDrag);
slipBlockRight.call(slipBlockDrag);

两个滑块一起拖动则在它们中间增加1个黄色连线。最后使用时间条元素调用拖拽方法。

// 主横条上处理两个滑块一起拖动事件
    var stickDrag = d3.drag()
      .on('drag', function () {
        // 计算移动前两个滑块位置
        var leftEventX = scale(splitBlockIndex.left),
          rightEventX = scale(splitBlockIndex.right);
        if (d3.event.x > rightEventX || d3.event.x < leftEventX) {
          return;
        }
        // 添加拖动线条
        if (!stickDragLine) {
          stickDragLine = _stickG.append('line')
            .attr('x1', leftEventX + 2)
            .attr('y1', stickTop + stickHeight / 2)
            .attr('x2', rightEventX + 2)
            .attr('y2', stickTop + stickHeight / 2)
            .attr('stroke-width', 1)
            .attr('stroke', 'yellow');
        }
        // 移动后的x
        var leftAfterX = leftEventX + d3.event.dx,
          rightAfterX = rightEventX + d3.event.dx,
          // 移动后的index
          leftIndex = Math.floor(scale().invert(leftAfterX)),
          rightIndex = Math.floor(scale().invert(rightAfterX));
        if ((leftIndex >= 0 && rightIndex < maxIndex) &&
          (rightIndex >= 0 && leftIndex < maxIndex)) {
          // 保存移动后的index
          splitBlockIndex.left = leftIndex;
          splitBlockIndex.right = rightIndex;
          // 移动各元素
          changeLeftBlock(leftAfterX, splitBlockIndex.left);
          changeRightBlock(rightAfterX, splitBlockIndex.right);
          stickDragLine
            .attr('x1', leftAfterX + 2)
            .attr('x2', rightAfterX + 2);
        }        
      });
    _stickG.call(stickDrag);

文中代码用来说明逻辑结构,具体功能函数实现起来很容易,所以没有给出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容

  • D3是用于数据可视化的Javascript库。使用SVG,Canvas和HTML。结合强大的可视化技术和数据驱动的...
    Evelynzzz阅读 7,896评论 7 5
  • 看完该API后,至少会画出一个简单的图形 D3.js 入门 1. d3-selection: 【 选择作图区域...
    Pretty_Boy阅读 984评论 0 1
  • d3 (核心部分)选择集d3.select - 从当前文档中选择一系列元素。d3.selectAll - 从当前文...
    谢大见阅读 3,447评论 1 4
  • Data Visualization with D3 D3: SVG中的jQurey 1. Add Documen...
    王策北阅读 766评论 0 2
  • 一、简介 1. D3是什么? D3(或D3.js) 是一个用来使用Web标准做数据可视化的JavaScript库。...
    朝朝_c53e阅读 828评论 0 2