FONGHOKCUNG
2023/4/20
Dynamic
- 斐波那契数列
- LIS, LCS
- 零钱兑换
2023/3/7
dataset
```
<div id="test" data-mydata="test">自定义属性data-</div>
let t = document.querySelector("#test");
t.setAttribute("data-test", "js-insert");
let t = document.querySelector("#test");
t.setAttribute("data-test", "js-insert");
console.log(t.getAttribute("data-mydata"));
let t = document.querySelector("#test");
t.setAttribute("data-test", "js-insert");
console.log(t.dataset["mydata"]); // test
console.log(t.dataset["test"]); // js-insert
```
> 浏览器会自动把data-*的属性名转为小写
矩形包围盒碰撞检测
https://heptaluan.github.io/2020/11/28/Essay/31/ https://heptaluan.github.io/demos/example/blog/OBB.html
针对于这种情况,两个矩形的 OBB 检测我们可以使用分离轴定理(Separating Axis Theorem)来进行解决,所谓分离轴定理,即通过判断任意两个矩形在『任意角度下的投影是否均存在重叠』来判断是否发生碰撞
如果两个多边形在所有轴上的投影都发生重叠,则判定为碰撞,否则没有发生碰撞
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OBB</title>
<style>
.a, .b {
width: 350px;
height: 150px;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
}
.a {
background: lightslategray;
top: 355px;
left: 171px;
}
.b {
background: lightseagreen;
transform: rotate(40deg);
top: 220px;
left: 400px;
}
</style>
</head>
<body>
<div class="box">
<div>元素 A 与 B 是否相交,<span class="text">true</span></div>
<br>
<button class="aBtn">调整 A 与 B 相交</button>
<button class="bBtn">调整 A 与 B 分离</button>
</div>
<div class="a">A</div>
<div class="b">B</div>
<script>
// OBB 算法
class OBB {
constructor(centerPoint, width, height, rotation) {
this.centerPoint = centerPoint
this.extents = [width / 2, height / 2]
this.axes = [new Vector2(Math.cos(rotation), Math.sin(rotation)), new Vector2(-1 * Math.sin(rotation), Math.cos(rotation))]
this._width = width
this._height = height
this._rotation = rotation
}
getProjectionRadius(axis) {
return this.extents[0] * Math.abs(axis.dot(this.axes[0])) + this.extents[1] * Math.abs(axis.dot(this.axes[1]))
}
}
class Vector2 {
constructor(x, y) {
this.x = x || 0
this.y = y || 0
}
sub(v) {
return new Vector2(this.x - v.x, this.y - v.y)
}
dot(v) {
return this.x * v.x + this.y * v.y
}
}
const detectorOBBvsOBB = (OBB1, OBB2) => {
var nv = OBB1.centerPoint.sub(OBB2.centerPoint)
var axisA1 = OBB1.axes[0]
if (OBB1.getProjectionRadius(axisA1) + OBB2.getProjectionRadius(axisA1) <= Math.abs(nv.dot(axisA1))) return false
var axisA2 = OBB1.axes[1]
if (OBB1.getProjectionRadius(axisA2) + OBB2.getProjectionRadius(axisA2) <= Math.abs(nv.dot(axisA2))) return false
var axisB1 = OBB2.axes[0]
if (OBB1.getProjectionRadius(axisB1) + OBB2.getProjectionRadius(axisB1) <= Math.abs(nv.dot(axisB1))) return false
var axisB2 = OBB2.axes[1]
if (OBB1.getProjectionRadius(axisB2) + OBB2.getProjectionRadius(axisB2) <= Math.abs(nv.dot(axisB2))) return false
return true
}
// 测试使用
function getElement() {
const rectOneClientRect = document.querySelector('.a').getBoundingClientRect()
const rectTwoClientRect = document.querySelector('.b').getBoundingClientRect()
const OBB1Options = {
x: rectOneClientRect.left + rectOneClientRect.width / 2,
y: rectOneClientRect.top + rectOneClientRect.height / 2,
w: 350,
h: 150,
r: 0
}
const OBB2Options = {
x: rectTwoClientRect.left + rectTwoClientRect.width / 2,
y: rectTwoClientRect.top + rectTwoClientRect.height / 2,
w: 350,
h: 150,
r: 220
}
return {
OBB1: new OBB(new Vector2(OBB1Options.x, OBB1Options.y), OBB1Options.w, OBB1Options.h, OBB1Options.r * Math.PI / 180),
OBB2: new OBB(new Vector2(OBB2Options.x, OBB2Options.y), OBB2Options.w, OBB2Options.h, OBB2Options.r * Math.PI / 180)
}
}
// ========================================================
// ========================================================
// ========================================================
// 测试使用
aBtn = document.querySelector('.aBtn')
bBtn = document.querySelector('.bBtn')
const { OBB1, OBB2 } = getElement()
document.querySelector('.text').innerHTML = detectorOBBvsOBB(OBB1, OBB2)
aBtn.addEventListener('click', function () {
document.querySelector('.a').style.top = 340 + 'px'
const { OBB1, OBB2 } = getElement()
document.querySelector('.text').innerHTML = detectorOBBvsOBB(OBB1, OBB2)
}, false)
bBtn.addEventListener('click', function () {
document.querySelector('.a').style.top = 355 + 'px'
const { OBB1, OBB2 } = getElement()
document.querySelector('.text').innerHTML = detectorOBBvsOBB(OBB1, OBB2)
}, false)
</script>
</body>
</html>