天天看點

PixiJS案例——順逆時鐘判斷

簡介:

關于手勢進行順/逆時鐘滑動的判斷,此方案不局限于使用 PixiJs 才能完成,隻要能夠擷取到手勢坐标即可。

思路:

  1. 在頁面上預設設定一個中心點
  1. 利用 touch 事件的特性,在 touchmove 觸發時,計算手勢的觸摸點到中心點連線與上次觸發時二者夾角變化值,并進行記錄
  1. 在觸發結束時進行統計或者計算,進而判斷方向

核心部分:

  1. 關于 touch 事件的觸發機制(80行到110行)
  1. 夾角、角度的計算

代碼:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta content="a1z51.23600852" name="spm-id" />
    <title>
        判斷順逆時鐘
    </title>
    <script src="./lib/zepto.min.js?t=1500513648235"></script>
    <script src="./lib/vue.min.js?t=1502325746688"></script>
    <script src="./lib/veryless.js?t=1502325746688"></script>
    <script src="./lib/pixi.js?t=1502325746688"></script>
    <style>
        html,
        body {
            position: relative;
            height: 100%;
        }

        body {
            background: #eee;
            font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
            font-size: 1rem;
            color: #000;
            margin: 0;
            padding: 0;
        }

        canvas {
            width: 100%;
            height: 100%;

        }
    </style>
</head>

<body>
    <div id="app">
        <div class="title_name">PIXI 判斷順逆時鐘</div>
        <div class="piximove" id="pixijs"></div>
        <div class="direction_01">第一種模式:{{direction_01}}</div>
        <div class="direction_02">第二種模式:{{direction_02}}</div>
        <button class="test_01" @click="test()">測試</button>
    </div>
    <script>
        //vue
        $(document).ready(() => {
            var app = new Vue({
                el: "#app",
                data() {
                    return {
                        frameStage: null, //舞台
                        direction_01:true,
                        direction_02:true,
                    }
                },
                methods: {
                    //初始化方法
                    Application() {
                        //建立一個Application,設定長寬
                        this.frameStage = new PIXI.Application({
                            width: 600,
                            height: 600,
                            // backgroundColor: 0x55FF55,
                            backgroundAlpha: 1, //是否透明
                            antialias: true //設定抗鋸齒
                            // forceCanvas: true //阻止選擇WebGL渲染器
                        });

                        console.log(this.frameStage);

                        //将舞台添加到DOM元素中
                        document.getElementById("pixijs").appendChild(this.frameStage.view);

                        // 添加一個操作矩形 用來操作
                        const graphics = new PIXI.Graphics();

                        graphics.beginFill(0x55FF55);
                        graphics.drawCircle(300, 300, 250);
                        graphics.endFill();

                        // **************************** //
                        // 需要定義的變量
                        let angle = 0; // 記錄角度
                        let angleArr = []; // 記錄角度變化

                        graphics.interactive = true;
                        graphics.on('touchstart', async (ev) => {
                            // 需要取到合理的坐标點和原點
                            angleArr = [];
                            angle = this.getAngle(300, 300, ev.screen.x, ev.screen.y);
                        });
                        graphics.on('touchmove', async (ev) => {
                            // 需要取到合理的坐标點和原點
                            let now_angle = this.getAngle(300, 300, ev.screen.x, ev.screen.y);
                            angleArr.push(this.getDifferenceAngle(now_angle, angle))
                            angle = now_angle
                        });
                        graphics.on('touchend', async (ev) => {
                            // 需要取到合理的坐标點和原點
                            let now_angle = this.getAngle(300, 300, ev.screen.x, ev.screen.y);
                            angleArr.push(this.getDifferenceAngle(now_angle, angle));
                            console.log('是否為順時鐘:', this.judgeDirection(angleArr));
                        });

                        // **************************** //

                        this.frameStage.stage.addChild(graphics);
                        // console.log(this.getAngle(300,300,300,500))
                        // let a = this.getDifferenceAngle(-20, 45);
                        // console.log(a);
                    },
                    test() {
                        // this.frameStage.destroy(true, true);
                        // this.frameStage.renderer.transparent = true;
                        // this.frameStage.renderer.reset();
                        // console.log(this.frameStage.renderer.transparent)
                        // this.frameStage.renderer.backgroundColor = '0x550fff';
                        this.test1(12, "xx", "11", "222")
                    },
                    // 計算兩個點組成直線的角度 x1,y1 為原點
                    getAngle(x1, y1, x2, y2) {
                        return Math.atan2((y2 - y1), (x2 - x1)) * (180 / Math.PI);
                    },
                    // 計算出兩個角度之間的小內插補點 angle1為現在的角度 angle2為之前的角度
                    getDifferenceAngle(angle1, angle2) {
                        let difference = (angle1 + 360) % 360 - (angle2 + 360) % 360;
                        if (difference <= -180) difference += 360;
                        if (difference > 180) difference -= 360;
                        return difference;
                    },
                    // 判斷順逆時鐘
                    // 第一種判斷模式:變化率個數累計(這種方式有一定的漏洞在裡面.例如:先快速的逆時鐘,然後慢慢的順時針往回走,最終不超過原來的位置,這裡的邏輯會錯誤的判斷為順時鐘)
                    // 第二種判斷模式:變化率大小累計
                    judgeDirection(arr) {
                        let clockwise = 0; // 順時鐘
                        let counterclockwise = 0; // 逆時鐘
                        let change = 0
                        arr.forEach(item => {
                            change += item;
                            if (item >= 0) clockwise += 1;
                            if (item < 0) counterclockwise += 1;
                        });
                        // 第一種模式
                        let direction_01 = clockwise >= counterclockwise ? true : false;
                        // 第二種模式
                        let direction_02 = change >= 0 ? true : false;
                        this.direction_01 = direction_01;
                        this.direction_02 = direction_02;
                        console.log(`判斷順逆時鐘:模式一 ${direction_01} 模式二 ${direction_02}`)
                        return direction_01;
                    },
                    test1() {
                        
                    }
                },
                mounted() {
                    this.Application();
                }

            })
        })
    </script>

    <style>
        .piximove {
            position: absolute;
            height: 8rem;
            width: 8rem;
            left: 1rem;
            top: 1rem;
            background-color: red;
        }
        .direction_01{
            position: absolute;
            width: 6rem;
            height: 1rem;
            top: 10rem;
            left: 2rem;
            text-align: center;
            font-size: 0.5rem;
            line-height: 1rem;
            background-color: rgba(255, 0, 0, .8);
        }
        .direction_02{
            position: absolute;
            width: 6rem;
            height: 1rem;
            top: 12rem;
            left: 2rem;
            text-align: center;
            font-size: 0.5rem;
            line-height: 1rem;
            background-color: rgba(255, 0, 0, .8);
        }

        .test_01 {
            position: absolute;
            width: 2rem;
            height: 1rem;
            bottom: 0rem;
            left: 0rem;
            text-align: center;
            font-size: 0.5rem;
            /*color: rgba(255,0,0,.8);*/
            line-height: 1rem;
            background-color: rgba(255, 0, 0, .8);
        }

        .test_02 {
            position: absolute;
            width: 2rem;
            height: 1rem;
            bottom: 0rem;
            left: 3rem;
            text-align: center;
            font-size: 0.5rem;
            /*color: rgba(255,0,0,.8);*/
            line-height: 1rem;
            background-color: rgba(255, 255, 0, .8);
        }

        .test_03 {
            position: absolute;
            width: 2rem;
            height: 1rem;
            bottom: 0rem;
            left: 6rem;
            text-align: center;
            font-size: 0.5rem;
            /*color: rgba(255,0,0,.8);*/
            line-height: 1rem;
            background-color: rgba(0, 255, 0, .8);
        }

        .test_04 {
            position: absolute;
            width: 2rem;
            height: 1rem;
            bottom: 2rem;
            left: 6rem;
            text-align: center;
            font-size: 0.5rem;
            /*color: rgba(255,0,0,.8);*/
            line-height: 1rem;
            background-color: rgba(0, 255, 0, .8);
        }

        .title_name {
            position: absolute;
            width: 10rem;
            height: 1rem;
            left: 0;
            top: 0;
            background-color: rgba(255, 255, 255, 0.2);
            font-size: 0.5rem;
            line-height: 1rem;
            text-align: center;
        }
    </style>

</body>

</html>
           

異常:

在整個案例中有一個漏洞,那就是我們預設了,從 a 角度到 b 角度永遠走的是短的路徑(假如從0度變化到90度,我們永遠預設時順時針走了90度,不會了解為是逆時鐘走了270度)

代碼:

代碼已經上傳,稽核中後續會同步位址

https://download.csdn.net/download/xiechao_5800/87387729