zoukankan      html  css  js  c++  java
  • js 实现3D旋转相册

     

    <style type='text/css'>
        * {
            margin: 0;
            padding: 0;
        }
        .container {
            display: flex;
            min-height: 100vh;
            perspective: 800px;
            background: #000;
            touch-action: none;
        }
        .wrap {
            position: relative;
             120px;
            height: 180px;
            margin: auto;
            transform-style: preserve-3d;
            pointer-events: none;
        }
        .wrap img {
            position: absolute;
            top: 0;
            left: 0;
             100%;
            height: 100%;
            object-fit: cover;
            border-radius: 2px;
        }
    </style>
    
    <div class="container">
        <div class="wrap">
            <img src="../images/incarnation/baiyuekui.jpg" alt="">
            <img src="../images/incarnation/heguanzhe.jpg" alt="">
            <img src="../images/incarnation/ailika.jpg" alt="">
            <img src="../images/incarnation/jiexika.jpg" alt="">
            <img src="../images/incarnation/chenmin4277.jpg" alt="">
            <img src="../images/incarnation/feixue.jpg" alt="">
            <img src="../images/incarnation/hongkou.jpg" alt="">
            <img src="../images/incarnation/peini.jpg" alt="">
            <img src="../images/incarnation/suixing.jpg" alt="">
            <img src="../images/incarnation/jingnan.jpg" alt="">
            <img src="../images/incarnation/xiadou.jpg" alt="">
            <img src="../images/incarnation/ranbing.jpg" alt="">
        </div>
    </div>
    
    
    js
    // 获取dom
    const container = document.querySelector('.container');
    const wrap = document.querySelector('.wrap');
    const imgList = document.querySelectorAll('.wrap img');
    const length = imgList.length;
    // 计算图片间隔角度
    const angle = 360 / length;
    
    // 开场动画 延时1000 / 60 = 16.666667 ≈ 17,否则transition不会生效
    setTimeout(() => {
        for (let i = 0; i < length; i++) {
            // 每张图片过渡效果间隔0.1s
            imgList[i].style.transition = 'transform 1s ease ' + (length - 1 - i) * 0.1 + 's';
            // 沿着z轴偏移320像素(此距离自己设置,觉得合适即可),否则图片会挤在一起
            imgList[i].style.transform = 'rotateY(' + (angle * i) + 'deg) translateZ(320px)';
        }
    }, 17);
    // wrap沿x轴旋转-10度
    const rotate = { x: -10, y: 0 };
    wrap.style.transform = 'rotateX(' + rotate.x + 'deg)';
    
    
    拖拽
    let isPointerDown = false;
    let point = null;
    let last = null;
    let diff = null;
    let rafId = null;
    // 监听pointerdown事件
    container.addEventListener('pointerdown', function (e) {
        this.setPointerCapture(e.pointerId);
        isPointerDown = true;
        // 停止动画
        cancelAnimationFrame(rafId);
        point = { x: e.clientX, y: e.clientY };
        last = { x: e.clientX, y: e.clientY };
        diff = { x: 0, y: 0 };
    });
    // 监听pointermove事件
    container.addEventListener('pointermove', function (e) {
        if (isPointerDown) {
            const current = { x: e.clientX, y: e.clientY };
            // 计算相对于上一次移动差值
            diff = { x: current.x - last.x, y: current.y - last.y };
            // 旋转角度,乘以0.1是为了降低旋转敏感度,防止旋转过快。可自行设置合适的值
            rotate.x -= diff.y * 0.1;
            rotate.y += diff.x * 0.1;
            last = { x: current.x, y: current.y };
            wrap.style.transform = 'rotateX(' + rotate.x + 'deg) rotateY(' + rotate.y + 'deg)';
        }
    });
    // 监听pointerup事件
    container.addEventListener('pointerup', function (e) {
        isPointerDown = false;
        // 惯性滚动
        raf();
    });
    // 监听pointercancel事件
    container.addEventListener('pointercancel', function (e) {
        isPointerDown = false;
    });
    
    
    function raf() {
        // ES6解构赋值
        let { x, y } = diff;
        function step() {
            // 摩擦力
            x *= 0.95;
            y *= 0.95;
            rotate.x -= y * 0.1;
            rotate.y += x * 0.05;
            wrap.style.transform = 'rotateX(' + rotate.x + 'deg) rotateY(' + rotate.y + 'deg)';
            // 小于1停止动画
            if (Math.abs(x) > 1 || Math.abs(y) > 1) {
                rafId = requestAnimationFrame(step);
            }
        }
        rafId = requestAnimationFrame(step);
    }

    原文 https://juejin.cn/post/6986553684096204807

  • 相关阅读:
    数据库的单表查询Ⅰ
    数据库的基本操作Ⅲ
    数据库基本操作Ⅱ
    数据库的基本操作Ⅰ
    MYSQL的三种安装方式
    操作系统学期小结二
    操作系统学期小结一
    MAP接口课堂练习
    关于list接口和set接口的示例应用
    课堂作业整理三 (集合:list接口)
  • 原文地址:https://www.cnblogs.com/chenzxl/p/15485237.html
Copyright © 2011-2022 走看看