From 76eebf1aac8dc484316c03cad7fc47fd51d849b8 Mon Sep 17 00:00:00 2001 From: Ali Asanov Date: Thu, 5 Dec 2019 14:30:31 +0300 Subject: [PATCH 1/9] add second knob --- demo/App.vue | 5 +---- src/components/CircleSlider.vue | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/demo/App.vue b/demo/App.vue index 68e4ffd..08fcc0e 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -1,14 +1,10 @@ @@ -66,9 +67,17 @@ export default { margin-top: 20px; } + .min-value { + font-size: 20px; + margin-top: 20px; + } + input { height: 30px; font-size: 20px; margin-top: 30px; } - \ No newline at end of file + + + +// @input_min="sliderMinValue = 0" \ No newline at end of file diff --git a/src/components/CircleSlider.vue b/src/components/CircleSlider.vue index 4828956..521dfaf 100644 --- a/src/components/CircleSlider.vue +++ b/src/components/CircleSlider.vue @@ -35,8 +35,8 @@ export default { let maxCurveWidth = Math.max(this.cpMainCircleStrokeWidth, this.cpPathStrokeWidth) this.radius = (this.side / 2) - Math.max(maxCurveWidth, this.cpKnobRadius * 2) / 2 - this.updateFromPropMinValue(this.minValue) this.updateFromPropMaxValue(this.value) + this.currentMinStepIndex > this.currentMaxStepIndex ? this.setDefaultMinValue() : this.updateFromPropMinValue(this.minValue) }, mounted () { this.containerElement = this.$refs._svg @@ -255,7 +255,6 @@ export default { this.setNewPosition(e) if (this.cpIsTouchWithinSliderRange) { const newAngle = this.cpSliderAngle - this.defineCurrentKnob(newAngle) if (this.currentKnob === 'min') this.animateSlider(this.minAngle, newAngle) @@ -284,6 +283,8 @@ export default { }, handleWindowMouseMove (e) { e.preventDefault() + if (this.minAngle >= this.maxAngle) return + if (this.mousemoveTicks < 5) { this.mousemoveTicks++ return @@ -376,7 +377,7 @@ export default { } if (this.steps[stepIndex] === this.value) { this.currentMaxStepIndex = stepIndex - break + // break } } }, @@ -418,6 +419,12 @@ export default { const offsetFromMin = Math.abs(this.minAngle - newAngle) this.currentKnob = offsetFromMax <= offsetFromMin ? 'max' : 'min' } + }, + setDefaultMinValue () { + const defaultMinValue = 0 + this.updateFromPropMinValue(defaultMinValue) + this.$emit('input_min') + alert('"Min" value cannot be greater than "Max" value. Please set the correct value.') } }, watch: { @@ -429,7 +436,7 @@ export default { minValue (val) { if (val === this.currentMinStepValue) return this.currentKnob = 'min' - this.updateFromPropMinValue(val) + this.currentMinStepIndex >= this.currentMaxStepIndex ? this.setDefaultMinValue() : this.updateFromPropMinValue(val) } } } From d18913e0ba20468e1299424048615bb15495a244 Mon Sep 17 00:00:00 2001 From: Ali Asanov Date: Mon, 9 Dec 2019 17:34:16 +0300 Subject: [PATCH 6/9] fix: make 2-way binding of minValue --- demo/App.vue | 2 +- src/components/CircleSlider.vue | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/demo/App.vue b/demo/App.vue index d69e705..1b47a6b 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -6,7 +6,7 @@ :circleWidth="20" :knobRadius="20" :minValue="sliderMinValueOrZero" - @input_min="sliderMinValue = 0" + @inputMin=" value => sliderMinValue = value " :minKnobColor="minKnobColor" > diff --git a/src/components/CircleSlider.vue b/src/components/CircleSlider.vue index 521dfaf..e074d47 100644 --- a/src/components/CircleSlider.vue +++ b/src/components/CircleSlider.vue @@ -310,11 +310,15 @@ export default { this.updateSlider() } }, - updateMinAngle (angle) { + updateMinAngle (angle, isAnimationFinished) { this.updateCurrentMinStepFromAngle(angle) this.minAngle = this.cpMinAngleValue this.currentMinStepValue = this.cpCurrentMinStep + + if (isAnimationFinished) { + this.$emit('inputMin', this.currentMinStepValue) + } }, updateMaxAngle (angle, isAnimationFinished) { this.updateCurrentMaxStepFromAngle(angle) @@ -360,11 +364,11 @@ export default { const animate = () => { if (Math.abs(endAngle - startAngle) < Math.abs(2 * curveAngleMovementUnit)) { if (this.currentKnob === 'max') this.updateMaxAngle(endAngle, true) - else if (this.currentKnob === 'min') this.updateMinAngle(endAngle) + else if (this.currentKnob === 'min') this.updateMinAngle(endAngle, true) } else { const newAngle = startAngle + curveAngleMovementUnit if (this.currentKnob === 'max') this.updateMaxAngle(newAngle, false) - else if (this.currentKnob === 'min') this.updateMinAngle(newAngle) + else if (this.currentKnob === 'min') this.updateMinAngle(newAngle, false) this.animateSlider(newAngle, endAngle) } } @@ -423,7 +427,7 @@ export default { setDefaultMinValue () { const defaultMinValue = 0 this.updateFromPropMinValue(defaultMinValue) - this.$emit('input_min') + this.$emit('inputMin', defaultMinValue) alert('"Min" value cannot be greater than "Max" value. Please set the correct value.') } }, From 7fea0c36dcb9f6ad14a236c3f82aaf4267dd7be3 Mon Sep 17 00:00:00 2001 From: Ali Asanov Date: Mon, 9 Dec 2019 18:21:39 +0300 Subject: [PATCH 7/9] fix: fix progress stroke disappearing when minValue = 0 and maxValue = 100, i.e. when knobs are at the same position --- demo/App.vue | 6 +++--- src/components/CircleSlider.vue | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/demo/App.vue b/demo/App.vue index 1b47a6b..3127b3b 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -21,9 +21,9 @@ export default { data () { return { - sliderMaxValue: 50, - sliderMinValue: 25, - minKnobColor: '#EA1313' + sliderMaxValue: 0, + sliderMinValue: 0, + // minKnobColor: '#EA1313' } }, computed: { diff --git a/src/components/CircleSlider.vue b/src/components/CircleSlider.vue index e074d47..c15f2ff 100644 --- a/src/components/CircleSlider.vue +++ b/src/components/CircleSlider.vue @@ -219,7 +219,7 @@ export default { return (Math.min( this.startAngleOffset + this.cpAngleUnit * this.currentMinStepIndex, Math.PI * 2 - Number.EPSILON - )) - 0.00001 // correct for 100% value + )) // - 0.00001 // correct for 100% value }, cpMaxAngleValue () { return (Math.min( From a9569801319b32ef68ffe0e8bccefe70bddda8f4 Mon Sep 17 00:00:00 2001 From: Ali Asanov Date: Mon, 9 Dec 2019 18:50:13 +0300 Subject: [PATCH 8/9] add props for minValue knob --- demo/App.vue | 9 +++------ src/components/CircleSlider.vue | 27 ++++++++++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/demo/App.vue b/demo/App.vue index 3127b3b..f9388f4 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -4,10 +4,10 @@ v-model="sliderMaxValueOrZero" :side="300" :circleWidth="20" - :knobRadius="20" + :maxKnobRadius="20" + :minKnobRadius="20" :minValue="sliderMinValueOrZero" @inputMin=" value => sliderMinValue = value " - :minKnobColor="minKnobColor" >
{{ sliderMaxValue }}
@@ -77,7 +77,4 @@ export default { font-size: 20px; margin-top: 30px; } - - - -// @input_min="sliderMinValue = 0" \ No newline at end of file + \ No newline at end of file diff --git a/src/components/CircleSlider.vue b/src/components/CircleSlider.vue index c15f2ff..f24f28d 100644 --- a/src/components/CircleSlider.vue +++ b/src/components/CircleSlider.vue @@ -9,8 +9,8 @@ - - + + @@ -33,7 +33,7 @@ export default { this.currentMaxStepValue = this.cpCurrentMaxStep let maxCurveWidth = Math.max(this.cpMainCircleStrokeWidth, this.cpPathStrokeWidth) - this.radius = (this.side / 2) - Math.max(maxCurveWidth, this.cpKnobRadius * 2) / 2 + this.radius = (this.side / 2) - Math.max(maxCurveWidth, this.cpMinKnobRadius * 2, this.cpMaxKnobRadius * 2) / 2 this.updateFromPropMaxValue(this.value) this.currentMinStepIndex > this.currentMaxStepIndex ? this.setDefaultMinValue() : this.updateFromPropMinValue(this.minValue) @@ -101,12 +101,22 @@ export default { required: false, default: '#00be7e' }, - knobRadius: { + minKnobRadius: { type: Number, required: false, default: null }, - knobRadiusRel: { + minKnobRadiusRel: { + type: Number, + required: false, + default: 7 + }, + maxKnobRadius: { + type: Number, + required: false, + default: null + }, + maxKnobRadiusRel: { type: Number, required: false, default: 7 @@ -195,8 +205,11 @@ export default { cpPathStrokeWidth () { return this.progressWidth || (this.side / 2) / this.progressWidthRel }, - cpKnobRadius () { - return this.knobRadius || (this.side / 2) / this.knobRadiusRel + cpMinKnobRadius () { + return this.minKnobRadius || (this.side / 2) / this.minKnobRadiusRel + }, + cpMaxKnobRadius () { + return this.maxKnobRadius || (this.side / 2) / this.maxKnobRadiusRel }, cpPathD () { let parts = [] From a1458bc8c82b499191a243378016999128ebcffd Mon Sep 17 00:00:00 2001 From: Ali Asanov Date: Mon, 9 Dec 2019 19:43:43 +0300 Subject: [PATCH 9/9] add prop for enabling 'rangeSlider' feature, limit minValue to maxValue value --- demo/App.vue | 1 + src/components/CircleSlider.vue | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/demo/App.vue b/demo/App.vue index f9388f4..4c95741 100644 --- a/demo/App.vue +++ b/demo/App.vue @@ -8,6 +8,7 @@ :minKnobRadius="20" :minValue="sliderMinValueOrZero" @inputMin=" value => sliderMinValue = value " + :rangeSlider="true" >
{{ sliderMaxValue }}
diff --git a/src/components/CircleSlider.vue b/src/components/CircleSlider.vue index f24f28d..6ac21c4 100644 --- a/src/components/CircleSlider.vue +++ b/src/components/CircleSlider.vue @@ -10,7 +10,7 @@ - + @@ -140,6 +140,11 @@ export default { type: Number, required: false, default: 10 + }, + rangeSlider: { + type: Boolean, + required: false, + default: false } // limitMin: { // type: Number, @@ -429,6 +434,11 @@ export default { this.relativeY = e.clientY - dimensions.top }, defineCurrentKnob (newAngle) { + if (!this.rangeSlider) { + this.currentKnob = 'max' + return + } + if (newAngle > this.maxAngle) this.currentKnob = 'max' else if (newAngle < this.minAngle) this.currentKnob = 'min' else { @@ -438,10 +448,9 @@ export default { } }, setDefaultMinValue () { - const defaultMinValue = 0 + const defaultMinValue = this.currentMaxStepValue this.updateFromPropMinValue(defaultMinValue) this.$emit('inputMin', defaultMinValue) - alert('"Min" value cannot be greater than "Max" value. Please set the correct value.') } }, watch: { @@ -451,7 +460,7 @@ export default { this.updateFromPropMaxValue(val) }, minValue (val) { - if (val === this.currentMinStepValue) return + if (!this.rangeSlider || val === this.currentMinStepValue) return this.currentKnob = 'min' this.currentMinStepIndex >= this.currentMaxStepIndex ? this.setDefaultMinValue() : this.updateFromPropMinValue(val) }