mirror of
https://github.com/primefaces/primevue.git
synced 2025-05-09 08:52:34 +00:00
Fixed #3802 - Improve folder structure for nuxt configurations
This commit is contained in:
parent
851950270b
commit
f5fe822afb
563 changed files with 1703 additions and 1095 deletions
310
components/lib/knob/Knob.vue
Normal file
310
components/lib/knob/Knob.vue
Normal file
|
@ -0,0 +1,310 @@
|
|||
<template>
|
||||
<div :class="containerClass">
|
||||
<svg
|
||||
viewBox="0 0 100 100"
|
||||
role="slider"
|
||||
:width="size"
|
||||
:height="size"
|
||||
:tabindex="readonly || disabled ? -1 : tabindex"
|
||||
:aria-valuemin="min"
|
||||
:aria-valuemax="max"
|
||||
:aria-valuenow="modelValue"
|
||||
:aria-labelledby="ariaLabelledby"
|
||||
:aria-label="ariaLabel"
|
||||
@click="onClick"
|
||||
@keydown="onKeyDown"
|
||||
@mousedown="onMouseDown"
|
||||
@mouseup="onMouseUp"
|
||||
@touchstart="onTouchStart"
|
||||
@touchend="onTouchEnd"
|
||||
>
|
||||
<path :d="rangePath" :stroke-width="strokeWidth" :stroke="rangeColor" class="p-knob-range"></path>
|
||||
<path :d="valuePath" :stroke-width="strokeWidth" :stroke="valueColor" class="p-knob-value"></path>
|
||||
<text v-if="showValue" :x="50" :y="57" text-anchor="middle" :fill="textColor" class="p-knob-text">{{ valueToDisplay }}</text>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Knob',
|
||||
emits: ['update:modelValue', 'change'],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
valueColor: {
|
||||
type: String,
|
||||
default: 'var(--primary-color, Black)'
|
||||
},
|
||||
rangeColor: {
|
||||
type: String,
|
||||
default: 'var(--surface-border, LightGray)'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: 'var(--text-color-secondary, Black)'
|
||||
},
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
default: 14
|
||||
},
|
||||
showValue: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
valueTemplate: {
|
||||
type: String,
|
||||
default: '{value}'
|
||||
},
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
'aria-labelledby': {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
'aria-label': {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
radius: 40,
|
||||
midX: 50,
|
||||
midY: 50,
|
||||
minRadians: (4 * Math.PI) / 3,
|
||||
maxRadians: -Math.PI / 3
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateValue(offsetX, offsetY) {
|
||||
let dx = offsetX - this.size / 2;
|
||||
let dy = this.size / 2 - offsetY;
|
||||
let angle = Math.atan2(dy, dx);
|
||||
let start = -Math.PI / 2 - Math.PI / 6;
|
||||
|
||||
this.updateModel(angle, start);
|
||||
},
|
||||
updateModel(angle, start) {
|
||||
let mappedValue;
|
||||
|
||||
if (angle > this.maxRadians) mappedValue = this.mapRange(angle, this.minRadians, this.maxRadians, this.min, this.max);
|
||||
else if (angle < start) mappedValue = this.mapRange(angle + 2 * Math.PI, this.minRadians, this.maxRadians, this.min, this.max);
|
||||
else return;
|
||||
|
||||
let newValue = Math.round((mappedValue - this.min) / this.step) * this.step + this.min;
|
||||
|
||||
this.$emit('update:modelValue', newValue);
|
||||
this.$emit('change', newValue);
|
||||
},
|
||||
updateModelValue(newValue) {
|
||||
if (newValue > this.max) this.$emit('update:modelValue', this.max);
|
||||
else if (newValue < this.min) this.$emit('update:modelValue', this.min);
|
||||
else this.$emit('update:modelValue', newValue);
|
||||
},
|
||||
mapRange(x, inMin, inMax, outMin, outMax) {
|
||||
return ((x - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
|
||||
},
|
||||
onClick(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
this.updateValue(event.offsetX, event.offsetY);
|
||||
}
|
||||
},
|
||||
onMouseDown(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
window.addEventListener('mousemove', this.onMouseMove);
|
||||
window.addEventListener('mouseup', this.onMouseUp);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
onMouseUp(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
window.removeEventListener('mousemove', this.onMouseMove);
|
||||
window.removeEventListener('mouseup', this.onMouseUp);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
onTouchStart(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
window.addEventListener('touchmove', this.onTouchMove);
|
||||
window.addEventListener('touchend', this.onTouchEnd);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
onTouchEnd(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
window.removeEventListener('touchmove', this.onTouchMove);
|
||||
window.removeEventListener('touchend', this.onTouchEnd);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
onMouseMove(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
this.updateValue(event.offsetX, event.offsetY);
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
onTouchMove(event) {
|
||||
if (!this.disabled && !this.readonly && event.touches.length == 1) {
|
||||
const rect = this.$el.getBoundingClientRect();
|
||||
const touch = event.targetTouches.item(0);
|
||||
const offsetX = touch.clientX - rect.left;
|
||||
const offsetY = touch.clientY - rect.top;
|
||||
|
||||
this.updateValue(offsetX, offsetY);
|
||||
}
|
||||
},
|
||||
onKeyDown(event) {
|
||||
if (!this.disabled && !this.readonly) {
|
||||
switch (event.code) {
|
||||
case 'ArrowRight':
|
||||
|
||||
case 'ArrowUp': {
|
||||
event.preventDefault();
|
||||
this.updateModelValue(this.modelValue + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'ArrowLeft':
|
||||
|
||||
case 'ArrowDown': {
|
||||
event.preventDefault();
|
||||
this.updateModelValue(this.modelValue - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Home': {
|
||||
event.preventDefault();
|
||||
this.$emit('update:modelValue', this.min);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'End': {
|
||||
event.preventDefault();
|
||||
this.$emit('update:modelValue', this.max);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PageUp': {
|
||||
event.preventDefault();
|
||||
this.updateModelValue(this.modelValue + 10);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PageDown': {
|
||||
event.preventDefault();
|
||||
this.updateModelValue(this.modelValue - 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
containerClass() {
|
||||
return [
|
||||
'p-knob p-component',
|
||||
{
|
||||
'p-disabled': this.disabled
|
||||
}
|
||||
];
|
||||
},
|
||||
rangePath() {
|
||||
return `M ${this.minX} ${this.minY} A ${this.radius} ${this.radius} 0 1 1 ${this.maxX} ${this.maxY}`;
|
||||
},
|
||||
valuePath() {
|
||||
return `M ${this.zeroX} ${this.zeroY} A ${this.radius} ${this.radius} 0 ${this.largeArc} ${this.sweep} ${this.valueX} ${this.valueY}`;
|
||||
},
|
||||
zeroRadians() {
|
||||
if (this.min > 0 && this.max > 0) return this.mapRange(this.min, this.min, this.max, this.minRadians, this.maxRadians);
|
||||
else return this.mapRange(0, this.min, this.max, this.minRadians, this.maxRadians);
|
||||
},
|
||||
valueRadians() {
|
||||
return this.mapRange(this.modelValue, this.min, this.max, this.minRadians, this.maxRadians);
|
||||
},
|
||||
minX() {
|
||||
return this.midX + Math.cos(this.minRadians) * this.radius;
|
||||
},
|
||||
minY() {
|
||||
return this.midY - Math.sin(this.minRadians) * this.radius;
|
||||
},
|
||||
maxX() {
|
||||
return this.midX + Math.cos(this.maxRadians) * this.radius;
|
||||
},
|
||||
maxY() {
|
||||
return this.midY - Math.sin(this.maxRadians) * this.radius;
|
||||
},
|
||||
zeroX() {
|
||||
return this.midX + Math.cos(this.zeroRadians) * this.radius;
|
||||
},
|
||||
zeroY() {
|
||||
return this.midY - Math.sin(this.zeroRadians) * this.radius;
|
||||
},
|
||||
valueX() {
|
||||
return this.midX + Math.cos(this.valueRadians) * this.radius;
|
||||
},
|
||||
valueY() {
|
||||
return this.midY - Math.sin(this.valueRadians) * this.radius;
|
||||
},
|
||||
largeArc() {
|
||||
return Math.abs(this.zeroRadians - this.valueRadians) < Math.PI ? 0 : 1;
|
||||
},
|
||||
sweep() {
|
||||
return this.valueRadians > this.zeroRadians ? 0 : 1;
|
||||
},
|
||||
valueToDisplay() {
|
||||
return this.valueTemplate.replace(/{value}/g, this.modelValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
//Derived and forked from https://github.com/kramer99/vue-knob-control
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@keyframes dash-frame {
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
.p-knob-range {
|
||||
fill: none;
|
||||
transition: stroke 0.1s ease-in;
|
||||
}
|
||||
.p-knob-value {
|
||||
animation-name: dash-frame;
|
||||
animation-fill-mode: forwards;
|
||||
fill: none;
|
||||
}
|
||||
.p-knob-text {
|
||||
font-size: 1.3rem;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue