最近朋友圈被很多网易云音乐的年底歌单给刷屏了, 我也去看了我的年度歌单, 发现一个有意思的交互成果, 抉择卡通形象, 通过滑动抉择人物的不同头像,衣服,裤子 最终塑造成一个领有独立共性的卡通形象.

界面成果预览

交互成果预览

制作素材

把每个滑动的图片进行了全屏截图, 而后通过图片解决工具去除背景, 制作成对立大小的png图片.



图片的卡通元素都是通过截图获取, 每个元素被解决成对立大小, 局部会有锯齿, 仅供参考. 这里头部比拟非凡, 每个形象的头部大小不一, 这里取一个对立的截止线, 不便前面整合成整个形象. 其它相似,顶对齐即可.

剖析交互的特点

1. 轮播图2. 跨屏3. 滑动循环4. 局部衣服滑动会触发裤子的扭转5. 局部裤子滑动会触发衣服的扭转6. ...


轮播图代码

<div id="slide" class="bui-slide bui-slide-skin01"></div>
var uiSlide = bui.slide({        id: "#slide",        height: 320,        // autopage: true, // 主动分页        data: [{            image: "images/banner01.png",            url: "pages/ui_controls/bui.slide_title.html",        }, {            image: "images/banner02.png",            url: "pages/ui_controls/bui.slide_title.html",        }, {            image: "images/banner03.png",            url: "pages/ui_controls/bui.slide_title.html",        }],        loop: true, // 循环    })

跨屏轮播图只需加上 cross:true 参数即可. 相熟BUI的敌人, 一眼就能找到相似的成果, 跨屏轮播图 第1-第3的特点就解决了.

有意思的是第4点第5点, 轮播图切换的时候局部须要互相关联.

实现的外围思路:

  1. 页面有一个动态全屏轮播图, 用于点击下一步,上一步的整屏切换. 动态轮播图的益处是构造能够自定义.
  2. 首屏初始化三个跨屏轮播图, 用于头部,衣服,裤子的失常抉择切换;
  3. 点击轮播图的时候, 切换激活状态, 非激活状态暗藏左右两个图片(暗藏通过css), 并禁止滑动 ;
  4. 当滑动选中当前,别离把头部,衣服,裤子的图片地址,索引 缓存在 bui.store (轮播图的to回调外面);
  5. 通过bui.store 创立衣服跟裤子的关联 conection 字段, 当检测到滑动的图片有配套裤子的时候,主动滑动下一个轮播图到指定地位;
  6. 点击下一步去到第2屏, 用于展现刚刚选中的数据;
// 衣服const cartoonBody = bui.slide({    id: "#cartoonBody",    height: 320,    stopPropagation: false,    autopage: false,    cross: true,    loop: true,    data: this.$data.cartoon.body}).on("to", function () {    let index = this.index();    // bui.store 读取的时候须要应用 this.$data.xxx ,如果应用 this.xxx 读取会导致最终的值不能设置正确.    let img = that.$data.cartoon.body[index].image;    // 设置    that.profile.body.image = img;    that.profile.body.index = index;    // 检测衣服跟裤子的关系索引    let item = bui.array.get(that.$data.conection, img, "body");    let footindex = bui.array.index(that.$data.cartoon.foot, item.foot, "image");    if (footindex >= 0 && that.$data.active[1] == "active-block") {        // 操作裤子的实例, 跳转的时候, 因为loop:true, 这里的索引须要在实在的索引下+1         that.$data.distances[2].to(footindex + 1, "none")    }}).lock();// lock禁止滑动// 裤子const cartoonFoot = bui.slide({    id: "#cartoonFoot",    height: 320,    stopPropagation: false,    autopage: false,    cross: true,    loop: true,    data: this.$data.cartoon.foot}).on("to", function () {    let index = this.index();    let img = that.$data.cartoon.foot[index].image;    that.profile.foot.image = img;    that.profile.foot.index = index;    // 检测衣服跟裤子的关系索引    let item = bui.array.get(that.$data.conection, img, "foot");    let bodyindex = bui.array.index(that.$data.cartoon.body, item.body, "image");    if (bodyindex >= 0 && that.$data.active[2] == "active-block") {        // 操作衣服的实例, 跳转的时候, 因为loop:true, 这里的索引须要在实在的索引下+1         that.$data.distances[1].to(bodyindex + 1, "none")    }}).lock();// lock禁止滑动

最终成果


github地址: https://github.com/imouou/BUI...

codepen地址: https://codepen.io/imouou/ful...

BUI专一挪动开发, 灵便超出你的设想, 感谢您的浏览.

多页残缺代码

<!DOCTYPE HTML><html><head>    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />    <title>BUI</title>    <meta name="format-detection" content="telephone=no" />    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/buijs@latest/lib/latest/bui.css" />    <style>    .cartoon-page main,    .step-item {        background-color: #f2c9bc;        padding-top: .2rem;    }    .step-item {        width: 100%;        height: 100%;    }    .cartoon-page h1,    .cartoon-page p {        text-align: center;        color: #675553;    }    .cartoon-wrap .bui-slide {        margin-bottom: .2rem;    }    .cartoon-wrap .bui-slide-img{        width: 4rem;        height: 3.2rem;        background-color: #e2b4a3;        border-radius: .2rem;    }    .cartoon-wrap .active-block .bui-slide-img{        background-color: #fff;    }    .cartoon-wrap .active-block .bui-cross-prev,    .cartoon-wrap .active-block .bui-cross-next{        visibility: visible;    }    .cartoon-wrap  .bui-cross-prev,    .cartoon-wrap  .bui-cross-next{        visibility: hidden;    }    .cartoon-wrap  .bui-cross-prev .bui-slide-img,    .cartoon-wrap  .bui-cross-next .bui-slide-img{        background-color: rgba(255,255,255,.3);    }    .bui-btn-step {        width: 1.4rem;        height: 1.4rem;        line-height: 1.4rem;        color: #fff;        background-color: #f5433b;        border: 3px solid rgba(255,255,255,0.8);        padding: 0;        margin-bottom: .2rem;    }    .bui-slide-cross .bui-cross-next .bui-slide-img,     .bui-slide-cross .li-next .bui-slide-img{        margin-left: 0;    }    .bui-slide-cross .bui-cross-prev .bui-slide-img,     .bui-slide-cross .li-prev .bui-slide-img{        margin-right: 0;    }    .bui-slide-fullscreen>.bui-slide-main>ul>li img.cartoonhead ,    .bui-slide-fullscreen>.bui-slide-main>ul>li img.cartoonbody,    .bui-slide-fullscreen>.bui-slide-main>ul>li img.cartoonfoot {        display: block;        width:3.2rem ;        height:3.2rem ;    }    .cartoonhead {        position: relative;        z-index: 3;    }    .cartoonbody {        margin-top: -1.1rem;        position: relative;        z-index: 2;    }    .cartoonfoot {        margin-top: -1.1rem;        position: relative;        z-index: 1;    }</style></head><body><!-- HTML Begin--><!-- 这里还是一个规范的BUI页面 --><div class="bui-page bui-box-vertical cartoon-page">    <header></header>    <main>        <!-- 动态轮播图 -->        <div id="uiSlide" class="bui-slide">            <div class="bui-slide-main">                <ul>                    <li>                        <!-- 垂直布局 -->                        <div class="step-item bui-box-center bui-box-vertical fullheight">                            <div class="span1">                                <h1>设置形象, 开启年度报告</h1>                                <p>左右切换抉择造型</p>                                <div class="bui-box bui-box-vertical cartoon-wrap">                                    <div class="span1" b-class="cartoons.active.0" b-click="cartoons.activeBlock(0)">                                        <div id="cartoonHead" class="bui-slide"></div>                                    </div>                                    <div class="span1" b-class="cartoons.active.1" b-click="cartoons.activeBlock(1)">                                        <div id="cartoonBody" class="bui-slide"></div>                                    </div>                                    <div class="span1" b-class="cartoons.active.2" b-click="cartoons.activeBlock(2)">                                        <div id="cartoonFoot" class="bui-slide"></div>                                    </div>                                    <!-- <div class="span1" b-class="cartoons.active.3" b-click="cartoons.activeBlock(3)">                                        <div id="cartoonDeco" class="bui-slide"></div>                                    </div> -->                                </div>                            </div>                            <div class="container-y">                                <div class="bui-btn-step ring" b-click="cartoons.next">下一步</div>                            </div>                        </div>                    </li>                    <li style="display:none;">                        <!-- 垂直布局 -->                        <div class="step-item bui-box-center bui-box-vertical fullheight">                            <!-- 最终形象 -->                            <div class="span1">                                <div class="bui-box-center">                                    <div class="wrap-img">                                        ![](cartoons.profile.head.image)                                        ![](cartoons.profile.body.image)                                        ![](cartoons.profile.foot.image)                                    </div>                                </div>                            </div>                            <div class="container-y">                                <div class="bui-btn-step ring" b-click="cartoons.prev">上一步</div>                            </div>                        </div>                    </li>                </ul>            </div>        </div>    </main></div><!-- HTML End-->    <!-- 依赖库 手机调试的js援用程序如下 -->    <script src="https://cdn.jsdelivr.net/npm/buijs@latest/lib/zepto.js"></script>    <script src="https://cdn.jsdelivr.net/npm/buijs@latest/lib/latest/bui.js"></script>    <script>        bui.ready(function () {            // 这里写业务及控件初始化, 一个页面只能有一个bui.ready            // 页面跳转的全屏轮播图            const uiSlideStep = bui.slide({                id: "#uiSlide",                autopage: false,                fullscreen: true,                swipe: false,                loop: false            })            // 初始化数据行为存储            const bs = bui.store({                el: `.bui-page`,                scope: "cartoons",                data: {                    // 衣服裤子的关系, 局部衣服关联裤子, 裤子关联衣服                    conection: [{                        body: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body02.png",                        foot: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot01.png"                    }, {                        body: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body03.png",                        foot: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot05.png"                    }, {                        body: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body12.png",                        foot: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot08.png"                    }, {                        body: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body13.png",                        foot: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot07.png"                    }, {                        body: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body14.png",                        foot: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot06.png"                    }],                    distances: [], // 存储滑动的实例                    active: {                        0: "active-block",                        1: "",                        2: "",                    },                    profile: {                        // 集体形象的存储                        head: {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head01.png",                            index: 0,                        },                        body: {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body01.png",                            index: 0,                        },                        foot: {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot01.png",                            index: 0,                        },                        deco: {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco01.png",                            index: 0,                        }                    },                    cartoon: {                        active: 0, // 激活的slide, 默认头部                        head: [{                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head01.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head02.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head03.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head04.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head05.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head06.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head07.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head08.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head09.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head10.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head11.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/head/head12.png",                        }],                        body: [{                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body01.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body02.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body03.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body04.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body05.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body06.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body07.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body08.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body09.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body10.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body11.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body12.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body13.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/body/body14.png",                        }],                        foot: [{                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot01.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot02.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot03.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot04.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot05.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot06.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot07.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot08.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/foot/foot09.png",                        }],                        deco: [{                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco01.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco02.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco03.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco04.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco05.png",                        }, {                            image: "https://gitee.com/imouou/bui-case-cartoon/raw/main/src/images/cartoon/deco/deco06.png",                        }],                    },                },                methods: {                    activeBlock(index) {                        for (let i = 0; i < Object.keys(this.$data.active).length; i++) {                            this.active[i] = "";                            this.$data.distances[i].lock();                        }                        // 给激活的滑动图加上款式,区别其它两个                        this.active[index] = "active-block";                        this.$data.distances[index].unlock();                    },                    next() {                        uiSlideStep.next();                    },                    prev() {                        uiSlideStep.prev();                    }                },                mounted: function () {                    // 焦点图 js 初始化:                    let that = this;                    const cartoonHead = bui.slide({                        id: "#cartoonHead",                        height: 320,                        autopage: false,                        stopPropagation: false,                        cross: true,                        loop: true,                        data: this.$data.cartoon.head                    }).on("to", function () {                        let index = this.index();                        // bui.store 读取的时候须要应用 this.$data.xxx ,如果应用 this.xxx 读取会导致最终的值不能设置正确.                        let img = that.$data.cartoon.head[index].image;                        // 设置                        that.profile.head.index = index;                        that.profile.head.image = img;                    })                    const cartoonBody = bui.slide({                        id: "#cartoonBody",                        height: 320,                        stopPropagation: false,                        autopage: false,                        cross: true,                        loop: true,                        data: this.$data.cartoon.body                    }).on("to", function () {                        let index = this.index();                        // bui.store 读取的时候须要应用 this.$data.xxx ,如果应用 this.xxx 读取会导致最终的值不能设置正确.                        let img = that.$data.cartoon.body[index].image;                        // 设置                        that.profile.body.image = img;                        that.profile.body.index = index;                        // 检测衣服跟裤子的关系索引                        let item = bui.array.get(that.$data.conection, img, "body");                        let footindex = bui.array.index(that.$data.cartoon.foot, item.foot, "image");                        if (footindex >= 0 && that.$data.active[1] == "active-block") {                            // 操作裤子的实例, 跳转的时候, 因为loop:true, 这里的索引须要在实在的索引下+1                             that.$data.distances[2].to(footindex + 1, "none")                        }                    }).lock();                    const cartoonFoot = bui.slide({                        id: "#cartoonFoot",                        height: 320,                        stopPropagation: false,                        autopage: false,                        cross: true,                        loop: true,                        data: this.$data.cartoon.foot                    }).on("to", function () {                        let index = this.index();                        let img = that.$data.cartoon.foot[index].image;                        that.profile.foot.image = img;                        that.profile.foot.index = index;                        // 检测衣服跟裤子的关系索引                        let item = bui.array.get(that.$data.conection, img, "foot");                        let bodyindex = bui.array.index(that.$data.cartoon.body, item.body, "image");                        if (bodyindex >= 0 && that.$data.active[2] == "active-block") {                            // 操作衣服的实例, 跳转的时候, 因为loop:true, 这里的索引须要在实在的索引下+1                             that.$data.distances[1].to(bodyindex + 1, "none")                        }                    }).lock();                    // const cartoonDeco = bui.slide({                    //     id: "#cartoonDeco",                    //     height: 320,                    //     stopPropagation: false,                    //     autopage: false,                    //     cross: true,                    //     loop: true,                    //     data: this.$data.cartoon.deco                    // }).on("to", function () {                    //     let index = this.index();                    //     that.profile.deco.image = that.$data.cartoon.deco[index].image                    //     that.profile.deco.index = index;                    // }).to(0, "none").lock();                    // 增加实例,跟cartoon.active 的数值对应.                    this.distances.push(cartoonHead, cartoonBody, cartoonFoot);                }            })        })    </script></body></html>