简介:
关于手势进行顺/逆时钟滑动的判断,此方案不局限于使用 PixiJs 才能完成,只要能够获取到手势坐标即可。
思路:
在页面上默认设置一个中心点
利用 touch 事件的特性,在 touchmove 触发时,计算手势的触摸点到中心点连线与上次触发时二者夹角变化值,并进行记录
在触发结束时进行统计或者计算,进而判断方向
核心部分:
关于 touch 事件的触发机制(80行到110行)
夹角、角度的计算
代码:
<!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度)
代码:
代码已经上传,审核中后续会同步地址