使指标绕一圈移动



我试图想出一些JS(纯JS(代码,使指示器在移动引脚时绕圈移动(就好像它是一个速度表(,但我失败了。我尝试使用偏移量,计算偏移量等,但它不起作用。请问谁能帮我?

如果有其他方法可以在不使用一些额外库的情况下做到这一点(例如,仅使用 css 选项(,请告诉我 - 我将不胜感激,因为理解这里的概念对我来说非常重要!

'use strict';
let firstIndicator = document.querySelector('.indicator');
let pinLevel = document.querySelector('.effect-level__pin');
let effectLevelLine = document.querySelector('.effect-level__line');
let effectLevelDepth = document.querySelector('.effect-level__depth');
let changeOverlay = function (percentage) {
pinLevel.style.left = percentage + '%';
effectLevelDepth.style.width = percentage + '%';
};
pinLevel.addEventListener('mousedown', function (evt) {
evt.preventDefault();
let startX = evt.clientX;
let startLevelDepthWidth = effectLevelDepth.offsetWidth;
let clickedPercentageLevel = startLevelDepthWidth / effectLevelLine.offsetWidth * 100;
changeOverlay(clickedPercentageLevel);
let onMouseMove = function (moveEvt) {
moveEvt.preventDefault();
let shift = moveEvt.clientX - startX;
let levelWidth = startLevelDepthWidth + shift;
let movedPercentageLevel = levelWidth / effectLevelLine.offsetWidth * 100;
movedPercentageLevel = Math.max(0, movedPercentageLevel);
movedPercentageLevel = Math.min(100, movedPercentageLevel);
changeOverlay(movedPercentageLevel);
firstIndicator.style.top = (firstIndicator.offsetHeight * 3) - (movedPercentageLevel / 100) + 'px';
	firstIndicator.style.transform = 'rotate('+ (52 + movedPercentageLevel * 2.4) + 'deg' + ')';
};
let onMouseUp = function (upEvt) {
upEvt.preventDefault();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
.circle {
margin: 0 auto;
margin-top: 50px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%
}
.indicator {
position: relative;
}
.indicator svg {
position: absolute;
top: -100px;
transform: rotate(82deg);
left: 108px;
}
.effect-level {
position: absolute;
bottom: -30px;
left: 50%;
width: 495px;
height: 33px;
font-size: 12px;
line-height: 42px;
text-align: center;
color: black;
white-space: nowrap;
background-color: #ffffff;
border: none;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
}
.effect-level__value {
display: none;
}
.effect-level__line {
position: absolute;
top: 50%;
right: 20px;
left: 20px;
height: 5px;
font-size: 0;
background-color: rgba(0, 0, 0, 0.2);
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.effect-level__pin {
position: absolute;
top: 50%;
left: 0%;
z-index: 1;
width: 18px;
height: 18px;
margin: -9px 0 0;
background-color: #fff;
border-radius: 50%;
border: 1px solid #323232;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
cursor: move;
}
.effect-level__depth {
position: absolute;
width: 0%;
height: 100%;
background-color: #323232;
}
<div class="circle"></div>
<div class="indicator">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="337.0744522647706 304.4241607573019 28.925547735229372 104" width="24.93" height="100"><defs><path d="" id="c6VRx4235S"></path><path d="M348.07 305.42L338.07 405.42" id="f84HmfmJk"></path><path d="M340.01 305.42L338.07 403.88" id="azVXtGrDR"></path></defs><g><g><g><use xlink:href="#c6VRx4235S" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#f84HmfmJk" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#azVXtGrDR" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g></g>
</svg>
</div>
<fieldset class="effect-level">
<input class="effect-level__value" type="number" name="effect-level" value="0">
<div class="effect-level__line">
<div class="effect-level__pin" tabindex="0">Кнопка изменения эффекта </div>
<div class="effect-level__depth">Глубина эффекта</div>
</div>
</fieldset>

您可以定义.indicator的大小,以便在使用transform: rotate(angle(旋转时,它围绕定义的圆心旋转。

最好将移动元素及其引用定义为位置:绝对,然后有容器div将其放置在您想要的任何位置。

.circle {
position: absolute;
top: 100px;
left: 100px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%;
}
.indicator {
position: absolute;
top: 6px;
left: 155px;
height: 340px;
width: 44px;
transform: rotate(0deg);
}
.indicator svg {
transform: rotate(177deg);
}

这使我们的生活非常轻松,我们只需要根据您的移动百分比水平旋转.indicator。

请查看以下代码片段。

'use strict';
let firstIndicator = document.querySelector('.indicator');
let pinLevel = document.querySelector('.effect-level__pin');
let effectLevelLine = document.querySelector('.effect-level__line');
let effectLevelDepth = document.querySelector('.effect-level__depth');
let changeOverlay = function(percentage) {
pinLevel.style.left = percentage + '%';
effectLevelDepth.style.width = percentage + '%';
};
pinLevel.addEventListener('mousedown', function(evt) {
evt.preventDefault();
let startX = evt.clientX;
let startLevelDepthWidth = effectLevelDepth.offsetWidth;
let clickedPercentageLevel = startLevelDepthWidth / effectLevelLine.offsetWidth * 100;
changeOverlay(clickedPercentageLevel);
let onMouseMove = function(moveEvt) {
moveEvt.preventDefault();
let shift = moveEvt.clientX - startX;
let levelWidth = startLevelDepthWidth + shift;
let movedPercentageLevel = levelWidth / effectLevelLine.offsetWidth * 100;
movedPercentageLevel = Math.max(0, movedPercentageLevel);
movedPercentageLevel = Math.min(100, movedPercentageLevel);
changeOverlay(movedPercentageLevel);
firstIndicator.style.transform = 'rotate(' + movedPercentageLevel * 3.6 + 'deg' + ')';
};
let onMouseUp = function(upEvt) {
upEvt.preventDefault();
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
};
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
});
.circle {
position: absolute;
top: 100px;
left: 100px;
width: 150px;
height: 150px;
border: 1px solid black;
border-radius: 50%;
}
.indicator {
position: absolute;
top: 6px;
left: 155px;
height: 340px;
width: 44px;
transform: rotate(0deg);
}
.indicator svg {
transform: rotate(177deg);
}
.effect-level {
position: absolute;
bottom: -30px;
left: 50%;
width: 495px;
height: 33px;
font-size: 12px;
line-height: 42px;
text-align: center;
color: black;
white-space: nowrap;
background-color: #ffffff;
border: none;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
}
.effect-level__value {
display: none;
}
.effect-level__line {
position: absolute;
top: 50%;
right: 20px;
left: 20px;
height: 5px;
font-size: 0;
background-color: rgba(0, 0, 0, 0.2);
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
.effect-level__pin {
position: absolute;
top: 50%;
left: 0%;
z-index: 1;
width: 18px;
height: 18px;
margin: -9px 0 0;
background-color: #fff;
border-radius: 50%;
border: 1px solid #323232;
-webkit-transform: translateX(-50%);
-ms-transform: translateX(-50%);
transform: translateX(-50%);
cursor: move;
}
.effect-level__depth {
position: absolute;
width: 0%;
height: 100%;
background-color: #323232;
}
<div class="circle"></div>
<div class="indicator">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="337.0744522647706 304.4241607573019 28.925547735229372 104" width="24.93" height="100"><defs><path d="" id="c6VRx4235S"></path><path d="M348.07 305.42L338.07 405.42" id="f84HmfmJk"></path><path d="M340.01 305.42L338.07 403.88" id="azVXtGrDR"></path></defs><g><g><g><use xlink:href="#c6VRx4235S" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#f84HmfmJk" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g><g><g><use xlink:href="#azVXtGrDR" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="1"></use></g></g></g>
</svg>
</div>
<fieldset class="effect-level">
<input class="effect-level__value" type="number" name="effect-level" value="0">
<div class="effect-level__line">
<div class="effect-level__pin" tabindex="0">Кнопка изменения эффекта </div>
<div class="effect-level__depth">Глубина эффекта</div>
</div>
</fieldset>

只是为了好玩,这里有一个更像javascript的风格,不需要任何元素旋转。只是一个圆和一条线,在围绕一个点旋转后重新绘制到新的坐标。

在这里,它只是在鼠标移动时更新,但所需的角度只需要作为偏移量输入到函数中。

'use strict';
// get the canvas element
const canvas = document.getElementById('canvas');
canvas.width = 170;
canvas.height = 170;
canvas.style.background = 'red';
canvas.style.border = '1px solid black';
// somewhere to store the position and state of the needle
const needle = { 
	start_angle: 0,
	current_angle: 0,
	point_x: canvas.width,
	point_y: canvas.height/2 // the 3oclock position is just straight to the right! from the centre of our circle,
}
// handy function to rotate a point about a point. first google result
const rotatePoint = (x, y, centerx, centery, degrees)=>{ // https://stackoverflow.com/a/45649110/2244284
	let newx = (x - centerx) * Math.cos(degrees * Math.PI / 180) - (y - centery) * Math.sin(degrees * Math.PI / 180) + centerx;
	let newy = (x - centerx) * Math.sin(degrees * Math.PI / 180) + (y - centery) * Math.cos(degrees * Math.PI / 180) + centery;
	return [newx, newy];
}
// handy function to convert degrees to radians
const d2r = (degree)=>{
	return degree * (Math.PI / 180);
}
// handy function to draw a circle
const drawCircle = ()=>{
	var ctx = canvas.getContext("2d");
	ctx.beginPath();
	ctx.arc(canvas.width/2, canvas.height/2, canvas.width/2, 0, d2r(360)); // just use the whole canvas
	ctx.stroke(); 
}
// draw our needle
const drawNeedle = (offset)=>{
	let xy = rotatePoint(needle.point_x, needle.point_y, canvas.width/2, canvas.height/2, offset); // point_x/y is the far end of the needle, the other side is just the centre of the circle/canvas
	// draw a line from centre to the new point of the needle
	var ctx = canvas.getContext("2d");
	ctx.beginPath();
	ctx.moveTo(canvas.width/2, canvas.height/2);
	ctx.lineTo(xy[0], xy[1]);
	ctx.stroke(); 
}
// --- init stuff
drawCircle(); // draw first circle
drawNeedle(needle.start_angle); // draw first needle
// add an event for every mouse move detected over the canvas
canvas.addEventListener('mousemove', (e)=>{
	canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height); // clear clear the canvas
	drawCircle(); // redraw the circle
	let offset = needle.start_angle + needle.current_angle++ % 360; // increase angle by 1 for every mouseover event, reset to 0 if a full circle is reached
	drawNeedle(offset) // draw needle
})
<html>
<body>
	<canvas id="canvas"></canvas>
</body>
</html>

最新更新