sortChart.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <template>  
  2. <div
  3. class="sortChart"
  4. :style="{'width':width + 'px', 'height': height+ 'px'}"
  5. >
  6. <!-- <div class="container"> -->
  7. <transition-group
  8. class="container"
  9. name="flip-list"
  10. tag="div"
  11. >
  12. <div
  13. v-for="item in listWithKey"
  14. :key="item.key"
  15. class="bar"
  16. :style="{'height': getHeight(item.value)+ 'px'
  17. ,'background-color': getColor(item.color)
  18. ,'top': getTop(item.value) + 'px'
  19. ,'width': itemWidth + 'px'
  20. }"
  21. >
  22. <div
  23. class="value"
  24. :style="{'left': itemWidth / 2 - 7 + 'px'}"
  25. >{{Math.abs(item["value"])}}</div>
  26. </div>
  27. </transition-group>
  28. <!-- </div> -->
  29. </div>
  30. </template>
  31. <script>
  32. /**
  33. * @name sortChart (组件名称)
  34. * @desc 柱状图,用于排序
  35. * @author Li Xuesong
  36. * @param list 传入要显示的内容
  37. * @param height 柱状图高度
  38. * @param itemContainerWidth 柱状图相邻两个柱子的宽度
  39. * @param itemWidth 柱子的宽度
  40. * @date
  41. * @example 调用示例
  42. * <sortChart></sortChart>
  43. */
  44. export default {
  45. name: 'sortChart',
  46. components: {},
  47. props: {
  48. list: {
  49. default: () => [],
  50. },
  51. height: {
  52. default: 150
  53. },
  54. itemContainerWidth: {
  55. default: 60
  56. },
  57. itemWidth: {
  58. default: 40
  59. }
  60. },
  61. data () {
  62. return {
  63. max: 20,
  64. width: 200,
  65. listWithKey: []
  66. }
  67. },
  68. mounted () {
  69. this.listWithKey = list.map((item, idx) => {
  70. return {
  71. key: idx,
  72. value: item.value,
  73. color: item.color
  74. }
  75. });
  76. },
  77. // computed: {
  78. // thisList (val) {
  79. // return this.list;
  80. // }
  81. // },
  82. watch: {
  83. list: {
  84. handler: function (data, old) {
  85. if (data == null || data.length == 0) {
  86. this.listWithKey = [];
  87. return;
  88. }
  89. // console.log(data, old);
  90. this.max = Math.max(...data.map(v => v["value"]));
  91. this.width = data.length * this.itemContainerWidth;
  92. if (old == null || old.length == 0) {
  93. this.listWithKey = data.map((item, idx) => {
  94. // console.log(idx);
  95. return {
  96. key: idx,
  97. value: item.value,
  98. color: item.color
  99. }
  100. });
  101. // console.log(this.listWithKey);
  102. } else this.diff(data, this.listWithKey);
  103. },
  104. immediate: true
  105. }
  106. },
  107. mounted () { },
  108. methods: {
  109. diff (val, old) {
  110. let status = {
  111. v0c1: [], //value 不变, color改变 => 全部变色
  112. v1c0: [], //value 变负, color不变 => 下移
  113. v1c1: [], //value 变负, color改变 => 下移+变色
  114. v2: [] //value 变其他数据 => 改变数据==2,交换; !=2,直接重新赋值
  115. };
  116. // old = [{value:1,color:red,key:0}, {value:2,color:red,key:1}]
  117. // val = [{value:2,color:red}, {value:1,color:red}]
  118. for (let i = 0; i < val.length; i++) {
  119. val[i]["key"] = old[i]["key"];
  120. }
  121. // console.log(val);
  122. for (let i = 0; i < val.length; i++) {
  123. if (old[i].value == val[i].value) {
  124. if (old[i].color != val[i].color) {
  125. status.v0c1.push(i);
  126. }
  127. } else if (old[i].value == -val[i].value) {
  128. if (old[i].color == val[i].color) {
  129. status.v1c0.push(i);
  130. }
  131. else {
  132. status.v1c1.push(i);
  133. }
  134. } else {
  135. status.v2.push(i);
  136. }
  137. }
  138. if (status.v2.length > 0 && status.v2.length != 2) return;
  139. status.v0c1.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
  140. status.v1c0.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
  141. status.v1c1.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
  142. if (status.v2.length == 2) {
  143. // console.log(status.v2);
  144. let tmp = val[status.v2[1]].key;
  145. val[status.v2[1]].key = val[status.v2[0]].key;
  146. val[status.v2[0]].key = tmp;
  147. this.$set(this.listWithKey, status.v2[1], val[status.v2[1]]);
  148. this.$set(this.listWithKey, status.v2[0], val[status.v2[0]]);
  149. }
  150. // console.log(this.listWithKey);
  151. },
  152. getTop (value) {
  153. return value >= 0 ? 0 : this.height;
  154. },
  155. getHeight (value) {
  156. return (value < 0 ? -value : value) / this.max * this.height + 1;
  157. },
  158. getColor (color) {
  159. switch (color) {
  160. case 'green': return '#00cec9';
  161. case 'orange': return '#e17055';
  162. case 'red': return '#ff7675';
  163. case 'purple': return '#a29bfe';
  164. case 'yellow': return '#fdcb6e';
  165. case 'white': return '#dfe6e9';
  166. case 'blue': return '#0984e3'
  167. }
  168. return color;
  169. }
  170. }
  171. }
  172. </script>
  173. <style scoped>
  174. .sortChart {
  175. /* width: 800px; */
  176. height: 300px;
  177. }
  178. .container {
  179. display: flex;
  180. width: 100%;
  181. height: 100%;
  182. align-items: flex-end;
  183. justify-content: space-around;
  184. flex-wrap: nowrap;
  185. flex-direction: row;
  186. }
  187. .bar {
  188. display: flex;
  189. width: 40px;
  190. position: relative;
  191. }
  192. .value {
  193. position: absolute;
  194. bottom: 10px;
  195. font-size: 14px;
  196. font-weight: 600;
  197. -moz-user-select: none; /* 火狐 */
  198. -webkit-user-select: none; /* 谷歌 */
  199. -ms-user-select: none; /* IE */
  200. user-select: none;
  201. }
  202. .flip-list-move {
  203. transition: transform 0.5s;
  204. }
  205. </style>