mirror of
https://github.com/akveo/ngx-admin.git
synced 2026-03-04 12:50:17 +01:00
feat(dashboard): add logic for temperature dragger
This commit is contained in:
parent
ce8055ca84
commit
2ed871ff20
13 changed files with 262 additions and 47 deletions
|
|
@ -1,29 +1,39 @@
|
|||
<svg #svgRoot xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
|
||||
[attr.viewBox]="styles.viewBox" preserveAspectRatio="xMinYMin meet" class="svg-content" (mousedown)="mouseDown($event)">
|
||||
<defs>
|
||||
<div class="svg-container">
|
||||
<svg #svgRoot xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
|
||||
[attr.viewBox]="styles.viewBox" preserveAspectRatio="xMinYMin meet" (mousedown)="mouseDown($event)">
|
||||
<defs>
|
||||
|
||||
<filter id="blurFilter" x="0" y="0" width="100%" height="100%">
|
||||
<feGaussianBlur in="SourceGraphic" [attr.stdDeviation]="styles.blurRadius" />
|
||||
<feComponentTransfer>
|
||||
<feFuncA type="discrete" tableValues="1 1"/>
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
<filter id="blurFilter" x="0" y="0" width="100%" height="100%">
|
||||
<feGaussianBlur in="SourceGraphic" [attr.stdDeviation]="styles.blurRadius" />
|
||||
<feComponentTransfer>
|
||||
<feFuncA type="discrete" tableValues="1 1"/>
|
||||
</feComponentTransfer>
|
||||
</filter>
|
||||
|
||||
<clipPath id="sliderClip">
|
||||
<path [attr.d]="styles.clipPathStr"></path>
|
||||
</clipPath>
|
||||
<clipPath id="sliderClip">
|
||||
<path [attr.d]="styles.clipPathStr"></path>
|
||||
</clipPath>
|
||||
|
||||
</defs>
|
||||
<g [attr.transform]="styles.arcTranslateStr">
|
||||
</defs>
|
||||
<g [attr.transform]="styles.arcTranslateStr">
|
||||
|
||||
<g class="toClip" clip-path="url(#sliderClip)">
|
||||
<g class="toFilter" filter="url(#blurFilter)">
|
||||
<path [attr.d]="arc.d" [attr.fill]="arc.color" *ngFor="let arc of styles.gradArcs"></path>
|
||||
<g class="toClip" clip-path="url(#sliderClip)">
|
||||
<g class="toFilter" filter="url(#blurFilter)">
|
||||
<path [attr.d]="arc.d" [attr.fill]="arc.color" *ngFor="let arc of styles.gradArcs"></path>
|
||||
</g>
|
||||
<path [attr.d]="styles.nonSelectedArc.d" [attr.fill]="styles.nonSelectedArc.color"></path>
|
||||
</g>
|
||||
<path [attr.d]="styles.nonSelectedArc.d" [attr.fill]="styles.nonSelectedArc.color"></path>
|
||||
</g>
|
||||
|
||||
<circle [attr.cx]="styles.knobPosition.x" [attr.cy]="styles.knobPosition.y" [attr.r]="pinRadius"
|
||||
[attr.stroke-width]="1 / scaleFactor" fill="#FFFFFF" stroke="#666666"></circle>
|
||||
</g>
|
||||
</svg>
|
||||
<circle [attr.cx]="styles.knobPosition.x" [attr.cy]="styles.knobPosition.y" [attr.r]="pinRadius"
|
||||
[attr.stroke-width]="1 / scaleFactor" fill="#FFFFFF" stroke="#666666"></circle>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="temperature-bg">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="power-bg" [ngClass]="{'off': off}" (click)="switchPower()">
|
||||
<i class="ion-power"></i>
|
||||
</div>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
|
@ -1,11 +1,66 @@
|
|||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@import '../../../../@theme/styles/variables';
|
||||
@import '~@akveo/nga-theme/styles/global/bootstrap/hero-buttons';
|
||||
|
||||
.svg-content {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@include nga-install-component() {
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.svg-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.temperature-bg {
|
||||
position: absolute;
|
||||
width: 94%;
|
||||
height: 94%;
|
||||
background-color: lighten(nga-theme(layout-bg), 2%);
|
||||
border-radius: 50%;
|
||||
top: 9%;
|
||||
left: 3%;
|
||||
z-index: 1;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.power-bg {
|
||||
position: absolute;
|
||||
width: 5.25rem;
|
||||
height: 5.25rem;
|
||||
background-color: nga-theme(card-bg);
|
||||
border-radius: 50%;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translate(-50%, 50%);
|
||||
z-index: 2;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: nga-theme(card-shadow);
|
||||
cursor: pointer;
|
||||
font-size: 2.5rem;
|
||||
color: nga-theme(color-fg-heading);
|
||||
text-shadow: 0 0 6px rgba(255, 255, 255, 0.5);
|
||||
transition: all 0.1s ease-out;
|
||||
|
||||
&:hover {
|
||||
background-color: lighten(nga-theme(card-bg), 5%);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: darken(nga-theme(card-bg), 5%);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&.off {
|
||||
color: nga-theme(color-fg);
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,15 +16,20 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
@Input() fillColors: string|string[] = '#2ec6ff';
|
||||
@Input() disableArcColor: string = '#999999';
|
||||
@Input() bottomAngle: number = 90;
|
||||
@Input() arcThickness: number = 6; // CSS pixels
|
||||
@Input() knobRadius: number = 10; // CSS pixels
|
||||
@Input() arcThickness: number = 20; // CSS pixels
|
||||
@Input() knobRadius: number = 15; // CSS pixels
|
||||
|
||||
value: number = 0.5;
|
||||
value: number = 50;
|
||||
@Output('valueChange') valueChange = new EventEmitter<Number>();
|
||||
@Input('value') set setValue(value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Input() min: number = 0; // min output value
|
||||
@Input() max: number = 100; // max output value
|
||||
|
||||
@Output() power = new EventEmitter<boolean>();
|
||||
|
||||
@HostListener('mouseup', ['$event'])
|
||||
onMouseUp(event) {
|
||||
this.recalculateValue(event);
|
||||
|
|
@ -41,6 +46,9 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
this.invalidate();
|
||||
}
|
||||
|
||||
off: boolean = false;
|
||||
oldValue: number;
|
||||
|
||||
scaleFactor: number = 1;
|
||||
bottomAngleRad = 0;
|
||||
radius: number = 100;
|
||||
|
|
@ -64,6 +72,7 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
private init = false;
|
||||
|
||||
constructor() {
|
||||
this.oldValue = this.value;
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
|
@ -79,7 +88,23 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
|
||||
mouseDown(event) {
|
||||
this.isMouseDown = true;
|
||||
this.recalculateValue(event);
|
||||
if (!this.off) {
|
||||
this.recalculateValue(event);
|
||||
}
|
||||
}
|
||||
|
||||
switchPower() {
|
||||
this.off = !this.off;
|
||||
this.power.emit(!this.off);
|
||||
|
||||
if (this.off) {
|
||||
this.oldValue = this.value;
|
||||
this.value = this.min;
|
||||
} else {
|
||||
this.value = this.oldValue;
|
||||
}
|
||||
|
||||
this.invalidatePinPosition();
|
||||
}
|
||||
|
||||
private invalidate(): void {
|
||||
|
|
@ -254,7 +279,7 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
}
|
||||
|
||||
private invalidateNonSelectedArc() {
|
||||
const angle = this.bottomAngleRad / 2 + (1 - this.value) * (2 * Math.PI - this.bottomAngleRad);
|
||||
const angle = this.bottomAngleRad / 2 + (1 - this.getValuePercentage()) * (2 * Math.PI - this.bottomAngleRad);
|
||||
this.styles.nonSelectedArc = {
|
||||
color: this.disableArcColor,
|
||||
d: `M ${this.radius},${this.radius}
|
||||
|
|
@ -269,7 +294,7 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
private invalidatePinPosition() {
|
||||
const radiusOffset = this.thickness / 2;
|
||||
const curveRadius = this.radius - radiusOffset;
|
||||
const actualAngle = (2 * Math.PI - this.bottomAngleRad) * this.value + this.bottomAngleRad / 2;
|
||||
const actualAngle = (2 * Math.PI - this.bottomAngleRad) * this.getValuePercentage() + this.bottomAngleRad / 2;
|
||||
this.styles.knobPosition = {
|
||||
x: curveRadius * (1 - Math.sin(actualAngle)) + radiusOffset,
|
||||
y: curveRadius * (1 + Math.cos(actualAngle)) + radiusOffset,
|
||||
|
|
@ -298,6 +323,8 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
value = (actualAngle - this.bottomAngleRad / 2) / (2 * Math.PI - this.bottomAngleRad);
|
||||
}
|
||||
|
||||
value = value * (this.max - this.min) + this.min;
|
||||
|
||||
if (this.value !== value) {
|
||||
this.value = value;
|
||||
this.valueChange.emit(this.value);
|
||||
|
|
@ -306,6 +333,10 @@ export class TemperatureDraggerComponent implements AfterViewInit, OnChanges {
|
|||
}
|
||||
}
|
||||
|
||||
private getValuePercentage() {
|
||||
return (this.value - this.min) / (this.max - this.min);
|
||||
}
|
||||
|
||||
private static toRad(angle) {
|
||||
return Math.PI * angle / 180;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue