first and second chapters ready

master
gman 1 year ago
parent d0a6a6bcfa
commit af96aa2391

@ -2,27 +2,29 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import react from '@astrojs/react';
// https://astro.build/config
export default defineConfig({
integrations: [
starlight({
title: 'My Docs',
social: {
github: 'https://github.com/withastro/starlight',
},
sidebar: [
{
label: 'Guides',
items: [
// Each item here is one entry in the navigation menu.
{ label: 'Example Guide', slug: 'guides/example' },
],
},
{
label: 'Reference',
autogenerate: { directory: 'reference' },
},
],
}),
],
});
redirects: {
'/': '/chapters',
},
integrations: [starlight({
title: 'Веб-картография',
locales: {
root: {
label: 'Русский',
lang: 'ru',
}
},
social: {
github: 'https://github.com/withastro/starlight',
},
sidebar: [
{
label: 'Введение в веб-картографию',
autogenerate: { directory: 'chapters' },
}
],
}), react()],
});

177
package-lock.json generated

@ -9,8 +9,13 @@
"version": "0.0.1",
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/react": "^3.6.2",
"@astrojs/starlight": "^0.28.2",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"astro": "^4.15.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sharp": "^0.32.5",
"typescript": "^5.6.2"
}
@ -157,6 +162,24 @@
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
}
},
"node_modules/@astrojs/react": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/@astrojs/react/-/react-3.6.2.tgz",
"integrity": "sha512-fK29lYI7zK/KG4ZBy956x4dmauZcZ18osFkuyGa8r3gmmCQa2NZ9XNu9WaVYEUm0j89f4Gii4tbxLoyM8nk2MA==",
"dependencies": {
"@vitejs/plugin-react": "^4.3.1",
"ultrahtml": "^1.5.3"
},
"engines": {
"node": "^18.17.1 || ^20.3.0 || >=21.0.0"
},
"peerDependencies": {
"@types/react": "^17.0.50 || ^18.0.21",
"@types/react-dom": "^17.0.17 || ^18.0.6",
"react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta",
"react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta"
}
},
"node_modules/@astrojs/sitemap": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.2.0.tgz",
@ -474,6 +497,34 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-react-jsx-self": {
"version": "7.25.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz",
"integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/plugin-transform-react-jsx-source": {
"version": "7.25.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz",
"integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==",
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.7"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@babel/runtime": {
"version": "7.25.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz",
@ -1877,6 +1928,28 @@
"undici-types": "~6.19.2"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.13",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA=="
},
"node_modules/@types/react": {
"version": "18.3.11",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz",
"integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/sax": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
@ -1895,6 +1968,24 @@
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
},
"node_modules/@vitejs/plugin-react": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz",
"integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==",
"dependencies": {
"@babel/core": "^7.25.2",
"@babel/plugin-transform-react-jsx-self": "^7.24.7",
"@babel/plugin-transform-react-jsx-source": "^7.24.7",
"@types/babel__core": "^7.20.5",
"react-refresh": "^0.14.2"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"peerDependencies": {
"vite": "^4.2.0 || ^5.0.0"
}
},
"node_modules/@volar/kit": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.5.tgz",
@ -2847,6 +2938,11 @@
"node": ">=4"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
@ -4205,6 +4301,17 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@ -5811,15 +5918,16 @@
}
},
"node_modules/prettier": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"optional": true,
"peer": true,
"bin": {
"prettier": "bin-prettier.js"
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=10.13.0"
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
@ -5909,6 +6017,37 @@
"rc": "cli.js"
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": {
"loose-envify": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
},
"peerDependencies": {
"react": "^18.3.1"
}
},
"node_modules/react-refresh": {
"version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
"integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -6308,6 +6447,14 @@
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
},
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": {
"loose-envify": "^1.1.0"
}
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",
@ -6754,6 +6901,11 @@
"semver": "^7.3.8"
}
},
"node_modules/ultrahtml": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.5.3.tgz",
"integrity": "sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg=="
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
@ -7392,6 +7544,21 @@
"prettier": "2.8.7"
}
},
"node_modules/yaml-language-server/node_modules/prettier": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
"integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
"optional": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/yaml-language-server/node_modules/request-light": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz",

@ -10,10 +10,15 @@
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/react": "^3.6.2",
"@astrojs/starlight": "^0.28.2",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1",
"astro": "^4.15.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"sharp": "^0.32.5",
"@astrojs/check": "^0.9.4",
"typescript": "^5.6.2"
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

@ -0,0 +1,65 @@
---
const { answer, ballast, explanation } = Astro.props;
---
<style>
input {
vertical-align: middle;
}
.option {
position: relative;
}
#answer-check {
color: white;
position: absolute;
transform: scale(-1, 1);
rotate: 95deg;
left: 6px;
top: 3px;
display: none;
}
</style>
<fieldset style={{ border: "none" }}>
{
[
<div class="option">
<i id="answer-check"></i>
<input type="radio" id="answer" name={answer} />
<label for="answer">{answer}</label>
</div>,
...ballast.map((b: string) => (
<div class="option">
<input type="radio" id={b} name={b} />
<label for={b}>{b}</label>
</div>
)),
].sort(() => Math.random() - 0.5)
}
</fieldset>
<span id="explanation" style="display: none;">😸 {explanation}</span>
<button id="repeat" style="display: none;">😿 Ещё разок!</button>
<script>
document.querySelectorAll("input").forEach((el) => {
el.addEventListener("change", () => {
document.querySelector("fieldset")!.disabled = true;
document.getElementById("repeat")!.style.display = "block";
});
});
document.querySelector("#answer")?.addEventListener("change", () => {
document.getElementById("explanation")!.style.display = "block";
document.getElementById("repeat")!.style.display = "none";
document.getElementById("answer-check")!.style.display = "inline"
});
document.querySelector("#repeat")!.addEventListener("click", () => {
document.querySelectorAll("input").forEach((el) => {
el.checked = false;
});
document.querySelector("fieldset")!.disabled = false;
document.getElementById("repeat")!.style.display = "none";
});
</script>

@ -0,0 +1,84 @@
---
title: Веб-картографирование
---
import { Card, LinkCard } from '@astrojs/starlight/components';
import Question from '../../../components/Question.astro'
Этот раздел содержит кратчайший практико-ориентированный *теоретический обзор* сферы веб-картографии
<LinkCard title='Руки чешутся' href='/chapters/2-webmap#создание-первой-веб-карты' description='Сразу перейти к практическому упражнению'/>
## Определение веб-картографирования
Под веб-картографированием понимается создание карт для их распространения и использования во Всемирной сети. Веб-картографирование является одним из направлений геоинформационного картографирования. Суть веб-картографирования заключается в интеграции геоинформационных подходов к картографированию и сетевых технологий.
> Можно встретить и такие варианты употребления как «Интернет-картографирование», «WWW-картографирование», «телекоммуникационное картографирование», «web-картографирование». Однако в словаре их бы одарили меткой *устар.*
Появление большого числа картографических веб-ресурсов свидетельствует, что сетевые технологии являются одним из ключевых драйверов эволюции геоинформационной картографии.
## Особенности веб-картографирования
Веб-картографирование наследует особенности геоинформационного картографирования и обладает собственными характерными чертами, к которым относятся:
1. Сетевая среда распространения
2. Интерактивность
3. Мультимасштабность
**Сетевая среда распространения** меняет подход к публикации картографических произведений. Карта генерируется для пользователя в момент запроса, поэтому обновление картографического содержания можно выполнять непрерывно без дополнительных действий пользователя. Например, изменение границ или переименование улиц не требует приобретения пользователем нового издания картографического произведения: если данные в картографическом произведении обновились, пользователь получит их при новом запросе.
Лучшие практики веб-разработки стимулируют активное использование **интерактивности** в картографическом произведении. Хотя возможности введения диалогового взаимодействия с картой появились на этапе компьютеризации картографии, по-настоящему доступной для широкого круга пользователей интерактивность карт стала именно с развитием Интернет-технологий. Пользователь по умолчанию ожидает возможности перемещения по карте, изменения масштаба, определения координат точки и получения дополнительной информации об объекте по клику. Часто веб-карта предоставляет и более широкие возможности, например, интерактивное изменение содержания карты, оформления слоёв, проекции, компоновки.
Одним из ключевых элементов интерактивности является функция изменения масштаба картографического изображения. Это требует от автора карты формирования **мультимасштабного** содержания или явного обозначения масштабов, которые соответствуют содержанию карты. Работа с мультимасштабным содержанием веб-карт должна начинаться на этапе проектирования.
Легко заметить соподчинённость выделенных особенностей. Веб-технологии способствуют вводу интерактивности в употребление. Активное использование интерактивности обуславливает мультимасштабность картографического содержания.
Кроме того веб-картографирование характеризуют
4. Общедоступность
5. Сходство с программным обеспечением
6. Расширение выразительности
Веб-ресурсы во Всемирной сети обычно являются **общедоступными**: обратиться к ним может любой пользователь, имеющий выход в Интернет. Возможно ограничение доступа к веб-ресурсу, например с помощью системы авторизации, однако сохраняется принципиальная доступность при наличии соответствующих прав. Картографические произведения в Интернете не исключение. Коммерциализация веб-карт базируется не на платном доступе к содержанию, а на широком доступе аудитории к содержанию карты, которое можно монетизировать, например, с помощью рекламы.
На этапе проектирования картографического произведения проявляются черты, характерные для разработки **программного обеспечения** и информационных систем; составление карт сводится к написанию программного кода, который генерирует экземпляр карты для каждого пользователя; изданием картографического произведения становится его публикация на веб-сайте.
Веб-технологии расширяют круг **выразительных средств**: появляется возможность использовать мультимедийные материалы (фото, аудио, видео), давать ссылки на другие веб-страницы, создавать интерактивные картографические анимации. Технически это реализуемо и на электронных картах, локально размещаемых на компьютере пользователя, однако активное использование новых выразительных средств характерно именно для веб-карт. Карта в веб-среде становится динамичной интерактивной моделью.
<Card title='Главная особенность веб-картографрования это'>
<Question answer="cетевая среда распространения" ballast={['интерактивность', 'использование стандартов']} explanation="Особенности веб-картографирования проистекают из сетевой среды распространения картографических материалов"/>
</Card>
Среди выделенных особенностей ключевой является сетевая среда распространения. Остальные особенности можно назвать производными от ключевой.
## Веб-картография
Наличие характерных особенностей позволяет говорить о веб-картографировании как о специфической деятельности, требующей рассмотрения в рамках отдельного направления — веб-картографии.
Реальная практика показывает, что сфера интересов веб-картографии не ограничивается изучаением процесса веб-картографирования. Это направление на пересечении картографии, геоинформатики и сетевых технологий.
![venn-web-mapping](../../../assets/venn-web-mapping.png)
Веб-картография изучает особенности оборота пространственных данных в сетевой среде. Так как эти особенности проявляются на всех этапах жизненного цикла веб-карты, то и в область интересов веб-картографии входит вся система создания-использования карт от сбора данных до чтения веб-карты пользователем. Внимание уделяется хранению, кодированию, передаче, обработке пространственных данных в сетевой среде, каталогизации и организации поиска пространственных данных, методологии разработки картографических веб-приложений, методам визуализации и интерактивного взаимодействия.
<Card title="Короче">
Веб-картографирование — это создание карт для распространения и использования в Интернете. Оно характеризуется сетевой средой распространения и производными от этого особенностями, в частности интерактивностью и мультимасштабностью.
Веб-картография формируется на пересечении сетевых технологий, картографии и геоинформатики изучает особенности оборота пространственных данных в сетевой среде, включая хранение, кодирование, передачу, обработку данных, разработку веб-приложений и другие аспекты.
</Card>
---
## Литература
1. ГОСТ Р 58570-2019. Инфраструктура Пространственных Данных. Общие Требования. Стандартинформ, 2019. [ссылка](https://docs.cntd.ru/document/1200168445)
1. Абдуллин Р. К., Пономарчук А. И. Технологии интернет-картографирования: учебное пособие / Пермский государственный национальный исследовательский университет. - Пермь, 2020. 132 с.: ил. [ссылка](https://gis.psu.ru/publications/технологии-интернет-картографирован/)
1. Берлянт А. М. Геоинформационное Картографирование. М.: Моск. гос. Ун-т им. М. В. Ломоносова, Рос. акад. естеств. наук, 1997. [ссылка](https://rusneb.ru/catalog/000199_000009_000611203/)
1. Каргашин П. Е. Основы цифровой картографии: Учебное пособие для бакалавров. 5-е изд., перераб. — Москва: Издательско-торговая корпорация Дашков и К, 2023. — 106 с. [ссылка](https://istina.msu.ru/publications/book/557759518/)
1. Лурье И.К., Самсонов Т.Е. Структура и содержание базы пространственных данных для мультимасштабного картографирования // Геодезия и картография. 2010. № 11. С. 17-23. [ссылка](https://istina.msu.ru/publications/article/427465/)
1. Титов Г. С., Прасолова А. И., Каргашин П. Е. Веб-картографирование ресурсов солнечной энергии Якутии // ИнтерКарто. ИнтерГИС. — 2021. — Т. 27, № 3. — С. 210220. [ссылка](https://istina.msu.ru/publications/article/412375618/)
1. Титов Г. С. Текущие проблемы терминологического аппарата отечественной веб-картографии // Геодезия, картография, геоинформатика и кадастры. Производство и образование : Сб. материалов IV Всероссийской науч.-практ. конф. — СПб Политехника: 2021. — С. 317323. [ссылка](https://istina.msu.ru/publications/article/716105082/)
1. Kraak M. J. Web Cartography: Developments and Prospects. Edited by M. J. Kraak and Allan Brown. New York: Taylor & Francis, 2001. [ссылка](https://doi.org/10.1201/9781482289237)
1. Muehlenhaus I. Web Cartography: Map Design for Interactive and Mobile Devices. Boca Raton, FL: CRC Press, 2014. [ссылка](https://doi.org/10.1201/b16229)
1. Neumann A. Web Mapping and Web Cartography. In Springer Handbook of Geographic Information, edited by Wolfgang Kresse and David M. Danko, 27387. Berlin, Heidelberg: Springer Berlin Heidelberg, 2011. [ссылка](https://doi.org/10.1007/978-3-540-72680-7_14)
1. Wind waves web atlas of the russian seas / Myslenkov S., Samsonov T., Shurygina A. et al. // Water. — 2023. — Vol. 15, no. 11. — P. 2036. [ссылка](http://dx.doi.org/10.3390/w15112036)

@ -0,0 +1,420 @@
---
title: Веб-карта
---
import { Card, FileTree, LinkCard } from '@astrojs/starlight/components';
import Question from '../../../components/Question.astro'
В этой главе
- понятие веб-карты
- типы веб-карт
- клиент и сервер
- HTML, CSS, JavaScript
## Карты в Интернете
Любую ли карту в Интернете можно назвать веб-картой?
> 2ГИС или Яндекс.Карты — конечно, да!
>
> Карты в формате JPEG, пересылаемые по электронной почте — пожалуй, нет.
>
> И между ними ещё огромное множество различных вариантов карт в Интернете.
### Определение веб-карты
Цель размещения карты в сети определяет веб-карту.
Файлам карт, передаваемым по сети, или размещаемым на сайтах, изображениям карт для печати, загрузки, иллюстрации, украшения будет отказано в праве называться веб-картой. А вот если карту разместили в Интернете для того, чтобы пользователи могли работать с ней по сети, то это веб-карта.
Другими словами, если целью размещения карты в сети является её публикация.
<Card title="Веб-карта —">это карта, предназначенная для использования в сети</Card>
### Типы веб-карт
Веб-карты можно разделить на интерактивные / неинтерактивные и статические / динамически
| | статические | динамические |
| --------------- | ------------------------------ | --------------------------- |
| неинтерактивные | карты-картинки | генераторы карт-картинок |
| интерактивные | "простые" веб-карты | картографические приложения |
Инерактивность подразумевает возможность пользователя перемещаться по карте, менять масштаб, получать подробную информацию по клику, скрывать слои, менять цвета и так далее. Неинтерактивные карты лишены этих возможностей. Но неинтерактивная карта будет веб-картой, если предназначена для использования в Интернете.
Статические веб-карты получают данные на клиент точно в том виде, в котором они хранятся на сервере, без какой-либо обработки. Из программного обеспечения требуется только веб-сервер, который будет принимать запросы от клиентов и возвращать в ответ файлы данных с сервера клиенту.
Динамические веб-карты подразумевают серверную обработку данных и позволяют запрашивать данные более гибко. Из программного обеспечения обычно используются база данных, программа для обработки данных и веб-сервер. В общем случае веб-сервер примет запрос и обратится к программе для обработки данных, она извлечёт данные из базы, обработает их и передаст веб-серверу, который отправит подготовленные данные клиенту.
Интерактивность касается интерфейса и клиентской части, а деление на статические и динамические веб-карты связано с обработкой данных в серверной части.
<LinkCard title='Другие продукты веб-картографии' href='/chapters/7-extra#другие-продукты-веб-картографии' description='Геопорталы, картографические веб-сервисы, веб-атласы, веб-ГИС'/>
## Клиент-серверная архитектура
Рассмотрим пример работы простого веб-ресурса.
![Схема клиент-серверной архитектуры](../../../assets/request.png)
*Схема клиент-серверной архитектуры*
Пользователь вводит адрес запрашиваемого веб-ресурса в адресную строку браузера и нажимает клавишу Enter (1). Браузер инициирует и выполняет запрос к серверу на получение данных для создания веб-страницы (2). Сервер возвращает ответ (3). Из этого ответа браузер формирует веб-страницу, которую видит пользователь (4).
<Card title="Короче">
Браузер -- это клиент. Сервер -- это сервер. Клиент обращается к серверу с запросом, сервер возвращает клиенту ответ. Вот суть клиент-серверной архитектуры.
</Card>
В реальности клиент может выполнять множество запросов к серверу, чтобы показать пользователю веб-страницу.
:::tip
Откройте инструменты разработчика, нажав на клавишу F12 или сочетание клавиш Ctrl+Shift+i, перейдите во вкладку Сеть (Network) и обновите страницу, чтобы увидеть, сколько запросов выполняет браузер, чтобы показать вашу любимую веб-страницу.
:::
Первый запрос инициирует пользователь выполняет путём ввода адреса. Дальнейшие действия пользователя на веб-странице могут инициировать последующие запросы. Запрашиваться могут как веб-страницы целиком, так и отдельные данные для обновления содержания текущей веб-страницы. Если мы обновляем только часть содержания веб-страницы данными с сервера, то речь идёт об асинхронном запросе.
![*Запросы, выполняемые с веб-страницы*](../../../assets/network-tab.png)
*Запросы, выполняемые с веб-страницы*
Веб-карты тоже строятся на основе клиент-серверной архитектуры. Рассмотрим интерактивную статическую карту.
Разметка, стили, логика (программный код) веб-карты, а также наборы пространственных данных веб-карты хранятся на сервере. Пользователь вводит адрес карты. Браузер запрашивает с сервера разметку веб-карты (html). Разметка приходит в браузер. Разметра содержит запросы к стилям и логике веб-карты. Логика веб-карты приходит в браузер и запрашивает наборы пространственных данных для создания веб-карты. Пространственные данные приходят [Взаимодействие с сервером закончено!] и кодом веб-карты превращаются в картографические слои.
<Card title='В клиент-серверной архитектуре браузер это'>
<Question answer="клиент" ballast={['сервер', 'пользователь']} explanation="Пользователь использует браузер (клиент), чтобы выполнить запрос к серверу"/>
</Card>
## Создание первой веб-карты
Мы рассмотрели интерактивную статическую карту, а сейчас мы её сделаем своими руками!
Выделим нашей первой веб-карте отдельную папку.
> В качестве среды разработки можно использовать [VS Code](https://code.visualstudio.com/), а чтобы запустить сервер -- расширение [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer).
### Инициализация карты
Создадим файл разметки `index.html`.
```html title="index.html"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Население мира</title>
<!-- Запрашиваем стили 👇 -->
<link rel="stylesheet" href="style.css">
<!-- Запрашиваем библиотеку Maplibre 👇 -->
<script src="https://unpkg.com/maplibre-gl@^4.7.1/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@^4.7.1/dist/maplibre-gl.css" rel="stylesheet" />
</head>
<body>
<!-- Размечаем контейнер для карты 👇 -->
<div id="map"></div>
<!-- Запрашиваем логику карты 👇 -->
<script src="main.js"></script>
</body>
</html>
```
Библиотеку Maplibre мы запрашиваем из внешнего ресурса, а вот стили и логику карты нам нужно создать.
Создадим файл стилей `style.css`.
```css title="style.css"
body {
margin: 0;
}
/* Объявляем, что контейнер карты должен занимать всю страницу */
#map {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
```
И файл с логикой карты `main.js`.
```js title="main.js"
// Инициализируем карту
const map = new maplibregl.Map({
container: 'map',
style: "https://raw.githubusercontent.com/gtitov/basemaps/refs/heads/master/positron-nolabels.json",
center: [51, 0],
zoom: 4
});
```
После этого запустим Live Server, перейдём по адресу локального сервера и увидим карту.
> Наименование файла `index.html` важно тем, что именно страница `index.html` загружается при обращении к корневому URL. Наименования файлов CSS и JavaScript особой роли не играют.
>
> Страница HTML является ключевой. Ей необходимо дать информацию о том, какие внешние библиотеки и файлы будут использоваться. В частности `style.css` и `main.js` являются внешними файлами. Для локальных файлов мы можем ввести относительные адреса. Удалённые (находящиеся на внешнем сервере) файлы необходимо подключать по URL.
>
> В роли сервера может выступать компьютер, за которым вы работаете. Веб-сервер, запущенный на компьютере, достуен с этого комьютера по IP-адресу `127.0.0.1` или `localhost`. Это внутренний адрес. Он будет одним и тем же у всех компьютеров. И он недоступен для запросов снаружи.
### Добавление слоёв
Создадим подпапку `data` и загрузим в неё данные о [странах](https://raw.githubusercontent.com/gtitov/geojson-maplibre-map/refs/heads/master/data/countries.geojson), [городах](https://raw.githubusercontent.com/gtitov/geojson-maplibre-map/refs/heads/master/data/cities.geojson), [реках](https://raw.githubusercontent.com/gtitov/geojson-maplibre-map/refs/heads/master/data/rivers.geojson) и [озёрах](https://raw.githubusercontent.com/gtitov/geojson-maplibre-map/refs/heads/master/data/lakes.geojson).
Должна получится такая структура. HTML отвечает за структуру веб-страницы, CSS за оформление веб-страницы, JavaScript за логику работы веб-страницы. GeoJSON файлы хранят пространственные данные.
<FileTree>
- data/ # данные
- cities.geojson # города
- countries.geojson # страны
- lakes.geojson # озёра
- rivers.geojson # реки
- index.html # разметка
- style.css # стили
- main.js # логика
</FileTree>
Все действия с картой выполняются после первичной загрузки исходной карты.
Добавление картографических слоёв включает два шага: добавление источника данных `addSource` и добавление слоя `addLayer`. На первом шаге указываем, откуда мы будем брать данные, а на втором, как их оформить. Из одного источника можно создать несколько слоёв.
```js title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
// Добавление источника данных
map.addSource('countries', {
type: 'geojson',
data: './data/countries.geojson',
attribution: 'Natural Earth'
})
// Добавление слоя
map.addLayer({
id: 'countries-layer',
type: 'fill',
source: 'countries',
paint: {
'fill-color': 'lightgray',
}
})
})
```
Мы добавили полигональный слой (`type: 'fill'`). Аналогично добавляем слой линий и слой точек.
```js title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.addSource('rivers', {
type: 'geojson',
data: './data/rivers.geojson'
})
map.addLayer({
id: 'rivers-layer',
type: 'line',
source: 'rivers',
paint: {
'line-color': '#00BFFF'
}
})
map.addSource('lakes', {
type: 'geojson',
data: './data/lakes.geojson'
})
map.addLayer({
id: 'lakes-layer',
type: 'fill',
source: 'lakes',
paint: {
'fill-color': 'lightblue',
'fill-outline-color': '#00BFFF'
}
})
map.addSource('cities', {
type: 'geojson',
data: './data/cities.geojson'
})
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities',
paint: {
'circle-color': 'rgb(123, 12, 234)',
'circle-radius': 3
}
})
})
```
В MapLibre слои можно фильтровать и оформлять на основе атрибутов с помощью [выражений](https://maplibre.org/maplibre-style-spec/expressions/).
Например, оставим только города с численностью населения больше 1 000 000
```diff lang="js" title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities',
paint: {
'circle-color': 'rgb(123, 12, 234)',
'circle-radius': 3
},
+ filter: ['>', ['get', 'POP_MAX'], 1000000]
})
})
```
Изобразим красным (`red`) цветом страны, у которых атрибут `MAPCOLOR7` равен 1, а остальные изобразим светло-серым (`lightgray`)
```diff lang="js" title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.addLayer({
id: 'countries-layer',
type: 'fill',
source: 'countries',
paint: {
- 'fill-color': 'lightgray',
+ 'fill-color': ['match', ['get', 'MAPCOLOR7'], 1, 'red', 'lightgray']
}
})
...
})
```
### Расширение интерактивности
Созданная нами карта сразу даёт пользователю возможности перемещения, зума и даже наклона (попробуйте зажать правую кнопку мыши). Однако чтобы, например, выводить атрибутивные сведения о слое по клику, надо указать это в коде.
Отследим событие клика по слою `cities-layer`. Назовём событие клика переменной `e`. Посмотрим в консоли браузера, что собой представляет это событие. Если мы отслеживаем событие клика по конкретному слою, а не по всей карте, то мы можем обратиться к набору объектов, по которым был выполнен клик `e.features`
```js title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.on('click', ['cities-layer'], (e) => {
console.log(e)
console.log(e.features)
})
})
```
Закомментируем вывод в консоль. Создадим попап. Установим его на координатах кликнутого объекта. Заполним попап текстом из атрибута с именем объекта. Добавим попап на карте.
```js title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.on('click', ['cities-layer'], (e) => {
// console.log(e)
// console.log(e.features)
new maplibregl.Popup() // создадим попап
.setLngLat(e.features[0].geometry.coordinates) // установим на координатах объекта
.setHTML(e.features[0].properties.NAME) // заполним текстом из атрибута с именем объекта
.addTo(map); // добавим на карту
})
})
```
Попап отображается, но надо показать пользователю, что на объект можно кликать. При попадании мыши на слой `cities-layer` поменяем курсор на pointer, а при покидании слоя `cities-layer` вернём значение по умолчанию.
```js title="main.js"
// Инициализируем карту
...
map.on('load', () => {
// Выполняется после загрузки карты
...
map.on('mouseenter', 'cities-layer', () => {
map.getCanvas().style.cursor = 'pointer'
})
map.on('mouseleave', 'cities-layer', () => {
map.getCanvas().style.cursor = ''
})
})
```
В качестве завершающего штриха уберём карту подложку и добавим фон. При этом фон добавляем перед всеми слоями, так как все слои должны рисоваться после фона, поверх него.
```diff lang="js" title="main.js"
// Инициализируем карту
const map = new maplibregl.Map({
container: 'map',
- style: "https://raw.githubusercontent.com/gtitov/basemaps/refs/heads/master/positron-nolabels.json",
+ style: {
+ "version": 8,
+ "sources": {},
+ "layers": []
+ },
center: [51, 0],
zoom: 4
});
map.on('load', () => {
// Выполняется после загрузки карты
+ map.addLayer({
+ id: 'background',
+ type: 'background',
+ paint: {
+ 'background-color': 'lightblue'
+ }
+ })
...
})
```
У нас получилась отличная карта!
При желании посмотрите [полный код](https://github.com/gtitov/geojson-maplibre-map) и [возможный результат](https://gtitov.github.io/geojson-maplibre-map/).
### Что мы получили
Откроем вкладку Сеть в инструментах разработчика и ещё разок проследим поток данных
![geojson-network-tab](../../../assets/geojson-network-tab.png)
1. Пользователь вводит адрес карты в браузере (в клиенте)
1. Клиент выполняет запрос к серверу по введённому адресу
1. Сервер обрабатывает запрос и возвращает разметку (HTML) (1)
1. В разметке содержаться запросы к офомлению (CSS), картографической библиотеке (MapLibre) и программной логике работы (JavaScript) веб-страницы (2)
1. Клиент (браузер), получив все необходимые сведения, отображает веб-страницу
1. Программная логика работы полученной веб-страницы выполняется и в соотстветвии с кодом инициирует запросы к данным (GeoJSON) для составления карты (3)
1. Полученные данные оформляются на веб-карте в рамках описанной разработчиком на языке JavaScript логики с использованием функций библиотеки MapLibre
1. Пользователь получает веб-карту
1. Веб-карта обогащается дополнительной интерактивностью в рамках описанной разработчиком логики
Такая карта удобна, когда немного данных, потому что мы всё переправляем пользователю данные как есть. Когда мы отправляем пользователю данные как есть, почти не требуется серверных мощностей, поэтому для таких карт есть варианты бесплатного размещения в Интернете.
### Упражнения
1. Покрасьте Москву в красный цвет
2. Выведите в попап один из атрибутов странах
3. Добавьте слой с границами озёр, установите им толщину в 2 пикселя
4. Замените курсор на перекрестие (`crosshair`) при расположении поверх стран

@ -0,0 +1,15 @@
---
title: Внеклассное чтение
---
В этом разделе содержатся дополнительные материалы
## Другие продукты веб-картографии
Определения для продуктов веб-картографии можно получить, добавляя к традиционному определению ГИС, глобуса, атласа “предназначенный для использования в Интернете” или “в компьютерных сетях”. Тогда отличие между, например, веб-ГИС и веб-атласом становится очевидным.
> Веб-ГИС должна не только визуализировать данные, но и реализовывать функции хранения, передачи, обработки пространственных данных
Отдельно стоит упомянуть геопортал и картографические веб-сервисы. Их мы формируем от родовых IT-терминов приземляя к картографии и пространственным данным. *Геопортал* — это веб-ресурс, предоставляющий доступ к каталогам пространственных данных, наборам пространственных данных, веб-сервисам, публикующим пространственные данные. *Картографический веб-сервис* — это веб-ресурс, предоставляющий возможности обращения к пространственным данным или метаданным, в т. ч. по стандартизированным протоколам обмена (WMS, WFS, WCS и т. д.). Картографические веб-сервисы обычно не имеют графического интерфейса пользователя, к этим сервисам обращаются программно через API (прикладной программный интерфейс).
Этими терминами злоупотребляют по отношению к любым веб-ресурсам, связанным с пространственными данными и картами. Картографические продукты, публикуемые в сети, правильнее объединить под названием *картографические веб-ресурсы*, так как они являются веб-ресурсами, основным назначением которых является предоставление доступа к картографической информации.

@ -0,0 +1,10 @@
---
title: Обзор содержания
tableOfContents: false
---
Курс широкими мазками обрисовывает картину веб-картографии, акцентируя внимание на принципах, ключевых компонентах, их взаимодействии.
Главный способ донесения информации -- практика. Мы создадим 4 функциональные веб-карты. Каждая из них может быть самодостаточным решением для ряда задач. Каждая карта сопровождается необходимым объёмом теоретических сведений для осознанного освоения практических навыков.
Опираясь на полученный опыт, мы зафиксируем походы к самостоятельной разработке веб-карт и пути дальнейшего развития в сфере веб-картографии.

@ -1,11 +0,0 @@
---
title: Example Guide
description: A guide in my new Starlight docs site.
---
Guides lead a user through a specific task they want to accomplish, often with a sequence of steps.
Writing a good guide requires thinking about what your users are trying to do.
## Further reading
- Read [about how-to guides](https://diataxis.fr/how-to-guides/) in the Diátaxis framework

@ -1,36 +0,0 @@
---
title: Welcome to Starlight
description: Get started building your docs site with Starlight.
template: splash
hero:
tagline: Congrats on setting up a new Starlight project!
image:
file: ../../assets/houston.webp
actions:
- text: Example Guide
link: /guides/example/
icon: right-arrow
- text: Read the Starlight docs
link: https://starlight.astro.build
icon: external
variant: minimal
---
import { Card, CardGrid } from '@astrojs/starlight/components';
## Next steps
<CardGrid stagger>
<Card title="Update content" icon="pencil">
Edit `src/content/docs/index.mdx` to see this page change.
</Card>
<Card title="Add new content" icon="add-document">
Add Markdown or MDX files to `src/content/docs` to create new pages.
</Card>
<Card title="Configure your site" icon="setting">
Edit your `sidebar` and other config in `astro.config.mjs`.
</Card>
<Card title="Read the docs" icon="open-book">
Learn more in [the Starlight Docs](https://starlight.astro.build/).
</Card>
</CardGrid>

@ -1,11 +0,0 @@
---
title: Example Reference
description: A reference page in my new Starlight docs site.
---
Reference pages are ideal for outlining how things work in terse and clear terms.
Less concerned with telling a story or addressing a specific use case, they should give a comprehensive outline of what you're documenting.
## Further reading
- Read [about reference](https://diataxis.fr/reference/) in the Diátaxis framework

@ -1,3 +1,7 @@
{
"extends": "astro/tsconfigs/strict"
"extends": "astro/tsconfigs/strict",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}
Loading…
Cancel
Save