<!--
 * @Author: your name
 * @Date: 2020-08-28 15:20:15
 * @LastEditTime: 2020-10-10 17:19:06
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: /xfhd-vue-scaffold/src/page/index/Home/Index.vue
-->
<template>
    <div class="sort">
        <div class="show-con orgin">
            <div
                class="color-span"
                v-for="(item, index) in hlsColorArr"
                :key="index"
                :style="rennderCssHSL(item)"
            ></div>
        </div>
        <div class="show-con sort" ref="sortCon">
            <div
                class="color-group"
                v-for="(item, index) in newColorArr"
                :key="index"
            >
                <div class="header">Group {{ item.name }}</div>
                <div class="spans">
                    <div
                        class="color-span"
                        v-for="(t, i) in item.data"
                        :key="i"
                        :style="rennderCssHSL(t)"
                    ></div>
                </div>

                <div class="desc" v-if="sortedStatus">
                    <div class="row">
                        <p>最小值: {{ item.min }}</p>
                        <div
                            class="color-span"
                            :style="rennderCssHex(item.min)"
                        ></div>
                    </div>
                    <div class="row">
                        <p>平均值: {{ item.average }}</p>
                        <div
                            class="color-span"
                            :style="rennderCssHex(item.average)"
                        ></div>
                    </div>
                    <div class="row">
                        <p>最大值: {{ item.max }}</p>
                        <div
                            class="color-span"
                            :style="rennderCssHex(item.max)"
                        ></div>
                    </div>
                </div>
            </div>
        </div>
        <div class="btn-groups">
            <div class="p">根据Hue色调分组</div>
            <div class="ios-checkbox">
                <input
                    type="checkbox"
                    id="ios-checkbox"
                    name="emulate-ios-button"
                    class="raw-checkbox"
                    v-model="hideOrigin"
                    @change="showGroup"
                    hidden
                />
                <label for="ios-checkbox" class="emulate-ios-button"></label>
            </div>

            <!-- <div class="p">根据固定颜色分组</div>
			<div class="ios-checkbox">
				<input
					type="checkbox"
					id="ios-checkbox2"
					name="emulate-ios-button2"
					class="raw-checkbox"
					v-model="hideOrigin2"
					@change="showGroup2"
					hidden
				/>
				<label for="ios-checkbox2" class="emulate-ios-button"></label>
			</div> -->
            <div
                class="btn"
                @click="sortColorLight"
                :class="{ active: active2 }"
                ref="btn2"
            >
                排序
            </div>
        </div>
    </div>
</template>
<script>
// @ is an alias to /src
import colorUtil from "color-util";
import colors from "@/data/color.json";
import { export_json_to_excel } from "@/utils/plugins/Export2Excel";
import gsap from "gsap";
export default {
    name: "ColorSort",
    components: {},
    data() {
        return {
            hideOrigin: false,
            colorArr: colors,
            sortedStatus: false,
            active1: false,
            active2: false,
            hlsColorArr: [],
            newColorArr: [
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
                {
                    name: "",
                    data: [],
                    average: "",
                    min: "",
                    max: "",
                },
            ],
            sortedColorArr: [],
            // 1-12 对应 hue 每30度  | 13 - 黑 | 14 - 白 | 15 - 灰
            balance: [0.9, 0, 0.01],
            balance2: [0.3, 0, 0],
            balance3: [0.5, 0.2, 0.1],
            caclulTime: 0,
        };
    },
    computed: {
        rennderCssHSL() {
            return function (item) {
                return `background-color: ${item.csshsl};`;
            };
        },
        rennderCssHex() {
            return function (item) {
                return `background-color: ${item};`;
            };
        },
        rennderHeaderCss() {
            return function (item) {
                return `background-color: ${item.csshsl};`;
            };
        },
    },
    mounted() {
        this.reHandleColor();
    },
    methods: {
        // 显示隐藏分组
        showGroup(index) {
            gsap.to(this.$refs.sortCon, {
                autoAlpha: 1,
                x: this.hideOrigin ? 0 : "100%",
                zIndex: this.hideOrigin ? 2 : 10,
                onStart: () => {},
            });
        },
        // 颜色数据转换为hsl
        reHandleColor() {
            // this.colorArr
            this.colorArr.forEach((item, index) => {
                this.hlsColorArr.push(
                    colorUtil.color(item.HEX) //item.HEX
                );
            });

            // console.log(this.hexColorArr);
            //根据hue分组
            this.sortColorByHue();
        },
        // 按照色环分组
        sortColorByHue() {
            this.hlsColorArr.forEach((item, index) => {
                let color = item.hsl;
                if (color.h) {
                    let _index = 8 - Math.floor((color.h * 360) / 40); //将360度色盘区分为12个维度
                    // // 灰
                    // if (
                    // 	// 当饱和度为0时
                    // 	color.s <= 0.3 &&
                    // 	color.l <= 0.7 &&
                    // 	color.l >= 0.1
                    // ) {
                    // 	_index = 11;
                    // }
                    // // 黑色
                    // if (color.l < 0.4 && color.s < 0.4) {
                    // 	_index = 9;
                    // }
                    // // 白色
                    // if (color.l > 0.7 && color.s < 0.3) {
                    // 	_index = 10;
                    // }
                    // 灰
                    if (
                        // 当饱和度为0时
                        color.s <= 0.15 &&
                        color.l <= 0.75 &&
                        color.l >= 0.2
                    ) {
                        _index = 11;
                    }
                    // 黑色
                    if (color.l < 0.2 && color.s < 0.18) {
                        _index = 9;
                    }
                    // 白色
                    if (color.l > 0.75 && color.s < 0.15) {
                        _index = 10;
                    }
                    this.newColorArr[_index].data.push(item);
                }
            });
            // console.log(this.newColorArr);
        },
        // 根据亮度
        sortColorLight() {
            this.active2 = true;
            this.caclulTime++;
            this.$Utils.showTips({
                message: `正在计算，请稍等...`,
            });

            let height = 100; //boxHeight
            // if (word.length > 180) {
            // 	height = 180;
            // }

            setTimeout(() => {
                if (this.hideOrigin) {
                    // 分组
                    this.newColorArr.forEach((item, index) => {
                        // 灰度区分
                        // item = this.sortColor(item);
                        // console.log(item)
                        // item.forEach((t, i) => {
                        // 	let rgb = t.rgb;
                        // 	t.grey = rgb.r * 0.299 + rgb.g * 0.587 + rgb.b * 0.114;
                        // });
                        // item.sort((a, b) => {
                        // 	let deltaGrey = b.grey - a.grey;
                        // 	let result = deltaGrey;
                        // 	return (
                        // 		// Math.random() > 0.5 ? 1 : -1
                        // 		result
                        // 	);
                        // });

                        let sortedArr = this.sortColors(item.data);
                        this.newColorArr[index].data = [];
                        this.newColorArr[index].data.push(...sortedArr);

                        // let other = this.getOtherInfo(sortedArr);
                        console.log(sortedArr[0]);
                        this.newColorArr[index].min = sortedArr[0].hex;
                        this.newColorArr[index].max =
                            sortedArr[sortedArr.length - 1].hex;
                        this.newColorArr[index].average =
                            sortedArr[Math.ceil(sortedArr.length / 2)].hex;
                        this.newColorArr[index].name =
                            this.newColorArr[index].average;
                    });
                } else {
                    // this.hlsColorArr.sort((a, b) => {
                    // 	return b.hsl.l - a.hsl.l;
                    // });
                    this.hlsColorArr = this.sortColors(this.hlsColorArr);
                }

                this.active2 = false;
                this.sortedStatus = true;
            }, 1000);

            // console.log(this.newColorArr);
        },
        // 计算hsl颜色距离
        colorDistanceHsl(_color1, _color2) {
            let color1 = _color1;
            let color2 = _color2;
            let result = 0;
            color1 = color1.hsl;
            color2 = color2.hsl;
            Object.keys(color1).forEach((key, index) => {
                if (key != "a") {
                    result +=
                        (color1[key] - color2[key]) *
                        (color1[key] - color2[key]) *
                        this.balance2[index];
                }
            });
            if (Math.floor(color1.r / 30) !== Math.floor(color2.r / 30)) {
                return 0;
            }
            return result;
        },
        // 计算rgb颜色距离
        colorDistanceRgb(_color1, _color2) {
            let color1 = _color1;
            let color2 = _color2;
            let result = 0;
            color1 = color1.rgb;
            color2 = color2.rgb;
            Object.keys(color1).forEach((key, index) => {
                if (key != "a") {
                    result +=
                        (color1[key] - color2[key]) *
                        (color1[key] - color2[key]) *
                        this.balance3[index];
                }
            });
            return result;
        },
        // 计算hsv颜色距离 然后和rgb 以及 hsl 距离相加
        colorDistance(_color1, _color2) {
            let color1 = _color1;
            let color2 = _color2;
            let result = 0;
            result += this.colorDistanceRgb(color1, color2);
            result += this.colorDistanceHsl(color1, color2);
            color1 = color1.hsv;
            color2 = color2.hsv;
            Object.keys(color1).forEach((key, index) => {
                if (key != "a") {
                    result +=
                        (color1[key] - color2[key]) *
                        (color1[key] - color2[key]) *
                        this.balance[index];
                }
            });
            return result;
        },
        // 根据根据颜色距离排序
        sortColors(colors) {
            // Calculate distance between each color
            console.log("origin length =", colors.length);
            if (colors.length === 0) return colors;
            const distances = [];
            for (let i = 0; i < colors.length; i++) {
                distances[i] = [];
                for (let j = 0; j < i; j++) {
                    // if (colors[i].hex === colors[j].hex){
                    // 	console.log('相同',colors[i].hex)
                    // }
                    distances.push([
                        colors[i],
                        colors[j],
                        this.colorDistance(colors[i], colors[j]),
                    ]);
                }
            }
            distances.sort((a, b) => a[2] - b[2]);

            // console.log(distances.length);

            // Put each color into separate cluster initially
            const colorToCluster = {};
            for (let i = 0; i < colors.length; i++) {
                colorToCluster[colors[i].hex] = [colors[i]];
            }

            // Merge clusters, starting with lowest distances
            let lastCluster;
            for (let i = 0; i < distances.length; i++) {
                const color1 = distances[i][0];
                const color2 = distances[i][1];

                const cluster1 = colorToCluster[color1 && color1.hex];
                const cluster2 = colorToCluster[color2 && color2.hex];

                if (!cluster1 || !cluster2 || cluster1 === cluster2) {
                    continue;
                }

                // Make sure color1 is at the end of its cluster and
                // color2 at the beginning.
                if (color1 !== cluster1[cluster1.length - 1]) {
                    // cluster1 = this.colorReverse(cluster1);
                    cluster1.reverse();
                }
                if (color2 !== cluster2[0]) {
                    cluster2.reverse();
                    // cluster2 = this.colorReverse(cluster2);
                }

                // Merge cluster2 into cluster1
                cluster1.push(...cluster2);
                delete colorToCluster[color1.hex];
                delete colorToCluster[color2.hex];
                colorToCluster[cluster1[0].hex] = cluster1;
                colorToCluster[cluster1[cluster1.length - 1].hex] = cluster1;
                lastCluster = cluster1;
            }
            console.log("sorted length =", lastCluster.length);
            // By now all colors should be in one cluster
            return lastCluster;
        },
    },
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.sort {
    .prLayout(100%,100%);
    overflow: hidden;
    color: #fff;
    .show-con {
        .paLayout(0,0,100%,100%,1);
        overflow: hidden;
        overflow-y: scroll;
        // .prLayout(100%,auto);
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        padding-bottom: 260px;
        // background: #e3e7e8;
        background: rgb(84, 83, 83);
        .color-span {
            .prLayout(25px,25px);
        }
        &.origin {
            z-index: 1;
        }
        &.sort,
        &.cluster {
            visibility: hidden;
            transform: translate(100%, 0);
            z-index: 2;
            flex-direction: column;
            flex-wrap: nowrap;
            .color-group {
                display: flex;
                flex-direction: row;
                flex-wrap: wrap;
                .header {
                    .prLayout(100%,60px);
                    margin: 0 0 0px 0;
                    line-height: 50px;
                    text-indent: 10px;
                    font-size: 30px;
                    color: rgba(0, 0, 0, 0.8);
                    display: flex;
                    flex-direction: row;
                    align-content: center;
                    align-items: center;
                    border-top: 2px solid #333;
                    border-bottom: 2px solid #333;
                    background: #e3e7e8;
                    .span {
                        .prLayout(30px,30px);
                    }
                }
                .spans {
                    .prLayout(100%,auto);
                    display: flex;
                    flex-direction: row;
                    align-content: center;
                    align-items: center;
                    flex-wrap: wrap;
                }
                .desc {
                    padding: 20px;
                    display: flex;
                    flex-direction: column;
                    align-content: center;
                    align-items: center;
                    flex-wrap: wrap;
                    .row {
                        .prLayout(100%,60px);
                        line-height: 60px;
                        display: flex;
                        flex-direction: row;
                        align-content: center;
                        align-items: center;
                        p {
                            width: 200px;
                            margin-right: 20px;
                        }
                    }
                }
                &::nth-first {
                    .header {
                        margin-top: 0;
                    }
                }
            }
        }
    }
    .btn-groups {
        .pfBottomLayout(0,0,100%,180px,10);
        background: #dd6969;
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-content: center;
        align-items: center;
        flex-wrap: wrap;
        color: rgba(0, 0, 0, 0.8);
        .first {
            width: 100%;
            display: flex;
            flex-direction: row;
            justify-content: center;
            align-content: center;
            align-items: center;
            flex-wrap: wrap;
        }
        .p {
            line-height: 26px;
        }
        .btn {
            .prLayout(auto,60px);
            line-height: 60px;
            text-align: center;
            border-radius: 20px;
            padding: 0 20px;
            margin: 40px;
            background: linear-gradient(315deg, #ec7070, #c75f5f);
            box-shadow: -14px -14px 28px #b15454, 14px 14px 28px #ff7e7e;
            cursor: pointer;
            &.active {
                color: rgba(255, 255, 255, 1);
                background: linear-gradient(315deg, #c75f5f, #ec7070);
                box-shadow: -14px -14px 28px #b15454, 14px 14px 28px #ff7e7e;
            }
        }
        .ios-checkbox {
            transform: scale(0.7);
        }
        &::before {
            content: "";
            .paLayout(0,-38px,100%,50px,2);
            background-image: linear-gradient(
                0deg,
                rgba(221, 105, 105, 1) 0%,
                rgba(221, 105, 105, 1) 50%,
                rgba(221, 105, 105, 0) 100%
            );
        }
        .show-color {
            visibility: hidden;
            .paLayout(10%, 100px ,80% ,40px,2);
            display: flex;
            flex-direction: row;
            justify-content: center;
            .color-span {
                .prLayout(40px,40px);
                margin: 0 5px;
            }
        }
    }
    /* ==========================================================================
                    label标签模拟按钮         
       ========================================================================== */
    .emulate-ios-button {
        display: block;
        width: 2rem;
        height: 1rem;
        background: #e68e8e;
        border-radius: 5rem;
        cursor: pointer;
        position: relative;
        -webkit-transition: all 0.3s ease;
        transition: all 0.3s ease;
    }

    /* ==========================================================================
                    设置伪类,来实现模拟滑块滑动,过渡用了transition来实现 ,
                    translateZ来强制启用硬件渲染   
       ========================================================================== */

    .emulate-ios-button:after {
        content: "";
        display: block;
        width: 0.9rem;
        height: 0.9rem;
        border-radius: 100%;
        background: #fff;
        box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
        position: absolute;
        left: 0.05rem;
        top: 0.05rem;
        -webkit-transform: translateZ(0);
        transform: translateZ(0);
        -webkit-transition: all 0.3s ease;
        transition: all 0.3s ease;
    }

    .emulate-ios-button:active:after {
        width: 1.1rem;
    }

    /* ==========================================================================
                    设置raw-checkbox,视觉直观比较 
       ========================================================================== */
    .raw-checkbox {
        height: 2rem;
        width: 2rem;
    }

    .raw-checkbox:checked + label {
        background: #34bf49;
    }

    /* 这里是伪元素偏移,初始是0.9+0.05 ,所以这里1.05rem */
    .raw-checkbox:checked + label:after {
        left: 1.05rem;
    }

    .raw-checkbox:checked + label:active:after {
        left: 0.5rem;
    }

    .raw-checkbox:disabled + label {
        background: #d5d5d5;
        pointer-events: none;
    }

    .raw-checkbox:disabled + label:after {
        background: #bcbdbc;
    }
}
</style>