zz-chart
Version:
Alauda Chart components by Alauda Frontend Team
184 lines • 6.13 kB
JavaScript
import { StyleSheet, css } from 'aphrodite/no-important.js';
import { get, isArray, isElement, isFunction, isNil, isString, } from 'lodash-es';
import placement from 'placement.js';
import { ChartEvent, } from '../types/index.js';
import { NOT_AVAILABLE } from '../utils/constant.js';
import { generateName, template } from '../utils/index.js';
import { BaseComponent } from './base.js';
import { symbolStyle } from './styles.js';
const styles = StyleSheet.create({
overlay: {
position: 'absolute',
visibility: 'hidden',
pointerEvents: 'none',
padding: '12px',
boxShadow: '0 2px 8px #00000029',
margin: 8,
zIndex: 999,
transition: 'transform 0.1s ease-out 0s',
// transition:
// 'top 0.3s cubic-bezier(0.23, 1, 0.32, 1) 0s',
fontSize: 12,
},
'tooltip-title': {
marginBottom: 8,
},
'tooltip-list': {
listStyle: 'none',
padding: 0,
margin: 0,
},
'tooltip-list-item': {
listStyleType: 'none',
padding: '2px 8px',
display: 'flex',
alignItems: 'center',
},
'tooltip-marker': {
marginRight: 4,
},
'tooltip-name': {
maxWidth: '197px',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
'tooltip-value': {
marginLeft: 30,
flex: 1,
textAlign: 'right',
whiteSpace: 'nowrap',
},
});
export class Tooltip extends BaseComponent {
constructor() {
super(...arguments);
this.showTooltip = () => {
this.container.style.visibility = 'visible';
this.container.style.background = this.ctrl.getTheme().tooltip.background;
this.container.style.color = this.ctrl.getTheme().tooltip.color;
};
this.hideTooltip = () => {
if (this.container) {
this.container.style.visibility = 'hidden';
}
};
}
get name() {
return 'tooltip';
}
render() {
const opt = this.ctrl.getOption();
this.option = get(opt, this.name, {});
this.create();
}
update() {
this.option = get(this.ctrl.getOption(), this.name);
this.createItem();
}
create() {
if (this.option) {
if (!this.container) {
const overlay = document.createElement('div');
overlay.className = `${generateName('tooltip')} ${css(styles.overlay)}`;
(get(this.option, 'popupContainer') || document.body).append(overlay);
overlay.style.visibility = 'hidden';
this.container = overlay;
}
this.createItem();
this.eventListener();
}
}
/**
* 创建 tooltip item
* @param title
* @param values
*/
createItem(title, values) {
const itemTpl = this.getTooltipItem(values);
if (!itemTpl) {
return;
}
const isEl = isElement(itemTpl);
const list = `<ul class="${css(styles['tooltip-list'])}">${itemTpl}</ul>`;
this.container.innerHTML = `
${this.getTooltipTitle(title, values)}
${isEl ? '' : list}
`;
if (isEl) {
this.container.remove();
this.container.append(itemTpl);
}
}
getTooltipTitle(title, values) {
const { showTitle, titleFormatter } = this.option;
if (String(showTitle) === 'false' || !title) {
return '';
}
let tpl = title || NOT_AVAILABLE;
if (isString(titleFormatter)) {
tpl = template(titleFormatter, { title });
}
if (isFunction(titleFormatter)) {
tpl = titleFormatter(title, values);
}
return `<div class="${css(styles['tooltip-title'])}">${tpl}</div>`;
}
getTooltipItem(values) {
if (!values || !values?.length) {
return '';
}
const { nameFormatter, valueFormatter, itemFormatter, sort } = this
.option;
let items = sort ? values.sort(sort) : values;
if (itemFormatter) {
const itemValue = itemFormatter(items);
if (isString(itemValue)) {
return itemValue;
}
if (isElement(itemValue)) {
return itemValue.innerHTML;
}
if (isArray(itemValue)) {
items = itemValue;
}
}
return items
?.map(item => {
const value = this.handleTemplateString(item.value, valueFormatter, item);
const name = this.handleTemplateString(String(item.name), nameFormatter, item);
return `<li class="${css(styles['tooltip-list-item'])}" style="background: ${item.activated ? this.ctrl.getTheme().tooltip.activeBg : 'unset'}">
<span class="${css(symbolStyle.symbol)} ${css(symbolStyle.line)}" style="background: ${item.color};"></span>
<span class="${generateName('tooltip-name')} ${css(styles['tooltip-name'])}">${name || NOT_AVAILABLE}</span>
<span class="${generateName('tooltip-value')} ${css(styles['tooltip-value'])}">${isNil(value) ? NOT_AVAILABLE : value}</span>
</li>`;
})
.join('');
}
handleTemplateString(text, formatter, data) {
let value = text;
if (isString(formatter)) {
value = template(formatter, { value: text });
}
if (isFunction(formatter)) {
value = formatter(value, data);
}
return value;
}
/**
* 添加事件监听
*/
eventListener() {
// TODO: 是否纳管到 interaction
this.ctrl.on(ChartEvent.U_PLOT_SET_CURSOR, ({ anchor, title, values, position }) => {
if (values?.length) {
// @ts-ignore
placement(anchor, this.container, {
placement: position || 'right',
});
this.createItem(title, values);
}
});
}
}
//# sourceMappingURL=tooltip.js.map