console
const svg = document.querySelector("#svg");
const rad = Math.PI / 180;
const max = 200;
let requestId = null;
let t = {
x: 25,
y: 25
};
let mouseAngle = 0;
let deltaAngle = mouseAngle;
class Point {
constructor(angle, elmt) {
this.a = 0;
this.elmt = elmt;
this.angle = angle;
this.x = 20 * Math.cos(this.angle);
this.y = 20 * Math.sin(this.angle);
this.vel = 0;
}
draw() {
this.elmt.setAttribute("cx", this.x);
this.elmt.setAttribute("cy", this.y);
}
updateAngle(target) {
let spring = 3 * rad - deltaAngle / 120;
this.dist = target - this.a;
this.acc = this.dist * spring;
this.vel += this.acc;
this.vel *= 0.80;
this.a += this.vel;
}
getAngle() {
this.angle = Math.atan2(this.y, this.x);
}
rotate() {
let cos = Math.cos(this.vel);
let sin = Math.sin(this.vel);
let p = {
x: this.x,
y: this.y
};
this.x = p.x * cos - p.y * sin;
this.y = p.x * sin + p.y * cos;
}
}
let p = new Point(0, A);
function Draw() {
requestId = window.requestAnimationFrame(Draw);
p.updateAngle(deltaAngle);
p.rotate();
p.draw();
}
Draw();
svg.addEventListener("click", function(e) {
mouseAngle = getMouseAngle(e, t);
number.value = getAngleInPercents(mouseAngle);
contT.innerText = number.value;
contT.innerText += ' X:' + e.clientX + ' Y:' + e.clientY;
tinput.value = number.value;
onEvent();
},
false);
number.addEventListener("input", function(e) {
mouseAngle = map(number.value, 0, max, 0, 360) * rad;
onEvent();
},
false);
function onEvent() {
if (requestId) {
cancelAnimationFrame(requestId);
requestId = null;
}
p.getAngle();
if (p.angle < mouseAngle - Math.PI) {
p.angle = p.angle + 2 * Math.PI;
}
if (p.angle > mouseAngle + Math.PI) {
p.angle = p.angle - 2 * Math.PI;
}
deltaAngle = mouseAngle - p.angle;
p.a = 0;
p.dist = 0;
p.vel = 0;
p.acc = 0;
Draw();
}
function oMousePosSVG(e) {
let p = svg.createSVGPoint();
p.x = e.clientX;
p.y = e.clientY;
let ctm = svg.getScreenCTM().inverse();
p = p.matrixTransform(ctm);
return p;
}
function transformedMousePos(e, t) {
let m = oMousePosSVG(e);
return {
x: m.x - t.x,
y: m.y - t.y
};
}
function getMouseAngle(e, t) {
let m = transformedMousePos(e, t);
return Math.atan2(m.y, m.x);
}
function getAngleInPercents(angle) {
let A = angle < 0 ? (angle + 2 * Math.PI) / rad: angle / rad;
return map(A, 0, 360, 0, max);
}
function map(n, a, b, _a, _b) {
var d = b - a;
var _d = _b - _a;
var u = _d / d;
return _a + n * u;
}
tinput.addEventListener("keyup", function(e){
number.value = tinput.value || 0;
mouseAngle = map(number.value, 0, max, 0, 360) * rad;
onEvent();
});
svg.addEventListener("touchstart", function(e) {
});
svg.addEventListener("touchmove", function(e) {
e = e.changedTouches[0];
mouseAngle = getMouseAngle(e, t);
number.value = getAngleInPercents(mouseAngle);
contT.innerText = number.value;
tinput.value = number.value;
onEvent();
});
<div style="position:relative; width:220px;height:220px;margin:auto">
<div id="cont">
<input id="number" type="range" value="0" min="0" max="200">
</div>
<div id="contT">
</div>
<svg id="svg" viewBox="0 0 50 50">
<defs>
<linearGradient x1="1" y1="0" x2="0" y2="0" id="gradient1">
<stop offset="3%" stop-color="#5d6aff">
</stop>
<stop offset="98%" stop-color="#a3a8e7">
</stop>
</linearGradient>
</defs>
<g transform="translate(25 25)">
<circle r="20" stroke="url('#gradient1')" stroke-width="4" fill="none"
fill-opacity="0.8" />
<circle r="18.6" fill="url('#gradient1')" fill-opacity="0.8" />
<circle class="point" id="A" r="2" />
<text x="-7" y="-6" class="title" font-size="2.5">
收缩压 (高压)
</text>
<text x="-12.5" y="8" class="title" font-size="2.5">
标准值:90-140mmHg
</text>
</g>
</svg>
<input type="number" class="form-control tt-input" id="tinput">
</div>
#svg {
width: 220px;
height: 220px;
margin: 0 auto;
display: block;
}
.point {
fill: #ffffff;
}
.title {
fill: #fff;
}
.form-control {
outline: none;
text-align: center;
border: 1px solid #ffffff;
border-radius: 100px;
width: 70px;
height: 27px;
}
.tt-input {
position: absolute;
top: 170px;
left: 80px;
background: transparent;
color: #fff;
}
#contT{
min-height: 47px;
display: block;
}