zoukankan      html  css  js  c++  java
  • d3.js制作条形时间范围选择器

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/12146688.html

    效果如上图所示。

    本项目使用主要d3.js v4制作,可以用来选择两年的时间范围,两端按钮切换年,在时间轴上标注可以选择的时间范围和关键时间点。时间数据可以在前端配置,也可以从后端请求。

    此程序相对比较简单,主要涉及d3的比例尺和拖动处理。

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

    此处,我们使用线性比例尺:d3.scaleLinear()

    它可以把一段连续的值域映射到另一段连续的值域,比如

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

    如果我们想知道两年中的具体某天在时间横条上对应点的x坐标,就可以把天数作为参数传给scale(),返回值就是对应的x坐标。

    当然,d3.js中还有很多其他比例尺,详细信息可以查询API文档:https://github.com/d3/d3-scale#scaleLinear

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/12146688.html

    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);

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

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/12146688.html

  • 相关阅读:
    BZOJ1183 Croatian2008 Umnozak 【数位DP】*
    算法--斯坦纳树
    BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
    BZOJ1833 ZJOI2010 count 数字计数 【数位DP】
    BZOJ1087 SCOI2005 互不侵犯King 【状压DP】
    BZOJ1026 SCOI2009 windy数 【数位DP】
    pytest灵魂产物
    django限流全局和单个视图
    论文阅读笔记四十一:Very Deep Convolutional Networks For Large-Scale Image Recongnition(VGG ICLR2015)
    某线 生成式模型预测算法实习生面试总结
  • 原文地址:https://www.cnblogs.com/eagle1098/p/12146688.html
Copyright © 2011-2022 走看看