天天看点

一百行js代码手写薪手引导功能

文章目录

  • ​​前言:​​
  • ​​一、项目的html代码​​
  • ​​二、项目的css代码​​
  • ​​三、项目的js代码​​
  • ​​四、手写的intro的css代码​​
  • ​​五、手写的intro的js代码​​

前言:

一、项目的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>吴迪-手写新手引导</title>
    <link rel="stylesheet" href="./index.css">
    <link rel="stylesheet" href="./intro.css">
</head>
<body>
    <span onclick="startIntro()">开始新手引导</span>
    <div class="wudi0">我就是测试的呀0~</div>
    <div class="wudi1">我就是测试的呀1~</div>
    <div class="wudi2">我就是测试的呀2~</div>
    <div class="wudi3">我就是测试的呀3~</div>
    <div class="wudi4">我就是测试的呀4~</div>
    <div class="wudi5">我就是测试的呀5~</div>
    <div class="wudi6">我就是测试的呀6~</div>
    <div class="wudi7">我就是测试的呀7~</div>
    <script src="./intro-wd.js"></script>
    <script src="./index.js"></script>
</body>
</html>      

二、项目的css代码

* {
    margin: 0;
    padding: 0;
}

div[class^="wudi"] {
    border: 1px solid;
    height: 40px;
    line-height: 40px;
    text-align: center;
    margin: 120px;
    background-color: #fff;
}

.wudi0, .wudi2, .wudi4 {
    width: 200px;
}

.wudi7 {
    width: 300px;
    height: 300px!important;
    line-height: 300px!important;
    border-radius: 50%;
}      

三、项目的js代码

const wdIntro = new WdIntro();

// 开始新手引导
function startIntro() {
    wdIntro.introElement();
}

// 注册新手引导步骤
function registerIntro() {
    wdIntro.registerIntro({
        intros: [
            {
                title: 'wd0',
                element: '.wudi0',
                intro: '这是介绍0',
            },
            {
                title: 'wd1',
                element: '.wudi1',
                intro: '这是介绍1',
            },
            {
                title: 'wd2',
                element: '.wudi2',
                intro: '这是介绍2',
            },
            {
                title: 'wd3',
                element: '.wudi3',
                intro: '这是介绍3',
            },
            {
                title: 'wd4',
                element: '.wudi4',
                intro: '这是介绍4',
            },
            {
                title: 'wd5',
                element: '.wudi5',
                intro: '这是介绍5',
            },
            {
                title: 'wd6',
                element: '.wudi6',
                intro: '这是介绍6',
            },
            {
                title: 'wd7',
                element: '.wudi7',
                intro: '这是圆球7哦~',
            },
        ]
    });
}
registerIntro();

// 下一步
function nextStep() {
    wdIntro.goToNextStep();
}
// 上一步
function prevStep() {
    wdIntro.goToPrevStep();
}
// 关闭新手引导
function closeIntro() {
    wdIntro.closeIntro();
}      

四、手写的intro的css代码

/* 蒙层 */
.wd-meng-cheng {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0.5;
    margin: 0;
    z-index: -1;
    background: black;
}
/* 隐藏 */
.hidden {
    display: none;
    z-index: -1;
}
/* 显示 */
.visible {
    display: block;
    z-index: 10;
}
/* 将元素置顶 */
.placed-at-the-top {
    z-index: 30;
    position: relative;
}
/* 新手引导每一步包括元素的盒子 */
.wd-intro-box {
    position: fixed;
    z-index: 11;
    margin: 0;
    filter: opacity(0.5);
    background: #fff;
    transition: all 0.3s;
}
/* 新手引导tooltip盒子 */
.wd-tooltip-box {
    margin: 0;
    position: absolute;
    left: 0;
    transition: all 0.3s;
}      

五、手写的intro的js代码

/* TODO: 1.蒙层出现禁止页面滚动 2.样式美化 */
window.WdIntro = function() {
    // 当前旅行的坐标
    this.currentIndex = 0;
    // 新手引导步骤
    this.intros = [];
    this.introsObj = {}; // 避免循环找元素,用空间换时间
    // 蒙层元素
    this.mengCheng = null;
    // 新手每一步的盒子
    this.introBox = null;
    // 新手引导的tooltip
    this.tooltipBox = null;

    // 注册新手引导
    this.registerIntro = ({ intros }) => {
        if (intros && intros.length > 0) {
            this.intros = intros;
            intros.forEach((item, index) => {
                this.introsObj[index] = item;
            });
            this.createIntroElement();
        } else {
            console.warn('你还没注册新手引导步骤!');
        }
    };

    // 创建新手引导元素
    this.createIntroElement = () => {
        // 创建一个蒙层,开始旅行的时候处理显示和隐藏
        this.mengCheng = document.createElement('div');
        document.body.appendChild(this.mengCheng);

        // 创建intro元素包裹住我们要旅行的元素用的
        this.introBox = document.createElement('div');
        document.body.appendChild(this.introBox);

        // 创建tooltip
        this.tooltipBox = document.createElement('div');
        this.introBox.appendChild(this.tooltipBox);

        this.changeVisble(false);
    }

    // 开始旅行
    this.introElement = function() {
        // 当前旅游到的这一项的全部信息
        const currentItem = this.introsObj[this.currentIndex];
        if (!currentItem || !currentItem.element) return alert('请注册旅行元素');
        // 找到当前元素
        const currentElement = document.querySelector(currentItem.element);
        currentElement.setAttribute('class', `${currentElement.getAttribute("class")} placed-at-the-top`);
        // 找到前一个和后一个元素【这块代码目前是为了效果,待整改】
        const prevItem = this.introsObj[this.currentIndex - 1];
        const prevElement = prevItem && document.querySelector(prevItem.element);
        prevElement && prevElement.setAttribute('class', `${prevElement.getAttribute("class")}`.split(' ')[0]);
        const nextItem = this.introsObj[this.currentIndex + 1];
        const nextElement = nextItem && document.querySelector(nextItem.element);
        nextElement && nextElement.setAttribute('class', `${nextElement.getAttribute("class")}`.split(' ')[0]);

        // 页面滚动并显示intro组件
        window.scrollTo(currentElement.offsetLeft, currentElement.offsetTop - 100);
        this.changeVisble(true);

        // 设置我们包裹的元素的样式
        const introBoxStyles = `
            width: ${currentElement.offsetWidth + 10}px; height: ${currentElement.offsetHeight + 10}px;
            top: ${currentElement.offsetTop - 5 - window.pageYOffset}px; left: ${currentElement.offsetLeft - 5 - window.pageXOffset}px;
            border-radius: ${window.getComputedStyle(currentElement).borderRadius || 0};
        `;
        this.introBox.setAttribute('style', introBoxStyles);
        
        // 设置tooltip的样式
        const tooltipBoxStyles = `top: ${currentElement.offsetHeight + 20}px;`;
        this.tooltipBox.setAttribute('style', tooltipBoxStyles);
        this.tooltipBox.innerHTML = `
            <span class='wd-tooltip-header'>${currentItem.title}</span>
            <span class='wd-tooltip-content'>${currentItem.intro}</span>
            <button οnclick="prevStep()">上一步</button><button οnclick="nextStep()">下一步</button>
            <button οnclick="closeIntro()">关闭新手引导</button>
        `;
    };

    // 上一步
    this.goToPrevStep = function() {
        if (this.currentIndex <= 0) return alert('没有上一步了哦');
        this.currentIndex -= 1;
        this.introElement();
    }

    // 下一步
    this.goToNextStep = function() {
        if (this.currentIndex >= this.intros?.length - 1) return alert('没有下一步了哦');
        this.currentIndex += 1;
        this.introElement();
    }

    // 关闭新手引导
    this.closeIntro = function() {
        this.currentIndex = 0;
        this.changeVisble(false);
    }

    // 设置新手引导全部组件的显示与隐藏
    this.changeVisble = function(visible) {
        this.mengCheng.setAttribute('class', `wd-meng-cheng ${visible ? 'visible' : 'hidden'}`);
        this.introBox.setAttribute('class', `wd-intro-box ${visible ? 'visible' : 'hidden'}`);
        this.tooltipBox.setAttribute('class', `wd-tooltip-box ${visible ? 'visible' : 'hidden'}`);
    }
}