feature: add text component
This commit is contained in:
parent
431239b8a4
commit
bf0090858b
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue