function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } var G = require('@antv/g/lib'); var Tooltip = require('./base'); var Util = require('../util'); var DomUtil = Util.DomUtil; var TooltipTheme = require('./theme'); var Crosshair = require('./crosshair'); var PositionMixin = require('./mixin/position'); var MarkerGroupMixin = require('./mixin/marker-group'); var CONTAINER_CLASS = 'g2-tooltip'; var TITLE_CLASS = 'g2-tooltip-title'; var LIST_CLASS = 'g2-tooltip-list'; var MARKER_CLASS = 'g2-tooltip-marker'; var VALUE_CLASS = 'g2-tooltip-value'; var LIST_ITEM_CLASS = 'g2-tooltip-list-item'; var MARKER_SIZE = 5; var Marker = G.Marker; function find(dom, cls) { return dom.getElementsByClassName(cls)[0]; } function mergeStyles(styles, cfg) { Object.keys(styles).forEach(function (k) { if (cfg[k]) { styles[k] = Util.mix(styles[k], cfg[k]); } }); return styles; } var HtmlTooltip = /*#__PURE__*/function (_Tooltip) { _inheritsLoose(HtmlTooltip, _Tooltip); var _super = _createSuper(HtmlTooltip); var _proto = HtmlTooltip.prototype; _proto.getDefaultCfg = function getDefaultCfg() { var cfg = _Tooltip.prototype.getDefaultCfg.call(this); return Util.mix({}, cfg, { /** * tooltip 容器模板 * @type {String} */ containerTpl: '
' + '
' + '' + '
', /** * tooltip 列表项模板 * @type {String} */ itemTpl: "
  • \n \n {name}{value}
  • ", /** * tooltip html内容 * @type {String} */ htmlContent: null, /** * tooltip 内容跟随鼠标移动 * @type {Boolean} */ follow: true, /** * 是否允许鼠标停留在 tooltip 上,默认不允许 * @type {Boolean} */ enterable: false }); }; function HtmlTooltip(cfg) { var _this; _this = _Tooltip.call(this, cfg) || this; Util.assign(_assertThisInitialized(_this), PositionMixin); Util.assign(_assertThisInitialized(_this), MarkerGroupMixin); var style = TooltipTheme; _this.style = mergeStyles(style, cfg); _this._init_(); if (_this.get('items')) { _this.render(); } // crosshair var crosshair = _this.get('crosshairs'); if (crosshair) { var plot = crosshair.type === 'rect' ? _this.get('backPlot') : _this.get('frontPlot'); var crosshairGroup = new Crosshair(Util.mix({ plot: plot, plotRange: _this.get('plotRange'), canvas: _this.get('canvas') }, _this.get('crosshairs'))); crosshairGroup.hide(); _this.set('crosshairGroup', crosshairGroup); } return _this; } _proto._init_ = function _init_() { var self = this; var containerTpl = self.get('containerTpl'); var outterNode = self.get('canvas').get('el').parentNode; var container; if (!this.get('htmlContent')) { if (/^\#/.test(containerTpl)) { // 如果传入 dom 节点的 id var id = containerTpl.replace('#', ''); container = document.getElementById(id); } else { container = DomUtil.createDom(containerTpl); DomUtil.modifyCSS(container, self.style[CONTAINER_CLASS]); outterNode.appendChild(container); outterNode.style.position = 'relative'; } self.set('container', container); } }; _proto.render = function render() { var self = this; self.clear(); if (self.get('htmlContent')) { var outterNode = self.get('canvas').get('el').parentNode; var container = self._getHtmlContent(); outterNode.appendChild(container); self.set('container', container); } else { self._renderTpl(); } }; _proto._renderTpl = function _renderTpl() { var self = this; var showTitle = self.get('showTitle'); var titleContent = self.get('titleContent'); var container = self.get('container'); var titleDom = find(container, TITLE_CLASS); var listDom = find(container, LIST_CLASS); var items = self.get('items'); if (titleDom && showTitle) { DomUtil.modifyCSS(titleDom, self.style[TITLE_CLASS]); titleDom.innerHTML = titleContent; } if (listDom) { DomUtil.modifyCSS(listDom, self.style[LIST_CLASS]); Util.each(items, function (item, index) { listDom.appendChild(self._addItem(item, index)); }); } }; _proto.clear = function clear() { var container = this.get('container'); if (this.get('htmlContent')) { container && container.remove(); } else { var titleDom = find(container, TITLE_CLASS); var listDom = find(container, LIST_CLASS); if (titleDom) { titleDom.innerHTML = ''; } if (listDom) { listDom.innerHTML = ''; } } }; _proto.show = function show() { var container = this.get('container'); if (!container || this.destroyed) { // 防止容器不存在或者被销毁时报错 return; } container.style.visibility = 'visible'; container.style.display = 'block'; var crosshairGroup = this.get('crosshairGroup'); crosshairGroup && crosshairGroup.show(); var markerGroup = this.get('markerGroup'); markerGroup && markerGroup.show(); _Tooltip.prototype.show.call(this); this.get('canvas').draw(); }; _proto.hide = function hide() { var container = this.get('container'); // relative: https://github.com/antvis/g2/issues/1221 if (!container || this.destroyed) { return; } container.style.visibility = 'hidden'; container.style.display = 'none'; var crosshairGroup = this.get('crosshairGroup'); crosshairGroup && crosshairGroup.hide(); var markerGroup = this.get('markerGroup'); markerGroup && markerGroup.hide(); _Tooltip.prototype.hide.call(this); this.get('canvas').draw(); }; _proto.destroy = function destroy() { var self = this; var container = self.get('container'); var containerTpl = self.get('containerTpl'); if (container && !/^\#/.test(containerTpl)) { container.parentNode.removeChild(container); } var crosshairGroup = this.get('crosshairGroup'); crosshairGroup && crosshairGroup.destroy(); var markerGroup = this.get('markerGroup'); markerGroup && markerGroup.remove(); _Tooltip.prototype.destroy.call(this); }; _proto._getMarkerSvg = function _getMarkerSvg(item) { var marker = item.marker || {}; var symbol = marker.activeSymbol || marker.symbol; var method; if (Util.isFunction(symbol)) { method = symbol; } else if (Util.isString(symbol)) { method = Marker.Symbols[symbol]; } method = Util.isFunction(method) ? method : Marker.Symbols.circle; var pathArr = method(MARKER_SIZE / 2, MARKER_SIZE / 2, MARKER_SIZE / 2); var path = pathArr.reduce(function (res, arr) { return "" + res + arr[0] + arr.slice(1).join(','); }, ''); return ""; }; _proto._addItem = function _addItem(item, index) { var itemTpl = this.get('itemTpl'); // TODO: 有可能是个回调函数 var itemDiv = Util.substitute(itemTpl, Util.mix({ index: index }, item)); var itemDOM = DomUtil.createDom(itemDiv); DomUtil.modifyCSS(itemDOM, this.style[LIST_ITEM_CLASS]); var markerDom = find(itemDOM, MARKER_CLASS); if (markerDom) { DomUtil.modifyCSS(markerDom, _extends({}, this.style[MARKER_CLASS], { borderRadius: 'unset' })); var markerPath = this._getMarkerSvg(item); markerDom.innerHTML = markerPath; } var valueDom = find(itemDOM, VALUE_CLASS); if (valueDom) { DomUtil.modifyCSS(valueDom, this.style[VALUE_CLASS]); } return itemDOM; }; _proto._getHtmlContent = function _getHtmlContent() { var htmlContent = this.get('htmlContent'); var title = this.get('titleContent'); var items = this.get('items'); var htmlString = htmlContent(title, items); var ele = DomUtil.createDom(htmlString); return ele; }; _proto.setPosition = function setPosition(x, y, target) { var container = this.get('container'); var outterNode = this.get('canvas').get('el'); var viewWidth = DomUtil.getWidth(outterNode); var viewHeight = DomUtil.getHeight(outterNode); var containerWidth = container.clientWidth; var containerHeight = container.clientHeight; var endx = x; var endy = y; var position; var prePosition = this.get('prePosition') || { x: 0, y: 0 }; // @2019-01-30 by blue.lb 由于display:none的元素获取clientWidth和clientHeight的值为0,这里强制显隐一下,其实直接在show和hide中去掉display设置最好,猜测为了更好的兼容浏览器 if (!containerWidth) { container.style.display = 'block'; containerWidth = container.clientWidth; containerHeight = container.clientHeight; container.style.display = 'none'; } if (this.get('enterable')) { y = y - container.clientHeight / 2; position = [x, y]; if (prePosition && x - prePosition.x > 0) { // 留 1px 防止鼠标点击事件无法在画布上触发 x -= container.clientWidth + 1; } else { x += 1; } } else if (this.get('position')) { // @2019-01-30 by blue.lb 这里应该是多余代码 // const containerWidth = container.clientWidth; // const containerHeight = container.clientHeight; position = this._calcTooltipPosition(x, y, this.get('position'), containerWidth, containerHeight, target); x = position[0]; y = position[1]; } else { position = this._constraintPositionInBoundary(x, y, containerWidth, containerHeight, viewWidth, viewHeight); x = position[0]; y = position[1]; } if (this.get('inPlot')) { // tooltip 必须限制在绘图区域内 var plotRange = this.get('plotRange'); position = this._constraintPositionInPlot(x, y, containerWidth, containerHeight, plotRange, this.get('enterable')); x = position[0]; y = position[1]; } var markerItems = this.get('markerItems'); if (!Util.isEmpty(markerItems)) { endx = markerItems[0].x; endy = markerItems[0].y; } this.set('prePosition', position); // 记录上次的位置 var follow = this.get('follow'); if (follow) { container.style.left = x + 'px'; container.style.top = y + 'px'; } var crosshairGroup = this.get('crosshairGroup'); if (crosshairGroup) { var items = this.get('items'); crosshairGroup.setPosition(endx, endy, items); } _Tooltip.prototype.setPosition.call(this, x, y); }; return HtmlTooltip; }(Tooltip); module.exports = HtmlTooltip;