import { Component, OnInit, HostBinding, Input, HostListener, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'farris-rate', templateUrl: './rate.component.html', styleUrls: ['./rate.component.css'] }) export class RateComponent implements OnInit { @HostBinding('class.farris-star-rating') fsr = true; @Input() set value(value: any) { if (value != this.realScore) { this.realScore = value; this.scoreChanged(); } } // 星星大小 @Input() size = 'large'; // 启用半颗星模式 @Input() enableHalf = false; // 启用再次点击后清除 @Input() enableClear = false; // 只读 @Input() disabled = false; // 分制 @Input() pointSystem = 5; // 星星亮色 @Input() lightColor: string; // 星星暗色(底色) @Input() darkColor: string; // 图案样式 @Input() iconClass = 'f-icon-star'; // 星星个数 private _numOfStar = 5; @Input() set numOfStar(value: number) { if (this._numOfStar != value) { this._numOfStar = value; this.updateStarConfig(); } } get numOfStar() { return this._numOfStar; } // 禁用单个星星的文字提示 @Input() toolTipDisabled = true; // 默认的满意度文案 @Input() toolTipContents = ['很不满意', '不满意', '一般', '满意', '非常满意']; // 启用评分 @Input() enableScore = true; // 启用满意度 @Input() enableSatisfaction = false; @Output() valueChange = new EventEmitter(); pointInfo: string; // 一颗星宽度 oneStarWidth: number; // 亮色区域虚拟宽度 lightStarAreaWidth: number; // 界面中亮色区域真实宽度 realWidth = 0; // 虚拟分数 score: any = 0; // 最终分数 realScore = 0; // 比率 rate = 1; // 切换的满意度 satisfaction: any; // 最终显示的满意度 realSatisfaction: any; // 配置 config = []; // 星星之间的间距,设计稿是4 distance = 4; constructor() { } ngOnInit() { switch (this.size) { case 'small': this.oneStarWidth = 14; break; case 'middle': this.oneStarWidth = 16; break; case 'large': this.oneStarWidth = 18; break; case 'extraLarge': this.oneStarWidth = 24; break; } // 更新Config this.updateStarConfig(); if (this.numOfStar) { this.rate = this.pointSystem / this.numOfStar; } if (this.realScore) { this.scoreChanged(); } } @HostListener('mouseover', ['$event']) onMouseOver(event: any) { if (!this.isTargetElement(event.target)) { return; } const id = parseInt(event.target.id); this.operateStar(event, id, false); } @HostListener('mousemove', ['$event']) onMouseMove(event: any) { if (!this.isTargetElement(event.target)) { return; } const id = parseInt(event.target.id); this.operateStar(event, id, false); } @HostListener('mouseout', ['$event']) onMouseOut(event: any) { if (!this.isTargetElement(event.target)) { return; } this.lightStarAreaWidth = 0; this.score = 0; this.satisfaction = null; } @HostListener('click', ['$event']) onClick(event: any) { if (!this.isTargetElement(event.target)) { return; } const id = parseInt(event.target.id); this.operateStar(event, id, true); } private updateStarConfig() { var inputNum = this.numOfStar; this.config = []; for (var i = 1; i <= inputNum; i++) { this.config.push({ 'id': i }); } } /** * 是否是目标元素 * @param element */ private isTargetElement(element: any) { if (element.className.indexOf('f-icon') !== -1) { return true; } else { return false; } } private scoreChanged() { let starId; if (this.enableHalf) { starId = Math.ceil(this.realScore / this.rate); } else { starId = this.realScore; } this.realWidth = (this.oneStarWidth * this.realScore + Math.floor(this.realScore) * this.distance) / this.rate; this.satisfaction = this.toolTipContents[starId - 1] } /** * 再次点击取消选中 */ private clear() { if (this.lightStarAreaWidth === this.realWidth && this.enableClear && this.realWidth !== 0) { this.realWidth = 0; this.realScore = 0; this.realSatisfaction = null; this.valueChange.emit(this.realScore); return true; } return false; } /** * * @param event 事件 * @param id 当前星星的id * @param token 是否点击事件触发 */ private operateStar(event: any, id: any, token: boolean) { // 禁用 if (this.disabled) { return; } // 满意度文案 if (this.enableSatisfaction) { this.satisfaction = this.toolTipContents[id - 1]; } // 如果滑动的距离小于一颗星星一半的距离(或者超过) if (event.offsetX < this.oneStarWidth / 2 && this.enableHalf === true) { this.lightStarAreaWidth = (this.oneStarWidth * id) - this.oneStarWidth / 2 + this.distance * (id - 1); this.score = (this.rate * id) - this.rate / 2; if (token === true) { if (this.clear()) { return; } this.realScore = this.score; this.valueChange.emit(this.realScore); this.realWidth = this.lightStarAreaWidth; this.realSatisfaction = this.satisfaction; } } else { this.lightStarAreaWidth = this.oneStarWidth * id + this.distance * (id - 1); this.score = this.rate * id; if (token === true) { if (this.clear()) { return; } this.realScore = this.score; this.valueChange.emit(this.realScore); this.realWidth = this.lightStarAreaWidth; this.realSatisfaction = this.satisfaction; } } } }