Модуль:Диаграмма круговая
Модуль:Диаграмма круговая предназначен для создания круговых диаграмм.
Для вызова модуля используется шаблон со следующими параметрами:
{{Диаграмма круговая | диаметр | вид | расположение | расположение легенды | проценты | округление | заголовок | значение1 | описание1 | цвет1 | значение2 | описание2 | цвет2 | значение3 | описание3 | цвет3 }}
где:
- диаметр — диаметр диаграммы в пикселях, возможны значения от 100 до 500. По умолчанию 100.
- вид — вид диаграммы, возможны следующие значения: круг или кольцо, по умолчанию круг.
- в случае круг+ и кольцо+ — зазор между секторами
- в случае круг- и кольцо- — диаграмма без рамки
- расположение — расположение диаграммы, возможны следующие значения: слева, справа и нет. По умолчанию нет.
- расположение легенды — возможны следующие значения: внизу, справа, ху и нет. По умолчанию нет.
- проценты — вывод процентов, возможны следующие значения: да и нет. Проценты выводятся в начале строки описания. По умолчанию нет. Если по какой-то причине вас не устраивает формат выводимых процентов — заблокируйте его и напишите вручную в строке описания.
- округление — округление процентов, возможны следующие значения: 0(округление до целых), 1(до одного знака после запятой) и 2(до двух знаков после запятой). По умолчанию 0.
- заголовок — заголовок диаграммы.
- значение1 — значение для первого сектора, положительное число. При нецелых числах вместо запятой используйте точку.
- описание1 — описание первого сектора
- цвет1 — цвет первого сектора. Цвет может быть указан в виде ключевых слов, используемых в HTML (пример: red, blue, black), шестнадцетиричным кодом (пример: #FF0000 или сокращённо #F00) или десятичным кодом (пример: rgb(255,0,0)). По умолчанию используется внутренняя таблица цветов. Подробнее смотри цвета HTML.
- максимальное количество секторов — 20.
- при «расположении легенды» ху расположение описания (легенды) для каждого сектора задаётся координатами х и у. Началом координат (0:0) является верхний левый угол диаграммы.
- ширина поля слева от диаграммы — значения от 0 до 500, заносится вместо процентов
- ширина поля справа от диаграммы — значения от 0 до 500, заносится вместо округления
- описание : х : у : цвет — описание сектора в данном случае
Примеры[править код]
{{Диаграмма круговая | | | | | | | Заголовок | 1| | | 1| | | 1| | }} |
|
{{Диаграмма круговая |240| круг | справа | внизу | нет | 0 | Круговая диаграмма | 1 | сектор 1 | | 1 | сектор 2 | | 1 | сектор 3 <br>| | 1 | сектор 4 | | 1 | сектор 5 | | 1 | сектор 6 | }} |
|
{{Диаграмма круговая |200| круг+ | слева | справа | да | 1 | Круговая диаграмма | 10| сектор 1 | | 20| сектор 2 | | 30| сектор 3 | gold | 20| сектор 4 | tomato | 10| сектор 5 | #FF00FF | 20| сектор 6 | rgb(32,178,170) | 10| сектор 7 | #00FF00 | 20| сектор 8 | silver | 10| сектор 9 | black }} |
|
{{Диаграмма круговая |200| кольцо+ | слева | справа | да | 2 | Круговая диаграмма кольцо <ref>[http://www.wikipedia.org ''Ссылка'']</ref> | 10| сектор 1 | | 20| сектор 2 | | 30| сектор 3 | | 20| сектор 4 | | 10| сектор 5 | | 20| сектор 6 | | 10| сектор 7 | | 20| сектор 8 | | 10| сектор 9 | }} |
|
{{Диаграмма круговая |200| круг | слева | ху | 0 | 0 | Круговая диаграмма |25| '''''Россия<br>25%''''': 130 : 85 : #FFF | |20| '''''США <br> 20%''''' : 145 : 160: #FFF | |15| '''''Канада<br>15%''''': 75 : 195: #FFF | |40| Остальные<br>страны<br>40%:20: 110: #FFF | }} |
Россия 25% США 20% Канада 15% Остальные страны 40% |
{{Диаграмма круговая |200| круг | слева | ху | 0 | 100 | Страны по ... |10| 10% Россия : 155 : 40 | |10| 10% США : 195 : 75 | |10| 10% Канада : 210 : 135 | |10| 10% Атлантида: 195 : 195 | |60| Остальные<br>страны<br>60%:20:120:#FFF| }} |
10% Россия 10% США 10% Канада 10% Атлантида Остальные страны 60% |
Примечания[править код]
local p = {} local function round(x, precision) x = math.floor(x * math.pow(10, precision) + 0.5) / math.pow(10, precision) if precision == 0 then return x end x = mw.ustring.gsub(x, "%.", ",") if precision == 1 and string.find(x, ",") == nil then x = x..",0" end return x end local function createSlice(sbeg, send, color, radius, art) str = '' rad = sbeg * math.pi / 50; -- convert % in radian if art == 'круг' or art == 'кольцо' then if sbeg <= 12 then border = radius * math.tan(rad) --border-left str = [[<div style="position:absolute; right:0; top:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]] if send > 50 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 25 then border = radius * math.tan(math.pi/2 - rad) --border-top str = [[<div style="position:absolute; left:0; bottom:0; width:0; height:0; background-color:transparent; border-style:solid; border-width:]]..border..[[px ]]..radius..[[px ]]..radius..[[px ]]..radius..[[px; border-color:transparent ]]..color..[[ ]]..color..[[ ]]..color..[[;"></div>]] if send > (100 - sbeg) then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 37 then border = radius * math.tan(rad - math.pi/2) --border-top str = [[<div style="position:absolute; left:0; bottom:0; width:0; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..color..[[;"></div>]] if send > (sbeg + 50) then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 50 then border = radius * math.tan(math.pi - rad) --border-right str = [[<div style="position:absolute; left:0; top:0; width:0; height:0; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px ]]..radius..[[px ]]..radius..[[px; border-color:transparent transparent ]]..color..[[ ]]..color..[[;"></div>]] if send > 87 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 62 then border = radius * math.tan(rad - math.pi) --border-right str = [[<div style="position:absolute; left:0; bottom:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..color..[[ transparent transparent transparent;"></div>]] if send > 75 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 75 then border = radius * math.tan(math.pi*1.5 - rad) --border-bottom str = [[<div style="position:absolute; right:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..color..[["></div>]] elseif sbeg <= 87 then border = radius * math.tan(rad - math.pi*1.5) --border-bottom str = [[<div style="position:absolute; left:0; top:0; width:0; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]] else border = radius * math.tan(math.pi*2 - rad) --border-right str = [[<div style="position:absolute; left:0; top:0; width:]]..(radius-border)..[[px; height:0; background-color:transparent; border-style:solid; border-width:0px ]]..border..[[px ]]..radius..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]] end else local x = 0; x = math.cos(rad) local y = 0; y = math.sin(rad) if x >= 0 then x = math.floor(x * 10 + 0.5) / 10 else x = math.floor(math.abs(x) * 10 + 0.5) / (-10) end if y >= 0 then y = math.floor(y * 10 + 0.5) / 10 else y = math.floor(math.abs(y) * 10 + 0.5) / (-10) end if sbeg <= 12 then border = radius * math.tan(rad) --border-left str = [[<div style="position:absolute; right: ]]..x..[[px; top:]]..(-1-y)..[[px; width:]]..(radius-border)..[[px;height:1px;background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..'#FFF'..[[ transparent;"></div>]] str = str..[[<div style="position:absolute; right:-]]..x..[[px; top:]]..(-1+y)..[[px; width:]]..(radius-border)..[[px;height:1px;background-color:transparent; border-style:solid; border-width:0px 0px ]]..(2*radius)..[[px ]]..(2*border)..[[px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]] if send > 50 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 25 then border = radius * math.tan(math.pi/2 - rad) --border-top str = [[<div style="position:absolute; left:-]]..x..[[px; bottom: ]]..y..[[px; width:]]..radius..[[px;height:]]..radius..[[px;background-color:transparent; border-style:solid; border-width:]]..border..'px '..radius..[[px 0px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]] str = str..[[<div style="position:absolute; left: ]]..x..[[px; bottom:-]]..y..[[px; width:]]..radius..[[px;height:]]..radius..[[px;background-color:transparent; border-style:solid; border-width:]]..border..'px '..radius..[[px 0px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]] if send > 50 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..(2*radius)..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 37 then border = radius * math.tan(rad - math.pi/2) str = [[<div style="position:absolute; left:]]..(-1*x)..[[px; bottom: ]]..y..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..'#FFF'..[[;"></div>]] str = str..[[<div style="position:absolute; left: ]]..x..[[px; bottom:-]]..y..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:]]..(2*border)..[[px 0px 0px ]]..(2*radius)..[[px; border-color:transparent transparent transparent ]]..color..[[;"></div>]] if send > 75 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 50 then border = radius * math.tan(math.pi - rad) --border-right str = [[<div style="position:absolute; left:]]..(-1*x)..[[px; top:-]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..border..'px '..radius..[[px 0px; border-color:transparent transparent ]]..'#FFF'..[[ transparent;"></div>]] str = str..[[<div style="position:absolute; left: ]]..x..[[px; top: ]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..border..'px '..radius..[[px 0px; border-color:transparent transparent ]]..color..[[ transparent;"></div>]] if send > 75 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 62 then border = radius * math.tan(rad - math.pi) --border-right str = [[<div style="position:absolute; left:]]..(-1*x)..[[px; bottom:]]..(-1+y)..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..'#FFF'..[[ transparent transparent transparent;"></div>]] str = str..[[<div style="position:absolute; left: ]]..x..[[px; bottom:]]..(-1-y)..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:]]..radius..[[px ]]..border..[[px 0px 0px; border-color:]]..color..[[ transparent transparent transparent;"></div>]] if send > 75 then str = str..[[<div style="position:absolute; left:0; top:0; width:]]..radius..[[px; height:]]..radius..[[px; background-color:]]..color..[["></div>]] end elseif sbeg <= 75 then border = radius * math.tan(math.pi*1.5 - rad) --border-bottom str = [[<div style="position:absolute; right:]]..x..[[px; top:]]..(-1*y)..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..'#FFF'..[["></div>]] str = str..[[<div style="position:absolute; right:]]..(-1*x)..[[px; top:]]..y..[[px; width:]]..radius..[[px; height:]]..radius..[[px; background-color:transparent; border-style:solid; border-width:0px 0px ]]..border..[[px ]]..radius..[[px; border-color:transparent transparent transparent ]]..color..[["></div>]] elseif sbeg <= 87 then border = radius * math.tan(rad - math.pi*1.5) -- str = [[<div style="position:absolute; left:]]..(-1-x)..[[px; top:]]..(-1*y)..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]] str = str..[[<div style="position:absolute; left:]]..(-1+x)..[[px; top:]]..y..[[px; width:1px; height:]]..(radius-border)..[[px; background-color:transparent; border-style:solid; border-width:0px ]]..radius..[[px ]]..border..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]] else border = radius * math.tan(math.pi*2 - rad) str = [[<div style="position:absolute; left:-]]..x..[[px; top:]]..(-1+(-1*y))..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:0px ]]..(border)..[[px ]]..radius..[[px 0px; border-color:transparent ]]..'#FFF'..[[ transparent transparent;"></div>]] str = str..[[<div style="position:absolute; left: ]]..x..[[px; top:]]..(-1+y)..[[px; width:]]..(radius-border)..[[px; height:1px; background-color:transparent; border-style:solid; border-width:0px ]]..(border)..[[px ]]..radius..[[px 0px; border-color:transparent ]]..color..[[ transparent transparent;"></div>]] end end return str end local function start(frame) local Dsize = 100 --size of diagram ( 10 - 500 ) local Dart = '' --art of diagram ( circle / ring ) local Dpos = '' --position of diagram ( left / right /no ) local Dleg = '' --view & position of legends ( no / bottom / right / coordin ) local Dpct = '' --percent (prozent) ( yes /no ) local Dprc = 0 --precision of rounding ( 0 / 1 / 2 ) local Dtit = '' --title of diagram local Dbrd = '' --border of diagram local i = 0 --counter local num = 0 --number local err = 0 --errors local sum = 0 --sum local color = {"#DC3912", "#3366CC", "#FF9900", "#109618", "#990099", "#0099C6", "#DD4477", "#66AA00", "#B82E2E", "#316395", "#994499", "#22AA99", "#AAAA11", "#6633CC", "#E67300", "#8B0707", "#651067", "#329262", "#5574A6", "#3B3EAC"} for k, v in pairs(frame.args) do if i > 7 and (i - 5) % 3 == 0 then if not tonumber(frame.args[i]) then err = 1; else num = num + 1; sum = sum + tonumber(frame.args[i]); end end i = i + 1 end if i < 10 or i > 67 or (i - 7) % 3 ~= 0 then err = 1 end if err == 0 then Dsize = tonumber(frame.args[1]); if not Dsize or Dsize < 30 or Dsize > 500 then Dsize = 100 end Dart = mw.text.trim(frame.args[2]); if Dart ~= 'круг' and Dart ~= 'круг+' and Dart ~= 'круг-' and Dart ~= 'кольцо' and Dart ~= 'кольцо+' and Dart ~= 'кольцо-' then Dart = 'круг'; end Dpos = mw.text.trim(frame.args[3]); if Dpos ~= 'справа' and Dpos ~= 'слева' and Dpos ~= 'нет' then Dpos = 'нет'; end Dleg = mw.text.trim(frame.args[4]); if Dleg ~= 'справа' and Dleg ~= 'внизу' and Dleg ~= 'нет' and Dleg ~= 'ху' then Dleg = 'нет'; end Dpct = mw.text.trim(frame.args[5]); Dprc = mw.text.trim(frame.args[6]); Dtit = mw.text.trim(frame.args[7]); Dsize = math.floor(Dsize/2)*2; if Dart == 'круг-' then Dart = 'круг'; Dbrd = 'border:0'; end if Dart == 'кольцо-' then Dart = 'кольцо'; Dbrd = 'border:0'; end if Dleg == 'ху' then Dpct = tonumber(Dpct) if not Dpct or Dpct > 500 then Dpct = 0 end Dprc = tonumber(Dprc) if not Dprc or Dprc > 500 then Dprc = 0 end end if Dleg ~= 'ху' then if Dpct ~= 'нет' and Dpct ~= 'да' then Dpct = 'нет'; end Dprc = tonumber(Dprc) if Dprc ~= 0 and Dprc ~= 1 and Dprc ~= 2 then Dprc = 0; end end end local n = 1 local Svalue = 0 local Spct = 0 --percent (prozent) of slice local Sbegin = 0 -- begin of slice in % local Send = 0 -- end of slice in % local Sdescr = '' local Scolor = '' local htmlCaption = '' local htmlLegendCont = '' local htmlLegendCont_= '' local htmlLegends = '' local BorderLeft = '' if Dleg == 'ху' then BorderLeft = [[border-left:]]..Dpct..[[px solid #FFF;]] end local BorderRight= '' if Dleg == 'ху' then BorderRight = [[border-right:]]..Dprc..[[px solid #FFF;]] end local floatL = '' local marginL = '' local bre = '' local slice = '' local percentage = '' local html = '' local html1 = '' if Dpos == 'слева' then html1 = [[<div class="thumb tleft">]] end if Dpos == 'справа' then html1 = [[<div class="thumb tright">]] end if Dpos == 'нет' then html1 = [[<div class="thumb" style="display:inline-block">]] end local html2 = [[<div class="thumbinner" style="position:relative; background-color:#FFF; ]]..Dbrd..[[;">]] local html2e= [[</div>]]; local html1e= [[</div>]]; if err == 0 then Scolor = mw.text.trim(frame.args[10]) if Scolor == '' then Scolor = color[1] end if Dleg == 'справа' then floatL = [[float:left;]] marginL = [[margin-left:15px;]] bre = [[<br />]] end if Dtit ~= '' then htmlCaption = [[<div class="thumbcaption" style="text-align:center; font-size:100%; font-weight:bold; padding:9px;">]]..Dtit..[[</div>]] end htmlLegendCont = [[<div class="thumbcaption" style="margin:5px; font-size:100%; line-height:1.5em;]]..marginL..floatL..[[">]] --begin of legends htmlLegendCont_= '</div>' -- end of legends slice = [[<div style="position:relative; width:]]..Dsize..[[px; height:]]..Dsize..[[px; background-color:]]..Scolor..[[; overflow:hidden; margin:5px;]]..floatL..BorderLeft..BorderRight..[[">]] --begin of slides while n <= num do Svalue = tonumber(frame.args[3*n+5]) Sdescr = mw.text.trim(frame.args[3*n+6]) Scolor = mw.text.trim(frame.args[3*n+7]) if Scolor == '' then Scolor = color[n] end Spct = 100 * Svalue / sum if n > 1 then Sbegin = Send end Send = Sbegin + Spct if n > 1 then slice = slice.. createSlice(Sbegin, Send, Scolor, Dsize/2, Dart) --function end if Dpct == 'да' then percentage = round(Spct, Dprc)..'% ' end if Dleg == 'справа' or Dleg == 'внизу' then htmlLegends = htmlLegends..[[<span style="box-shadow:2px -1px 3px 0px #C0C0C0; color:]]..Scolor..[[; background-color:]]..Scolor..[[;">     </span>  ]]..percentage..Sdescr..bre end if Dleg == 'ху' then local legv, legx, legy, legc = unpack(mw.text.split(Sdescr, '%s*:%s*')) if legc == nil then legc = '#000' end if not tonumber(legx) or not tonumber(legy) then legx = 2; legy = n*10; legv = 'ошибка с'..n; legc = '#F00'; end htmlLegends = htmlLegends..[[<div style="position:absolute; left:]]..legx..[[px; top:]]..legy..[[px; color:]]..legc..[[; font-size:100%; line-height:1.4em;">]]..legv..[[</div>]] end n = n + 1 end if Dart == 'круг+' or Dart == 'кольцо+' then slice = slice..[[<div style="position:absolute; left:]]..(Dsize/2-1)..[[px; top:0px; width:2px; height:]]..(Dsize/2)..[[px; background-color:#F9F9F9;"></div>]] end slice = slice..[[<div style="position:absolute;left:0;top:0">]]..'[[Файл:Circle200.svg|'..Dsize..'px|link=|alt=]]</div>' -- end of slices --slice = slice..[[<div style="position:absolute; left:-]]..(Dsize/4)..[[px; top:-]]..(Dsize/4)..[[px; width:]]..Dsize..[[px; height:]]..Dsize..[[px; border-radius:100%; border:]]..(Dsize/4)..[[px solid #F9F9F9;"></div>]] -- circle if Dart == 'кольцо' or Dart == 'кольцо+' then slice = slice..[[<div style="position:absolute;left:0;top:0">]]..'[[Файл:Circle200c.svg|'..Dsize..'px|link=|alt=]]</div>' --ring --slice = slice..[[<div style="position:absolute; left:]]..(Dsize/4)..[[px; top:]]..(Dsize/4)..[[px; width:]]..(Dsize/2)..[[px; height:]]..(Dsize/2)..[[px; background:#F9F9F9; border-radius:100%; border:0;"></div>]] --ring end slice = slice..'</div>' --end of slices end if Dleg == 'нет' then htmlLegendCont = ''; htmlLegendCont_= ''; htmlLegends = ''; end if Dleg == 'ху' then htmlLegendCont = ''; htmlLegendCont_= ''; end if err == 0 then html = html1..html2..htmlCaption..slice.. htmlLegendCont..htmlLegends.. htmlLegendCont_..html2e..html1e; end return html end p.init = function (f) -- if string.match(f:getParent():getTitle(), '%P+') == mw.site.namespaces.Template.name then f = f:getParent() -- end return start(f) end return p