SVGに輪を描く
🍩 ドーナツを描く
最近プロジェクトをする時にドーナツを描きたいです.divブロックを削って作ろうとしたが、opggデスクトップアプリケーションのこの美しいグラフを見ると、divには明らかに限界がある.特にあの太いショットは...可能ですか.
グラフライブラリを書きたいのですが、勉強している人の立場に立って、何でも、できるだけ本機(?)を使います.実施はいいんじゃないですか...
以下の資料は助かります.
https://a11y.gitbook.io/graphics-aria/svg-graphics/svg-basic-shapes
https://wit.nts-corp.com/2021/04/23/6338
環境はtypescript/reactです.
svgを使用して円を描く場合は、svgタグと円タグを使用するか、svg内でpathを使用して直接描くことができます.path方式は複雑に見えるし、必要もないのでcircle方式を使ってみます.体現すべき資料は大体以下の通りである.
KDAPerMatch: 0
champUseRatio: 25
deathPerMatch: 0
foreignLanguageRatio: 0
isPrevSeason: 25
maxDeathPerCount: 0
positionRatio: 7.5
userLevel: 23
winRate: 0
それらの最高和は100で、点数からドーナツのグラフを求めればいいです.まず、各アイテムの色を披露しました.index署名が必要なので、タイプも事前に宣言します.const scoreColor:{[index:string]:string} = {
deathPerMatch:'red',
KDAPerMatch:'orange',
winRate:'yellow',
maxDeathPerCount:'green',
foreignLanguageRatio:'blue',
positionRatio:'navy',
champUseRatio:'purple',
userLevel:'black',
isPrevSeason:'white',
}
虹色...ほほほ正式にラベルを入力します.実際、ラベル内のpropertyの大部分は直接見ればわかります.
<svg width={size} height={size} viewBox={"0 0 100 100"} style={{transform:'rotate(-90deg)'}}>
{Object.keys(offset).length>0 && Object.keys(score).map((prop, index)=>{
const value = score[prop]
const color = scoreColor[prop]
if(typeof value=="number"&& value){
console.log(offset)
return(
<circle
stroke={color}
cx={50}
cy={50}
r={45}
strokeDasharray={`${2*Math.PI*45*(value/100)} ${2*Math.PI*45*(1-(value/100))}`}
strokeDashoffset={`${2*Math.PI*45*(offset[prop])/100}`}
fill={'none'} strokeWidth={10} />
)
}
})
}
</svg>
上から下へstrokeDasharray
よく見られる資料から見ると,この属性は破線の点長を意味する.周長で表すので、2πrという円の周長の公式を覚え続けたほうがいいです.重要なのは、1つのアトリビュート値を書くと、繰り返し撮影される点線の長さしか定義できませんが、2つのアトリビュート値を書くと、点線間の空白に調整できます.歯を食いしばる
StrokeDasharray={(私が望む弧の周長)(円の周長-1)}
入力すれば、私が望むように線を引くことができます.
ex) strokeDasharray = {2πr*0.25 2πr0.75}
strokeDashoffset
こいつは線を引く起点を設定する.これも円の周長値から簡単に計算できます.上の図で同じ弧を9点から12点に引くには、円の周長(1/4)のstrokeDashoffsetを設定するだけです.
最初は12時がデフォルトになるように変換しました.ディポルトは3時だったのか.
ex)strokeDasharray = {2πr0.25 2πr0.75} strokeDashoffset={2πr0.25}
これを利用して、strokeDashoffsetを加算すればドーナツグラフを描くことができます.私はuseEffectレンダリング時にすべてのoffset値を事前に求め、useState配列に配置することで実現します.
私は無責任にコードをあなたに投げて、あなたは自分で理解して、未来の私は......
import React ,{useState, useEffect}from "react";
import { algoScoreType } from "../types/algorithm.type";
type ScoreCircleType = {
size:number,
stroke:number,
score:algoScoreType
}
const scoreColor:{[index:string]:string} = {
deathPerMatch:'red',
KDAPerMatch:'orange',
winRate:'yellow',
maxDeathPerCount:'green',
foreignLanguageRatio:'blue',
positionRatio:'navy',
champUseRatio:'purple',
userLevel:'black',
isPrevSeason:'white',
}
export default function ScoreCircle({size, stroke , score}:ScoreCircleType){
const [offset, setOffset] = useState<{[index:string]:number}>({});
useEffect(() => {
setOffset(getOffset(score))
}, [score]);
const getOffset = (score:algoScoreType) =>{
const arr:{[index:string]:number} = {};
let prev = 0;
Object.keys(score).forEach((v:string)=>{
const value = score[v]
console.log(prev)
if(typeof value=="number"&& value){
arr[v] = value+prev
prev = value+prev
}
})
console.log(arr)
return arr
}
return(
<svg width={size} height={size} viewBox={"0 0 100 100"} style={{transform:'rotate(-90deg)'}}>
{Object.keys(offset).length>0 && Object.keys(score).map((prop, index)=>{
const value = score[prop]
const color = scoreColor[prop]
if(typeof value=="number"&& value){
console.log(offset)
return(
<circle
style={{zIndex:Object.keys(score).length-index}}
stroke={color}
cx={50}
cy={50}
r={45}
strokeDasharray={`${2*Math.PI*45*(value/100)} ${2*Math.PI*45*(1-(value/100))}`}
strokeDashoffset={`${2*Math.PI*45*(offset[prop])/100}`}
fill={'none'} strokeWidth={stroke} />
)
}
})
}
</svg>
)
}
ボロボロだけど…ははは考えましたが、特に太いタッチは必要ありません・・・
ショートショット
strokeLinecap={"round"}
あげるなら使えます.
それを理解すれば、アニメーションや上質なアプリケーションを与えることができます.
Reference
この問題について(SVGに輪を描く), 我々は、より多くの情報をここで見つけました https://velog.io/@gomiseki/SVG에서-도넛을-그려보자テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol