item.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <template>
  2. <div
  3. v-show="ready"
  4. class="el-carousel__item"
  5. :class="{
  6. 'is-active': active,
  7. 'el-carousel__item--card': $parent.type === 'card',
  8. 'is-in-stage': inStage,
  9. 'is-hover': hover,
  10. 'is-animating': animating
  11. }"
  12. @click="handleItemClick"
  13. :style="itemStyle">
  14. <div
  15. v-if="$parent.type === 'card'"
  16. v-show="!active"
  17. class="el-carousel__mask">
  18. </div>
  19. <slot></slot>
  20. </div>
  21. </template>
  22. <script>
  23. import { autoprefixer } from 'element-ui/src/utils/util';
  24. const CARD_SCALE = 0.83;
  25. export default {
  26. name: 'ElCarouselItem',
  27. props: {
  28. name: String,
  29. label: {
  30. type: [String, Number],
  31. default: ''
  32. }
  33. },
  34. data() {
  35. return {
  36. hover: false,
  37. translate: 0,
  38. scale: 1,
  39. active: false,
  40. ready: false,
  41. inStage: false,
  42. animating: false
  43. };
  44. },
  45. methods: {
  46. processIndex(index, activeIndex, length) {
  47. if (activeIndex === 0 && index === length - 1) {
  48. return -1;
  49. } else if (activeIndex === length - 1 && index === 0) {
  50. return length;
  51. } else if (index < activeIndex - 1 && activeIndex - index >= length / 2) {
  52. return length + 1;
  53. } else if (index > activeIndex + 1 && index - activeIndex >= length / 2) {
  54. return -2;
  55. }
  56. return index;
  57. },
  58. calcCardTranslate(index, activeIndex) {
  59. const parentWidth = this.$parent.$el.offsetWidth;
  60. if (this.inStage) {
  61. return parentWidth * ((2 - CARD_SCALE) * (index - activeIndex) + 1) / 4;
  62. } else if (index < activeIndex) {
  63. return -(1 + CARD_SCALE) * parentWidth / 4;
  64. } else {
  65. return (3 + CARD_SCALE) * parentWidth / 4;
  66. }
  67. },
  68. calcTranslate(index, activeIndex, isVertical) {
  69. const distance = this.$parent.$el[isVertical ? 'offsetHeight' : 'offsetWidth'];
  70. return distance * (index - activeIndex);
  71. },
  72. translateItem(index, activeIndex, oldIndex) {
  73. const parentType = this.$parent.type;
  74. const parentDirection = this.parentDirection;
  75. const length = this.$parent.items.length;
  76. if (parentType !== 'card' && oldIndex !== undefined) {
  77. this.animating = index === activeIndex || index === oldIndex;
  78. }
  79. if (index !== activeIndex && length > 2 && this.$parent.loop) {
  80. index = this.processIndex(index, activeIndex, length);
  81. }
  82. if (parentType === 'card') {
  83. if (parentDirection === 'vertical') {
  84. console.warn('[Element Warn][Carousel]vertical direction is not supported in card mode');
  85. }
  86. this.inStage = Math.round(Math.abs(index - activeIndex)) <= 1;
  87. this.active = index === activeIndex;
  88. this.translate = this.calcCardTranslate(index, activeIndex);
  89. this.scale = this.active ? 1 : CARD_SCALE;
  90. } else {
  91. this.active = index === activeIndex;
  92. const isVertical = parentDirection === 'vertical';
  93. this.translate = this.calcTranslate(index, activeIndex, isVertical);
  94. this.scale = 1;
  95. }
  96. this.ready = true;
  97. },
  98. handleItemClick() {
  99. const parent = this.$parent;
  100. if (parent && parent.type === 'card') {
  101. const index = parent.items.indexOf(this);
  102. parent.setActiveItem(index);
  103. }
  104. }
  105. },
  106. computed: {
  107. parentDirection() {
  108. return this.$parent.direction;
  109. },
  110. itemStyle() {
  111. const translateType = this.parentDirection === 'vertical' ? 'translateY' : 'translateX';
  112. const value = `${translateType}(${ this.translate }px) scale(${ this.scale })`;
  113. const style = {
  114. transform: value
  115. };
  116. return autoprefixer(style);
  117. }
  118. },
  119. created() {
  120. this.$parent && this.$parent.updateItems();
  121. },
  122. destroyed() {
  123. this.$parent && this.$parent.updateItems();
  124. }
  125. };
  126. </script>