模拟生产线的运动加工过程,个人记录下

1.把页面封装成单独的组件,可以重复调用
2.通过websocket推送并触发动画效果
3.动画运行完毕自行删除

注意:
1.我调整了动画执行时的速度,速度不是一致的,因为业务需求,也能有对比效果
2.当执行到下面时,中间断掉了,因为业务需求只需要在中间消失,可自行设置位置

demo尺寸是按1920x1080的固定尺寸设置的
在这里插入图片描述

【demo截图】
在这里插入图片描述

【开发时的截图】

在这里插入图片描述

【录了个动画效果】

模拟websocket推送+动画实现

组件完整代码

<style lang="less" scoped>
.steel_layer {
    position: absolute;
    color: rgba(255, 255, 255, 0.8);
    width: 1900px;
    height: 600px;
    // background: red;
    //   overflow: hidden;
    z-index: 2;
    border: 1px red solid;
}
.steel_box {
    width: 126px;
    height: 33px;
    background: url('@/assets/images/nwimg/nw-steel.png');
    // background: url('~@/assets/img/nwProductionTrack/nw-steel.png');
    background-size: contain;
    background-position: center;
    position: absolute;
    left: 160px;
    top: 70px;
    display: flex;
    align-items: center;
}
.name {
    font-size: 16px;
    text-align: center;
    width: 100%;
    position: relative;
    top: -2px;
    left: -2px;
}

.enterFurnace1 {
    top: 90px;
    left: 170px;
    animation: enterFurnace1 5s linear forwards 1;
}
@keyframes enterFurnace1 {
    0% {
        background: url('@/assets/images/nwimg/nw-steel.png');
        // background: url('~@/assets/img/nwProductionTrack/nw-steel.png');
        transform: translateX(0px) scale(0.59);
        background-size: 100% 100%;
        text-align: center;
    }
    30% {
        width: 200px;
        // height: 28px;
        // line-height: 24px;
        background: url('@/assets/images/nwimg/nw-steel.png');
        background-size: contain;
        background-position: center;
        background-size: 100% 100%;
        text-align: center;
        // background-repeat: no-repeat;
        transform: translate(300px) scale(0.59);
        // top: 82x;
    }
    50% {
        width: 660px;
        // height: 22px;
        // line-height: 24px;
        background: url('@/assets/images/nwimg/nw-steel.png');
        background-size: contain;
        background-position: center;
        background-size: 100% 100%;
        text-align: center;
        // background-repeat: no-repeat;
        transform: translate(500px) scale(0.59);
        // top: 82x;
    }

    100% {
        width: 800px;
        // height: 24px;
        // line-height: 24px;
        background: url('@/assets/images/nwimg/nw-steel.png');
        background-size: contain;
        background-position: center;
        background-size: 100% 100%;
        text-align: center;
        // background-repeat: no-repeat;
        transform: translate(1600px) scale(0.5);
        // top: 82x;
    }
}

.block-shade {
    position: absolute;
    top: 290px;
    flex-direction: row;
    width: 1200px;
    height: 234px;
    //   border: 1px red solid;
    left: -10px;
    opacity: 0;
    //   width: 300px;
    //   clip-path: circle(50%);
    .shade-left {
        // display: none;
        width: 1200px;
        height: 234px;

        background: url('@/assets/images/nwimg/nw-bg-track.png');
        // background: url('~@/assets/img/nwProductionTrack/nw-bg-track.png');
        // background-position: center;
        // background-repeat: no-repeat;
        // position: absolute;
        // left: 1px;
    }
}

.enterFurnace2 {
    left: -11px;
    animation: enterFurnace2 5s linear forwards 1;
    display: flex;
    opacity: 1;
}
@keyframes enterFurnace2 {
    0% {
        width: 0px;
        display: flex;
        opacity: 1;
        // opacity: 1;
    }
    50% {
        width: 500px;
        overflow: hidden;
        opacity: 1;
        // transform: translate(500px) scale(1);
    }
    100% {
        width: 1200px;
        opacity: 1;
        // width: 900px;
        // height: 24px;
        // line-height: 24px;
        // transform: translate(2000px) scale(1);
        // top: 82x;
    }
}

.location-sty {
    position: relative;
    right: 710px;
    top: 290px;

    .container {
        //   display: none;
        position: absolute;
        top: 0;
        right: 0; /* 固定右侧位置 */
        width: 1200px; /* 初始宽度 */
        overflow: hidden; /* 裁剪左侧超出的内容 */
        transition: width 5s; /* 宽度变化动画 */
        height: 234px;
    }
    /* 内容区域:右对齐,禁止换行 */
    .content {
        width: 1200px;
        height: 234px;
        background: url('@/assets/images/nwimg/nw-bg-track.png');
        // background-size: contain;
        // background-position: center;
        // background-size: 100% 100%;
    }

    /* 缩小容器宽度(左侧被裁剪) */
    .container.small {
        width: 0;
    }
}
.none-sty {
    opacity: 0;
}
</style>
<template>
    <div class="steel_layer">
        <!-- <button onclick="document.querySelector('.container').classList.toggle('small')">
            切换宽度(裁剪左侧)
        </button> -->
        <div class="flex">
            <div class="steel_box "
                 @animationend="animationend(item)"
                 v-for="item in model.steelList"
                 :class="item.class"
                 :key="item.billetNo">
                <!-- :class="item.class" -->
                <div class="name">
                    {{ item.billetNo }}
                </div>
            </div>
        </div>

        <div class="block-shade "
             v-for="item in model.steelList2"
             :class="item.class"
             :key="item.billetNo"
             @animationend="animationend(item)">
            <div class="shade-left"></div>
        </div>

        <div class="location-sty ">
            <div v-for="item in model.steelList3"
                 :key="item.billetNo"
                 class="container"
                 :class="item.class"
                 @transitionend.stop="animationend(item)">
                <div class="container">
                    <div class="content"></div>
                </div>
            </div>
        </div>

    </div>
</template>

<script lang="ts" setup>
// import { Component, Vue, Watch, Prop } from 'vue-property-decorator';

import { reactive, watch } from 'vue';

const props = defineProps({
    lineNo: {
        type: Array,
        default: null
    }
});

watch(props.lineNo, () => {
    model.steelList = [];
});

const model = reactive({
    steelList: [] as any,
    state2: null,
    steelList2: [] as any,
    steelList3: [] as any
});

const animation = (data: any) => {
    model.steelList.push({
        billetNo: data.billetNo,
        class: 'enterFurnace1'
    });
    console.log(model.steelList);
};

const animationend = (data) => {
    if (!data) {
        return;
    }
    // 第一段动画结束
    if (data.class == 'enterFurnace1') {
        data.class = 'enterFurnace2';
        model.steelList.splice(model.steelList.indexOf(data), 1);
        model.steelList2.push({ billetNo: data.billetNo, class: 'enterFurnace2' });
    } else if (data.class == 'enterFurnace2') {
        data.class = 'small';
        model.steelList2.splice(model.steelList2.indexOf(data), 1);
        model.steelList3.push({ billetNo: data.billetNo, class: '' });
        setTimeout(() => {
            for (let i = 0; i < model.steelList3.length; i++) {
                if (model.steelList3[i].billetNo == data.billetNo) {
                    model.steelList3[i].class = 'small';
                }
            }
        }, 100);
    } else if (data.class == 'small') {
        model.steelList3.splice(model.steelList3.indexOf(data), 1);
    }
};

defineExpose({
    animation
});
</script>

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐