三个实战JS例子来锻炼JS能力

本文是https://www.bilibili.com/video/BV1nGDsYzEZX/?spm_id_from=333.337.search-card.all.click 的笔记

一个可以拖拽的div

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            width: 100%;
            height: 600px;
            border: 1px solid red;
            position: relative;
        }

        .mover {
            width: 100px;
            height: 100px;
            background-color: blue;
            position: absolute;
            user-select: none;
        }
    </style>
</head>

<body>
    <div class="container" id="container">
    </div>
    <script>
        let num = 0;
        let canMove = false;
        let divOffsetLeft = 0;
        let divOffsetTop = 0;
        function init() {
            const container = document.getElementById("container");
            // 绑定 onmousedown 事件处理函数,当用户按下鼠标时触发。
            // targetDom 获取鼠标点击的目标元素。
            // 如果点击的是 container 元素本身(不是其中的拖动 div),调用 createMoveDiv() 函数创建一个新的可拖动 div,并传入鼠标相对容器的 x 和 y 坐标(即 event.offsetX 和 event.offsetY)。
            // 如果点击的是一个已有的 mover(可拖动的 div),则设置 canMove 为 true,表示允许拖动,并记录鼠标在 div 中的偏移量(divOffsetLeft 和 divOffsetTop)。同时,设置该 div 的 z-index 为最大,确保它处于最上层,避免被其他元素遮挡。
            container.onmousedown = function (event) {
                const targetDom = event.target;
                if (targetDom.getAttribute('class') === 'container') {
                    //如果是容器就创建div
                    createMoveDiv(container, event.offsetX, event.offsetY);
                } else if (targetDom.getAttribute('class') === 'mover') {
                    //如果点的是可拖动的div
                    canMove = true;
                    divOffsetLeft = event.offsetX;
                    divOffsetTop = event.offsetY;
                    event.target.style.zIndex = 999999;
                    //dom元素的x怎么获取
                    // console.log(event.target.getBoundingClientRect());
                }
            }
            // 绑定 onmousemove 事件处理函数,当用户移动鼠标时触发。
            // 如果 canMove 为 true(即用户正在拖动元素),则调用 move() 函数,将 div 移动到新的位置。
            // e.pageX 和 e.pageY 获取当前鼠标相对于页面的位置。
            container.onmousemove = function (e) {
                if (canMove) {
                    //一定是在div移动时,才会触发这些东西
                    console.log("移动监听生效")
                    move(e.pageX, e.pageY, e.target);
                }
            }
            //  绑定 onmouseup 事件处理函数,当用户松开鼠标时触发。
            // 设置 canMove 为 false,停止拖动。
            // 重置拖动元素的 z-index 为 100,恢复原来的层级
            container.onmouseup = function (e) {
                canMove = false;
                e.target.style.zIndex = 100;
            }
        }
        function createMoveDiv(contaienr, x, y) {
            const _div = document.createElement("div");
            _div.setAttribute("class", "mover");
            _div.innerHTML = num;
            _div.setAttribute('style', `left:${x}px;top:${y}px;`)
            _div.onmouseleave = function () {
                canMove = false;
            }
            contaienr.appendChild(_div);
            num += 1;
        }
        function move(x, y, dom) {
            //因为已经有style属性在div上了,所以可以直接dom.style
            dom.style.left = `${x - divOffsetLeft - 8}px`
            dom.style.top = `${y - divOffsetTop - 8}px`
        }
        init();
    </script>
</body>

</html>
````<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            width: 100%;
            height: 600px;
            border: 1px solid red;
            position: relative;
        }

        .mover {
            width: 100px;
            height: 100px;
            background-color: blue;
            position: absolute;
            user-select: none;
        }
    </style>
</head>

<body>
    <div class="container" id="container">
    </div>
    <script>
        let num = 0;
        let canMove = false;
        let divOffsetLeft = 0;
        let divOffsetTop = 0;
        function init() {
            const container = document.getElementById("container");
            // 绑定 onmousedown 事件处理函数,当用户按下鼠标时触发。
            // targetDom 获取鼠标点击的目标元素。
            // 如果点击的是 container 元素本身(不是其中的拖动 div),调用 createMoveDiv() 函数创建一个新的可拖动 div,并传入鼠标相对容器的 x 和 y 坐标(即 event.offsetX 和 event.offsetY)。
            // 如果点击的是一个已有的 mover(可拖动的 div),则设置 canMove 为 true,表示允许拖动,并记录鼠标在 div 中的偏移量(divOffsetLeft 和 divOffsetTop)。同时,设置该 div 的 z-index 为最大,确保它处于最上层,避免被其他元素遮挡。
            container.onmousedown = function (event) {
                const targetDom = event.target;
                if (targetDom.getAttribute('class') === 'container') {
                    //如果是容器就创建div
                    createMoveDiv(container, event.offsetX, event.offsetY);
                } else if (targetDom.getAttribute('class') === 'mover') {
                    //如果点的是可拖动的div
                    canMove = true;
                    divOffsetLeft = event.offsetX;
                    divOffsetTop = event.offsetY;
                    event.target.style.zIndex = 999999;
                    //dom元素的x怎么获取
                    // console.log(event.target.getBoundingClientRect());
                }
            }
            // 绑定 onmousemove 事件处理函数,当用户移动鼠标时触发。
            // 如果 canMove 为 true(即用户正在拖动元素),则调用 move() 函数,将 div 移动到新的位置。
            // e.pageX 和 e.pageY 获取当前鼠标相对于页面的位置。
            container.onmousemove = function (e) {
                if (canMove) {
                    //一定是在div移动时,才会触发这些东西
                    console.log("移动监听生效")
                    move(e.pageX, e.pageY, e.target);
                }
            }
            //  绑定 onmouseup 事件处理函数,当用户松开鼠标时触发。
            // 设置 canMove 为 false,停止拖动。
            // 重置拖动元素的 z-index 为 100,恢复原来的层级
            container.onmouseup = function (e) {
                canMove = false;
                e.target.style.zIndex = 100;
            }
        }
        function createMoveDiv(contaienr, x, y) {
            const _div = document.createElement("div");
            _div.setAttribute("class", "mover");
            _div.innerHTML = num;
            _div.setAttribute('style', `left:${x}px;top:${y}px;`)
            _div.onmouseleave = function () {
                canMove = false;
            }
            contaienr.appendChild(_div);
            num += 1;
        }
        function move(x, y, dom) {
            //因为已经有style属性在div上了,所以可以直接dom.style
            dom.style.left = `${x - divOffsetLeft - 8}px`
            dom.style.top = `${y - divOffsetTop - 8}px`
        }
        init();
    </script>
</body>

</html>

轮播图 自动播放

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .container {
            width: 980px;
            height: 400px;
            overflow: hidden;
            margin: 0 auto;
            position: relative;
        }

        .banner-wraper {
            display: flex;
            width: 980px;
            height: 400px;
            transition: all 0.4s ease-in;
        }

        .item {
            flex: 0;
            width: 980px;
            height: 400px;
        }

        .item img {
            width: 980px;
            height: 400px;
        }

        .point-wraper {
            height: 25px;
            position: absolute;
            bottom: 20px;
            left: 50%;
            width: 100px;
            margin-left: -50px;
            display: flex;
        }

        .point {
            width: 25px;
            height: 25px;
            border-radius: 25px;
            background-color: white;
        }
    </style>
</head>

<body>
    <div class="container" id="container">
    </div>

    <script>
        //实现了一个自动播放的图片轮播功能,同时用户可以点击圆点来手动切换图片
        const imgsrc = ["./img/pic1.jpeg", "./img/pic2.jpeg", "./img/pic3.jpeg"]
        class Banner {
            imgArr = [];
            time = 3000;
            nowIndex = 0;
            bannerItemWrapper = null;
            timer = null;
            constructor(imgarr, time) {
                this.imgArr = imgarr;
                this.time = time || 3500;
            }
            init() {
                //创建轮播图片的容器
                const container = document.getElementById("container");
                const _banerItemWrapper = document.createElement("div")
                _banerItemWrapper.setAttribute("class", "banner-wraper")
                this.bannerItemWrapper = _banerItemWrapper;
                //点击切换的点的容器
                //创建一个 div 元素 _pointWrapper,用来放置控制轮播图切换的圆点(即用户点击的按钮)。
                const _pointWrapper = document.createElement("div")
                _pointWrapper.setAttribute('class', 'point-wraper')
                //绑定点击切换 事件,直接给容器,根据e.target判断具体点的谁
                // 给 pointWrapper 绑定点击事件,当用户点击某个圆点时:
                // e.target 获取被点击的圆点元素。
                // 通过 data-index 获取当前点击的圆点代表的是第几张图片(通过 data-index 属性设置)。
                // 设置 this.nowIndex 为当前点击的图片索引。
                // clearInterval(this.timer) 清除自动播放定时器,以便用户点击后不再自动切换图片。
                // 调用 this.goNext() 来跳转到用户点击的图片。
                // 最后调用 this.autoPlay() 重新启动自动播放。
                _pointWrapper.onclick = (e) => {
                    const _dom = e.target;
                    //通过data-index知道这个dom代表第几张
                    const _targetIndex = _dom.getAttribute("data-index")
                    this.nowIndex = _targetIndex - 0
                    clearInterval(this.timer)
                    this.goNext();
                    this.autoPlay();
                }
                //循环创建每张轮播图
                // this.imgArr.forEach 遍历图片数组,为每张图片做以下操作:
                // 创建一个 div 元素 _bannerItem,将图片添加进去。
                // 设置 class 为 item,将其加入到 bannerItemWrapper 中。
                // 创建一个新的 div 元素 _point,作为点击切换的圆点,设置其 class 为 point。
                // 设置 data-index 属性,表示当前图片的索引。
                // 将所有的圆点元素 _point 添加到 pointWrapper 中。
                // 最后将 _banerItemWrapper 和 _pointWrapper 都添加到 container 容器中。
                this.imgArr.forEach((img, index) => {
                    //创建单个轮播图片
                    const _bannerItem = document.createElement("div");
                    _bannerItem.innerHTML = `<img src="${img}"/>`
                    _bannerItem.setAttribute("class", 'item')
                    _banerItemWrapper.appendChild(_bannerItem);
                    //把_banerItemWrapper加入容器
                    container.appendChild(_banerItemWrapper);
                    //创建点击切换的点
                    const _point = document.createElement("div");
                    _point.setAttribute("class", 'point');
                    //设置一个自定义属性,说明第几张
                    _point.setAttribute("data-index", index)
                    _pointWrapper.appendChild(_point);
                    //把_banerItemWrapper加入容器
                    container.appendChild(_pointWrapper)
                })
                this.autoPlay();
            }
            // 自动播放函数 autoPlay()
            // autoPlay 定义了一个定时器,用于每隔 this.time 毫秒自动切换到下一张图片。
            // this.nowIndex += 1:当前图片索引加 1。
            // if (this.nowIndex === this.imgArr.length):当索引超出图片数组的范围时,重置为 0,从第一张图片开始。
            // this.goNext():调用 goNext() 跳转到下一张图片。
            autoPlay() {
                this.timer = setInterval(() => {
                    this.nowIndex += 1;
                    if (this.nowIndex === this.imgArr.length) {
                        this.nowIndex = 0;
                    }
                    this.goNext();
                }, this.time)
            }
            clickPlay() {

            }
            //下一个图片
            goNext() {
                this.bannerItemWrapper.setAttribute('style', `transform:translateX(-${this.nowIndex * 980}px)`)
            }
        }
        new Banner(imgsrc, 3000).init();
    </script>
</body>

</html>

给文本添加备注

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style></style>
    <style>
        body {
            padding-top: 100px;
        }

        .edit {
            width: 800px;
            height: 400px;
            border: 1px solid red;
            margin: 0 auto;
        }

        .mark {
            color: red;
            position: relative;
        }

        .popCover {
            position: fixed;
            z-index: 9999;
            background-color: rgba(0, 0, 0, 0.4);
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
        }

        .popcontent {
            background-color: white;
            width: 200px;
            height: 200px;
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -100px;
            margin-top: -100px;
        }

        .marktext {
            display: none;
            position: absolute;
            left: 0;
            width: 200px;
            background-color: white;
            color: black;
            top: -20px;
            z-index: 9999
        }
    </style>
</head>

<body>
    <div class="edit" id="edit" contenteditable="true"></div>
    <button id="mark">备注</button>

    <div id="popCover" class="popCover" style="display: none;">
        <div class="popcontent">
            <h2>输入备注内容</h2>
            <input id='markValue' />
            <div>
                <button id="confirm">确认</button>
                <button id="cancel">取消</button>
            </div>
        </div>
    </div>
    <script>
        let selecText = '';

        function bindEvent() {
            document.getElementById('mark').addEventListener("click", () => {
                getSelectionText();
                togglePop("show");
            })
            document.getElementById('confirm').addEventListener("click", () => {
                togglePop("hidden");
                setMark();
            })
            document.getElementById('cancel').addEventListener("click", () => {
                togglePop("hidden");
            })
            document.getElementById("edit").addEventListener("click", (e) => {
                if (e.target.getAttribute("class") === 'mark') {
                    toggleMarkContent(e.target)
                }

            })
        }
        // 这个函数用于获取用户选中的文本内容。使用 window.getSelection() 获取当前的选区,并将选中的文本转换为字符串存储在 selecText 变量中。
        function getSelectionText() {
            const selection = window.getSelection();
            selecText = selection.toString();
        }
        //togglePop-切换弹窗显示映射
        function togglePop(handle) {
            const pop = document.getElementById('popCover');

            if (handle === 'show') {
                //显示弹窗
                pop.style.display = 'block'
            } else if (handle === 'hidden') {
                //隐藏弹窗
                pop.style.display = 'none';
            }
        }
        //setMark:这个函数会将用户输入的备注内容插入到选中的文本中。具体步骤:
        // 获取备注输入框的值,即用户输入的备注内容。
        // 获取当前编辑区(#edit)的 HTML 内容。
        // 查找选中文本的开始和结束位置。
        // 分别截取选中文本之前和之后的部分。
        // 将选中文本和备注内容拼接起来,并将新的 HTML 更新到编辑区中。
        function setMark() {
            //三个获取
            //获取备注内容
            const markContent = document.getElementById("markValue").value;
            //获取选中内容-取selecText就好了,因为点击备注按钮时候已经存在里面了
            //获取当前edit的文字
            const nowHTML = document.getElementById("edit").innerHTML;
            //获取选中的文本在原文中开始的位置
            const start = nowHTML.indexOf(selecText)
            //获取选中的文本在原文中结束的位置
            const end = start + selecText.length
            //截取选中文本之前的文本
            const beforeSelect = nowHTML.substr(0, start)
            //截取选中文本之后的文本
            const afterSelect = nowHTML.substr(end, nowHTML.length);
            const newHTML = beforeSelect + `<span class='mark'>${selecText}<font class='marktext'>${markContent}</font></span>` + afterSelect;

            document.getElementById("edit").innerHTML = newHTML;
        }


        // toggleMarkContent:这个函数用于显示或隐藏某个已标记文本的备注内容。当用户点击一个已标记的文本时,会显示或隐藏备注内容(<font class='marktext'> 部分)。具体实现是遍历该文本的子元素,找到 class="marktext" 的元素,并根据其当前的显示状态切换显示与隐藏。
        function toggleMarkContent(dom) {
            const children = dom.children;
            for (let i = 0; i < children.length; i++) {
                if (children[i].getAttribute('class') === "marktext") {
                    if (children[i].style.display === 'block') {
                        children[i].style.display = 'none'
                    } else {
                        children[i].setAttribute("style", "display:block")
                    }

                }
            }
        }
        //调用bindEvent绑定事件
        bindEvent();
    </script>
</body>

</html>

`

相关推荐
心仪悦悦1 分钟前
Scala的Array(2)
开发语言·后端·scala
沉默璇年18 分钟前
react中useMemo的使用场景
前端·react.js·前端框架
yqcoder24 分钟前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
2401_8827275733 分钟前
BY组态-低代码web可视化组件
前端·后端·物联网·低代码·数学建模·前端框架
baivfhpwxf202335 分钟前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
许嵩6637 分钟前
IC脚本之perl
开发语言·perl
长亭外的少年1 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
直裾1 小时前
Scala全文单词统计
开发语言·c#·scala
心仪悦悦1 小时前
Scala中的集合复习(1)
开发语言·后端·scala
JIAY_WX1 小时前
kotlin
开发语言·kotlin