gpt4 book ai didi

javascript - 用于范围输入的 SVG 弧形 slider

转载 作者:行者123 更新时间:2023-12-05 01:07:40 27 4
gpt4 key购买 nike

我的目标是设计一个看起来像这样的弧形 slider

enter image description here

我的模板结构如下

<svg width="500" height="300">
<path id="track" stroke="lightgrey" fill="transparent" stroke-width="20" d="
M 50 50
A 90 90 0 0 0 300 50
"/>
<path id="trackFill" fill="cyan" stroke-width="20" d="
M 50 50
A 90 90 0 0 0 [some dynamic value?] [some dynamic value?]
"/>
<circle id="knob" fill="lightblue" cx="[dynamic, initial - 50]" cy="[dynamic, initial - 50]" r="25"/>
</svg>

knob - 用户应该拖动以更改值的控件

track - 幻灯片的完整弧线

trackFill - 旋钮之前的 slider 路径部分

是否可以使 trackFill 在沿 slider 曲线拖动时覆盖旋钮之前的 slider 部分?如果是这样,哪些 API 或 CSS 规则将帮助我实现这样的结果?

最佳答案

你追求的是这样的吗?

let svg = document.getElementById("slider");
let trackFill = document.getElementById("trackFill");
let knob = document.getElementById("knob");
let isDragging = false;
let sliderDragOffset = {dx: 0, dy: 0};
let ARC_CENTRE = {x: 175, y: 50};
let ARC_RADIUS = 125;

let sliderValue = 0;
setSliderValue(sliderValue);


function setSliderValue(value)
{
// Limit value to (0..sliderMax)
let sliderMax = track.getTotalLength();
sliderValue = Math.max(0, Math.min(value, sliderMax));
// Calculate new position of knob
let knobRotation = sliderValue * Math.PI / sliderMax;
let knobX = ARC_CENTRE.x - Math.cos(knobRotation) * ARC_RADIUS;
let knobY = ARC_CENTRE.y + Math.sin(knobRotation) * ARC_RADIUS;
// Adjust trackFill dash patter to only draw the portion up to the knob position
trackFill.setAttribute("stroke-dasharray", sliderValue + " " + sliderMax);
// Update the knob position
knob.setAttribute("cx", knobX);
knob.setAttribute("cy", knobY);
}


knob.addEventListener("mousedown", evt => {
isDragging = true;
// Remember where we clicked on knob in order to allow accurate dragging
sliderDragOffset.dx = evt.offsetX - knob.cx.baseVal.value;
sliderDragOffset.dy = evt.offsetY - knob.cy.baseVal.value;
// Attach move event to svg, so that it works if you move outside knob circle
svg.addEventListener("mousemove", knobMove);
// Attach move event to window, so that it works if you move outside svg
window.addEventListener("mouseup", knobRelease);
});


function knobMove(evt)
{
// Calculate adjusted drag position
let x = evt.offsetX + sliderDragOffset.dx;
let y = evt.offsetY + sliderDragOffset.dy;
// Position relative to centre of slider arc
x -= ARC_CENTRE.x;
y -= ARC_CENTRE.y;
// Get angle of drag position relative to slider centre
let angle = Math.atan2(y, -x);
// Positions above arc centre will be negative, so handle them gracefully
// by clamping angle to the nearest end of the arc
angle = (angle < -Math.PI / 2) ? Math.PI : (angle < 0) ? 0 : angle;
// Calculate new slider value from this angle (sliderMaxLength * angle / 180deg)
setSliderValue(angle * track.getTotalLength() / Math.PI);
}


function knobRelease(evt)
{
// Cancel event handlers
svg.removeEventListener("mousemove", knobMove);
window.removeEventListener("mouseup", knobRelease);
isDragging = false;
}
<svg id="slider" width="500" height="300">
<g stroke="lightgrey">
<path id="track" fill="transparent" stroke-width="20" d="
M 50 50
A 125 125 0 0 0 300 50
"/>
</g>
<use id="trackFill" xlink:href="#track" stroke="cyan"/>
<circle id="knob" fill="lightblue" cx="50" cy="50" r="25"/>
</svg>

为了清楚起见,我使这段代码保持简单,但以牺牲一些限制为代价。

假设每页只有一个 slider 。如果您需要更多,则必须将 slider 特定的值(例如,sliderValue 和 isDragging)分开。您可以为此使用数据属性。您还需要从通过 id 属性访问 SVG 元素切换到另一种方式(例如 class 属性),因为 id 属性在页面上必须是唯一的。

关于javascript - 用于范围输入的 SVG 弧形 slider ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67111347/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com