🎉 添加工具类的说明文档
This commit is contained in:
parent
be91c65c89
commit
fd5bcd163b
266
src/main/java/demo/1.html
Normal file
266
src/main/java/demo/1.html
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="author" content="Vasanth.V" />
|
||||||
|
<meta name="theme-color" content="#FFFFFF" />
|
||||||
|
|
||||||
|
<title>xxxx</title>
|
||||||
|
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, "Helvetica Neue", sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
background: #fbf9f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas {
|
||||||
|
display: none;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 640px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: auto;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#canvas svg {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
line-height: 1.75;
|
||||||
|
padding: 0rem 2rem 1rem;
|
||||||
|
color: #2c3d51;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about a {
|
||||||
|
font-weight: 500;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ball {
|
||||||
|
transform: translateZ(0);
|
||||||
|
animation: rot 2000ms infinite linear;
|
||||||
|
animation-play-state: paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ball.started {
|
||||||
|
animation-play-state: running;
|
||||||
|
}
|
||||||
|
|
||||||
|
#play {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#finalscore,
|
||||||
|
#best {
|
||||||
|
font-size: 70%;
|
||||||
|
fill: #34495e;
|
||||||
|
}
|
||||||
|
|
||||||
|
#best {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tip {
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 18%;
|
||||||
|
font-style: italic;
|
||||||
|
padding: 0.5rem 2rem 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#shareBtn {
|
||||||
|
background: #1d9bf0;
|
||||||
|
color: #fff;
|
||||||
|
width: 150px;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 2rem;
|
||||||
|
padding: 0.3rem 1.5rem;
|
||||||
|
margin: 1rem auto 0px;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#shareBtn.hide {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rot {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg) translate(40%) rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg) translate(40%) rotate(-360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<section id="canvas" v-bind:style="'display:flex;'">
|
||||||
|
<svg id="looptap" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||||
|
<rect id="bg" x="0" cy="0" height="100" width="100" fill="none" />
|
||||||
|
<text x="50" y="50" dominant-baseline="middle" text-anchor="middle" class="score" id="score"
|
||||||
|
v-if="state === 'started'" v-html="score"></text>
|
||||||
|
<text x="50" y="32" text-anchor="middle" class="score" id="finalscore" v-if="state === 'stopped'"
|
||||||
|
v-html="score"></text>
|
||||||
|
<text x="50" y="70" text-anchor="middle" class="score" id="best" v-if="state === 'stopped'"
|
||||||
|
v-html="'Best: '+best"></text>
|
||||||
|
<g id="tip" v-if="state === 'init'">
|
||||||
|
<text x="50" y="68" text-anchor="middle" class="tip">
|
||||||
|
点击 ▶️ 开始 / 点击任何地方停止
|
||||||
|
</text>
|
||||||
|
<text x="50" y="74" text-anchor="middle" class="tip">
|
||||||
|
让球停在有颜色的区域就行!
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
<path id="arc" fill="none"
|
||||||
|
v-bind:stroke="colors[Math.floor(score / 10)] || colors[Math.floor((score - 270) / 10)] || '#bdc3c7'"
|
||||||
|
stroke-width="10" stroke-linejoin="round" stroke-linecap="round" v-bind:d="arcDValue" />
|
||||||
|
<circle id="ball" cx="50" cy="50" r="4" fill="#2C3D51" v-bind:class="state"
|
||||||
|
v-bind:style="'animation-duration: '+(2000 - taps * 40) + 'ms'" />
|
||||||
|
<polygon id="play" points="45,45 55,50 45,55" fill="#2C3D51" stroke="#2C3D51" stroke-width="5"
|
||||||
|
stroke-linejoin="round" stroke-linecap="round" v-if="state !== 'started'" v-on:click="startPlay" />
|
||||||
|
</svg>
|
||||||
|
</section>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
const loopTapApp = new Vue({
|
||||||
|
el: "#canvas",
|
||||||
|
data: {
|
||||||
|
arc: [180, 270],
|
||||||
|
taps: 0,
|
||||||
|
score: 0,
|
||||||
|
best: window.localStorage.best || 0,
|
||||||
|
state: "init",
|
||||||
|
prevTapTime: 0,
|
||||||
|
colors: [
|
||||||
|
'#F26D22',
|
||||||
|
'#F1B21D',
|
||||||
|
'#ECE82F',
|
||||||
|
'#AED136',
|
||||||
|
'#7EC242',
|
||||||
|
'#63BC46',
|
||||||
|
'#65BD5D',
|
||||||
|
'#64C29A',
|
||||||
|
'#61C8D2',
|
||||||
|
'#2DAAE1',
|
||||||
|
'#456EB5',
|
||||||
|
'#4451A3',
|
||||||
|
'#6151A2'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
arcDValue: function () {
|
||||||
|
return this.describeArc(50, 50, 40, this.arc[0], this.arc[1]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
polarToCartesian: function (centerX, centerY, radius, angleInDegrees) {
|
||||||
|
const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0;
|
||||||
|
return {
|
||||||
|
x: centerX + radius * Math.cos(angleInRadians),
|
||||||
|
y: centerY + radius * Math.sin(angleInRadians),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
describeArc: function (x, y, radius, startAngle, endAngle) {
|
||||||
|
const start = this.polarToCartesian(x, y, radius, endAngle);
|
||||||
|
const end = this.polarToCartesian(x, y, radius, startAngle);
|
||||||
|
const arcFlag = endAngle - startAngle <= 180 ? "0" : "1";
|
||||||
|
const d = ["M", start.x, start.y, "A", radius, radius, 0, arcFlag, 0, end.x, end.y].join(" ");
|
||||||
|
return d;
|
||||||
|
},
|
||||||
|
|
||||||
|
getAngle: function (cx, cy, ex, ey) {
|
||||||
|
const dy = ey - cy;
|
||||||
|
const dx = ex - cx;
|
||||||
|
let theta = Math.atan2(dx, -dy);
|
||||||
|
theta *= 180 / Math.PI;
|
||||||
|
theta = theta < 0 ? theta + 360 : theta;
|
||||||
|
return theta;
|
||||||
|
},
|
||||||
|
|
||||||
|
getBallAngle: function () {
|
||||||
|
const bg = document.getElementById("bg").getBoundingClientRect();
|
||||||
|
const bgCenter = { x: bg.left + bg.width / 2, y: bg.top + bg.height / 2 };
|
||||||
|
const ball = document.getElementById("ball").getBoundingClientRect();
|
||||||
|
const ballCenter = { x: ball.left + ball.width / 2, y: ball.top + ball.height / 2 };
|
||||||
|
return this.getAngle(bgCenter.x, bgCenter.y, ballCenter.x, ballCenter.y);
|
||||||
|
},
|
||||||
|
|
||||||
|
setArc: function () {
|
||||||
|
const random = (i, j) => Math.floor(Math.random() * (j - i)) + i;
|
||||||
|
arc = [];
|
||||||
|
arc.push(random(0, 300));
|
||||||
|
arc.push(random(arc[0] + 10, arc[0] + 110));
|
||||||
|
arc[1] = arc[1] > 360 ? 360 : arc[1];
|
||||||
|
this.arc = arc;
|
||||||
|
},
|
||||||
|
|
||||||
|
startPlay: function () {
|
||||||
|
this.state = "started";
|
||||||
|
this.taps = 0;
|
||||||
|
this.score = 0;
|
||||||
|
this.prevTapTime = Date.now();
|
||||||
|
},
|
||||||
|
stopPlay: function () {
|
||||||
|
if (this.state === "started") {
|
||||||
|
this.state = "stopped";
|
||||||
|
if (this.score > this.best) window.localStorage.best = this.best = this.score;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
tap: function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (this.state === "started") {
|
||||||
|
const ballAngle = this.getBallAngle();
|
||||||
|
// adding a 6 for better accuracy as the arc stroke extends beyond the angle.
|
||||||
|
if (ballAngle + 6 > this.arc[0] && ballAngle - 6 < this.arc[1]) {
|
||||||
|
const currentTapTime = Date.now();
|
||||||
|
const tapInterval = currentTapTime - this.prevTapTime;
|
||||||
|
this.taps++;
|
||||||
|
if (this.taps >= 28){this.taps = 28;}
|
||||||
|
this.score = this.score + (tapInterval < 500 ? 5 : tapInterval < 1000 ? 2 : 1);
|
||||||
|
this.prevTapTime = currentTapTime;
|
||||||
|
this.setArc();
|
||||||
|
} else this.stopPlay();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if ("ontouchstart" in window) {
|
||||||
|
window.addEventListener("touchstart", loopTapApp.tap);
|
||||||
|
} else {
|
||||||
|
window.addEventListener("mousedown", loopTapApp.tap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user