Reputation: 41
I'm working on an Ionic mobile application, and I need to divide an SVG circle into three equal parts with a focus on responsive design. I've experimented with the element, but I'm facing challenges in achieving both equal division and responsiveness.
Here's a simplified example of what I've attempted:
<svg width="1000" height="1000" viewBox="0 0 1020 1040" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Green Stroke -->
<path
d="M240 120 A120 120 0 0 1 360 240"
stroke="green"
stroke-width="60"
fill="none"
/>
<!-- Red Stroke -->
<path
d="M240 360 A120 120 0 0 1 240 120"
stroke="red"
stroke-width="60"
fill="none"
/>
<!-- Yellow Stroke -->
<path
d="M360 240 A120 120 0 0 1 240 360"
stroke="yellow"
stroke-width="60"
fill="none"
/>
</svg>
I've attached screenshots illustrating the desired outcome. Could anyone provide guidance on adjusting the parameters for both equal parts and responsiveness to achieve a similar look in my Ionic mobile app? Any insights or code examples would be greatly appreciated. Thank you!
Upvotes: 0
Views: 162
Reputation: 57939
Really create an arc is dificult using svg, but we can create a directive.
When an arc is less than 180 degrees it's not dificult and we can do it indicate the point inicial and the point final. But if the arc is greater that 180 degrees we need create two arcs.
Well, we can make a directive in the way
@Directive({
selector: 'path [arc]',
standalone: true,
})
export class SvgArc {
radius: number = 0;
center: { x: number; y: number } = { x: 0, y: 0 };
range: { from: number; to: number } = { from: 0, to: 0 };
@Input('radius') set _radius(value: number | string) {
this.radius = +value;
this.calculatePath();
}
@Input('center') set _center(value: { x: number; y: number }) {
this.center = { x: value.x, y: value.y };
this.calculatePath();
}
@Input('range') set _range(value: { from: number; to: number }) {
this.range = { from: value.from, to: value.to };
this.calculatePath();
}
constructor(private element: ElementRef) {}
calculatePath() {
const [ang1, ang2] = [
this.range.from < this.range.to ? this.range.from : this.range.from - 360,
this.range.to,
];
const point1 = {
x: this.center.x + this.radius * Math.cos((Math.PI / 180) * ang1),
y: this.center.y + this.radius * Math.sin((Math.PI / 180) * ang1),
};
const point2 = {
x: this.center.x + this.radius * Math.cos((Math.PI / 180) * ang2),
y: this.center.y + this.radius * Math.sin((Math.PI / 180) * ang2),
};
if (Math.abs(ang1 - ang2) <= 180) {
this.element.nativeElement.setAttribute(
'd',
`M${point1.x} ${point1.y} A ${this.radius} ${this.radius} 0 0 1 ${point2.x} ${point2.y}`
);
} else {
const point3 = {
x:
this.center.x +
this.radius * Math.cos((Math.PI / 180) * (ang1 + 180)),
y:
this.center.y +
this.radius * Math.sin((Math.PI / 180) * (ang1 + 180)),
};
this.element.nativeElement.setAttribute(
'd',
`M${point1.x} ${point1.y} A ${this.radius} ${this.radius} 0 0 1 ${point3.x} ${point3.y} A ${this.radius} ${this.radius} 0 0 1 ${point2.x} ${point2.y}`
);
}
}
}
Where range from/to goes from 0 to 360 degrees and the arc goes always in direction from to to in clock direction So, we can do, e.g.
<svg viewBox="0 0 100 100" >
<path stroke-width="30" arc [center]="{x:50,y:50}" radius="34"
[range]="{from:ang1,to:ang2}" />
</svg>
or
<svg viewBox="0 0 100 100" style="max-width:50%;margin:auto" fill="transparent">
<path stroke-width="30" stroke="green" arc [center]="{x:50,y:50}" radius="34"
[range]="{from:-90,to:30}" />
<path stroke-width="30" stroke="red" arc [center]="{x:50,y:50}" radius="34"
[range]="{from:30,to:150}" />
<path stroke-width="30" stroke="yellow" arc [center]="{x:50,y:50}" radius="34"
[range]="{from:150,to:270}" />
</svg>
see stackblitz
Upvotes: 0
Reputation: 57939
you need understand a bit about the values of viewBox and width and height
In your case simple write some like:
<svg width="100%"
viewBox="80 80 320 320" fill="none"
xmlns="http://www.w3.org/2000/svg">
...
</svg>
See that the two first parameters of the viewbox translate the svg, the two last is a "scale" the svg.
NOTE: In general viewbox in the way
viewBox="minX minY width height"
Arcs are the more difficult svg concept. We can use some arcs generators like
http://xahlee.info/js/svg_circle_arc.html#google_vignette
or
https://milevski.co/svg-arc-corners/demo/
e.g. we can write
<svg width="100%" viewBox="50 50 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Green Stroke -->
<path
d="M 209 100 A 100 100 275 0 1 291 242"
stroke="green"
stroke-width="60"
fill="none"
/>
<path
d="M 282 257 A 100 100 395 0 1 118 257"
stroke="red"
stroke-width="60"
fill="none"
/>
<path
d="M 109 242 A 100 100 515 0 1 191 100"
stroke="yellow"
stroke-width="60"
fill="none"
/>
</svg>
Upvotes: 2