feature: add text component

This commit is contained in:
Sagi 2022-09-28 17:40:27 +08:00
parent 431239b8a4
commit bf0090858b
5 changed files with 0 additions and 336 deletions

View File

View File

@ -1,336 +0,0 @@
import {
Component, Input, TemplateRef, ElementRef, OnInit,
ViewChild, ViewContainerRef, HostBinding, ViewEncapsulation, SimpleChanges, Renderer2, NgZone
} from '@angular/core';
import { AfterViewInit } from '@angular/core';
@Component({
selector: 'farris-tooltip',
templateUrl: './tooltip.component.html',
styleUrls: ['./tooltip.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class TooltipComponent implements OnInit, AfterViewInit {
@ViewChild('contentViewf', { read: ViewContainerRef }) contentViewf: ViewContainerRef;
@ViewChild('tooltipEle', { read: ElementRef }) tooltipNode: ElementRef;
@ViewChild('arrowEle', { read: ElementRef }) arrowNode: ElementRef;
@ViewChild('innerEle', { read: ElementRef }) innerNode: ElementRef;
contentIsString = true;
/* 普通文本内容 */
@Input()
set content(value: string | TemplateRef<any>) {
if (value instanceof TemplateRef) {
this.contentIsString = false;
this.contentViewf.createEmbeddedView(value);
} else {
this.contentIsString = true;
this.nfContent = value;
}
}
get content() {
return this.nfContent;
}
private _tipWidth = '';
/**因为表单生成没有排除factory,不能使用模板 */
@Input()
set tipWidth(value) {
if (value != this._tipWidth) {
if (value) {
this.render.setStyle(this.innerNode.nativeElement, 'width', value);
this.render.setStyle(this.innerNode.nativeElement, 'max-width', 'none');
} else {
this.render.removeStyle(this.innerNode.nativeElement, 'width');
this.render.removeStyle(this.innerNode.nativeElement, 'max-width');
}
this._tipWidth = value;
}
}
get tipWidth() {
return this._tipWidth;
}
private _tipCls = '';
@Input()
set tipCls(value) {
if (value != this._tipCls) {
//移除旧样式
this._tipCls && this.render.removeClass(this.el.nativeElement, this._tipCls);
//追加新样式
value && this.render.addClass(this.el.nativeElement, value);
this._tipCls = value;
}
}
get tipCls() {
return this._tipCls;
}
/* 位置 */
@Input() placement = 'top';
private rectifyPlacement = 'top';
// 箭头位置参照
hostBoundingClientRect: any;
// 边界位置参照
referenceBoundingRect: any;
private rectifyGutter = 20;
nfContent: string | TemplateRef<any>;
/* 位置样式 */
positionStyle = {};
constructor(
public el: ElementRef,
private render: Renderer2
) {
}
ngOnInit() {
}
ngAfterViewInit() {
if (this.hostBoundingClientRect) {
this.judgeWidth();
this.autoRectifyDirection();
this.calculatePosition(this.hostBoundingClientRect);
}
}
/**
*
*/
judgeWidth() {
if (this.innerNode.nativeElement.scrollHeight > this.innerNode.nativeElement.clientHeight) {
this.render.addClass(this.innerNode.nativeElement, 'tooltip-inner-lg');
}
}
// 自动纠正方向
private autoRectifyDirection() {
// 标记默认值
this.rectifyPlacement = this.placement;
// 整个提示位置
const tooltipSize = this.tooltipNode.nativeElement.getBoundingClientRect();
const arrowSize = this.arrowNode.nativeElement.getBoundingClientRect();
/*,
if(this.referenceBoundingRect.width>tooltipSize){
}*/
switch (this.placement) {
case 'top':
case 'top-left':
case 'top-right':
if (Math.abs(this.hostBoundingClientRect.top - this.referenceBoundingRect.top) < tooltipSize.height + arrowSize.height) {
// 高度放不开,转向
this.rectifyPlacement = this.rectifyPlacement.replace('top', 'bottom');
}
break;
case 'bottom':
case 'bottom-left':
case 'bottom-right':
if (Math.abs(this.hostBoundingClientRect.bottom - this.referenceBoundingRect.bottom) < tooltipSize.height + arrowSize.height) {
// 高度放不开,转向
this.rectifyPlacement = this.rectifyPlacement.replace('bottom', 'top');
}
break;
case 'right':
case 'right-top':
case 'right-bottom':
if (Math.abs(this.hostBoundingClientRect.right - this.referenceBoundingRect.right) < tooltipSize.width + arrowSize.width) {
// 宽度放不开,转向
this.rectifyPlacement = this.rectifyPlacement.replace('right', 'left');
}
break;
case 'left':
case 'left-top':
case 'left-bottom':
if (Math.abs(this.hostBoundingClientRect.left - this.referenceBoundingRect.left) < tooltipSize.width + arrowSize.width) {
// 宽度放不开,转向
this.rectifyPlacement = this.rectifyPlacement.replace('left', 'right');
}
break;
}
if (this.rectifyPlacement != this.placement) {
this.tooltipNode.nativeElement.classList.remove('bs-tooltip-' + this.offsetDirection(this.placement));
this.tooltipNode.nativeElement.classList.add('bs-tooltip-' + this.offsetDirection(this.rectifyPlacement));
}
}
/**
*
*/
private isOverBounding(rect, value) {
let isOver = false;
let newValue = 0;
switch (rect) {
case 'left':
if (value <= this.referenceBoundingRect.left) {
isOver = true;
newValue = this.referenceBoundingRect.left + this.rectifyGutter;
}
break;
case 'right':
if (value >= this.referenceBoundingRect.right) {
isOver = true;
newValue = this.referenceBoundingRect.right - this.rectifyGutter;
}
break;
case 'top':
if (value <= this.referenceBoundingRect.top) {
isOver = true;
newValue = this.referenceBoundingRect.top + this.rectifyGutter;
}
break;
case 'bottom':
if (value >= this.referenceBoundingRect.bottom) {
isOver = true;
newValue = this.referenceBoundingRect.bottom - this.rectifyGutter;
}
break;
}
return { isOver, newValue };
}
private containsEl(datas, specialEl = '') {
if (!specialEl) {
specialEl = this.rectifyPlacement;
}
for (var i = 0; i < datas.length; i++) {
if (datas[i] == specialEl)
return true;
}
return false;
}
/* 计算tooltip最新位置 */
calculatePosition(hostPosition: any) {
let top = 0;
let left = 0;
let right = 0;
let bottom = 0;
// 整个提示位置
const tooltipSize = this.tooltipNode.nativeElement.getBoundingClientRect();
const arrowSize = this.arrowNode.nativeElement.getBoundingClientRect();
switch (this.rectifyPlacement) {
case 'top':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.left + (hostPosition.width - tooltipSize.width) / 2;
right = left + tooltipSize.width;
break;
case 'left':
top = hostPosition.top + (hostPosition.height - tooltipSize.height) / 2;
left = hostPosition.left - tooltipSize.width - 2;
break;
case 'right':
top = hostPosition.top + (hostPosition.height - tooltipSize.height) / 2;
left = hostPosition.right + 2;
break;
case 'bottom':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.left + (hostPosition.width - tooltipSize.width) / 2;
right = left + tooltipSize.width;
break;
case 'top-left':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.left;
right = left + tooltipSize.width;
break;
case 'top-right':
top = hostPosition.top - tooltipSize.height - 2;
left = hostPosition.right - tooltipSize.width;
right = hostPosition.right;
break;
case 'right-top':
top = hostPosition.top;
left = hostPosition.right + 2;
this.arrowNode.nativeElement.style.top = '10%';
break;
case 'right-bottom':
top = hostPosition.bottom - tooltipSize.height;
left = hostPosition.right + 2;
this.arrowNode.nativeElement.style.bottom = '10%';
break;
case 'bottom-left':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.left;
right = left + tooltipSize.width;
break;
case 'bottom-right':
top = hostPosition.bottom + arrowSize.height + 2;
left = hostPosition.right - tooltipSize.width;
right = hostPosition.right;
break;
case 'left-top':
top = hostPosition.top;
left = hostPosition.left - tooltipSize.width - 2;
this.arrowNode.nativeElement.style.top = '10%';
break;
case 'left-bottom':
top = hostPosition.bottom - tooltipSize.height;
left = hostPosition.left - tooltipSize.width - 2;
this.arrowNode.nativeElement.style.bottom = '10%';
}
let overResult;
let arrowLeft = 0;
let arrowTop = 0
switch (this.rectifyPlacement) {
case 'top':
case 'top-left':
case 'top-right':
case 'bottom':
case 'bottom-left':
case 'bottom-right':
overResult = this.isOverBounding('left', left);
if (overResult.isOver) {
left = overResult.newValue;
} else {
overResult = this.isOverBounding('right', right);
if (overResult.isOver) {
left = overResult.newValue - tooltipSize.width;
}
}
arrowLeft = left - hostPosition.left - hostPosition.width * 0.5 + arrowSize.width * 0.5;
if (this.rectifyPlacement.indexOf('-left') > 0) {
arrowLeft += hostPosition.width * 0.4;
} else if (this.rectifyPlacement.indexOf('-right') > 0) {
arrowLeft -= hostPosition.width * 0.4;
}
this.arrowNode.nativeElement.style.left = Math.abs(arrowLeft) + 'px';
break;
default:
overResult = this.isOverBounding('top', top);
if (overResult.isOver) {
top = overResult.newValue;
} else {
overResult = this.isOverBounding('bottom', bottom);
if (overResult.isOver) {
top = overResult.newValue - tooltipSize.height;
}
}
arrowTop = top - hostPosition.top - hostPosition.height * 0.5 + arrowSize.height * 0.5;;
if (this.rectifyPlacement.indexOf('-top') > 0) {
arrowTop += hostPosition.height * 0.4;
} else if (this.rectifyPlacement.indexOf('-bottom') > 0) {
arrowTop -= hostPosition.height * 0.4;
}
this.arrowNode.nativeElement.style.top = Math.abs(arrowTop) + 'px';
}
this.tooltipNode.nativeElement.style.top = top + 'px';
this.tooltipNode.nativeElement.style.left = left + 'px';
}
/*
*12
* factory,使[class],
*/
offsetDirection(tplacement = '') {
if (!tplacement) {
tplacement = this.placement;
}
if (tplacement.indexOf('-') !== -1) {
const index = tplacement.indexOf('-');
return tplacement.substring(0, index);
}
return tplacement;
}
}