前端基础(四十):拖放功能的实现

效果

源码

html 复制代码
<div class="draggable-wrap">
    <div class="draggable-box" draggable="true" data-json='{"name": "Lee"}'>
        <h1>Lee</h1>
        <div class="drop-box" data-json='{"name": "Lee"}'>
            <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
                <path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
                <path
                    d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
                    fill="#FFCE54"></path>
                <path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
                <path
                    d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
                    fill="#DA4453"></path>
                <path
                    d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
                    fill="#F6BB42"></path>
            </svg>
        </div>
    </div>
    <div class="draggable-box" draggable="true" data-json='{"name": "Tom"}'>
        <h1>Tom</h1>
        <div class="drop-box" data-json='{"name": "Tom"}'>
            <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
                <path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
                <path
                    d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
                    fill="#FFCE54"></path>
                <path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
                <path
                    d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
                    fill="#DA4453"></path>
                <path
                    d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
                    fill="#F6BB42"></path>
            </svg>
        </div>
    </div>
    <div class="draggable-box" draggable="true" data-json='{"name": "Jerry"}'>
        <h1>Jerry</h1>
        <div class="drop-box" data-json='{"name": "Jerry"}'>
            <svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
                <path d="M639.996 1023.988H384.002l42.656-512.582h170.684z" fill="#ED5564"></path>
                <path
                    d="M939.552 310.66l-295.43-42.936L512 0.012l-132.124 267.712L84.448 310.66l213.774 208.402-50.466 294.242L512 674.372l264.244 138.932-50.468-294.242z"
                    fill="#FFCE54"></path>
                <path d="M939.552 310.66L512 469.312l213.776 49.75z" fill="#F6BB42"></path>
                <path
                    d="M512 874.648c-11.782 0-21.344 9.562-21.344 21.344v127.996h42.686v-127.996c0-11.782-9.562-21.344-21.342-21.344z"
                    fill="#DA4453"></path>
                <path
                    d="M512 469.312v205.06l264.244 138.932zM298.222 519.062l-50.466 294.242L512 469.312zM379.876 267.724L84.448 310.66 512 469.312zM512 0.012v469.3l132.122-201.588z"
                    fill="#F6BB42"></path>
            </svg>
        </div>
    </div>
</div>
css 复制代码
body {
    margin: 0;
    user-select: none;
}

.draggable-wrap {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 80px;

    .draggable-box {
        position: relative;
        width: 240px;
        height: 140px;
        border: 3px solid black;
        scale: 1.2;

        h1 {
            text-align: center;
        }

        &:nth-child(1) {
            background-color: red;
        }

        &:nth-child(2) {
            background-color: green;
        }

        &:nth-child(3) {
            background-color: blue;
        }

        &[drag="start"] {
            opacity: .2;
        }

        &[drag="end"] {
            opacity: 1;
        }

        .drop-box {
            opacity: 0;
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            border: 3px dashed black;
            background-color: rgba(0, 0, 0, .5);
            transition: 1s;
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 20px;

            .icon {
                display: none;
                width: 80px;
                height: 80px;
            }

            &[drag="enter"] {
                opacity: 1;

                &::after {
                    content: '';
                    display: block;
                    position: absolute;
                    top: 0;
                    right: 0;
                    bottom: 0;
                    left: 0;
                }

                .icon {
                    display: block;
                }
            }


            &[drag="leave"] {
                opacity: 0;

                .icon {
                    display: none;
                }
            }


            &[drag="drop"] {
                opacity: 1;

                .icon {
                    display: block;
                }
            }
        }
    }
}
js 复制代码
const draggables = document.querySelectorAll('.draggable-box');
const drops = document.querySelectorAll('.drop-box');

draggables.forEach(el => {
    el.addEventListener('dragstart', e => {
        e.target.setAttribute('drag', 'start');
        e.dataTransfer.setData('data', e.target.getAttribute('data-json'));
    });
    el.addEventListener('dragend', e => {
        e.target.setAttribute('drag', 'end');
    });
});

drops.forEach(el => {
    el.addEventListener('dragenter', e => {
        e.stopPropagation();
        e.target.setAttribute('drag', 'enter');
    });
    el.addEventListener('dragover', e => e.preventDefault());
    el.addEventListener('dragleave', e => {
        e.stopPropagation();
        e.target.setAttribute('drag', 'leave');
    });
    el.addEventListener('drop', e => {
        e.target.setAttribute('drag', 'drop');
        const source = JSON.parse(e.dataTransfer.getData('data'));
        const target = JSON.parse(e.target.getAttribute('data-json'));
        console.log(source, target);
    });
});
相关推荐
cellurw6 小时前
20260724 六组件编译收尾与全局构建验证
前端
寒水馨6 小时前
Windows下载、安装electron-v43.2.0(附安装包electron-v43.2.0-win32-x64.zip)
javascript·windows·typescript·electron·跨平台·桌面应用·chromium
用户2930750976697 小时前
用React 完成Todos 的 组件应用:深入理解单向数据流与组件通信
前端
玉宇夕落7 小时前
React 父子组件通信 Todo List 看透单向数据流与不可变数据
前端
软件开发技术深度爱好者7 小时前
国际音标魔法实验室工具HTML5实现
前端·html5·英语学习
FogLetter7 小时前
嘘!WebSocket正在“偷听”你的网络请求——全双工通信的魔法
前端·面试
用户938515635077 小时前
从零构建 React Todo 应用:组件化设计与数据流深度解析
前端·javascript
IT_陈寒7 小时前
Python线程池把我坑惨了,这些盲区你不踩?
前端·人工智能·后端
mONESY7 小时前
从 DeepSeek WebGPU 输入框,吃透 React+TS 四大核心开发实践
javascript·后端
程序员爱钓鱼7 小时前
第一个 Go 程序:Hello World
前端·后端·go