我正在创建一个具有不同分段的 svg 圆圈,其工作方式类似于用于显示/隐藏内容的选项卡。它基本上是一个饼图。我无法在视觉上区分我正在创建的片段。我需要它从圆的中心到外侧进行描边。我觉得我需要弄清楚 stroke-dasharray 属性?希望得到一些帮助来了解如何配置。
我的其他想法是使用边距来抵消segmentPath函数,但客户不喜欢它的外观。最后有一个想法,即为每个线段添加一个单独的线元素 - 从圆的边缘到中心。任何帮助都会很棒。
/**
* Polar to Cartesian.
*
* Håken Lid's SVG circle segments.
*
* @see https://observablehq.com/@haakenlid/svg-circle
* @see https://blog.logrocket.com/interactive-svg-circle-of-fifths/#arcs-circles
*/
function polarToCartesian(x, y, r, degrees) {
const radians = degrees * Math.PI / 180.0;
return [x + (r * Math.cos(radians)), y + (r * Math.sin(radians))]
}
/**
* Segment Path.
*
* Håken Lid's SVG circle segments.
*
* @see https://observablehq.com/@haakenlid/svg-circle
* @see https://blog.logrocket.com/interactive-svg-circle-of-fifths/#arcs-circles
*/
function segmentPath(x, y, r0, r1, d0, d1) {
const arc = Math.abs(d0 - d1) > 180 ? 1 : 0
const point = (radius, degree) =>
polarToCartesian(x, y, radius, degree)
.map(n => n.toPrecision(5))
.join(',')
return [
`M${point(r0, d0)}`,
`A${r0},${r0},0,${arc},1,${point(r0, d1)}`,
`L${point(r1, d1)}`,
`A${r1},${r1},0,${arc},0,${point(r1, d0)}`,
'Z',
].join('')
}
/**
* Segment Function.
*
* Modified version of Håken Lid's SVG circle segments.
*
* @see https://observablehq.com/@haakenlid/svg-circle
* @see https://blog.logrocket.com/interactive-svg-circle-of-fifths/#arcs-circles
*/
function segment(i, segments, size, radius, width, className, fillColor) {
const center = size/2
const degrees = 360 / segments
const start = degrees * i
const end = (degrees * (i + 1) + 1)
const path = segmentPath(center, center, radius, radius-width, start, end);
const el = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
el.setAttribute(
'd',
path
);
el.classList.add( 'path-segment', className );
el.style.fill = fillColor;
return el;
}
/**
* Render.
*
* Function that will render the svg circle.
*/
function render() {
// Circle Div.
const circleDiv = document.getElementById( 'interactive-circle-svg' );
if ( null !== circleDiv ) {
// Setup environment.
const svgSize = 580
const segments = 6
const segmentWidth = 60
const outerFill = '#FB8D00'
const middleFill = '#E68E36'
const innerFill = '#F9B46F'
// Set cirlce div attributes.
circleDiv.style.height = svgSize + 'px';
circleDiv.style.width = svgSize + 'px';
circleDiv.style.transform = `rotate(${ 360/2 }deg)`
circleDiv.style.transformOrigin = '50% 50%'
// SVG NS.
const svgns = 'http://www.w3.org/2000/svg';
// Create the <svg>.
const svg = document.createElementNS( svgns, 'svg' )
svg.setAttribute( 'viewbox', `0 0 ${svgSize} ${svgSize}` );
svg.setAttribute( 'overflow', 'visible' );
svg.setAttribute( 'stroke', '#000' );
svg.setAttribute( 'stroke-width', 3 );
// Attach the children nodes.
for ( let i = 0; i < segments; i++ ) {
// Create the first <g>.
let n = i + 1,
radius1 = svgSize/2,
radius2 = svgSize/2-segmentWidth+1,
radius3 = svgSize/2-(segmentWidth*2)+2,
g1 = document.createElementNS( svgns, 'g' );
g1.classList.add( 'segment', `segment-${n}` );
g1.setAttribute( 'data-segment-number', n );
// Attach segments to the <g>.
g1.appendChild( segment( i, segments, svgSize, radius1, segmentWidth, 'outer', outerFill ) );
g1.appendChild( segment( i, segments, svgSize, radius2, segmentWidth, 'middle', middleFill ) );
g1.appendChild( segment( i, segments, svgSize, radius3, segmentWidth, 'inner', innerFill ) );
// Attach the <g> to the <svg>
svg.appendChild( g1 );
// Create event handlers with the g1.
g1.addEventListener( 'click', function(e){
const segNumber = this.getAttribute( 'data-segment-number' );
// Hide bodies.
const bodies = document.getElementsByClassName( 'segment-body' )
for ( let i = 0; i < bodies.length; i++ ) {
if ( ! bodies[i].classList.contains( 'hide' ) ) {
bodies[i].classList.add( 'hide' );
}
}
// Show correct body.
const body = document.getElementById( 'segment-body-' + segNumber);
body.classList.remove( 'hide' );
});
}
// Attach to div.
circleDiv.append( svg );
}
}
// Attach render to onload.
window.onload = render;
<div id="interactive-circle-svg"></div>
根据提供的代码,实现所需的功能,将线元素添加到从圆心到圆边缘的每个线段,这段代码,
g1.appendChild( segment( i, segments, svgSize, radius3, segmentWidth, 'inner', innerFill ) );
应替换为此代码,
g1.appendChild( segment( i, segments, svgSize, radius3, radius3, 'inner', innerFill ) );
可以检查一下是否有效。