效果圖:
按每個標簽出現(xiàn)的頻次大小渲染出不同比例大小的圓,渲染的圓的寬度區(qū)間為 [40, 160] ,其中的文字的大小區(qū)間為 [12, 30] ,圓的位置隨機擺放且不重疊。
根據(jù)已知條件可得出,標簽中頻次最高的對應圓的寬度(直徑)為160px、字號為30px,頻次最低的圓的寬度(直徑)為40px、字號為12px,那么最終問題的關鍵就是如何計算出其他標簽頻次對應的圓的大小?
假設標簽頻次中的最大值為max,最小值為min??僧嫵鋈缦聢D:
那么想要計算出current對應的寬度和字號,需要先計算出橙色這段線占整段線的比例,再根據(jù)比例計算這段線代表的寬度大小和字號大小。計算過程如下:
1、求比例:percent = (current-min) / (max-min)
2、根據(jù)比例求該段線對應的寬度大小,percent * (160-40)
3、同理求對應的字體大小,percent * (30-12)
4、那么current對應的字體和寬度為12 + percent * (30-12), 30 + percent * (160-40)
根據(jù)上述計算過程可以寫出如下函數(shù):
const getSize = (cur: number, min: number, max: number, minFontSize: number, maxFontSize: number, minWidth: number, maxWidth: number) => {
const countRange = max - min
const curRange = cur - min
const fontSizeRange = maxFontSize - minFontSize
const widthRange = maxWidth - minWidth
// 考慮min,max相同的情況
return {
fontSize: countRange > 0 ? minFontSize + curRange / countRange * fontSizeRange : maxFontSize,
width: countRange > 0 ? minWidth + curRange / countRange * widthRange : maxWidth
}
}
接下來思考:如何將圓隨機擺放在矩形中,且保證圓不重疊,已知矩形的rectangleWidth和rectangleHeight,圓的直徑width。
1、采用相對/絕對定位來放置圓,只需計算圓在矩形中的left, top值。
2、圓的位置隨機,但是圓要保證在矩形區(qū)域內(nèi),那么left值的取值范圍可以為[0, rectangleWidth],同時考慮圓的大小,區(qū)間最終為[0, rectangleWidth - width]
3、top值的取值范圍可以為[0, rectangleHeight],同時考慮圓的大小,區(qū)間最終為[0, rectangleHeight - height]
// width, fontSize 可根據(jù)上述的getSize計算得出
interface Label {
count: number;
label: string;
width: number;
fontSize: number;
left: number;
top: number;
}
const labelData: Array<Label> = []
// 設置圓的left和top值
const setPosition = () => {
labelData.forEach((v) => {
v.left = Math.random() * (rectangleWidth - v.width)
v.top = Math.random() * (rectangleHeight - v.width)
})
}
考慮圓不重疊的情況優(yōu)化上述代碼,圓重疊即圓出現(xiàn)相交的情況,如何判斷圓是否相交,根據(jù)數(shù)學公式: ( x 1 ? x 2 ) 2 + ( y 1 ? y 2 ) 2 < r 1 + r 2 \sqrt{(x1-x2)^ 2 + (y1-y2)^2} \quad < r1 + r2 (x1?x2)2+(y1?y2)2?<r1+r2該公式成立則兩圓相交,其中(x1,y1)為圓1的中心坐標,(x2,y2)為圓2的中心坐標,r1、r2分別為兩個圓的半徑。那么我們需要記錄每次畫的圓的中心坐標和半徑,繪制圓之前先找出之前繪畫的圓有沒有與之相交的,如果有,則重新獲取left、top的值文章來源:http://www.zghlxwxcb.cn/news/detail-839046.html
const circles: Array<{x: number, y: number, radius: number}> = []
const setPosition = () => {
labelData.forEach((v) => {
const radius = v.width / 2
let left: number, top: number, x: number, y: number;
// do while 判斷之前會先do一次,如果找到相交圓,則繼續(xù)執(zhí)行do
do {
left = Math.random() * (rectangleWidth - v.width)
top = Math.random() * (rectangleHeight - v.width)
x = left + radius
y = top + radius
} while (
circles.some(circle => Math.sqrt(Math.pow(circle.x - x, 2) + Math.pow(circle.y - y, 2)) < radius + circle.radius)
)
v.left = left
v.top = top
circles.push({x, y, radius})
})
}
這里其實還需要考慮到適配的問題,如果矩形區(qū)域被縮放,那么文字和圓的大小也應該進行縮放,我這里采用的是scale的方式,計算當前屏幕相對于1920(我們開發(fā)的參考尺寸是1920*1080)的比例,然后將對應的maxFontSize * scale ,maxWidth * scale,最小的尺寸就不需要再考慮啦,已經(jīng)很小啦,當然如果最大尺寸被縮放到比最小的都小的時候就直接取最小尺寸吧??!文章來源地址http://www.zghlxwxcb.cn/news/detail-839046.html
到了這里,關于根據(jù)標簽出現(xiàn)的頻次渲染不同大小的圓和文字,圓隨機擺放且相互之間不重疊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!