diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b05cb3..a15e6ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,21 +1,26 @@ name: Release mapgl-gltf on: - release: - types: [created] + release: + types: [created] jobs: - - release-mapgl-gltf: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 16 - registry-url: https://registry.npmjs.org/ - - run: npm ci - - run: npm run build - - run: npm publish --access public - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} + release-mapgl-gltf: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + registry-url: https://registry.npmjs.org/ + - run: npm ci + - run: npm run build + - run: echo $GITHUB_REF_NAME + - run: | + if [[ $GITHUB_REF_NAME == v1.* ]]; then + npm publish --access public --tag ver.1 + else + npm publish --access public + fi + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/README.md b/README.md index 8aa3429..73b950a 100644 --- a/README.md +++ b/README.md @@ -35,18 +35,6 @@ plugin.addModels([{ }]); ``` -## Release - -1. Update the package version by running `npm version patch|minor|major`. This command returns a new package version. Let assume it's 1.2.3 -1. Push changes to github and merge them to the «master» branch -1. Go to https://github.com/2gis/mapgl-gltf/releases/new -1. Click the «Choose tag» button and create a new tag according to the version in package.json, for example v1.2.3 -1. Make sure the release target is the «master» branch -1. Paste the release tag into the «Release title» field, for example v1.2.3 -1. Add a release description -1. Click the «Publish release» button -1. Go to https://github.com/2gis/mapgl-gltf/actions and wait for completing the release workflow - ## Testing If you write screenshot tests, you will need run `npm run docker:test` after coding. @@ -55,4 +43,4 @@ This guarantees the authenticity of the screenshots used. ## Documentation -You can find the more information in the official [documentation](https://docs.2gis.ru/ru/mapgl/examples/gltf-plugin). +You can find the more information in the official [documentation](https://docs.2gis.com/en/mapgl/immersive/gltf2-plugin). diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000..e943fca --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,28 @@ +## Release v2 + +**All changes have to be made on «master» branch.** + +1. Update the package version by running `npm version patch|minor`. This command returns a new package version. Let assume it's 2.3.4 +1. Push changes to github and merge them to the «master» branch +1. Go to https://github.com/2gis/mapgl-gltf/releases/new +1. Click the «Choose tag» button and create a new tag according to the version in package.json, for example v2.3.4 +1. Make sure the release target is the «master» branch +1. Paste the release tag into the «Release title» field, for example v2.3.4 +1. Add a release description +1. Click the «Publish release» button +1. Go to https://github.com/2gis/mapgl-gltf/actions and wait for completing the release workflow + +## Release v1 + +**All changes have to be made on «plugin-v1» branch.** + +1. Update the package version by running `npm version patch|minor`. This command returns a new package version. Let assume it's 1.2.3 +1. Push changes to github and merge them to the «plugin-v1» branch +1. Go to https://github.com/2gis/mapgl-gltf/releases/new +1. Click the «Choose tag» button and create a new tag according to the version in package.json, for example v1.2.3 +1. Make sure the release target is the «plugin-v1» branch +1. Paste the release tag into the «Release title» field, for example v1.2.3 +1. Add a release description +1. Unset the «Set as the latest release» checkbox because version 1 release can't be the latest +1. Click the «Publish release» button +1. Go to https://github.com/2gis/mapgl-gltf/actions and wait for completing the release workflow \ No newline at end of file diff --git a/demo/index.ts b/demo/index.ts index 3cbc863..6db198f 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -37,7 +37,6 @@ async function start() { }) .getContainer() .addEventListener('click', () => { - plugin.removeRealtyScene(); plugin.addRealtyScene(REALTY_SCENE); }); @@ -54,7 +53,6 @@ async function start() { }) .getContainer() .addEventListener('click', () => { - plugin.removeRealtyScene(); plugin.addRealtyScene(REALTY_SCENE_1, { buildingId: 'ds321ba234cb', }); @@ -68,6 +66,22 @@ async function start() { plugin.removeRealtyScene(); }); + new mapglAPI.Control(map, '', { + position: 'topLeft', + }) + .getContainer() + .addEventListener('click', () => { + plugin.hideRealtyScene(); + }); + + new mapglAPI.Control(map, '', { + position: 'topLeft', + }) + .getContainer() + .addEventListener('click', () => { + plugin.showRealtyScene(); + }); + new mapglAPI.Control(map, '', { position: 'topLeft', }) diff --git a/demo/mocks.ts b/demo/mocks.ts index 963a2ae..c8d3b5c 100644 --- a/demo/mocks.ts +++ b/demo/mocks.ts @@ -45,6 +45,7 @@ export const REALTY_SCENE: BuildingOptions[] = [ elevation: 5, fontSize: 12, fontColor: '#3a3a3a', + interactive: true, labels: [ { coordinates: [47.245048150280994, 56.134470449142164], @@ -75,6 +76,7 @@ export const REALTY_SCENE: BuildingOptions[] = [ elevation: 5, fontSize: 12, fontColor: '#3a3a3a', + interactive: true, labels: [ { coordinates: [47.245350349632965, 56.134414208205776], @@ -125,6 +127,7 @@ export const REALTY_SCENE: BuildingOptions[] = [ elevation: 35, fontSize: 12, fontColor: '#fff', + interactive: true, labels: [ { coordinates: [47.245048150280994, 56.134470449142164], @@ -204,6 +207,7 @@ export const REALTY_SCENE: BuildingOptions[] = [ elevation: 7, fontSize: 12, fontColor: '#3a3a3a', + interactive: true, labels: [ { coordinates: [47.24452417991248, 56.13469284843933], @@ -275,6 +279,7 @@ export const REALTY_SCENE: BuildingOptions[] = [ elevation: 53, fontSize: 12, fontColor: '#fff', + interactive: true, labels: [ { coordinates: [47.24452417991248, 56.13469284843933], diff --git a/package-lock.json b/package-lock.json index 5d3a9b5..1ef0f36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@2gis/mapgl-gltf", - "version": "1.3.1", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@2gis/mapgl-gltf", - "version": "1.3.1", + "version": "2.0.0", "license": "BSD-2-Clause", "devDependencies": { - "@2gis/mapgl": "1.46.0", + "@2gis/mapgl": "^1.47.0", "@documentalist/compiler": "^2.8.1", "@types/geojson": "^7946.0.10", "@types/jest": "^27.4.0", @@ -36,9 +36,9 @@ } }, "node_modules/@2gis/mapgl": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@2gis/mapgl/-/mapgl-1.46.0.tgz", - "integrity": "sha512-fHgVnzNXMof3cZ1vBcZMMGcUdjtQNOG5pymJyaeVg01rkHEEvhg8zupcjYlqnCDaATR33mItV/f0/N9bGiMKmg==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@2gis/mapgl/-/mapgl-1.47.0.tgz", + "integrity": "sha512-aAMXb/+AveKZeusP/ZU/wCtI20F3nyH4pX99E6OpVJjRIL8jhGptyxpP45oPaGozG+3fZypoQVFp8lb7tMYKGQ==", "dev": true, "dependencies": { "@types/geojson": "^7946.0.7" @@ -10553,9 +10553,9 @@ }, "dependencies": { "@2gis/mapgl": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@2gis/mapgl/-/mapgl-1.46.0.tgz", - "integrity": "sha512-fHgVnzNXMof3cZ1vBcZMMGcUdjtQNOG5pymJyaeVg01rkHEEvhg8zupcjYlqnCDaATR33mItV/f0/N9bGiMKmg==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/@2gis/mapgl/-/mapgl-1.47.0.tgz", + "integrity": "sha512-aAMXb/+AveKZeusP/ZU/wCtI20F3nyH4pX99E6OpVJjRIL8jhGptyxpP45oPaGozG+3fZypoQVFp8lb7tMYKGQ==", "dev": true, "requires": { "@types/geojson": "^7946.0.7" diff --git a/package.json b/package.json index e7babad..3910765 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@2gis/mapgl-gltf", - "version": "1.3.1", + "version": "2.0.0", "description": "Plugin for the rendering glTF models with MapGL", "main": "dist/bundle.js", "typings": "dist/types/index.d.ts", @@ -9,7 +9,6 @@ "url": "https://github.com/2gis/mapgl-gltf.git" }, "files": [ - "dist/libs", "dist/types", "dist/docs.json", "dist/*.LICENSE.txt" @@ -37,7 +36,7 @@ "author": "2GIS WebMaps Team", "license": "BSD-2-Clause", "devDependencies": { - "@2gis/mapgl": "1.46.0", + "@2gis/mapgl": "^1.47.0", "@documentalist/compiler": "^2.8.1", "@types/geojson": "^7946.0.10", "@types/jest": "^27.4.0", diff --git a/src/control/index.ts b/src/control/index.ts index ec964f3..14adaf0 100644 --- a/src/control/index.ts +++ b/src/control/index.ts @@ -1,5 +1,5 @@ import type { Map as MapGL, ControlOptions } from '@2gis/mapgl/types'; -import type { ControlShowOptions, FloorLevel } from './types'; +import type { ControlShowOptions } from './types'; import icon_building from 'raw-loader!./icon_building.svg'; import icon_parking from 'raw-loader!./icon_parking.svg'; diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts index 4f74b82..d83dcbd 100644 --- a/src/defaultOptions.ts +++ b/src/defaultOptions.ts @@ -1,3 +1,4 @@ +import { DEFAULT_FONT_COLOR, DEFAULT_FONT_SIZE, DEFAULT_IMAGE } from './labelGroups'; import type { PluginOptions } from './types/plugin'; export const defaultOptions: Required = { @@ -6,6 +7,11 @@ export const defaultOptions: Required = { }, modelsBaseUrl: '', modelsLoadStrategy: 'waitAll', + labelGroupDefaults: { + fontSize: DEFAULT_FONT_SIZE, + fontColor: DEFAULT_FONT_COLOR, + image: DEFAULT_IMAGE, + }, floorsControl: { position: 'centerLeft', }, diff --git a/src/labelGroups.ts b/src/labelGroups.ts index da8923b..c5f9084 100644 --- a/src/labelGroups.ts +++ b/src/labelGroups.ts @@ -1,10 +1,13 @@ import type { Map as MapGL, Label, LabelImage } from '@2gis/mapgl/types'; import type { BuildingState, LabelGroupOptions, PluginOptions } from './types/plugin'; import type { GltfPlugin } from './plugin'; -// import { pluginEvents } from './constants'; -// import { createLabelEvenData } from './utils/events'; +import { pluginEvents } from './constants'; +import { createLabelEvenData } from './utils/events'; -const DEFAULT_IMAGE: LabelImage = { +const DEFAULT_INTERACTIVE = false; +export const DEFAULT_FONT_SIZE = 14; +export const DEFAULT_FONT_COLOR = '#000000'; +export const DEFAULT_IMAGE: LabelImage = { url: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHJ4PSI0IiBmaWxsPSIjZWFlYWVhIi8+PHJlY3QgeD0iMSIgeT0iMSIgd2lkdGg9IjI2IiBoZWlnaHQ9IjI2IiByeD0iMyIgZmlsbD0id2hpdGUiLz48L3N2Zz4=', size: [38, 38], stretchX: [[4, 24]], @@ -30,27 +33,39 @@ export class LabelGroups { return; } - const { image, minZoom, maxZoom, fontColor: color, fontSize } = groupOptions; + const { + image, + minZoom, + maxZoom, + fontColor, + fontSize, + elevation: groupElevation, + interactive: groupInteractive, + } = groupOptions; + const { labelGroupDefaults, zIndex } = this.options; + const labels = groupOptions.labels.map((labelOptions) => { - const { coordinates, text, userData } = labelOptions; + const { coordinates, text, userData, elevation, interactive } = labelOptions; const label = new mapgl.Label(this.map, { - coordinates, // + label.elevation ?? groupOptions.elevation + coordinates: [...coordinates, elevation ?? groupElevation], text, userData, - image: image === 'default' ? DEFAULT_IMAGE : image, + image: image === 'default' ? labelGroupDefaults.image ?? DEFAULT_IMAGE : image, minZoom, maxZoom, - color, - fontSize, + color: fontColor ?? labelGroupDefaults.fontColor ?? DEFAULT_FONT_COLOR, + fontSize: fontSize ?? labelGroupDefaults.fontSize ?? DEFAULT_FONT_SIZE, relativeAnchor: [0.5, 1], - zIndex: this.options.zIndex + 0.00001, // чтобы были выше моделей + zIndex: zIndex + 0.00001, // чтобы были выше моделей + interactive: interactive ?? groupInteractive ?? DEFAULT_INTERACTIVE, + labeling: { type: 'pointLabelsOnly' }, }); - // pluginEvents.forEach((eventType) => { - // label.on(eventType, (ev) => { - // this.plugin.emit(eventType, createLabelEvenData(ev, labelOptions, state)); - // }); - // }); + pluginEvents.forEach((eventType) => { + label.on(eventType, (ev) => { + this.plugin.emit(eventType, createLabelEvenData(ev, labelOptions, state)); + }); + }); return label; }); diff --git a/src/plugin.ts b/src/plugin.ts index cc4859f..0fff720 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -295,10 +295,25 @@ export class GltfPlugin extends Evented { * @param state A state of building and floor that should be active on realty scene initialization. */ public async addRealtyScene(scene: BuildingOptions[], state?: BuildingState) { + this.realtyScene?.destroy(); this.realtyScene = new RealtyScene(this, this.map, this.options); return this.realtyScene.init(scene, state); } + /** + * Shows a hidden realty scene on the map. + */ + public showRealtyScene() { + this.realtyScene?.show(); + } + + /** + * Hides a shown realty scene on the map. + */ + public hideRealtyScene() { + this.realtyScene?.hide(); + } + /** * Removes an interactive realty scene from the map. */ diff --git a/src/realtyScene/realtyScene.ts b/src/realtyScene/realtyScene.ts index 169cadc..0a8a625 100644 --- a/src/realtyScene/realtyScene.ts +++ b/src/realtyScene/realtyScene.ts @@ -41,8 +41,8 @@ export class RealtyScene { private state: RealtySceneState = { activeModelId: undefined, buildingVisibility: new Map(), + status: 'visible', }; - private isDestroyed = false; private groundCoveringSource: GeoJsonSource; private control: GltfFloorControl; @@ -83,6 +83,15 @@ export class RealtyScene { } private setState(newState: RealtySceneState) { + if (this.state.status === 'destroyed') { + return; + } + + if (newState.status === 'destroyed') { + this.state = newState; + return; + } + const prevState = this.state; // т.к. стейт может меняться асинхронно и иногда нужно показывать @@ -95,7 +104,10 @@ export class RealtyScene { const newModelOptions = newState.buildingVisibility.get(buildingId); // если опции не изменились, то ничего не делаем - if (prevModelOptions?.modelId === newModelOptions?.modelId) { + if ( + prevModelOptions?.modelId === newModelOptions?.modelId && + prevState.status === newState.status + ) { buildingVisibility.set(buildingId, prevModelOptions); return; } @@ -131,58 +143,76 @@ export class RealtyScene { } if (newModelOptions) { - const modelStatus = this.plugin.getModelStatus(newModelOptions.modelId); - - // если новая модель готова, то показываем ее - if (modelStatus === ModelStatus.Loaded) { - this.plugin.showModel(newModelOptions.modelId); - buildingVisibility.set(buildingId, newModelOptions); - - // если модель активна, то применяем опции карты и включаем подложку, если нужно - if ( - newState.activeModelId !== undefined && - newState.activeModelId === newModelOptions.modelId - ) { - const options = - this.buildings.get(newModelOptions.modelId) ?? - this.floors.get(newModelOptions.modelId); - - if (options) { - this.setMapOptions(options.mapOptions); - } - - if (this.undergroundFloors.has(newModelOptions.modelId)) { - this.switchOnGroundCovering(); + // если текущий этаж - подземный, а новая активная модель не готова, + // то не показываем модели, за исключанием подземного этажа + if ( + !prevModelOptions && + prevState.activeModelId !== undefined && + this.undergroundFloors.has(prevState.activeModelId) && + newState.activeModelId !== undefined && + this.plugin.getModelStatus(newState.activeModelId) !== ModelStatus.Loaded + ) { + buildingVisibility.set(buildingId, prevModelOptions); + } else { + const modelStatus = this.plugin.getModelStatus(newModelOptions.modelId); + + // если новая модель готова, то показываем ее + if (modelStatus === ModelStatus.Loaded) { + buildingVisibility.set(buildingId, newModelOptions); + + if (newState.status === 'visible') { + this.plugin.showModel(newModelOptions.modelId); + + // если модель активна, то применяем опции карты и включаем подложку, если нужно + if ( + newState.activeModelId !== undefined && + newState.activeModelId === newModelOptions.modelId + ) { + const options = + this.buildings.get(newModelOptions.modelId) ?? + this.floors.get(newModelOptions.modelId); + + if (options) { + this.setMapOptions(options.mapOptions); + } + + if (this.undergroundFloors.has(newModelOptions.modelId)) { + this.switchOnGroundCovering(); + } + + const floorOptions = this.floors.get(newModelOptions.modelId); + if (floorOptions) { + floorOptions.labelGroups?.forEach((group) => { + this.plugin.addLabelGroup(group, { + buildingId, + floorId: floorOptions.id, + }); + }); + } + } } - - const floorOptions = this.floors.get(newModelOptions.modelId); - if (floorOptions) { - floorOptions.labelGroups?.forEach((group) => { - this.plugin.addLabelGroup(group, { - buildingId, - floorId: floorOptions.id, + } else { + if (modelStatus === ModelStatus.NoModel) { + this.plugin.addModel(newModelOptions, true).then(() => { + if (this.state.status === 'destroyed') { + return; + } + + if (this.state.activeModelId !== newModelOptions.modelId) { + return; + } + + // откладываем выставление нужного стейта до момента загрузки модели + this.setState({ + ...newState, + status: this.state.status, }); }); } - } - } else { - if (modelStatus === ModelStatus.NoModel) { - this.plugin.addModel(newModelOptions, true).then(() => { - if (this.isDestroyed) { - return; - } - - if (this.state.activeModelId !== newModelOptions.modelId) { - return; - } - // откладываем выставление нужного стейта до момента загрузки модели - this.setState(newState); - }); + // если новые модели не готовы, то пока показываем предыдущие + buildingVisibility.set(buildingId, prevModelOptions); } - - // если новые модели не готовы, то пока показываем предыдущие - buildingVisibility.set(buildingId, prevModelOptions); } } }); @@ -191,8 +221,10 @@ export class RealtyScene { const prevBuildingModelId = this.getBuildingModelId(prevState.activeModelId); const newBuildingModelId = this.getBuildingModelId(newState.activeModelId); - if (prevBuildingModelId !== newBuildingModelId) { - if (newBuildingModelId !== undefined && newState.activeModelId !== undefined) { + if (prevBuildingModelId !== newBuildingModelId || prevState.status !== newState.status) { + if (newState.status === 'hidden') { + this.control.hide(); + } else if (newBuildingModelId !== undefined && newState.activeModelId !== undefined) { const buildingOptions = this.buildings.get(newBuildingModelId); if (buildingOptions) { this.control.show({ @@ -214,6 +246,7 @@ export class RealtyScene { this.state = { buildingVisibility, activeModelId: newState.activeModelId, + status: newState.status, }; } @@ -295,15 +328,19 @@ export class RealtyScene { } return this.plugin - .addModels(Array.from(modelsToLoad.values()), Array.from(buildingVisibility.keys())) + .addModels( + Array.from(modelsToLoad.values()), + Array.from(buildingVisibility).map(([_, options]) => options.modelId), + ) .then(() => { - if (this.isDestroyed) { + if (this.state.status === 'destroyed') { return; } this.setState({ activeModelId, buildingVisibility, + status: this.state.status, }); this.plugin.on('click', this.onSceneClick); @@ -323,8 +360,34 @@ export class RealtyScene { } } + public show() { + if (this.state.status !== 'hidden') { + return; + } + + this.setState({ + ...this.state, + status: 'visible', + }); + } + + public hide() { + if (this.state.status !== 'visible') { + return; + } + + this.setState({ + ...this.state, + status: 'hidden', + }); + } + public destroy() { - this.isDestroyed = true; + if (this.state.status === 'destroyed') { + return; + } + + this.setState({ ...this.state, status: 'destroyed' }); this.map.off('styleload', this.onStyleLoad); this.plugin.off('click', this.onSceneClick); this.plugin.off('mouseover', this.onSceneMouseOver); @@ -433,6 +496,7 @@ export class RealtyScene { this.setState({ activeModelId: ev.modelId, buildingVisibility, + status: this.state.status, }); return; } @@ -449,6 +513,7 @@ export class RealtyScene { this.setState({ activeModelId: ev.modelId, buildingVisibility, + status: this.state.status, }); return; } @@ -486,6 +551,7 @@ export class RealtyScene { this.setState({ buildingVisibility, activeModelId, + status: this.state.status, }); }; diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 9f45ce7..4f6493c 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -33,6 +33,21 @@ export interface HoverOptions { color: string; } +export interface LabelGroupDefaults { + /** + * A font size of labels in a group. + */ + fontSize?: number; + /** + * A font color of labels in a group. + */ + fontColor?: string; + /** + * Image settings for a text background of labels in a group. + */ + image?: LabelImage; +} + /** * Options for the plugin. */ @@ -42,11 +57,17 @@ export interface PluginOptions { */ modelsBaseUrl?: string; /** - * Strategies for loading of models: - * - dontWaitAll - show models as soon as possible. - * - waitAll - show models only when all models are ready for rendering. + * Strategies for loading and rendering of models: + * - dontWaitAll - show every model on its loading completion. In case of a realty scene it allows to download less data and + * show every model in the scene as soon as possible, but there will be a delay between switching floor plans if they are not loaded. + * - waitAll - show models only when all models are loaded. In case of a realty scene it leads to an increase in amount of + * loaded data and time of rendering scene, but it allows to avoid a delay between switching floor plans. */ modelsLoadStrategy?: 'dontWaitAll' | 'waitAll'; + /** + * Defaults for any label group used when such options aren't specified in label group options directly. + */ + labelGroupDefaults?: LabelGroupDefaults; /** * Settings for floors' control. */ @@ -135,7 +156,7 @@ export interface ModelOptions { */ userData?: any; /** - * Interactivity of model. All models are interactive by default. + * Interactivity of a model. The model isn't interactive by default. */ interactive?: boolean; } @@ -149,7 +170,7 @@ export interface LabelOptions { */ coordinates: [number, number]; /** - * An elevation of a label. + * An elevation of a label in meters. */ elevation?: number; /** @@ -160,6 +181,10 @@ export interface LabelOptions { * User specific data. */ userData?: any; + /** + * Interactivity of a label. The label isn't interactive by default. + */ + interactive?: boolean; } /** @@ -171,17 +196,13 @@ export interface LabelGroupOptions { */ id: string; /** - * An elevation of a label group. + * An elevation of a label group in meters. */ elevation: number; /** * An array of labels to add on the map */ labels: LabelOptions[]; - /** - * Image settings for labels' text background. - */ - image?: LabelImage | 'default'; /** * A minimum display styleZoom of a label group. */ @@ -198,6 +219,14 @@ export interface LabelGroupOptions { * A color of a label's font. */ fontColor?: string; + /** + * Image settings for labels' text background. + */ + image?: LabelImage | 'default'; + /** + * Interactivity of a label group. The label group isn't interactive by default. + */ + interactive?: boolean; } /** diff --git a/src/types/realtyScene.ts b/src/types/realtyScene.ts index 60c52fd..fbf90dd 100644 --- a/src/types/realtyScene.ts +++ b/src/types/realtyScene.ts @@ -104,6 +104,9 @@ export interface RealtySceneState { // id здания мапится на опции здания или опции этажа этого здания buildingVisibility: Map; + + // статус сцены недвижимости + status: 'visible' | 'hidden' | 'destroyed'; } /** diff --git a/test/mocks/labels.ts b/test/mocks/labels.ts index ea79bfa..5c68c6d 100644 --- a/test/mocks/labels.ts +++ b/test/mocks/labels.ts @@ -16,7 +16,7 @@ export const LABEL_ASCII_LETTERS: LabelGroupOptions = { labels: [ { coordinates: [82.886454, 54.98075], - elevation: 30, + elevation: 15, text: '@<>?|!@#$%\n^&*()_+-=\n3к\n78.4 м²', userData: { url: 'https://example.com/', @@ -28,13 +28,13 @@ export const LABEL_ASCII_LETTERS: LabelGroupOptions = { export const LABEL_ENG_RUS_LETTERS: LabelGroupOptions = { id: '2', minZoom: 12, - elevation: 20, + elevation: 10, fontSize: 10, fontColor: '#3a3a3a', labels: [ { coordinates: [82.886104, 54.98075], - elevation: 30, + elevation: 15, text: 'qwe RTY пои ГРУП', userData: { url: 'https://example.com/', diff --git a/test/mocks/realtyScene.ts b/test/mocks/realtyScene.ts index fc12d26..3b1cd68 100644 --- a/test/mocks/realtyScene.ts +++ b/test/mocks/realtyScene.ts @@ -23,8 +23,9 @@ export const REALTY_SCENE: BuildingOptions[] = [ id: '235034', text: '1-10', modelUrl: 'zgktechnology1_floor2.glb', + isUnderground: true, mapOptions: { - center: [47.24524342863023, 56.13449524271827], + center: [47.245244380223404, 56.13440013744883], pitch: 40, zoom: 20, rotation: -57.5, diff --git a/test/puppeteer/config.ts b/test/puppeteer/config.ts index 7523ac2..ff4fdd1 100644 --- a/test/puppeteer/config.ts +++ b/test/puppeteer/config.ts @@ -8,4 +8,4 @@ export const WAIT_FOR_TIMEOUT = 150000; export const MAP_CENTER = [82.920412, 55.030111]; export const MAP_ZOOM = 6; -export const API_KEY = '4970330e-7f1c-4921-808c-0eb7c4e63001'; +export const API_KEY = 'cb20c5bf-34d3-4f0e-9b2b-33e9b8edb57f'; diff --git a/test/puppeteer/index.ts b/test/puppeteer/index.ts index 071296f..991405f 100644 --- a/test/puppeteer/index.ts +++ b/test/puppeteer/index.ts @@ -48,7 +48,7 @@ export async function pageSetUp(): Promise { page.setDefaultTimeout(WAIT_FOR_TIMEOUT); page.on('console', async (msg) => { - const args = await Promise.all(msg.args().map((arg) => describeLog(arg))); + await Promise.all(msg.args().map((arg) => describeLog(arg))); }); await page.goto(REFERENCE_DEMO); diff --git a/test/screenshots/__screenshots__/plugin/add_label_group-snap.png b/test/screenshots/__screenshots__/plugin/add_label_group-snap.png index 1f4a1c2..c6b52f2 100644 Binary files a/test/screenshots/__screenshots__/plugin/add_label_group-snap.png and b/test/screenshots/__screenshots__/plugin/add_label_group-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/add_model-snap.png b/test/screenshots/__screenshots__/plugin/add_model-snap.png index c5836c9..96f038b 100644 Binary files a/test/screenshots/__screenshots__/plugin/add_model-snap.png and b/test/screenshots/__screenshots__/plugin/add_model-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/add_models-snap.png b/test/screenshots/__screenshots__/plugin/add_models-snap.png index 650a89d..23b4cc2 100644 Binary files a/test/screenshots/__screenshots__/plugin/add_models-snap.png and b/test/screenshots/__screenshots__/plugin/add_models-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/add_models_partially-snap.png b/test/screenshots/__screenshots__/plugin/add_models_partially-snap.png index c5836c9..96f038b 100644 Binary files a/test/screenshots/__screenshots__/plugin/add_models_partially-snap.png and b/test/screenshots/__screenshots__/plugin/add_models_partially-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/add_realty_scene-snap.png b/test/screenshots/__screenshots__/plugin/add_realty_scene-snap.png index 6d5d0bf..d1635ed 100644 Binary files a/test/screenshots/__screenshots__/plugin/add_realty_scene-snap.png and b/test/screenshots/__screenshots__/plugin/add_realty_scene-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/change_style-snap.png b/test/screenshots/__screenshots__/plugin/change_style-snap.png index 16d58df..8f0f758 100644 Binary files a/test/screenshots/__screenshots__/plugin/change_style-snap.png and b/test/screenshots/__screenshots__/plugin/change_style-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/hide_realty_scene-snap.png b/test/screenshots/__screenshots__/plugin/hide_realty_scene-snap.png new file mode 100644 index 0000000..6c12b57 Binary files /dev/null and b/test/screenshots/__screenshots__/plugin/hide_realty_scene-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/hide_underground_realty_scene-snap.png b/test/screenshots/__screenshots__/plugin/hide_underground_realty_scene-snap.png new file mode 100644 index 0000000..6c12b57 Binary files /dev/null and b/test/screenshots/__screenshots__/plugin/hide_underground_realty_scene-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/show_realty_scene-snap.png b/test/screenshots/__screenshots__/plugin/show_realty_scene-snap.png new file mode 100644 index 0000000..d1635ed Binary files /dev/null and b/test/screenshots/__screenshots__/plugin/show_realty_scene-snap.png differ diff --git a/test/screenshots/__screenshots__/plugin/show_underground_realty_scene-snap.png b/test/screenshots/__screenshots__/plugin/show_underground_realty_scene-snap.png new file mode 100644 index 0000000..4851db3 Binary files /dev/null and b/test/screenshots/__screenshots__/plugin/show_underground_realty_scene-snap.png differ diff --git a/test/screenshots/plugin.screen.ts b/test/screenshots/plugin.screen.ts index 37568c7..fc5abe4 100644 --- a/test/screenshots/plugin.screen.ts +++ b/test/screenshots/plugin.screen.ts @@ -16,6 +16,7 @@ const init = async ( page: Page, opts: Pick & { modelsBaseUrl?: string; + groundCoveringColor?: string; } = {}, ) => { await initMapWithOptions(page, { @@ -35,14 +36,16 @@ const init = async ( }); await page.evaluate( - ({ modelsBaseUrl }) => { + ({ modelsBaseUrl, groundCoveringColor }) => { window.gltfPlugin = new window.GltfPlugin(window.map, { modelsLoadStrategy: 'dontWaitAll', modelsBaseUrl, + groundCoveringColor, }); }, { modelsBaseUrl: opts.modelsBaseUrl ?? '', + groundCoveringColor: opts.groundCoveringColor ?? '#F8F8EBCC', }, ); @@ -158,6 +161,7 @@ describe('GltfPlugin', () => { await init(page, { center: [47.245286302641034, 56.134743473834099], rotation: 330, + groundCoveringColor: 'rgba(0, 0, 0, 0.8)', modelsBaseUrl: 'https://disk.2gis.com/digital-twin/models_s3/realty_ads/zgktechnology/', }); @@ -171,6 +175,48 @@ describe('GltfPlugin', () => { await makeSnapshot(page, dirPath, 'add_realty_scene'); }); + it('Hide and show a realty scene', async () => { + await page.evaluate(() => { + return window.gltfPlugin.addRealtyScene(window.MOCKS.realtyScene); + }); + await waitForReadiness(page); + + await page.evaluate(() => { + return window.gltfPlugin.hideRealtyScene(); + }); + await makeSnapshot(page, dirPath, 'hide_realty_scene'); + + await page.evaluate(() => { + return window.gltfPlugin.showRealtyScene(); + }); + await waitForReadiness(page); + await makeSnapshot(page, dirPath, 'show_realty_scene'); + }); + + // Тест пока заскипан, т.к. на скринах появляется контрол сцены + // недвижимости, что приводит к падению теста на разных платформах + it.skip('Hide and show an underground realty scene', async () => { + await page.evaluate(() => { + return window.gltfPlugin.addRealtyScene(window.MOCKS.realtyScene, { + buildingId: '03a234cb', + floorId: '235034', + }); + }); + await waitForReadiness(page); + + await page.evaluate(() => { + return window.gltfPlugin.hideRealtyScene(); + }); + await waitForReadiness(page); + await makeSnapshot(page, dirPath, 'hide_underground_realty_scene'); + + await page.evaluate(() => { + return window.gltfPlugin.showRealtyScene(); + }); + await waitForReadiness(page); + await makeSnapshot(page, dirPath, 'show_underground_realty_scene'); + }); + it('#removeRealtyScene', async () => { await page.evaluate(() => { return window.gltfPlugin.addRealtyScene(window.MOCKS.realtyScene); diff --git a/tsconfig.json b/tsconfig.json index 13c5221..65094f7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,8 +11,8 @@ "skipLibCheck": true, "outDir": "dist/", "sourceMap": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, + "noUnusedLocals": true, + "noUnusedParameters": true, }, "include": ["project.d.ts", "modules.d.ts", "src/**/*.ts"] }