Exemple #1
0
    Util.each(items, function(item, index) {
      const checked = item.checked;
      const value = self._formatItemValue(item.value);
      const markerColor = item.marker.fill || item.marker.stroke;
      const color = checked ? markerColor : unCheckedColor;
      let domStr;
      if (Util.isFunction(itemTpl)) {
        domStr = itemTpl(value, color, checked, index);
      } else {
        domStr = itemTpl;
      }
      const itemDiv = Util.substitute(domStr, {
        index,
        checked: checked ? 'checked' : 'unChecked',
        value,
        color,
        originColor: markerColor,
        originValue: item.value
      });
      const itemDom = DomUtil.createDom(itemDiv);
      const markerDom = findNodeByClass(itemDom, MARKER_CLASS);
      DomUtil.modifyCSS(itemDom, itemStyle);
      markerDom && DomUtil.modifyCSS(markerDom, markerStyle);

      if (!checked) {
        itemDom.style.color = unCheckedColor;
        if (markerDom) {
          markerDom.style.backgroundColor = unCheckedColor;
        }
      }
      itemListDom.appendChild(itemDom);
    });
Exemple #2
0
  _setDomPosition(parentDom, childDom, point) {
    const self = this;
    const alignX = self.alignX;
    const alignY = self.alignY;
    const domWidth = DomUtil.getOuterWidth(childDom);
    const domHeight = DomUtil.getOuterHeight(childDom);

    const position = {
      x: point.x,
      y: point.y
    };

    if (alignX === 'middle' && alignY === 'top') {
      position.x -= Util.round(domWidth / 2);
    } else if (alignX === 'middle' && alignY === 'bottom') {
      position.x -= Util.round(domWidth / 2);
      position.y -= Util.round(domHeight);
    } else if (alignX === 'left' && alignY === 'bottom') {
      position.y -= Util.round(domHeight);
    } else if (alignX === 'left' && alignY === 'middle') {
      position.y -= Util.round(domHeight / 2);
    } else if (alignX === 'left' && alignY === 'top') {
      position.x = point.x;
      position.y = point.y;
    } else if (alignX === 'right' && alignY === 'bottom') {
      position.x -= Util.round(domWidth);
      position.y -= Util.round(domHeight);
    } else if (alignX === 'right' && alignY === 'middle') {
      position.x -= Util.round(domWidth);
      position.y -= Util.round(domHeight / 2);
    } else if (alignX === 'right' && alignY === 'top') {
      position.x -= Util.round(domWidth);
    } else { // 默认位于中心点
      position.x -= Util.round(domWidth / 2);
      position.y -= Util.round(domHeight / 2);
    }

    if (self.offsetX) {
      position.x += self.offsetX;
    }

    if (self.offsetY) {
      position.y += self.offsetY;
    }

    DomUtil.modifyCSS(parentDom, {
      position: 'absolute',
      top: Math.round(position.y) + 'px',
      left: Math.round(position.x) + 'px',
      visibility: 'visible',
      zIndex: self.zIndex
    });
  }
Exemple #3
0
  _createText(cfg) {
    const htmlTemplate = this.get('htmlTemplate');
    let customDiv = this.get('customDiv');
    let labelShape;

    if (htmlTemplate) {
      if (!customDiv) {
        const containerTpl = this.get('_containerTpl');
        const wrapper = this.get('canvas').get('el').parentNode;
        customDiv = DomUtil.createDom(containerTpl);
        wrapper.style.position = 'relative';
        wrapper.appendChild(customDiv);
        this.set('customDiv', customDiv);
      }

      const node = this._createDom(cfg);
      customDiv.appendChild(node);
      this._setCustomPosition(cfg, node);
    } else {
      const origin = cfg.point;
      delete cfg.point; // 临时解决,否则影响动画
      labelShape = this.addShape('text', {
        attrs: cfg
      });
      labelShape.setSilent('origin', origin);
      labelShape.name = 'label'; // 用于事件标注
      this.get('appendInfo') && labelShape.setSilent('appendInfo', this.get('appendInfo'));
      return labelShape;
    }
  }
Exemple #4
0
  _addItem(item, index) {
    const itemTpl = this.get('itemTpl'); // TODO: 有可能是个回调函数

    const itemDiv = Util.substitute(itemTpl, Util.mix({
      index
    }, item));

    const itemDOM = DomUtil.createDom(itemDiv);
    DomUtil.modifyCSS(itemDOM, this.get(LIST_ITEM_CLASS));
    const markerDom = find(itemDOM, MARKER_CLASS);
    if (markerDom) {
      DomUtil.modifyCSS(markerDom, this.get(MARKER_CLASS));
    }

    return itemDOM;
  }
Exemple #5
0
 _initTooltipWrapper() {
   const self = this;
   const containerTpl = self.get('containerTpl');
   const outterNode = self.get('canvas').get('el').parentNode;
   let container;
   if (/^\#/.test(containerTpl)) { // 如果传入 dom 节点的 id
     const id = containerTpl.replace('#', '');
     container = document.getElementById(id);
   } else {
     container = DomUtil.createDom(containerTpl);
     DomUtil.modifyCSS(container, self.get(CONTAINER_CLASS));
     outterNode.appendChild(container);
     outterNode.style.position = 'relative';
   }
   self.set('container', container);
 }
Exemple #6
0
  getHeight() {
    if (this.get('useHtml')) {
      return DomUtil.getOuterHeight(this.get('legendWrapper'));
    }

    return super.getHeight();
  }
Exemple #7
0
  render(coord, group) {
    const self = this;
    const position = self.parsePoint(coord, self.position);

    const parentNode = group.get('canvas').get('el').parentNode;
    const wrapperNode = DomUtil.createDom('<div class="g-guide"></div>');
    parentNode.appendChild(wrapperNode);

    let html = self.html;
    if (Util.isFunction(html)) {
      html = html(self.xScales, self.yScales);
    }
    const htmlNode = DomUtil.createDom(html);
    wrapperNode.appendChild(htmlNode);
    self._setDomPosition(wrapperNode, htmlNode, position);
    self.el = wrapperNode;
  }
Exemple #8
0
  _setCustomPosition(cfg, htmlDom) {
    const textAlign = cfg.textAlign || 'left';
    let top = cfg.y;
    let left = cfg.x;
    const width = DomUtil.getOuterWidth(htmlDom);
    const height = DomUtil.getOuterHeight(htmlDom);

    top = top - height / 2;
    if (textAlign === 'center') {
      left = left - width / 2;
    } else if (textAlign === 'right') {
      left = left - width;
    }

    htmlDom.style.top = parseInt(top, 10) + 'px';
    htmlDom.style.left = parseInt(left, 10) + 'px';
  }
Exemple #9
0
 move(x, y) {
   if (this.get('useHtml') && !(/^\#/.test(this.get('container')))) {
     DomUtil.modifyCSS(this.get('legendWrapper'), {
       left: x + 'px',
       top: y + 'px'
     });
   } else {
     super.move(x, y);
   }
 }
Exemple #10
0
  _createDom(cfg) {
    const itemTpl = this.get('_itemTpl');
    const htmlTemplate = this.get('htmlTemplate');

    if (Util.isString(htmlTemplate)) {
      cfg.text = Util.substitute(htmlTemplate, { text: cfg.text });
    }

    const str = Util.substitute(itemTpl, { text: cfg.text });

    return DomUtil.createDom(str);
  }
Exemple #11
0
  _renderTooltip() {
    const self = this;
    const showTitle = self.get('showTitle');
    const titleContent = self.get('titleContent');
    const container = self.get('container');
    const titleDom = find(container, TITLE_CLASS);
    const listDom = find(container, LIST_CLASS);
    const items = self.get('items');
    self._clearDom();

    if (titleDom && showTitle) {
      DomUtil.modifyCSS(titleDom, self.get(TITLE_CLASS));
      titleDom.innerHTML = titleContent;
    }

    if (listDom) {
      DomUtil.modifyCSS(listDom, self.get(LIST_CLASS));
      Util.each(items, (item, index) => {
        listDom.appendChild(self._addItem(item, index));
      });
    }
  }
Exemple #12
0
  setPosition(x, y, target) {
    const container = this.get('container');
    const crossLineShapeX = this.get('crossLineShapeX');
    const crossLineShapeY = this.get('crossLineShapeY');
    const crosshairsRectShape = this.get('crosshairsRectShape');
    let endx = x;
    let endy = y;
    // const outterNode = this.get('canvas').get('el').parentNode;
    const outterNode = this.get('canvas').get('el');
    const viewWidth = DomUtil.getWidth(outterNode);
    const viewHeight = DomUtil.getHeight(outterNode);
    let offset = this.get('offset');

    let position;
    if (this.get('position')) {
      position = calcTooltipPosition(x, y, this.get('position'), container, target);
      x = position[0];
      y = position[1];
    } else if (!this.get('position')) {
      position = refixTooltipPosition(x, y, container, viewWidth, viewHeight);
      x = position[0];
      y = position[1];
    }

    if (this.get('inPlot')) { // tooltip 必须限制在绘图区域内
      const plotRange = this.get('plotRange');
      position = confineTooltipPosition(x, y, container, plotRange);
      x = position[0];
      y = position[1];
    }

    if (this.get('x') !== x || this.get('y') !== y) {
      const markerItems = this.get('markerItems');
      if (!Util.isEmpty(markerItems)) {
        endx = markerItems[0].x;
        endy = markerItems[0].y;
      }
      if (crossLineShapeY) { // 第一次进入时,画布需要单独绘制,所以需要先设定corss的位置
        crossLineShapeY.move(endx, 0);
      }
      if (crossLineShapeX) {
        crossLineShapeX.move(0, endy);
      }

      if (crosshairsRectShape) {
        const isTransposed = this.get('isTransposed');
        const items = this.get('items');
        const firstItem = items[0];
        const lastItem = items[items.length - 1];
        const dim = isTransposed ? 'y' : 'x';
        const attr = isTransposed ? 'height' : 'width';
        let startDim = firstItem[dim];
        if (items.length > 1 && firstItem[dim] > lastItem[dim]) {
          startDim = lastItem[dim];
        }

        if (this.get('crosshairs').width) { // 用户定义了 width
          crosshairsRectShape.attr(dim, startDim - this.get('crosshairs').width / 2);
          crosshairsRectShape.attr(attr, this.get('crosshairs').width);
        } else {
          offset = (firstItem.size / 2 + firstItem.size / 4) || 10;
          crosshairsRectShape.attr(dim, startDim - offset);

          if (items.length === 1) {
            crosshairsRectShape.attr(attr, firstItem.size + firstItem.size / 2);
          } else {
            const lastItem = items[items.length - 1];
            crosshairsRectShape.attr(attr, Math.abs(lastItem[dim] - firstItem[dim]) + 2 * offset);
          }
        }
      }

      const follow = this.get('follow');
      container.style.left = follow ? (x + 'px') : 0;
      container.style.top = follow ? (y + 'px') : 0;
    }
  }
Exemple #13
0
 getWidth() {
   if (this.get('useHtml')) {
     return DomUtil.getOuterWidth(this.get('legendWrapper'));
   }
   return super.getWidth();
 }
Exemple #14
0
  _renderHTML() {
    const self = this;
    const canvas = self.get('canvas');
    const outterNode = canvas.get('el').parentNode;
    const title = this.get('title');
    const containerTpl = self.get('containerTpl');
    const legendWrapper = DomUtil.createDom(containerTpl);
    const titleDom = findNodeByClass(legendWrapper, TITLE_CLASS);
    const itemListDom = findNodeByClass(legendWrapper, LIST_CLASS);
    const unCheckedColor = self.get('unCheckColor');
    const mode = self.get('selectedMode');
    const LEGEND_STYLE = Global.legend.html;

    DomUtil.modifyCSS(itemListDom, Util.mix({}, LEGEND_STYLE[LIST_CLASS], self.get(LIST_CLASS)));

    if (titleDom) {
      if (title && title.text) {
        titleDom.innerHTML = title.text;
        DomUtil.modifyCSS(titleDom, Util.mix({}, LEGEND_STYLE[TITLE_CLASS], self.get(TITLE_CLASS)));
      } else {
        legendWrapper.removeChild(titleDom);
      }
    }

    // 开始渲染图例项
    const items = self.get('items');
    let itemTpl = self.get('_defaultItemTpl');
    const userItemTpl = self.get('itemTpl');
    if (userItemTpl && userItemTpl !== itemTpl) {
      itemTpl = userItemTpl;
    }

    if (self.get('reversed')) {
      items.reverse();
    }

    const position = self.get('position');
    const itemStyle = Util.mix({}, LEGEND_STYLE[ITEM_CLASS], {
      display: (position === 'right' || position === 'left') ? 'block' : 'inline-block'
    }, self.get(ITEM_CLASS));
    const markerStyle = Util.mix({}, LEGEND_STYLE[MARKER_CLASS], self.get(MARKER_CLASS));
    Util.each(items, function(item, index) {
      const checked = item.checked;
      const value = self._formatItemValue(item.value);
      const markerColor = item.marker.fill || item.marker.stroke;
      const color = checked ? markerColor : unCheckedColor;
      let domStr;
      if (Util.isFunction(itemTpl)) {
        domStr = itemTpl(value, color, checked, index);
      } else {
        domStr = itemTpl;
      }
      const itemDiv = Util.substitute(domStr, {
        index,
        checked: checked ? 'checked' : 'unChecked',
        value,
        color,
        originColor: markerColor,
        originValue: item.value
      });
      const itemDom = DomUtil.createDom(itemDiv);
      const markerDom = findNodeByClass(itemDom, MARKER_CLASS);
      DomUtil.modifyCSS(itemDom, itemStyle);
      markerDom && DomUtil.modifyCSS(markerDom, markerStyle);

      if (!checked) {
        itemDom.style.color = unCheckedColor;
        if (markerDom) {
          markerDom.style.backgroundColor = unCheckedColor;
        }
      }
      itemListDom.appendChild(itemDom);
    });

    if (self.get('clickable')) {
      const childNodes = itemListDom.childNodes;
      // 注册事件
      legendWrapper.onclick = ev => {
        const target = ev.target;
        let targetClass = target.className;
        targetClass = targetClass.split(' ');
        if (targetClass.indexOf(CONTAINER_CLASS) > -1 || targetClass.indexOf(LIST_CLASS) > -1) {
          return;
        }
        const parentDom = getParentNode(target, ITEM_CLASS);
        const textDom = findNodeByClass(parentDom, TEXT_CLASS);
        const markerDom = findNodeByClass(parentDom, MARKER_CLASS);
        const clickedItem = findItem(items, parentDom.getAttribute('data-value'));

        if (!clickedItem) {
          return;
        }
        // update checked status
        clickedItem.checked = (mode === 'single') ? true : !(clickedItem.checked);
        const domClass = parentDom.className;
        const originColor = parentDom.getAttribute('data-color');
        if (mode === 'single') { // 单选模式
          // 其他图例项全部置灰
          Util.each(childNodes, child => {
            if (child !== parentDom) {
              const childMarkerDom = findNodeByClass(child, MARKER_CLASS);
              childMarkerDom.style.backgroundColor = unCheckedColor;
              child.className = Util.replace(child.className, 'checked', 'unChecked');
              child.style.color = unCheckedColor;

              const childItem = findItem(items, child.getAttribute('data-value'));
              childItem.checked = false;
            } else {
              if (textDom) {
                textDom.style.color = self.get('textStyle').fill;
              }
              if (markerDom) {
                markerDom.style.backgroundColor = originColor;
              }
              parentDom.className = Util.replace(domClass, 'unChecked', 'checked');
            }
          });
        } else { // 混合模式
          const clickedItemChecked = domClass.includes('checked');
          let count = 0;
          Util.each(childNodes, child => {
            if (child.className.includes('checked')) {
              count++;
            }
          });
          if (!this.get('allowAllCanceled') && clickedItemChecked && count === 1) {
            return;
          }
          if (clickedItemChecked) {
            if (markerDom) {
              markerDom.style.backgroundColor = unCheckedColor;
            }
            parentDom.className = Util.replace(domClass, 'checked', 'unChecked');
            parentDom.style.color = unCheckedColor;
          } else {
            if (markerDom) {
              markerDom.style.backgroundColor = originColor;
            }
            parentDom.className = Util.replace(domClass, 'unChecked', 'checked');
            parentDom.style.color = self.get('textStyle').fill;
          }
        }

        self.emit('itemclick', {
          item: clickedItem,
          currentTarget: parentDom,
          checked: (mode === 'single') ? true : clickedItem.checked
        });
      };
    }
    if (self.get('hoverable')) {
      legendWrapper.onmousemove = ev => {
        const target = ev.target;
        let targetClass = target.className;
        targetClass = targetClass.split(' ');
        if (targetClass.indexOf(CONTAINER_CLASS) > -1 || targetClass.indexOf(LIST_CLASS) > -1) {
          return;
        }
        const parentDom = getParentNode(target, ITEM_CLASS);
        const domClass = parentDom.className;
        const hoveredItem = findItem(items, parentDom.getAttribute('data-value'));
        if (hoveredItem && domClass.includes('checked')) {
          self.emit('itemhover', {
            item: hoveredItem,
            currentTarget: parentDom,
            checked: hoveredItem.checked
          });
        } else if (!hoveredItem) {
          self.emit('itemunhover', ev);
        }
      };

      legendWrapper.onmouseout = ev => {
        self.emit('itemunhover', ev);
      };
    }

    let container = self.get('container');
    if (/^\#/.test(container)) { // 如果传入 dom 节点的 id
      const id = container.replace('#', '');
      container = document.getElementById(id);
      // container.style.position = 'relative';
      container.appendChild(legendWrapper);
    } else {
      const position = self.get('position');
      const canvas = self.get('canvas');
      let rangeStyle = {};
      if (position === 'left' || position === 'right') {
        rangeStyle = {
          maxHeight: (self.get('maxLength') || canvas.get('height')) + 'px'
        };
      } else {
        rangeStyle = {
          maxWidth: (self.get('maxLength') || canvas.get('width')) + 'px'
        };
      }

      DomUtil.modifyCSS(legendWrapper, Util.mix({}, LEGEND_STYLE[CONTAINER_CLASS], rangeStyle, self.get(CONTAINER_CLASS)));
      outterNode.appendChild(legendWrapper);
    }
    self.set('legendWrapper', legendWrapper);
  }