我用html+css写了一款"价格亲民"的风扇,竟然还搭载外星科技"摇头"!

285 阅读3分钟

昨天刚刚发布了一款"空调",但是考虑到不是所有人都能"负担"的起空调的费用,所以昨晚上思来想去决定今天再造一台"风扇"。

uwyho-upqgs.gif

这款风扇不但不费电,而且还没噪音,简直是居家旅行的必备物品。毕竟"科技产品还是要亲民"的,"良心的产品,厚道的价格",你值得拥有!

hgh56-i6r28.gif

甚至他还搭载了"外星科技",它竟然还能摇头,史诗级功能!!!

<template>
    <div class="fan-wrap">
        <div class="fan-container">
            <div class="fan-head" :class="{'fan-head-shake': isStart && isShake}">
                <div class="fan-head-on">
                    <div class="fan-head-content"></div>
                </div>

                <div
                    v-for="i in 24"
                    :key="i"
                    :class="`fan-head-row fan-head-row-${i}`"
                    :style="{ transform: `rotate(${(i - 1) * 15}deg)` }"
                ></div>

                <div class="fan-blade" :class="isBladeGear">
                    <svg t="1748402144356" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2775" width="340" height="340"><path d="M512 607.744c-5.632 0-11.264-0.512-16.896-1.536-3.072 20.992-11.776 45.056-29.696 70.144-73.728 113.152-160.768 261.632-31.232 279.552h1.536c151.552 24.576 338.944-59.392 237.056-260.096-29.184-60.928-58.368-100.352-81.92-129.536-16.896 25.088-46.08 41.472-78.848 41.472zM416.256 512c0-5.632 0.512-11.264 1.536-16.896-21.504-3.072-45.056-11.776-70.144-29.696-113.152-73.728-261.632-160.768-279.552-31.232v1.536c-24.576 151.552 59.392 338.944 260.096 237.056 60.928-29.184 100.352-58.368 129.536-81.92-25.088-16.896-41.472-46.08-41.472-78.848zM512 416.256c5.632 0 11.264 0.512 16.896 1.536 3.072-21.504 11.776-45.056 29.696-70.144 73.728-113.152 160.768-261.632 31.232-279.552h-1.536C436.736 43.52 249.344 127.488 351.232 328.192 380.416 389.12 409.6 428.544 433.152 457.728c16.896-25.088 46.08-41.472 78.848-41.472zM695.808 351.232c-60.928 29.184-100.352 58.368-129.536 81.92 25.088 17.408 41.472 46.08 41.472 78.848 0 5.632-0.512 11.264-1.536 16.896 21.504 3.072 45.056 11.776 70.144 29.696 113.152 73.728 261.632 160.768 279.552 31.232v-1.536c24.576-151.552-59.392-338.944-260.096-237.056zM560.64 512c0 26.624-22.016 48.64-48.64 48.64-27.136 0-48.64-22.016-48.64-48.64 0-27.136 22.016-48.64 48.64-48.64 27.136 0 48.64 22.016 48.64 48.64z" p-id="2776" fill="#cdcdcd" data-spm-anchor-id="a313x.search_index.0.i0.73203a81yUFPFN" class="selected"></path></svg>
                </div>
            </div>
            <div class="fan-body">
                <div class="gear-1" :class="{'open': gear >= 1}"></div>
                <div class="gear-2" :class="{'open': gear >= 2}"></div>
                <div class="gear-3" :class="{'open': gear >= 3}"></div>
                <div class="gear-4" :class="{'open': gear >= 4}"></div>
                <div class="off-on-btn" @click="handleChangeGear"></div>
                <div class="shake-btn" :class="{'shake-open': isShake}" @click="handleChangeShake">
                    摇头
                </div>
            </div>
            <div class="fan-footer"></div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'fan',
        data() {
            return {
                isStart: false,
                gear: 0,
                isShake: false
            }
        },
        computed: {
            isBladeGear() {
                if(this.gear > 0 && this.gear <= 4) {
                    return `gear-action-${this.gear}`
                } else if(this.gear === 0 && this.isStart) {
                    return 'gear-stop'
                }
            }
        },
        methods: {
            handleChangeGear() {
                this.isStart = true;
                this.gear += 1;
                if (this.gear === 5) {
                    this.gear = 0;
                    setTimeout(() => {
                        this.isStart = false;
                    }, 3000);
                }
            },
            handleChangeShake() {
                if (this.isStart) {
                    this.isShake = !this.isShake;
                }
            }
        }
    }
</script>

<style scoped>
.fan-container {
    width: 500px;
}

.fan-head {
    width: 340px;
    height: 340px;
    border-radius: 50%;
    border: 4px solid #ddd;
    margin: 0 auto -150px;
    position: relative;
    z-index: 100;
    box-sizing: border-box;
}

.fan-head-shake {
    animation: shake 5s infinite;
}

@keyframes shake {
    0% {
        transform: translate(0, 0) rotateY(0deg);
    }
    25% {
        transform: translateX(-40px) rotateY(-40deg);
    }
    50% {
        transform: translate(0, 0) rotateY(0deg);
    }
    75% {
        transform: translateX(40px) rotateY(40deg);
    }
    100% {
        transform: translate(0, 0) rotateY(0deg);
    }
}

.fan-head-on {
    width: 240px;
    height: 240px;
    border-radius: 50%;
    border: 2px solid #ddd;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 99;
}

.fan-head-content {
    width: 100px;
    height: 100px;
    border-radius: 50%;
    border: 1px solid #ddd;
    background-color: #fff;
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 99;
    transform: translate(-50%, -50%);
    text-align: center;
    line-height: 100px;
    font-size: 30px;
    color: #ddd;
}

.fan-head-row {
    width: 2px;
    height: 170px;
    background-color: #ddd;
    position: absolute;
    top: 0;
    left: calc(50% - 1px);
    transform-origin: center bottom;
    z-index: 90;
}

.fan-blade {
    width: 340px;
    height: 340px;
    position: absolute;
    top: calc(50% - 170px);
    left: calc(50% - 170px);
}

.gear-action-1 {
    animation: spin 2s linear infinite;
}

.gear-action-2 {
    animation: spin 1s linear infinite;
}

.gear-action-3 {
    animation: spin 0.5s linear infinite;
}

.gear-action-4 {
    animation: spin 0.2s linear infinite;
}

.gear-stop {
    animation: spin-slow-stop 3s forwards;
}

@keyframes spin {
    from {
        transform: rotate(0deg); /* 从0度开始 */
    }
    to {
        transform: rotate(360deg); /* 到360度结束 */
    }
}

/* 减速停止动画 */
@keyframes spin-slow-stop {
    0% {
        transform: rotate(0deg);
        animation-timing-function: linear;
    }
    100% {
        transform: rotate(720deg); /* 可根据需要调整最后停在哪个角度 */
        animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1); /* 模拟减速 */
    }
}

.fan-body {
    width: 180px;
    height: 320px;
    background-image: linear-gradient(to right, #ececec 0%, #fff 50%, #fff 50%, #ececec 100%);
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    margin: 0 auto;
    clip-path: polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%);
    position: relative;
}

.gear-1 {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #c1c1c1;
    position: absolute;
    bottom: 90px;
    left: 65px;
    transition: all 0.2s;
}

.gear-2 {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #c1c1c1;
    position: absolute;
    bottom: 98px;
    left: 79px;
    transition: all 0.2s;
}

.gear-3 {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #c1c1c1;
    position: absolute;
    bottom: 98px;
    right: 79px;
    transition: all 0.2s;
}

.gear-4 {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background-color: #c1c1c1;
    position: absolute;
    bottom: 90px;
    right: 65px;
    transition: all 0.2s;
}

.open {
    background-color: #0ac2fa;
    box-shadow: 0 0 6px #0ac2fa;
}

.off-on-btn {
    width: 50px;
    height: 50px;
    border-radius: 50%;
    background-image: radial-gradient(circle, #ea8a7c 0%, #ec4c41 100%);
    position: absolute;
    bottom: 40px;
    left: 50%;
    transform: translateX(-50%);
    cursor: pointer;
}

.shake-btn {
    padding: 2px 5px;
    box-sizing: border-box;
    border-radius: 5px;
    color: #c1c1c1;
    border: 1px solid #ddd;
    font-size: 12px;
    position: absolute;
    bottom: 12px;
    left: 50%;
    transform: translateX(-50%);
    cursor: pointer;
}

.shake-btn.shake-open {
    background-color: #ddd;
    color: #fff;
}

.fan-footer {
    width: 150px;
    height: 6px;
    background-image: linear-gradient(to right, #b1b1b1 0%, #f4f4f4 50%, #f4f4f4 50%, #b1b1b1 100%);
    border-bottom-left-radius: 2px;
    border-bottom-right-radius: 2px;
    clip-path: polygon(5% 0%, 95% 0%, 100% 100%, 0% 100%);
    margin: 0 auto;
}
</style>