@meta2d/core
Version:
@meta2d/core: Powerful, Beautiful, Simple, Open - Web-Based 2D At Its Best .
175 lines • 6.04 kB
JavaScript
import { getParent } from '../pen';
export class Tooltip {
parentElement;
store;
box;
text;
arrowUp;
arrowDown;
x;
y;
currentPen; // 本次 tooltip 在哪个画笔上
constructor(parentElement, store) {
this.parentElement = parentElement;
this.store = store;
this.box = document.createElement('div');
this.text = document.createElement('div');
this.arrowUp = document.createElement('div');
this.arrowDown = document.createElement('div');
this.box.className = 'meta2d-tooltip';
this.text.className = 'text';
this.arrowUp.className = 'arrow';
this.arrowDown.className = 'arrow down';
this.box.appendChild(this.text);
this.box.appendChild(this.arrowUp);
this.box.appendChild(this.arrowDown);
parentElement.appendChild(this.box);
this.box.onmouseleave = () => {
this.hide();
this.store.lastHover = undefined;
};
let sheet;
for (let i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].title === 'le5le.com/tooltip') {
sheet = document.styleSheets[i];
}
}
if (!sheet) {
let style = document.createElement('style');
style.type = 'text/css';
style.title = 'le5le.com/tooltip';
document.head.appendChild(style);
style = document.createElement('style');
style.type = 'text/css';
document.head.appendChild(style);
sheet = style.sheet;
sheet.insertRule('.meta2d-tooltip{position:absolute;padding:8px 0;z-index:10;left: -9999px;top: -9999px;}');
sheet.insertRule('.meta2d-tooltip .text{max-width:320px;min-height:30px;max-height:400px;outline:none;padding:8px 16px;border-radius:4px;background:#777777;color:#ffffff;line-height:1.8;overflow-y:auto;}');
sheet.insertRule('.meta2d-tooltip .arrow{position:absolute;border:10px solid transparent;background:transparent;top:-5px;left:50%;transform:translateX(-50%)}');
sheet.insertRule('.meta2d-tooltip .arrow.down{top:initial;bottom: -1px;}');
}
}
/**
* 通过 pen 的 titleFn titleFnJs title 来获取 title
* @returns 此次应该展示的 title
*/
static getTitle(pen) {
if (pen.titleFnJs && !pen.titleFn) {
try {
pen.titleFn = new Function('pen', pen.titleFnJs);
}
catch (error) {
console.log('titleFnJs', error);
}
}
return pen.titleFn ? pen.titleFn(pen) : String(pen.title);
}
/**
* 更改 tooltip dom 的文本
* @returns 返回设置前的 rect
*/
setText(pen) {
const oldElemRect = this.box.getBoundingClientRect();
let marked = globalThis.marked;
const title = Tooltip.getTitle(pen);
if (marked) {
this.text.innerHTML = marked(title);
const a = this.text.getElementsByTagName('A');
for (let i = 0; i < a.length; ++i) {
a[i].setAttribute('target', '_blank');
}
}
else {
this.text.innerHTML = title;
}
return oldElemRect;
}
/**
* 更新文字
*/
updateText(pen) {
if (this.currentPen?.id !== pen.id) {
return;
}
if (Tooltip.titleEmpty(pen)) {
return;
}
if (pen.titleUnUpdate) {
return;
}
const oldRect = this.setText(pen);
const newRect = this.box.getBoundingClientRect();
this.changePositionByText(oldRect, newRect);
}
/**
* 改变文字会 影响 box 的大小,需要重新设置位置
* @param oldRect 原
* @param newRect 新
*/
changePositionByText(oldRect, newRect) {
this.x -= (newRect.width - oldRect.width) / 2;
this.y -= newRect.height - oldRect.height;
this.box.style.left = this.x + 'px';
this.box.style.top = this.y + 'px';
}
static titleEmpty(pen) {
return !pen.title && !pen.titleFn && !pen.titleFnJs;
}
show(pen, pos) {
this.currentPen = pen;
if (Tooltip.titleEmpty(pen)) {
let parent = getParent(pen, true);
if (parent) {
this.show(parent, pos);
}
return;
}
this.setText(pen);
const elemRect = this.box.getBoundingClientRect();
const rect = pen.calculative.worldRect;
let x = pen.calculative.canvas.store.data.x + pos.x - elemRect.width / 2;
let y = pen.calculative.canvas.store.data.y + pos.y - elemRect.height;
if (!pen.type) {
x =
pen.calculative.canvas.store.data.x +
rect.x -
(elemRect.width - rect.width) / 2;
y =
pen.calculative.canvas.store.data.y +
rect.ey -
elemRect.height -
rect.height;
}
if (y > 0) {
this.arrowUp.style.borderBottomColor = 'transparent';
this.arrowDown.style.borderTopColor = '#777777';
}
else {
y += elemRect.height + rect.height + 5;
this.arrowUp.style.borderBottomColor = '#777777';
this.arrowDown.style.borderTopColor = 'transparent';
}
this.x = x;
this.y = y;
this.box.style.left = this.x + 'px';
this.box.style.top = this.y + 'px';
}
hide() {
this.currentPen = null;
this.x = -9999;
this.box.style.left = '-9999px';
}
translate(x, y) {
if (this.x < -1000) {
return;
}
this.x += x;
this.y += y;
this.box.style.left = this.x + 'px';
this.box.style.top = this.y + 'px';
}
destroy() {
this.box.onmouseleave = null;
}
}
//# sourceMappingURL=tooltip.js.map