计算圆 SVG 内路径末端的 x 和 y
Calculate the x and y for end of path within a circle SVG
我有一个进度条,正在通过更改路径的 stroke-dashoffset
属性 来更新。但是,每次更新时,我都需要计算海军路径端点(圆边)的 x 和 y 坐标。我将来会在这些点上添加标签。一段时间以来,我一直在为这个问题苦思冥想。我曾尝试使用类似于 const x = radius * Math.sin(Math.PI * 2 * angle / 360);
和 const y = radius * Math.cos(Math.PI * 2 * angle / 360);
的东西,但我认为我没有正确使用它们。有人可以帮助我吗?旁注我只使用 Vanilla JS。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e)
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
</g>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>
SVG 提供了一种关于 <path>
元素的方法,您会在此处发现它非常有用:
myPath.getPointAtLength(len)
示例如下。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const showEndPoint = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
// Get the X,Y position of a point at "dashOffset" along the path
const pt = document
.getElementById('progress-meter')
.getPointAtLength(dashOffset);
// Update our red dot to show the location
// Note that we are switching X and Y here to compensate for the fact that you rotate the original path
const endpoint = document.getElementById('endpoint')
endpoint.setAttribute('cx', pt.y);
endpoint.setAttribute('cy', pt.x);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e);
showEndPoint(e);
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
</g>
<circle id="endpoint" r="3" fill="red"/>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>
这里是您的 SVG 的一个略微修改版本,它避免了切换 X 和 Y 坐标的必要性 - 如前一版本的代码中所述。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const showEndPoint = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
// Get the X,Y position of a point at "dashOffset" along the path
const path = document.getElementById('progress-meter');
const pt = path.getPointAtLength(path.getTotalLength() - dashOffset);
// Update our red dot to show the location
const endpoint = document.getElementById('endpoint')
endpoint.setAttribute('cx', pt.x);
endpoint.setAttribute('cy', pt.y);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e);
showEndPoint(e);
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
transform: rotate(90deg);
transform-origin: center;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<circle id="endpoint" r="3" fill="red"/>
</g>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>
我有一个进度条,正在通过更改路径的 stroke-dashoffset
属性 来更新。但是,每次更新时,我都需要计算海军路径端点(圆边)的 x 和 y 坐标。我将来会在这些点上添加标签。一段时间以来,我一直在为这个问题苦思冥想。我曾尝试使用类似于 const x = radius * Math.sin(Math.PI * 2 * angle / 360);
和 const y = radius * Math.cos(Math.PI * 2 * angle / 360);
的东西,但我认为我没有正确使用它们。有人可以帮助我吗?旁注我只使用 Vanilla JS。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e)
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
</g>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>
SVG 提供了一种关于 <path>
元素的方法,您会在此处发现它非常有用:
myPath.getPointAtLength(len)
示例如下。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const showEndPoint = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
// Get the X,Y position of a point at "dashOffset" along the path
const pt = document
.getElementById('progress-meter')
.getPointAtLength(dashOffset);
// Update our red dot to show the location
// Note that we are switching X and Y here to compensate for the fact that you rotate the original path
const endpoint = document.getElementById('endpoint')
endpoint.setAttribute('cx', pt.y);
endpoint.setAttribute('cy', pt.x);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e);
showEndPoint(e);
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
transform: rotate(90deg);
transform-origin: center;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
</g>
<circle id="endpoint" r="3" fill="red"/>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>
这里是您的 SVG 的一个略微修改版本,它避免了切换 X 和 Y 坐标的必要性 - 如前一版本的代码中所述。
const setStrokeDashOffset = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
document
.getElementById('progress-meter')
.setAttribute('stroke-dashoffset', dashOffset);
}
const showEndPoint = (e) => {
const dashOffset = e.target.getAttribute('data-attr');
// Get the X,Y position of a point at "dashOffset" along the path
const path = document.getElementById('progress-meter');
const pt = path.getPointAtLength(path.getTotalLength() - dashOffset);
// Update our red dot to show the location
const endpoint = document.getElementById('endpoint')
endpoint.setAttribute('cx', pt.x);
endpoint.setAttribute('cy', pt.y);
}
const btn = document.querySelectorAll('button');
btn.forEach(x => {
x.addEventListener('click', (e) => {
setStrokeDashOffset(e);
showEndPoint(e);
});
});
.donut-progress__svg {
transform: scaleX(-1);
}
.donut-progress__circle {
fill: none;
stroke: none;
transform: rotate(90deg);
transform-origin: center;
}
.donut-progress__path-elapsed {
stroke: #aaaaaa;
stroke-width: 10;
}
.donut-progress__path-remaining {
stroke: navy;
stroke-linecap: round;
stroke-width: 10;
transition: 0.3s linear all;
}
.donut-progress__path-start {
stroke: orange;
stroke-linecap: round;
stroke-width: 10;
}
<svg id="donut-progress__svg" class="donut-progress__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g class="donut-progress__circle">
<circle class="donut-progress__path-elapsed" cx="50" cy="50" r="45"></circle>
<path id="progress-meter" stroke-dasharray="283 283" stroke-dashoffset="165.08333333333334" class="donut-progress__path-remaining" stroke="#4764ae" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<path opacity="1" id="progress-meter-start" class="donut-progress__path-start" stroke-dashoffset="282" stroke-dasharray="283" d="
M 50, 50
m -45, 0
a 45,45 0 1,0 90,0
a 45,45 0 1,0 -90,0
"></path>
<circle id="endpoint" r="3" fill="red"/>
</g>
</svg>
<button data-attr="100" class="one">move to 100</button>
<button data-attr="150" class="one">move to 150</button>
<button data-attr="200" class="one">move to 200</button>