vis-timeline groups存在时左上角颜色自定义

在使用vis时,碰到一个需求,需要将时间轴颜色设置为自定义颜色,如下图红色框

API中找了一下,可以通过.vis-background设置背景颜色

好像是不能满足需求,继续找,时间轴在上方,vis-top设置完

嗯。。。有一半满足需求了,剩下的怎么办?

好吧,翻源码吧 node_modules/vis-timeline/peer/esm/vis-timeline-graph2d.js

找到构造函数Timeline定义

function Timeline(container, items, groups, options) {
    ...
    // Create the DOM, props, and emitter
    _this._create(container);
    ...
}
/**
 * Create a timeline visualization
 * @constructor Core
 */
 var Core = /*#__PURE__*/function () {
    function Core() {
      _classCallCheck(this, Core);
    }
    _createClass(Core, [{
      key: "_create",
      value:
      /**
       * Create the main DOM for the Core: a root panel containing left, right,
       * top, bottom, content, and background panel.
       * @param {Element} container  The container element where the Core will
       *                             be attached.
       * @protected
       */
      function _create(container) {
        var _this = this,
          _context,
          _context2,
          _context3;
        this.dom = {};
        this.dom.container = container;
        this.dom.container.style.position = 'relative';
        this.dom.root = document.createElement('div');
        this.dom.background = document.createElement('div');
        this.dom.backgroundVertical = document.createElement('div');
        this.dom.backgroundHorizontal = document.createElement('div');
        this.dom.centerContainer = document.createElement('div');
        this.dom.leftContainer = document.createElement('div');
        this.dom.rightContainer = document.createElement('div');
        this.dom.center = document.createElement('div');
        this.dom.left = document.createElement('div');
        this.dom.right = document.createElement('div');
        this.dom.top = document.createElement('div');
        this.dom.bottom = document.createElement('div');
        this.dom.shadowTop = document.createElement('div');
        this.dom.shadowBottom = document.createElement('div');
        this.dom.shadowTopLeft = document.createElement('div');
        this.dom.shadowBottomLeft = document.createElement('div');
        this.dom.shadowTopRight = document.createElement('div');
        this.dom.shadowBottomRight = document.createElement('div');
        this.dom.rollingModeBtn = document.createElement('div');
        this.dom.loadingScreen = document.createElement('div');
        this.dom.root.className = 'vis-timeline';
        this.dom.background.className = 'vis-panel vis-background';
        this.dom.backgroundVertical.className = 'vis-panel vis-background vis-vertical';
        this.dom.backgroundHorizontal.className = 'vis-panel vis-background vis-horizontal';
        this.dom.centerContainer.className = 'vis-panel vis-center';
        this.dom.leftContainer.className = 'vis-panel vis-left';
        this.dom.rightContainer.className = 'vis-panel vis-right';
        this.dom.top.className = 'vis-panel vis-top';
        this.dom.bottom.className = 'vis-panel vis-bottom';
        this.dom.left.className = 'vis-content';
        this.dom.center.className = 'vis-content';
        this.dom.right.className = 'vis-content';
        this.dom.shadowTop.className = 'vis-shadow vis-top';
        this.dom.shadowBottom.className = 'vis-shadow vis-bottom';
        this.dom.shadowTopLeft.className = 'vis-shadow vis-top';
        this.dom.shadowBottomLeft.className = 'vis-shadow vis-bottom';
        this.dom.shadowTopRight.className = 'vis-shadow vis-top';
        this.dom.shadowBottomRight.className = 'vis-shadow vis-bottom';
        this.dom.rollingModeBtn.className = 'vis-rolling-mode-btn';
        this.dom.loadingScreen.className = 'vis-loading-screen';
        this.dom.root.appendChild(this.dom.background);
        this.dom.root.appendChild(this.dom.backgroundVertical);
        this.dom.root.appendChild(this.dom.backgroundHorizontal);
        this.dom.root.appendChild(this.dom.centerContainer);
        this.dom.root.appendChild(this.dom.leftContainer);
        this.dom.root.appendChild(this.dom.rightContainer);
        this.dom.root.appendChild(this.dom.top);
        this.dom.root.appendChild(this.dom.bottom);
        this.dom.root.appendChild(this.dom.rollingModeBtn);
        this.dom.centerContainer.appendChild(this.dom.center);
        this.dom.leftContainer.appendChild(this.dom.left);
        this.dom.rightContainer.appendChild(this.dom.right);
        this.dom.centerContainer.appendChild(this.dom.shadowTop);
        this.dom.centerContainer.appendChild(this.dom.shadowBottom);
        this.dom.leftContainer.appendChild(this.dom.shadowTopLeft);
        this.dom.leftContainer.appendChild(this.dom.shadowBottomLeft);
        this.dom.rightContainer.appendChild(this.dom.shadowTopRight);
        this.dom.rightContainer.appendChild(this.dom.shadowBottomRight);
  
        // size properties of each of the panels
        this.props = {
          root: {},
          background: {},
          centerContainer: {},
          leftContainer: {},
          rightContainer: {},
          center: {},
          left: {},
          right: {},
          top: {},
          bottom: {},
          border: {},
          scrollTop: 0,
          scrollTopMin: 0
        };
        ...
        
      }
    },...{
      key: "redraw",
      value: function redraw() {
        this._redraw();
      }
  
      /**
       * Redraw for internal use. Redraws all components. See also the public
       * method redraw.
       * @protected
       */
    }, {
      key: "_redraw",
      value: function _redraw() {
        var _context20;
        this.redrawCount++;
        var dom = this.dom;
        if (!dom || !dom.container || dom.root.offsetWidth == 0) return; // when destroyed, or invisible
  
        var resized = false;
        var options = this.options;
        var props = this.props;
        updateHiddenDates(this.options.moment, this.body, this.options.hiddenDates);
  
        // update class names
        if (options.orientation == 'top') {
          availableUtils.addClassName(dom.root, 'vis-top');
          availableUtils.removeClassName(dom.root, 'vis-bottom');
        } else {
          availableUtils.removeClassName(dom.root, 'vis-top');
          availableUtils.addClassName(dom.root, 'vis-bottom');
        }
        if (options.rtl) {
          availableUtils.addClassName(dom.root, 'vis-rtl');
          availableUtils.removeClassName(dom.root, 'vis-ltr');
        } else {
          availableUtils.addClassName(dom.root, 'vis-ltr');
          availableUtils.removeClassName(dom.root, 'vis-rtl');
        }
  
        // update root width and height options
        dom.root.style.maxHeight = availableUtils.option.asSize(options.maxHeight, '');
        dom.root.style.minHeight = availableUtils.option.asSize(options.minHeight, '');
        dom.root.style.width = availableUtils.option.asSize(options.width, '');
        var rootOffsetWidth = dom.root.offsetWidth;
  
        // calculate border widths
        props.border.left = 1;
        props.border.right = 1;
        props.border.top = 1;
        props.border.bottom = 1;
  
        // calculate the heights. If any of the side panels is empty, we set the height to
        // minus the border width, such that the border will be invisible
        props.center.height = dom.center.offsetHeight;
        props.left.height = dom.left.offsetHeight;
        props.right.height = dom.right.offsetHeight;
        props.top.height = dom.top.clientHeight || -props.border.top;
        props.bottom.height = Math.round(dom.bottom.getBoundingClientRect().height) || dom.bottom.clientHeight || -props.border.bottom;
  
        // TODO: compensate borders when any of the panels is empty.
  
        // apply auto height
        // TODO: only calculate autoHeight when needed (else we cause an extra reflow/repaint of the DOM)
        var contentHeight = Math.max(props.left.height, props.center.height, props.right.height);
        var autoHeight = props.top.height + contentHeight + props.bottom.height + props.border.top + props.border.bottom;
        dom.root.style.height = availableUtils.option.asSize(options.height, "".concat(autoHeight, "px"));
  
        // calculate heights of the content panels
        props.root.height = dom.root.offsetHeight;
        props.background.height = props.root.height;
        var containerHeight = props.root.height - props.top.height - props.bottom.height;
        props.centerContainer.height = containerHeight;
        props.leftContainer.height = containerHeight;
        props.rightContainer.height = props.leftContainer.height;
  
        // calculate the widths of the panels
        props.root.width = rootOffsetWidth;
        props.background.width = props.root.width;
        if (!this.initialDrawDone) {
          props.scrollbarWidth = availableUtils.getScrollBarWidth();
        }
        var leftContainerClientWidth = dom.leftContainer.clientWidth;
        var rightContainerClientWidth = dom.rightContainer.clientWidth;
        if (options.verticalScroll) {
          if (options.rtl) {
            props.left.width = leftContainerClientWidth || -props.border.left;
            props.right.width = rightContainerClientWidth + props.scrollbarWidth || -props.border.right;
          } else {
            props.left.width = leftContainerClientWidth + props.scrollbarWidth || -props.border.left;
            props.right.width = rightContainerClientWidth || -props.border.right;
          }
        } else {
          props.left.width = leftContainerClientWidth || -props.border.left;
          props.right.width = rightContainerClientWidth || -props.border.right;
        }
        this._setDOM();
  
        // update the scrollTop, feasible range for the offset can be changed
        // when the height of the Core or of the contents of the center changed
        var offset = this._updateScrollTop();
  
        // reposition the scrollable contents
        if (options.orientation.item != 'top') {
          offset += Math.max(props.centerContainer.height - props.center.height - props.border.top - props.border.bottom, 0);
        }
        dom.center.style.transform = "translateY(".concat(offset, "px)");
  
        // show shadows when vertical scrolling is available
        var visibilityTop = props.scrollTop == 0 ? 'hidden' : '';
        var visibilityBottom = props.scrollTop == props.scrollTopMin ? 'hidden' : '';
        dom.shadowTop.style.visibility = visibilityTop;
        dom.shadowBottom.style.visibility = visibilityBottom;
        dom.shadowTopLeft.style.visibility = visibilityTop;
        dom.shadowBottomLeft.style.visibility = visibilityBottom;
        dom.shadowTopRight.style.visibility = visibilityTop;
        dom.shadowBottomRight.style.visibility = visibilityBottom;
        if (options.verticalScroll) {
          dom.rightContainer.className = 'vis-panel vis-right vis-vertical-scroll';
          dom.leftContainer.className = 'vis-panel vis-left vis-vertical-scroll';
          dom.shadowTopRight.style.visibility = "hidden";
          dom.shadowBottomRight.style.visibility = "hidden";
          dom.shadowTopLeft.style.visibility = "hidden";
          dom.shadowBottomLeft.style.visibility = "hidden";
          dom.left.style.top = '0px';
          dom.right.style.top = '0px';
        }
        if (!options.verticalScroll || props.center.height < props.centerContainer.height) {
          dom.left.style.top = "".concat(offset, "px");
          dom.right.style.top = "".concat(offset, "px");
          dom.rightContainer.className = dom.rightContainer.className.replace(new RegExp('(?:^|\\s)' + 'vis-vertical-scroll' + '(?:\\s|$)'), ' ');
          dom.leftContainer.className = dom.leftContainer.className.replace(new RegExp('(?:^|\\s)' + 'vis-vertical-scroll' + '(?:\\s|$)'), ' ');
          props.left.width = leftContainerClientWidth || -props.border.left;
          props.right.width = rightContainerClientWidth || -props.border.right;
          this._setDOM();
        }
  
        // enable/disable vertical panning
        var contentsOverflow = props.center.height > props.centerContainer.height;
        this.hammer.get('pan').set({
          direction: contentsOverflow ? Hammer.DIRECTION_ALL : Hammer.DIRECTION_HORIZONTAL
        });
  
        // set the long press time
        this.hammer.get('press').set({
          time: this.options.longSelectPressTime
        });
  
        // redraw all components
        _forEachInstanceProperty(_context20 = this.components).call(_context20, function (component) {
          resized = component.redraw() || resized;
        });
        var MAX_REDRAW = 5;
        if (resized) {
          if (this.redrawCount < MAX_REDRAW) {
            this.body.emitter.emit('_change');
            return;
          } else {
            console.log('WARNING: infinite loop in redraw?');
          }
        } else {
          this.redrawCount = 0;
        }
  
        //Emit public 'changed' event for UI updates, see issue #1592
        this.body.emitter.emit("changed");
      }
  
      /**
       * sets the basic DOM components needed for the timeline\graph2d
       */
    }, {
      key: "_setDOM",
      value: function _setDOM() {
        var props = this.props;
        var dom = this.dom;
        props.leftContainer.width = props.left.width;
        props.rightContainer.width = props.right.width;
        var centerWidth = props.root.width - props.left.width - props.right.width;
        props.center.width = centerWidth;
        props.centerContainer.width = centerWidth;
        props.top.width = centerWidth;
        props.bottom.width = centerWidth;
  
        // resize the panels
        dom.background.style.height = "".concat(props.background.height, "px");
        dom.backgroundVertical.style.height = "".concat(props.background.height, "px");
        dom.backgroundHorizontal.style.height = "".concat(props.centerContainer.height, "px");
        dom.centerContainer.style.height = "".concat(props.centerContainer.height, "px");
        dom.leftContainer.style.height = "".concat(props.leftContainer.height, "px");
        dom.rightContainer.style.height = "".concat(props.rightContainer.height, "px");
        dom.background.style.width = "".concat(props.background.width, "px");
        dom.backgroundVertical.style.width = "".concat(props.centerContainer.width, "px");
        dom.backgroundHorizontal.style.width = "".concat(props.background.width, "px");
        dom.centerContainer.style.width = "".concat(props.center.width, "px");
        dom.top.style.width = "".concat(props.top.width, "px");
        dom.bottom.style.width = "".concat(props.bottom.width, "px");
  
        // reposition the panels
        dom.background.style.left = '0';
        dom.background.style.top = '0';
        dom.backgroundVertical.style.left = "".concat(props.left.width + props.border.left, "px");
        dom.backgroundVertical.style.top = '0';
        dom.backgroundHorizontal.style.left = '0';
        dom.backgroundHorizontal.style.top = "".concat(props.top.height, "px");
        dom.centerContainer.style.left = "".concat(props.left.width, "px");
        dom.centerContainer.style.top = "".concat(props.top.height, "px");
        dom.leftContainer.style.left = '0';
        dom.leftContainer.style.top = "".concat(props.top.height, "px");
        dom.rightContainer.style.left = "".concat(props.left.width + props.center.width, "px");
        dom.rightContainer.style.top = "".concat(props.top.height, "px");
        dom.top.style.left = "".concat(props.left.width, "px");
        dom.top.style.top = '0';
        dom.bottom.style.left = "".concat(props.left.width, "px");
        dom.bottom.style.top = "".concat(props.top.height + props.centerContainer.height, "px");
        dom.center.style.left = '0';
        dom.left.style.left = '0';
        dom.right.style.left = '0';
      }
  
      /**
       * Set a current time. This can be used for example to ensure that a client's
       * time is synchronized with a shared server time.
       * Only applicable when option `showCurrentTime` is true.
       * @param {Date | string | number} time     A Date, unix timestamp, or
       *                                          ISO date string.
       */
    }]);
    return Core;
  }(); // turn Core into an event emitter

查看源码可知,先new Timeline,然后setOptions,setData,最后在创建dom、props、emitter。

这下思路就来了,先创建一个root下的子元素div,

const customLeft = document.createElement("div");

绑定到root元素下,添加自定义样式

timeline.dom.root.appendChild(customLeft);
customLeft.className = "vis-custom vis-left-top";

高度自行设置,此时宽度想要跟groups保持一致,查看源码得知,props中left的width为groups宽度

customLeft.style.width = timeline.props.left.width + "px";

如此,得到动态宽度(红色区域为自定义颜色)

完整代码

const container = document.getElementById("visualization");
const customLeft = document.createElement("div");
timeline = new Timeline(container);
timeline.setOptions({ ...options, ...times.value });
timeline.setData({ groups: groups.value, items: items.value });
timeline.dom.root.appendChild(customLeft);
customLeft.className = "vis-custom vis-left-top";
customLeft.style.width = timeline.props.left.width + "px";
timeline.on("doubleClick", timelineDoubleClick);

如果你想在你的网站或应用程序中展示间轴,可以使用vis-timelinevis-timeline是一个用JavaScript编写的开源库,允许你创建可交互的间轴,并在上面显示事件或数据。它支持平移、缩放和导航,可以用于展示历史事件、项目进度、日程安排等等。 要引入vis-timeline,可以按照以下步骤进行操作: 1. 下载vis-timeline。你可以从其官方网站https://visjs.github.io/vis-timeline/docs/vis-timeline/下载vis-timeline的最新版本,也可以使用npm或yarn安装它,命令如下: ```bash npm install vis-timeline ``` 或 ```bash yarn add vis-timeline ``` 2. 引入vis-timeline的CSS和JavaScript文件。你可以在HTML文档中使用以下代码引入它们: ```html <link href="https://unpkg.com/vis-timeline/standalone/vis-timeline-graph2d.min.css" rel="stylesheet" type="text/css" /> <script src="https://unpkg.com/vis-timeline/standalone/vis-timeline-graph2d.min.js"></script> ``` 3. 创建一个包含容器元素的div。vis-timeline需要一个容器元素来呈现间轴。你可以在HTML文档中创建一个div元素,并为它设置一个唯一的ID。例如: ```html <div id="timeline"></div> ``` 4. 初始化vis-timeline。在JavaScript中,你需要使用以下代码初始化vis-timeline: ```javascript var container = document.getElementById('timeline'); var options = {}; // 选项可以根据需要进行配置 var timeline = new vis.Timeline(container, items, options); ``` 其中,container是你在步骤3中创建的div元素,items是一个包含事件或数据的数组,options是一个包含配置选项的对象。 5. 在items数组中添加事件或数据。在vis-timeline中,你需要使用一个包含事件或数据的数组来初始化间轴。每个事件或数据都应该是一个对象,至少包含start属性,表示事件或数据的开始间。例如: ```javascript var items = [ {id: 1, content: '事件1', start: '2022-01-01'}, {id: 2, content: '事件2', start: '2022-01-02', end: '2022-01-05'}, {id: 3, content: '事件3', start: '2022-01-06', type: 'point'} ]; ``` 其中,id是事件或数据的唯一标识符,content是事件或数据的显示文本,start是事件或数据的开始间,end是事件或数据的结束间(可选),type是事件或数据的类型(可选)。 这样,你就可以使用vis-timeline创建一个基本的间轴了。如果需要更高级的功能,可以查看vis-timeline的文档,了解更多选项和方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值