🎉 添加工具类的说明文档
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