瀏覽代碼

Slider: add marks attribute (#15133)

luckyCao 6 年之前
父節點
當前提交
da01541d60

+ 48 - 10
examples/docs/en-US/slider.md

@@ -64,14 +64,14 @@ The options can be discrete.
   <div class="block">
     <span class="demonstration">Breakpoints not displayed</span>
     <el-slider
-      v-model="value6"
+      v-model="value1"
       :step="10">
     </el-slider>
   </div>
   <div class="block">
     <span class="demonstration">Breakpoints displayed</span>
     <el-slider
-      v-model="value7"
+      v-model="value2"
       :step="10"
       show-stops>
     </el-slider>
@@ -82,8 +82,8 @@ The options can be discrete.
   export default {
     data() {
       return {
-        value6: 0,
-        value7: 0
+        value1: 0,
+        value2: 0
       }
     }
   }
@@ -101,7 +101,7 @@ Set value via a input box.
 <template>
   <div class="block">
     <el-slider
-      v-model="value8"
+      v-model="value"
       show-input>
     </el-slider>
   </div>
@@ -111,7 +111,7 @@ Set value via a input box.
   export default {
     data() {
       return {
-        value8: 0
+        value: 0
       }
     }
   }
@@ -128,7 +128,7 @@ Selecting a range of values is supported.
 <template>
   <div class="block">
     <el-slider
-      v-model="value9"
+      v-model="value"
       range
       show-stops
       :max="10">
@@ -140,7 +140,7 @@ Selecting a range of values is supported.
   export default {
     data() {
       return {
-        value9: [4, 8]
+        value: [4, 8]
       }
     }
   }
@@ -155,7 +155,7 @@ Selecting a range of values is supported.
 <template>
   <div class="block">
     <el-slider
-      v-model="value10"
+      v-model="value"
       vertical
       height="200px">
     </el-slider>
@@ -166,7 +166,44 @@ Selecting a range of values is supported.
   export default {
     data() {
       return {
-        value10: 0
+        value: 0
+      }
+    }
+  }
+</script>
+```
+:::
+
+### Show marks
+
+:::demo Setting this `marks` attribute can show mark on slider.
+```html
+<template>
+  <div class="block">
+    <el-slider
+      v-model="value"
+      range
+      :marks="marks">
+    </el-slider>
+  </div>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        value: [30, 60],
+        marks: {
+          0: '0°C',
+          8: '8°C',
+          37: '37°C',
+          50: {
+            style: {
+              color: '#1989FA'
+            },
+            label: this.$createElement('strong', '50%')
+          }
+        }
       }
     }
   }
@@ -194,6 +231,7 @@ Selecting a range of values is supported.
 | label | label for screen reader | string | — | — |
 | debounce | debounce delay when typing, in milliseconds, works when `show-input` is true | number | — | 300 |
 | tooltip-class | custom class name for the tooltip | string | — | — |
+| marks | marks, type of key must be `number` and must in closed interval `[min, max]`, each mark can custom style| object | — | — |
 
 ## Events
 | Event Name | Description | Parameters |

+ 48 - 10
examples/docs/es/slider.md

@@ -64,14 +64,14 @@ Las opciones pueden ser discretas.
   <div class="block">
     <span class="demonstration">Breakpoints not displayed</span>
     <el-slider
-      v-model="value6"
+      v-model="value"
       :step="10">
     </el-slider>
   </div>
   <div class="block">
     <span class="demonstration">Breakpoints displayed</span>
     <el-slider
-      v-model="value7"
+      v-model="value"
       :step="10"
       show-stops>
     </el-slider>
@@ -82,8 +82,8 @@ Las opciones pueden ser discretas.
   export default {
     data() {
       return {
-        value6: 0,
-        value7: 0
+        value: 0,
+        value: 0
       }
     }
   }
@@ -101,7 +101,7 @@ Inserte el valor a traves de un input
 <template>
   <div class="block">
     <el-slider
-      v-model="value8"
+      v-model="value"
       show-input>
     </el-slider>
   </div>
@@ -111,7 +111,7 @@ Inserte el valor a traves de un input
   export default {
     data() {
       return {
-        value8: 0
+        value: 0
       }
     }
   }
@@ -129,7 +129,7 @@ Se soporta la selección de un rango de valores.
 <template>
   <div class="block">
     <el-slider
-      v-model="value9"
+      v-model="value"
       range
       show-stops
       :max="10">
@@ -141,7 +141,7 @@ Se soporta la selección de un rango de valores.
   export default {
     data() {
       return {
-        value9: [4, 8]
+        value: [4, 8]
       }
     }
   }
@@ -157,7 +157,7 @@ Se soporta la selección de un rango de valores.
 <template>
   <div class="block">
     <el-slider
-      v-model="value10"
+      v-model="value"
       vertical
       height="200px">
     </el-slider>
@@ -168,7 +168,44 @@ Se soporta la selección de un rango de valores.
   export default {
     data() {
       return {
-        value10: 0
+        value: 0
+      }
+    }
+  }
+</script>
+```
+:::
+
+### Show marks
+
+:::demo Setting this `marks` attribute can show mark on slider.
+```html
+<template>
+  <div class="block">
+    <el-slider
+      v-model="value"
+      range
+      :marks="marks">
+    </el-slider>
+  </div>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        value: [30, 60],
+        marks: {
+          0: '0°C',
+          8: '8°C',
+          37: '37°C',
+          50: {
+            style: {
+              color: '#1989FA'
+            },
+            label: this.$createElement('strong', '50%')
+          }
+        }
       }
     }
   }
@@ -196,6 +233,7 @@ Se soporta la selección de un rango de valores.
 | label               | etiqueta para screen reader              | string          | —                 | —           |
 | debounce            | retardo al escribir, en milisegundos, funciona cuando`show-input` es true. | number          | —                 | 300         |
 | tooltip-class       | nombre personalizado de clase para el tooltip | string | — | — |
+| marks | marks, type of key must be `number` and must in closed interval `[min, max]`, each mark can custom style| object | — | — |
 
 ## Eventos
 | Nombre | Descripción                              | Parametros               |

+ 46 - 10
examples/docs/fr-FR/slider.md

@@ -64,14 +64,14 @@ Les valeurs peuvent être discrètes.
   <div class="block">
     <span class="demonstration">Points absents</span>
     <el-slider
-      v-model="value6"
+      v-model="value1"
       :step="10">
     </el-slider>
   </div>
   <div class="block">
     <span class="demonstration">Points affichés</span>
     <el-slider
-      v-model="value7"
+      v-model="value2"
       :step="10"
       show-stops>
     </el-slider>
@@ -82,8 +82,8 @@ Les valeurs peuvent être discrètes.
   export default {
     data() {
       return {
-        value6: 0,
-        value7: 0
+        value1: 0,
+        value2: 0
       }
     }
   }
@@ -101,7 +101,7 @@ Vous pouvez afficher un champ d'input synchronisé pour entrer une valeur préci
 <template>
   <div class="block">
     <el-slider
-      v-model="value8"
+      v-model="value"
       show-input>
     </el-slider>
   </div>
@@ -111,7 +111,7 @@ Vous pouvez afficher un champ d'input synchronisé pour entrer une valeur préci
   export default {
     data() {
       return {
-        value8: 0
+        value: 0
       }
     }
   }
@@ -128,7 +128,7 @@ Vous pouvez sélectionner des intervalles de valeurs au lieu d'une valeur unique
 <template>
   <div class="block">
     <el-slider
-      v-model="value9"
+      v-model="value"
       range
       show-stops
       :max="10">
@@ -140,7 +140,7 @@ Vous pouvez sélectionner des intervalles de valeurs au lieu d'une valeur unique
   export default {
     data() {
       return {
-        value9: [4, 8]
+        value: [4, 8]
       }
     }
   }
@@ -155,7 +155,7 @@ Vous pouvez sélectionner des intervalles de valeurs au lieu d'une valeur unique
 <template>
   <div class="block">
     <el-slider
-      v-model="value10"
+      v-model="value"
       vertical
       height="200px">
     </el-slider>
@@ -166,7 +166,42 @@ Vous pouvez sélectionner des intervalles de valeurs au lieu d'une valeur unique
   export default {
     data() {
       return {
-        value10: 0
+        value: 0
+      }
+    }
+  }
+</script>
+```
+:::
+
+:::demo Setting this `marks` attribute can show mark on slider.
+```html
+<template>
+  <div class="block">
+    <el-slider
+      v-model="value"
+      range
+      :marks="marks">
+    </el-slider>
+  </div>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        value: [30, 60],
+        marks: {
+          0: '0°C',
+          8: '8°C',
+          37: '37°C',
+          50: {
+            style: {
+              color: '#1989FA'
+            },
+            label: this.$createElement('strong', '50%')
+          }
+        }
       }
     }
   }
@@ -195,6 +230,7 @@ Vous pouvez sélectionner des intervalles de valeurs au lieu d'une valeur unique
 | label | Label pour les lecteurs d'écran. | string | — | — |
 | debounce | Délai après écriture en millisecondes, marche quand `show-input` est `true`. | number | — | 300 |
 | tooltip-class | Classe du tooltip. | string | — | — |
+| marks | marks, type of key must be `number` and must in closed interval `[min, max]`, each mark can custom style| object | — | — |
 
 ## Évènements
 

+ 48 - 10
examples/docs/zh-CN/slider.md

@@ -62,14 +62,14 @@
   <div class="block">
     <span class="demonstration">不显示间断点</span>
     <el-slider
-      v-model="value6"
+      v-model="value1"
       :step="10">
     </el-slider>
   </div>
   <div class="block">
     <span class="demonstration">显示间断点</span>
     <el-slider
-      v-model="value7"
+      v-model="value2"
       :step="10"
       show-stops>
     </el-slider>
@@ -80,8 +80,8 @@
   export default {
     data() {
       return {
-        value6: 0,
-        value7: 0
+        value1: 0,
+        value2: 0
       }
     }
   }
@@ -98,7 +98,7 @@
 <template>
   <div class="block">
     <el-slider
-      v-model="value8"
+      v-model="value"
       show-input>
     </el-slider>
   </div>
@@ -108,7 +108,7 @@
   export default {
     data() {
       return {
-        value8: 0
+        value: 0
       }
     }
   }
@@ -125,7 +125,7 @@
 <template>
   <div class="block">
     <el-slider
-      v-model="value9"
+      v-model="value"
       range
       show-stops
       :max="10">
@@ -137,7 +137,7 @@
   export default {
     data() {
       return {
-        value9: [4, 8]
+        value: [4, 8]
       }
     }
   }
@@ -152,7 +152,7 @@
 <template>
   <div class="block">
     <el-slider
-      v-model="value10"
+      v-model="value"
       vertical
       height="200px">
     </el-slider>
@@ -163,7 +163,44 @@
   export default {
     data() {
       return {
-        value10: 0
+        value: 0
+      }
+    }
+  }
+</script>
+```
+:::
+
+### 展示标记
+
+:::demo 设置 `marks` 属性可以展示标记
+```html
+<template>
+  <div class="block">
+    <el-slider
+      v-model="value"
+      range
+      :marks="marks">
+    </el-slider>
+  </div>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        value: [30, 60],
+        marks: {
+          0: '0°C',
+          8: '8°C',
+          37: '37°C',
+          50: {
+            style: {
+              color: '#1989FA'
+            },
+            label: this.$createElement('strong', '50%')
+          }
+        }
       }
     }
   }
@@ -191,6 +228,7 @@
 | label | 屏幕阅读器标签 | string | — | — |
 | debounce | 输入时的去抖延迟,毫秒,仅在`show-input`等于true时有效 | number | — | 300 |
 | tooltip-class | tooltip 的自定义类名 | string | — | — |
+| marks | 标记, key 的类型必须为 number 且取值在闭区间 `[min, max]` 内,每个标记可以单独设置样式 | object | — | — |
 
 ### Events
 | 事件名称      | 说明    | 回调参数      |

+ 43 - 3
packages/slider/src/main.vue

@@ -49,9 +49,26 @@
         class="el-slider__stop"
         v-for="(item, key) in stops"
         :key="key"
-        :style="vertical ? { 'bottom': item + '%' } : { 'left': item + '%' }"
+        :style="getStopStyle(item)"
         v-if="showStops">
       </div>
+      <template v-if="markList.length > 0">
+        <div>
+          <div
+            v-for="(item, key) in markList"
+            :style="getStopStyle(item.position)"
+            class="el-slider__stop el-slider__marks-stop"
+            :key="key">
+          </div>
+        </div>
+        <div class="el-slider__marks">
+          <slider-marker
+            :mark="item.mark" v-for="(item, key) in markList"
+            :key="key"
+            :style="getStopStyle(item.position)">
+          </slider-marker>
+        </div>
+      </template>
     </div>
   </div>
 </template>
@@ -59,6 +76,7 @@
 <script type="text/babel">
   import ElInputNumber from 'element-ui/packages/input-number';
   import SliderButton from './button.vue';
+  import SliderMarker from './marker';
   import Emitter from 'element-ui/src/mixins/emitter';
 
   export default {
@@ -132,12 +150,14 @@
       label: {
         type: String
       },
-      tooltipClass: String
+      tooltipClass: String,
+      marks: Object
     },
 
     components: {
       ElInputNumber,
-      SliderButton
+      SliderButton,
+      SliderMarker
     },
 
     data() {
@@ -275,6 +295,10 @@
         this.$nextTick(() => {
           this.$emit('change', this.range ? [this.minValue, this.maxValue] : this.value);
         });
+      },
+
+      getStopStyle(position) {
+        return this.vertical ? { 'bottom': position + '%' } : { 'left': position + '%' };
       }
     },
 
@@ -302,6 +326,22 @@
         }
       },
 
+      markList() {
+        if (!this.marks) {
+          return [];
+        }
+
+        const marksKeys = Object.keys(this.marks);
+        return marksKeys.map(parseFloat)
+          .sort((a, b) => a - b)
+          .filter(point => point <= this.max && point >= this.min)
+          .map(point => ({
+            point,
+            position: (point - this.min) * 100 / (this.max - this.min),
+            mark: this.marks[point]
+          }));
+      },
+
       minValue() {
         return Math.min(this.firstValue, this.secondValue);
       },

+ 18 - 0
packages/slider/src/marker.js

@@ -0,0 +1,18 @@
+export default {
+  name: 'ElMarker',
+
+  props: {
+    mark: {
+      type: [String, Object]
+    }
+  },
+  render() {
+    let label = typeof this.mark === 'string' ? this.mark : this.mark.label;
+
+    return (
+      <div class="el-slider__marks-text" style={ this.mark.style || {} }>
+        { label }
+      </div>
+    );
+  }
+};

+ 22 - 0
packages/theme-chalk/src/slider.scss

@@ -5,6 +5,7 @@
 @import "common/var";
 
 @include b(slider) {
+
   @include utils-clearfix;
 
   @include e(runway) {
@@ -151,6 +152,21 @@
     transform: translateX(-50%);
   }
 
+  @include e(marks) {
+    top: 0;
+    left: 12px;
+    width: 18px;
+    height: 100%;
+
+    @include e(marks-text) {
+      position: absolute;
+      transform: translateX(-50%);
+      font-size: 14px;
+      color: $--color-info;
+      margin-top: 15px;
+    }
+  }
+
   @include when(vertical) {
     position: relative;
     .el-slider__runway {
@@ -224,5 +240,11 @@
         }
       }
     }
+
+    @include e(marks-text) {
+      margin-top: 0;
+      left: 15px;
+      transform: translateY(50%);
+    }
   }
 }

+ 39 - 0
test/unit/specs/slider.spec.js

@@ -458,5 +458,44 @@ describe('Slider', () => {
         done();
       }, 10);
     });
+
+    it('marks', async() => {
+      vm = createVue({
+        template: `
+        <div>
+          <el-slider
+            v-model="value"
+            range
+            :step="10"
+            :marks="marks"
+            :min="20"
+            show-stops></el-slider>
+        </div>
+      `,
+
+        data() {
+          return {
+            value: [30, 60],
+            marks: {
+              0: '0°C',
+              8: '8°C',
+              37: '37°C',
+              50: {
+                style: {
+                  color: '#f50'
+                },
+                label: <strong>50°C</strong>
+              }
+            }
+          };
+        }
+      }, true);
+
+      waitImmediate();
+      const stops = vm.$el.querySelectorAll('.el-slider__marks-stop.el-slider__stop');
+      const marks = vm.$el.querySelectorAll('.el-slider__marks .el-slider__marks-text');
+      expect(marks.length).to.equal(2);
+      expect(stops.length).to.equal(2);
+    });
   });
 });

+ 6 - 0
types/slider.d.ts

@@ -1,3 +1,4 @@
+import { VNode } from 'vue';
 import { ElementUIComponent } from './component'
 
 export interface SliderTooltipFormat {
@@ -59,4 +60,9 @@ export declare class ElSlider extends ElementUIComponent {
 
   /** Custom class name for the tooltip */
   tooltipClass: string
+
+  /** Custom marks */
+  marks: {
+    [key: number]: string | { style: object; label: string | VNode }
+  }
 }