Загрузка данных
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Лепесток звёздного глобуса — 1000 мм</title>
<style>
html,body{
margin:0;
padding:0;
background:#fff;
}
svg{
display:block;
width:1000mm;
height:1000mm;
}
.grid{
fill:none;
stroke:#f8f8f8;
stroke-width:0.3;
vector-effect:non-scaling-stroke;
}
.edge{
fill:none;
stroke:#808080;
stroke-width:0.3;
vector-effect:non-scaling-stroke;
}
#download{
position:fixed;
top:10px;
left:10px;
z-index:100;
padding:10px 16px;
font-size:16px;
cursor:pointer;
}
</style>
</head>
<body>
<button id="download">Скачать SVG</button>
<svg
id="petal"
xmlns="http://www.w3.org/2000/svg"
width="1000mm"
height="1000mm"
viewBox="-550 -550 1100 1100">
<rect x="-550" y="-550" width="1100" height="1100" fill="white"/>
<g id="grid"></g>
<g id="edges"></g>
</svg>
<script>
const svg = document.getElementById("petal");
const grid = document.getElementById("grid");
const edges = document.getElementById("edges");
const NS = "http://www.w3.org/2000/svg";
const R = 500;
// Один лепесток = 1 час = 15°
// Центральный меридиан = 0°
// Края лепестка = -7.5° и +7.5°
const HALF_LON = 7.5;
// Масштаб по широте.
// Для плоской развёртки сферы используем
// истинную дугу меридиана:
// 90° = πR/2.
function Y(latDeg){
return -R * latDeg * Math.PI / 180;
}
// Поперечная координата:
// x = R * sin(longitude) * cos(latitude)
function X(latDeg, lonDeg){
const lat = latDeg * Math.PI / 180;
const lon = lonDeg * Math.PI / 180;
return R * Math.sin(lon) * Math.cos(lat);
}
function makePath(d, cls, parent){
const p = document.createElementNS(NS,"path");
p.setAttribute("d",d);
p.setAttribute("class",cls);
parent.appendChild(p);
return p;
}
/*
====================================================
ПАРАЛЛЕЛИ КАЖДЫЕ 5°
====================================================
От -85° до +85°.
*/
for(let lat=-85; lat<=85; lat+=5){
const y=Y(lat);
const x1=X(lat,-HALF_LON);
const x2=X(lat, HALF_LON);
makePath(
`M ${x1.toFixed(4)} ${y.toFixed(4)}
L ${x2.toFixed(4)} ${y.toFixed(4)}`,
"grid",
grid
);
}
/*
====================================================
МЕРИДИАНЫ
====================================================
15 минут = 3.75°
30 минут = 7.5°
45 минут = 11.25°
В пределах одного лепестка находятся:
- центральный меридиан 0°
- ±3.75° = четверть часа
- ±7.5° = границы лепестка
Но для удобства разметки внутри лепестка
рисуем также линии ±3.75°.
*/
/*
Центральный меридиан
*/
{
let d="";
for(let lat=-90;lat<=90;lat+=1){
const x=X(lat,0);
const y=Y(lat);
if(lat===-90)
d+=`M ${x.toFixed(4)} ${y.toFixed(4)} `;
else
d+=`L ${x.toFixed(4)} ${y.toFixed(4)} `;
}
makePath(d,"grid",grid);
}
/*
Меридианы ±15 минут
*/
for(const lon of [-3.75,3.75]){
let d="";
for(let lat=-90;lat<=90;lat+=1){
const x=X(lat,lon);
const y=Y(lat);
if(lat===-90)
d+=`M ${x.toFixed(4)} ${y.toFixed(4)} `;
else
d+=`L ${x.toFixed(4)} ${y.toFixed(4)} `;
}
makePath(d,"grid",grid);
}
/*
====================================================
КРАЯ ЛЕПЕСТКА
====================================================
Края серые, 0.3 мм.
*/
for(const lon of [-HALF_LON,HALF_LON]){
let d="";
for(let lat=-90;lat<=90;lat+=0.5){
const x=X(lat,lon);
const y=Y(lat);
if(lat===-90)
d+=`M ${x.toFixed(4)} ${y.toFixed(4)} `;
else
d+=`L ${x.toFixed(4)} ${y.toFixed(4)} `;
}
makePath(d,"edge",edges);
}
/*
====================================================
ПОЛЮСА
====================================================
Добавляем короткие замыкающие дуги,
чтобы контур лепестка был замкнут.
*/
function poleEdge(lat){
let d="";
for(let i=0;i<=30;i++){
const lon=-HALF_LON + i*(15/30);
const x=X(lat,lon);
const y=Y(lat);
if(i===0)
d+=`M ${x.toFixed(4)} ${y.toFixed(4)} `;
else
d+=`L ${x.toFixed(4)} ${y.toFixed(4)} `;
}
makePath(d,"edge",edges);
}
poleEdge(90);
poleEdge(-90);
/*
====================================================
СКАЧИВАНИЕ SVG
====================================================
*/
document.getElementById("download").addEventListener("click",()=>{
const clone=svg.cloneNode(true);
const serializer=new XMLSerializer();
let source=serializer.serializeToString(clone);
source='<?xml version="1.0" encoding="UTF-8"?>\n'+source;
const blob=new Blob(
[source],
{type:"image/svg+xml;charset=utf-8"}
);
const url=URL.createObjectURL(blob);
const a=document.createElement("a");
a.href=url;
a.download="lepetok_zvezdnogo_globusa_1chas_1000mm.svg";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(()=>{
URL.revokeObjectURL(url);
},1000);
});
</script>
</body>
</html>