Знакомство с кальцитом с помощью Svelte


Веб-компоненты

Если вы хоть сколько-нибудь долго создаете веб-приложения, вы наверняка сталкивались с веб-компонентами. Веб-компоненты могут многое предложить. Они позволяют создать набор общих компонентов, которые можно использовать везде, независимо от используемого фреймворка. Я не буду подробно останавливаться на этом, но хочу подчеркнуть, что вы можете использовать библиотеку Web-компонентов, например Calcite Components, в своих собственных приложениях. Сегодня использовать Web-компоненты в некоторых фреймворках проще, чем в других. Одним из самых дружелюбных является Svelte.

В этом посте мы будем следовать этому руководству по Calcite Components, чтобы создать картографическое приложение, но с использованием Svelte!

Исходный код для демонстрации в этой статье находится на github.

Начало работы

Вы можете прочитать отличное введение по использованию Svelte с ArcGIS API for JavaScript в блоге Esri.

Мы можем начать создание приложения Svelte с помощью Vite, и да, я использую Vite практически для всего.

npm init @vitejs/app svelte-calcite
cd svelte-calcite
npm install @arcgis/core
Вход в полноэкранный режим Выход из полноэкранного режима

После установки мы можем установить ArcGIS API for JavaScript. Вместе с ним будет установлена библиотека Calcite Components. На этом этапе мы можем очистить файлы css и .svelte в приложении scaffold. Мы можем добавить несколько основных CSS для начала работы.

/** app.css **/
@import "https://js.arcgis.com/calcite-components/1.0.0-beta.86/calcite.css";
@import "https://js.arcgis.com/4.24/esri/themes/light/main.css";

html,
body,
#app {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Создание картографического приложения

Затем мы можем начать обновлять наш компонент App.svelte, следуя руководству по созданию картографического приложения. Мы можем просто начать с HTML-скелета приложения.

<calcite-shell content-behind>
    <h2 id="header-title" slot="header">
    <!-- Dynamically populated -->
    </h2>
    <calcite-shell-panel slot="primary-panel" detached>
    </calcite-shell-panel>
    <div class="viewDiv"></div>
</calcite-shell>
Вход в полноэкранный режим Выход из полноэкранного режима

Это базовая оболочка для приложения, но нам все еще нужно подключить ее к некоторым другим компонентам, чтобы отобразить карту.

<script>
  // calcite components
  import "@esri/calcite-components/dist/components/calcite-shell";
  import "@esri/calcite-components/dist/components/calcite-shell-panel";

  // arcgis js api
  import config from "@arcgis/core/config";
  import WebMap from "@arcgis/core/WebMap";
  import MapView from "@arcgis/core/views/MapView";

  import { onMount } from "svelte";

  config.apiKey = import.meta.env.VITE_API_KEY;

  let viewContainer;

  let item = {};

  onMount(() => {
    const map = new WebMap({
      portalItem: {
        id: "cc3bd744b9a44feaa493dd867a1d48dd",
      },
    });
    const view = new MapView({
      container: viewContainer,
      map,
      padding: {
        left: 49,
      },
    });

    view.ui.move("zoom", "bottom-right");

    map.when(() => {
      item = map.portalItem;
    });
  });
</script>
Вход в полноэкранный режим Выход из полноэкранного режима

Для начала мы делаем несколько вещей. Во-первых, мы импортируем модули из Calcite Components, которые мы уже использовали в нашем приложении. Если мы этого не сделаем, они не зарегистрируются как пользовательские элементы и не будут отображаться. Затем мы определяем пару переменных, на которые можно ссылаться на странице. В Svelte есть очень четкий способ привязки переменных и придания им реактивности. Это глоток свежего воздуха, исходящий от некоторых других фреймворков. Переменная viewContainer будет использоваться как ссылка на элемент, в котором мы можем отобразить нашу карту, а объект item может быть использован для отображения текста.

<calcite-shell content-behind>
    <h2 id="header-title" slot="header">
    {item.title || "...loading"}
    </h2>
    <calcite-shell-panel slot="primary-panel" detached>
    </calcite-shell-panel>
    <div class="viewDiv" bind:this={viewContainer} />
</calcite-shell>
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что мы просто ссылаемся на item.title, и когда мы обновим эту переменную, она будет отражена на нашей странице. Мы используем синтаксис bind:this для привязки переменной viewContainer к элементу div. Синтаксис this относится к элементу, для которого вы используете синтаксис bind:. Мне очень нравится этот API.

Следующим шагом в этом руководстве будет настройка панели действий и панелей, куда будет помещен виджет.

<calcite-shell content-behind>
  <h2 id="header-title" slot="header">
    {item.title || "...loading"}
  </h2>
  <calcite-shell-panel slot="primary-panel" detached>
    <calcite-action-bar slot="action-bar">
      <calcite-action data-action-id="layers" icon="layers" text="Layers" />
      <calcite-action
        data-action-id="basemaps"
        icon="basemap"
        text="Basemaps"
      />
      <calcite-action data-action-id="legend" icon="legend" text="Legend" />
      <calcite-action
        data-action-id="bookmarks"
        icon="bookmark"
        text="Bookmarks"
      />
      <calcite-action data-action-id="print" icon="print" text="Print" />
      <calcite-action
        data-action-id="information"
        icon="information"
        text="Information"
      />
    </calcite-action-bar>

    <calcite-panel
      heading="Layers"
      height-scale="l"
      data-panel-id="layers"
      hidden
    >
      <div id="layers-container" bind:this={layerListContainer} />
    </calcite-panel>
    <calcite-panel
      heading="Basemaps"
      height-scale="l"
      data-panel-id="basemaps"
      hidden
    >
      <div id="basemaps-container" bind:this={bmgContainer} />
    </calcite-panel>
    <calcite-panel
      heading="Legend"
      height-scale="l"
      data-panel-id="legend"
      hidden
    >
      <div id="legend-container" bind:this={legendContainer} />
    </calcite-panel>
    <calcite-panel
      heading="Bookmarks"
      height-scale="l"
      data-panel-id="bookmarks"
      hidden
    >
      <div id="bookmarks-container" bind:this={bookmarksContainer} />
    </calcite-panel>
    <calcite-panel
      heading="Print"
      height-scale="l"
      data-panel-id="print"
      hidden
    >
      <div id="print-container" bind:this={printContainer} />
    </calcite-panel>
    <!-- Info panel (populates with info from the web map) -->
    <calcite-panel heading="Details" data-panel-id="information" hidden>
      <div id="info-content">
        <img
          id="item-thumbnail"
          alt="webmap thumbnail"
          src={item.thumbnailUrl}
        />
        <div id="item-description">
          <!-- Dynamically populated -->
          {item.description}
        </div>
        <calcite-label layout="inline">
          <b>Rating:</b>
          <calcite-rating id="item-rating" read-only>
            <!-- Dynamically populated -->
            {item.avgRating}
          </calcite-rating>
        </calcite-label>
      </div>
    </calcite-panel>
  </calcite-shell-panel>
  <div class="viewDiv" bind:this={viewContainer} />
</calcite-shell>
Вход в полноэкранный режим Выход из полноэкранного режима

Итак, теперь мы многое добавили. У нас есть еще несколько компонентов и панель действий, которая позволяет нам добавлять кнопки и переключать видимость некоторых виджетов. Мы используем тот же синтаксис bind:this, который мы использовали ранее. Поскольку мы добавили больше компонентов, нам нужно импортировать еще несколько модулей, плюс мы можем начать инициализацию наших виджетов.

<script>
  // calcite components
  import "@esri/calcite-components/dist/components/calcite-shell";
  import "@esri/calcite-components/dist/components/calcite-shell-panel";
  import "@esri/calcite-components/dist/components/calcite-action";
  import "@esri/calcite-components/dist/components/calcite-action-bar";
  import "@esri/calcite-components/dist/components/calcite-panel";
  import "@esri/calcite-components/dist/components/calcite-label";
  import "@esri/calcite-components/dist/components/calcite-rating";

  // arcgis js api
  import config from "@arcgis/core/config";
  import WebMap from "@arcgis/core/WebMap";
  import MapView from "@arcgis/core/views/MapView";
  import Bookmarks from "@arcgis/core/widgets/Bookmarks";
  import BasemapGallery from "@arcgis/core/widgets/BasemapGallery";
  import LayerList from "@arcgis/core/widgets/LayerList";
  import Legend from "@arcgis/core/widgets/Legend";
  import Print from "@arcgis/core/widgets/Print";
  import { onMount } from "svelte";

  config.apiKey = import.meta.env.VITE_API_KEY;

  let viewContainer;

  let bookmarksContainer;
  let bmgContainer;
  let layerListContainer;
  let legendContainer;
  let printContainer;

  let item = {};

  onMount(() => {
    const map = new WebMap({
      portalItem: {
        id: "cc3bd744b9a44feaa493dd867a1d48dd",
      },
    });
    const view = new MapView({
      container: viewContainer,
      map,
      padding: {
        left: 49,
      },
    });

    view.ui.move("zoom", "bottom-right");

    const basemaps = new BasemapGallery({
      view,
      container: bmgContainer,
    });
    const bookmarks = new Bookmarks({
      view,
      container: bookmarksContainer,
    });
    const layerList = new LayerList({
      view,
      selectionEnabled: true,
      container: layerListContainer,
    });
    const legend = new Legend({
      view,
      container: legendContainer,
    });
    const print = new Print({
      view,
      container: printContainer,
    });

    map.when(() => {
      item = map.portalItem;
    });
  });
</script>
Вход в полноэкранный режим Выход из полноэкранного режима

На данный момент наше приложение почти готово. За исключением того, что у нас пока нет возможности переключать виджеты. В учебнике по отображению есть синтаксис кода, который мы можем использовать в точности как есть.

let activeWidget;

const handleActionBarClick = ({ target }) => {
if (target.tagName !== "CALCITE-ACTION") {
    return;
}

if (activeWidget) {
    document.querySelector(`[data-action-id=${activeWidget}]`).active = false;
    document.querySelector(`[data-panel-id=${activeWidget}]`).hidden = true;
}

const nextWidget = target.dataset.actionId;
if (nextWidget !== activeWidget) {
    document.querySelector(`[data-action-id=${nextWidget}]`).active = true;
    document.querySelector(`[data-panel-id=${nextWidget}]`).hidden = false;
    activeWidget = nextWidget;
} else {
    activeWidget = null;
}
};
Войти в полноэкранный режим Выйти из полноэкранного режима

Нам просто нужно добавить слушателя событий на панель действий.

<calcite-action-bar slot="action-bar" on:click={handleActionBarClick}>
...
</calcite-action-bar>
Вход в полноэкранный режим Выход из полноэкранного режима

Синтаксис on:eventname — это то, как вы можете добавлять слушателей событий в Svelte.

Теперь наше приложение завершено, и вы можете просматривать карту и переключать виджеты.

Резюме

Я не являюсь опытным пользователем Svelte, но он быстро набирает обороты. Любой фреймворк, который может облегчить мне использование веб-компонентов, мне нравится. Calcite Components также является отличной библиотекой веб-компонентов для создания приложений ArcGIS Platform.

Вы можете посмотреть это видео для получения дополнительной информации!

Оцените статью
devanswers.ru
Добавить комментарий