• anime 动态线


    在这里插入图片描述

    app.vue

    <template>
        <div class="View" ref="View">
            <div class="Layout" :style="Layout">
                <Block v-for="item in blockData" :data="item" />
            div>
            <svg class="Layout" :style="Layout">
                <Line v-for="item in LinkData" :data="item" :count="XCounts" />
            svg>
        div>
    template>
    <script setup>
    import { onMounted, ref } from 'vue';
    import Block from './Block.vue';
    import Line from './Line.vue'
    
    const View = ref();
    // 随机函数
    
    const Layout = ref({});
    const random = (min, max) => min + Math.floor(Math.random() * (max - min + 1));
    
    const blockData = ref([]);
    const LinkData = ref([]);
    const XCounts = ref(0);
    
    // 生成测试数据
    onMounted(() => {
        var XLength = parseInt(View.value.clientWidth / 100);
        var Ylength = parseInt(View.value.clientHeight / 100);
        // console.log(XLength);
        XCounts.value = XLength;
    
        var AllCounts = XLength * Ylength;
    
        Layout.value.width = XLength * 100 + 'px';
        Layout.value.height = Ylength * 100 + 'px';
        Layout.value.left = (View.value.clientWidth - XLength * 100) / 2 + 'px';
        Layout.value.top = (View.value.clientHeight - Ylength * 100) / 2 + 'px';
    
    
        // 生成测试数据
        for (let i = 0; i < AllCounts; i++) {
            var Data = {
                isLink: Math.random() < 0.333,
                i: i,
            };
            blockData.value.push(Data);
            if (Data.isLink) {
                LinkData.value.push(Data);
            }
        };
        var ActiveIndex = random(0, LinkData.value.length - 1)
        for (let i = 0; i < LinkData.value.length; i++) {
            const element = LinkData.value[i];
            element.linkTo = LinkData.value[ActiveIndex].i;
        }
    
    })
    
    
    script>
    <style lang="less" scoped>
    .View {
        width: 100%;
        height: 100%;
        position: relative;
    }
    
    .Layout {
        position: absolute;
    }
    
    svg.Layout {
        pointer-events: none;
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    Block.vue

    <template>
        <div class="Block" :class="{ 'HasAni': data.isLink }" @mouseenter="Play">
            <environment-outlined v-if="data.isLink" class="Icon" ref="icon" />
        div>
    template>
    <script setup>
    import { EnvironmentOutlined } from '@ant-design/icons-vue'
    import anime from 'animejs'
    import { onMounted, onUnmounted, ref } from 'vue';
    const props = defineProps({
        data: Object
    })
    const icon = ref();
    let AniObj = null;
    
    onMounted(() => {
        // 创建一个动画(其实也可以中关键帧实现,原理是一样的)
        AniObj = anime({
            targets: icon.value,
            keyframes: [
                { rotateY: 0 },
                { translateY: -15, rotateY: 180 },
                { translateY: 0, rotateY: 360 },
            ],
            easing: 'linear',
            // 持续时间
            duration: 1000,
            autoplay: false,
        })
    })
    
    // 鼠标进入时,中心播放动画
    // 用 CSS 实现时,就是删除动画的 Class,间隔 1毫秒, 再添加这个Class就可以了
    const Play = () => {
        AniObj.restart();
    }
    
    onUnmounted(() => {
        // 目前 Anime 没有释放缓存的办法,
        // 只能停止动画
        AniObj.pause();
    })
    script>
    <style lang="less" scoped>
    .Block {
        width: 100px;
        height: 100px;
        float: left;
        background-color: rgba(127, 255, 212, 0.1);
        text-align: center;
        line-height: 85px;
        position: relative;
    }
    
    .HasAni {
        transition: box-shadow 0.3s, background-color 0.2s;
    }
    
    .HasAni:hover {
        box-shadow: inset 0 0 10px rgba(0, 255, 255, 0.3);
        background-color: rgba(127, 255, 212, 0.2);
    }
    
    .Icon {
        position: relative;
        z-index: 2;
        font-size: 25px;
        color: rgb(27, 141, 216);
        transform: translateY(0px) rotateY(0deg);
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    Line.vue

    <template>
        <path ref="path" :style="{ 'animation-delay': delayTime + 's' }"
            :d="`M${Start[0]} ${Start[1]} S${Control[0]} ${Control[1]} ${End[0]} ${End[1]}`" />
    
    template>
    <script setup>
    import { ref } from 'vue';
    import { computePosition, ControlPointCompute } from './Uint.js'
    const props = defineProps({
        data: Object,
        count: Number
    })
    var delayTime = Math.random();
    var { Form, To } = computePosition(props.data.linkTo, props.data.i, props.count);
    const Start = ref(Form);
    const End = ref(To);
    const Control = ref(ControlPointCompute(Form, To));
    
    script>
    <style lang="less" scoped>
    path {
        stroke: rgba(255, 0, 0, 0.5);
        stroke-width: 3;
        fill: none;
        stroke-width: 4;
        stroke-dasharray: 500, 500;
        animation: dash linear infinite 3s;
    }
    
    @keyframes dash {
        to {
            stroke-dashoffset: -1000;
        }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    Uint.js

    
    // 格式化传入点的信息
    export var computePosition = (Form, to, count) => {
        return {
            Form: [Form % count * 100 + 50, parseInt(Form / count) * 100 + 50],
            To: [to % count * 100 + 50, parseInt(to / count) * 100 + 50],
        }
    }
    
    // 弧度值转角度值的常量
    const R2A = 180 / Math.PI;
    // 角度值转弧度值的常量
    const A2R = (2 * Math.PI) / 360
    
    const ConstantAngle = 45;
    
    export var ControlPointCompute = (X, Y) => {
        // X轴坐标点差值
        const DX = Y[0] - X[0];
        // Y轴坐标点差值
        const DY = Y[1] - X[1];
        // 鼠标位置与原点的弧度值
        const radian = Math.atan2(DY, DX);
        // 鼠标点与坐标点的 余弦 值
        const CosRadian = Math.cos(radian);
        // 计算控制点与原点的距离
        const dis = Math.sqrt(Math.pow(Math.abs(DX), 2) + Math.pow(Math.abs(DY), 2)) / (2 - Math.abs(CosRadian) * (1 - 0.414));
        // 计算控制点的弧度值
        const ControlRadian = A2R * (radian * R2A - (CosRadian * ConstantAngle));
        // 计算控制点位置
        return [Math.cos(ControlRadian) * dis + X[0], Math.sin(ControlRadian) * dis + X[1]];
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    能动的电脑配件「GitHub 热点速览 v.22.11」
    快速排序详解
    MyBatisPlus(十六)逻辑删除
    java生成随机数的三种写法
    手写小程序摇树工具(二)——遍历js文件
    radiobutton的使用
    Spring Boot集成Minio插件快速入门
    阿帽的小狗
    Node.js学习(二)
    零基础学Java(13)方法参数
  • 原文地址:https://blog.csdn.net/qq_38946996/article/details/127988234