|
|
@@ -0,0 +1,211 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="sortChart"
|
|
|
+ :style="{'width':width + 'px', 'height': height+ 'px'}"
|
|
|
+ >
|
|
|
+ <!-- <div class="container"> -->
|
|
|
+ <transition-group
|
|
|
+ class="container"
|
|
|
+ name="flip-list"
|
|
|
+ tag="div"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ v-for="item in listWithKey"
|
|
|
+ :key="item.key"
|
|
|
+ class="bar"
|
|
|
+ :style="{'height': getHeight(item.value)+ 'px'
|
|
|
+ ,'background-color': getColor(item.color)
|
|
|
+ ,'top': getTop(item.value) + 'px'
|
|
|
+ ,'width': itemWidth + 'px'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ class="value"
|
|
|
+ :style="{'left': itemWidth / 2 - 7 + 'px'}"
|
|
|
+ >{{Math.abs(item["value"])}}</div>
|
|
|
+ </div>
|
|
|
+ </transition-group>
|
|
|
+ <!-- </div> -->
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+ /**
|
|
|
+ * @name sortChart (组件名称)
|
|
|
+ * @desc 柱状图,用于排序
|
|
|
+ * @author Li Xuesong
|
|
|
+ * @param list 传入要显示的内容
|
|
|
+ * @param height 柱状图高度
|
|
|
+ * @param itemContainerWidth 柱状图相邻两个柱子的宽度
|
|
|
+ * @param itemWidth 柱子的宽度
|
|
|
+ * @date
|
|
|
+ * @example 调用示例
|
|
|
+ * <sortChart></sortChart>
|
|
|
+ */
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name: 'sortChart',
|
|
|
+ components: {},
|
|
|
+ props: {
|
|
|
+ list: {
|
|
|
+ default: () => [],
|
|
|
+ },
|
|
|
+ height: {
|
|
|
+ default: 150
|
|
|
+ },
|
|
|
+ itemContainerWidth: {
|
|
|
+ default: 60
|
|
|
+ },
|
|
|
+ itemWidth: {
|
|
|
+ default: 40
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ max: 20,
|
|
|
+ width: 200,
|
|
|
+ listWithKey: []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted () {
|
|
|
+ this.listWithKey = list.map((item, idx) => {
|
|
|
+ return {
|
|
|
+ key: idx,
|
|
|
+ value: item.value,
|
|
|
+ color: item.color
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // computed: {
|
|
|
+ // thisList (val) {
|
|
|
+ // return this.list;
|
|
|
+ // }
|
|
|
+ // },
|
|
|
+ watch: {
|
|
|
+ list: {
|
|
|
+ handler: function (data, old) {
|
|
|
+ if (data == null || data.length == 0) {
|
|
|
+ this.listWithKey = [];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // console.log(data, old);
|
|
|
+ this.max = Math.max(...data.map(v => v["value"]));
|
|
|
+ this.width = data.length * this.itemContainerWidth;
|
|
|
+ if (old == null || old.length == 0) {
|
|
|
+ this.listWithKey = data.map((item, idx) => {
|
|
|
+ // console.log(idx);
|
|
|
+ return {
|
|
|
+ key: idx,
|
|
|
+ value: item.value,
|
|
|
+ color: item.color
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // console.log(this.listWithKey);
|
|
|
+ } else this.diff(data, this.listWithKey);
|
|
|
+ },
|
|
|
+ immediate: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted () { },
|
|
|
+ methods: {
|
|
|
+ diff (val, old) {
|
|
|
+ let status = {
|
|
|
+ v0c1: [], //value 不变, color改变 => 全部变色
|
|
|
+ v1c0: [], //value 变负, color不变 => 下移
|
|
|
+ v1c1: [], //value 变负, color改变 => 下移+变色
|
|
|
+ v2: [] //value 变其他数据 => 改变数据==2,交换; !=2,直接重新赋值
|
|
|
+ };
|
|
|
+ // old = [{value:1,color:red,key:0}, {value:2,color:red,key:1}]
|
|
|
+ // val = [{value:2,color:red}, {value:1,color:red}]
|
|
|
+
|
|
|
+ for (let i = 0; i < val.length; i++) {
|
|
|
+ val[i]["key"] = old[i]["key"];
|
|
|
+ }
|
|
|
+ // console.log(val);
|
|
|
+ for (let i = 0; i < val.length; i++) {
|
|
|
+ if (old[i].value == val[i].value) {
|
|
|
+ if (old[i].color != val[i].color) {
|
|
|
+ status.v0c1.push(i);
|
|
|
+ }
|
|
|
+ } else if (old[i].value == -val[i].value) {
|
|
|
+ if (old[i].color == val[i].color) {
|
|
|
+ status.v1c0.push(i);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ status.v1c1.push(i);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ status.v2.push(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (status.v2.length > 0 && status.v2.length != 2) return;
|
|
|
+ status.v0c1.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
|
|
|
+ status.v1c0.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
|
|
|
+ status.v1c1.forEach(idx => this.$set(this.listWithKey, idx, val[idx]));
|
|
|
+ if (status.v2.length == 2) {
|
|
|
+ // console.log(status.v2);
|
|
|
+ let tmp = val[status.v2[1]].key;
|
|
|
+ val[status.v2[1]].key = val[status.v2[0]].key;
|
|
|
+ val[status.v2[0]].key = tmp;
|
|
|
+ this.$set(this.listWithKey, status.v2[1], val[status.v2[1]]);
|
|
|
+ this.$set(this.listWithKey, status.v2[0], val[status.v2[0]]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(this.listWithKey);
|
|
|
+ },
|
|
|
+ getTop (value) {
|
|
|
+ return value >= 0 ? 0 : this.height;
|
|
|
+ },
|
|
|
+ getHeight (value) {
|
|
|
+ return (value < 0 ? -value : value) / this.max * this.height + 1;
|
|
|
+ },
|
|
|
+ getColor (color) {
|
|
|
+ switch (color) {
|
|
|
+ case 'green': return '#00cec9';
|
|
|
+ case 'orange': return '#e17055';
|
|
|
+ case 'red': return '#ff7675';
|
|
|
+ case 'purple': return '#a29bfe';
|
|
|
+ case 'yellow': return '#fdcb6e';
|
|
|
+ case 'white': return '#dfe6e9';
|
|
|
+ case 'blue': return '#0984e3'
|
|
|
+ }
|
|
|
+ return color;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+ .sortChart {
|
|
|
+ /* width: 800px; */
|
|
|
+ height: 300px;
|
|
|
+ }
|
|
|
+ .container {
|
|
|
+ display: flex;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ align-items: flex-end;
|
|
|
+ justify-content: space-around;
|
|
|
+ flex-wrap: nowrap;
|
|
|
+ flex-direction: row;
|
|
|
+ }
|
|
|
+ .bar {
|
|
|
+ display: flex;
|
|
|
+ width: 40px;
|
|
|
+ position: relative;
|
|
|
+ }
|
|
|
+ .value {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 10px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ -moz-user-select: none; /* 火狐 */
|
|
|
+ -webkit-user-select: none; /* 谷歌 */
|
|
|
+ -ms-user-select: none; /* IE */
|
|
|
+ user-select: none;
|
|
|
+ }
|
|
|
+ .flip-list-move {
|
|
|
+ transition: transform 0.5s;
|
|
|
+ }
|
|
|
+</style>
|