├── .all-contributorsrc ├── .eslintrc.js ├── .github ├── FUNDING.yml └── workflows │ └── publish.yml ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── babel.config.js ├── cypress.json ├── cypress ├── fixtures │ └── example.json ├── integration │ └── tests.js ├── plugins │ └── index.js └── support │ ├── commands.js │ └── index.js ├── deploy.sh ├── docs ├── .vuepress │ ├── config.js │ └── public │ │ ├── examples │ │ ├── custom-balloon.jpg │ │ └── custom-icon.jpg │ │ └── hero.jpg ├── README.md ├── en │ ├── README.md │ ├── examples │ │ └── README.md │ └── guide │ │ ├── Map.md │ │ ├── Marker.md │ │ └── README.md ├── examples │ ├── README.md │ ├── balloon-slot │ │ ├── script.js │ │ └── template.html │ ├── base │ │ ├── script.js │ │ └── template.html │ ├── custom-balloon │ │ ├── script.js │ │ ├── style.css │ │ └── template.html │ ├── custom-cluster │ │ ├── script.js │ │ └── template.html │ ├── custom-icon │ │ ├── script.js │ │ └── template.html │ └── load-ymap │ │ └── script.js └── guide │ ├── Map.md │ ├── Marker.md │ └── README.md ├── examples ├── Cypress │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── index.html │ └── src │ │ ├── App.vue │ │ ├── main.js │ │ └── markers.json ├── Nuxt │ ├── .editorconfig │ ├── .gitignore │ ├── README.md │ ├── assets │ │ └── README.md │ ├── components │ │ ├── Logo.vue │ │ └── README.md │ ├── layouts │ │ ├── README.md │ │ └── default.vue │ ├── middleware │ │ └── README.md │ ├── nuxt.config.js │ ├── package.json │ ├── pages │ │ ├── README.md │ │ └── index.vue │ ├── plugins │ │ ├── README.md │ │ └── ymapPlugin.js │ ├── static │ │ ├── README.md │ │ └── favicon.ico │ └── store │ │ └── README.md ├── Vue │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── index.html │ ├── src │ │ ├── App.vue │ │ └── main.js │ └── yarn.lock ├── cdn │ └── index.html └── vue3 │ ├── .browserslistrc │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── babel.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ └── index.html │ ├── src │ ├── App.vue │ └── main.js │ └── yarn.lock ├── jest.config.js ├── makefile ├── nuxt ├── index.js └── plugin.js ├── old-docs.md ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── Marker.js ├── YMap.js ├── index.js └── utils.js ├── tests └── test.test.js └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "Wormaster", 10 | "name": "Wormaster", 11 | "avatar_url": "https://avatars1.githubusercontent.com/u/4989842?v=4", 12 | "profile": "https://github.com/Wormaster", 13 | "contributions": [ 14 | "code" 15 | ] 16 | }, 17 | { 18 | "login": "NelinD", 19 | "name": "Nikitenko Andrey", 20 | "avatar_url": "https://avatars3.githubusercontent.com/u/10078264?v=4", 21 | "profile": "https://github.com/NelinD", 22 | "contributions": [ 23 | "code" 24 | ] 25 | }, 26 | { 27 | "login": "KamilOcean", 28 | "name": "Kamil", 29 | "avatar_url": "https://avatars3.githubusercontent.com/u/16609819?v=4", 30 | "profile": "https://twitter.com/kamil_ocean", 31 | "contributions": [ 32 | "code" 33 | ] 34 | }, 35 | { 36 | "login": "k0va1", 37 | "name": "Alexander Koval", 38 | "avatar_url": "https://avatars3.githubusercontent.com/u/3451694?v=4", 39 | "profile": "https://github.com/k0va1", 40 | "contributions": [ 41 | "code" 42 | ] 43 | }, 44 | { 45 | "login": "soldatovsh", 46 | "name": "alex", 47 | "avatar_url": "https://avatars3.githubusercontent.com/u/992553?v=4", 48 | "profile": "https://github.com/soldatovsh", 49 | "contributions": [ 50 | "code" 51 | ] 52 | }, 53 | { 54 | "login": "Pinegin", 55 | "name": "Антон Пинегин", 56 | "avatar_url": "https://avatars2.githubusercontent.com/u/5644410?v=4", 57 | "profile": "https://github.com/Pinegin", 58 | "contributions": [ 59 | "code" 60 | ] 61 | }, 62 | { 63 | "login": "VadimMalykhin", 64 | "name": "Vadim Malykhin", 65 | "avatar_url": "https://avatars3.githubusercontent.com/u/158365?v=4", 66 | "profile": "https://github.com/VadimMalykhin", 67 | "contributions": [ 68 | "code" 69 | ] 70 | }, 71 | { 72 | "login": "dmitrytarassov", 73 | "name": "Dmitriy", 74 | "avatar_url": "https://avatars3.githubusercontent.com/u/12485596?v=4", 75 | "profile": "https://github.com/dmitrytarassov", 76 | "contributions": [ 77 | "code" 78 | ] 79 | }, 80 | { 81 | "login": "VanishMax", 82 | "name": "VanishMax", 83 | "avatar_url": "https://avatars3.githubusercontent.com/u/29180358?v=4", 84 | "profile": "http://t.me/vanishmax", 85 | "contributions": [ 86 | "code" 87 | ] 88 | }, 89 | { 90 | "login": "rdemirbay", 91 | "name": "Rasim Demirbay", 92 | "avatar_url": "https://avatars1.githubusercontent.com/u/12648626?v=4", 93 | "profile": "https://github.com/rdemirbay", 94 | "contributions": [ 95 | "code" 96 | ] 97 | }, 98 | { 99 | "login": "genius-spirit", 100 | "name": "Andrei Detenkov", 101 | "avatar_url": "https://avatars3.githubusercontent.com/u/32195682?v=4", 102 | "profile": "https://github.com/genius-spirit", 103 | "contributions": [ 104 | "translation" 105 | ] 106 | }, 107 | { 108 | "login": "KorolPaul", 109 | "name": "CSSKing", 110 | "avatar_url": "https://avatars3.githubusercontent.com/u/3993155?v=4", 111 | "profile": "https://github.com/KorolPaul", 112 | "contributions": [ 113 | "code" 114 | ] 115 | }, 116 | { 117 | "login": "mrswylet", 118 | "name": "MrSwylet", 119 | "avatar_url": "https://avatars1.githubusercontent.com/u/37118883?v=4", 120 | "profile": "https://github.com/mrswylet", 121 | "contributions": [ 122 | "ideas" 123 | ] 124 | }, 125 | { 126 | "login": "cvaize", 127 | "name": "Орлов Дмитрий", 128 | "avatar_url": "https://avatars2.githubusercontent.com/u/26907947?v=4", 129 | "profile": "https://github.com/cvaize", 130 | "contributions": [ 131 | "ideas" 132 | ] 133 | }, 134 | { 135 | "login": "windstep", 136 | "name": "windstep", 137 | "avatar_url": "https://avatars1.githubusercontent.com/u/51027899?v=4", 138 | "profile": "https://github.com/windstep", 139 | "contributions": [ 140 | "ideas" 141 | ] 142 | }, 143 | { 144 | "login": "antoinematyja", 145 | "name": "antoinematyja", 146 | "avatar_url": "https://avatars2.githubusercontent.com/u/9961462?v=4", 147 | "profile": "https://github.com/antoinematyja", 148 | "contributions": [ 149 | "ideas" 150 | ] 151 | }, 152 | { 153 | "login": "alxnkt", 154 | "name": "alxnkt", 155 | "avatar_url": "https://avatars3.githubusercontent.com/u/49128174?v=4", 156 | "profile": "https://github.com/alxnkt", 157 | "contributions": [ 158 | "tutorial" 159 | ] 160 | }, 161 | { 162 | "login": "sleleko", 163 | "name": "Sergey Leleko", 164 | "avatar_url": "https://avatars3.githubusercontent.com/u/2923963?v=4", 165 | "profile": "https://leleko.ru", 166 | "contributions": [ 167 | "tutorial" 168 | ] 169 | }, 170 | { 171 | "login": "nikolawan", 172 | "name": "nikolawan", 173 | "avatar_url": "https://avatars1.githubusercontent.com/u/9902286?v=4", 174 | "profile": "https://github.com/nikolawan", 175 | "contributions": [ 176 | "tutorial" 177 | ] 178 | }, 179 | { 180 | "login": "Alex-Sokolov", 181 | "name": "Alexander Sokolov", 182 | "avatar_url": "https://avatars3.githubusercontent.com/u/4497128?v=4", 183 | "profile": "https://github.com/Alex-Sokolov", 184 | "contributions": [ 185 | "code" 186 | ] 187 | }, 188 | { 189 | "login": "kirillunlimited", 190 | "name": "Kirill Ivanov", 191 | "avatar_url": "https://avatars1.githubusercontent.com/u/7703762?v=4", 192 | "profile": "http://kirillunlimited.ru", 193 | "contributions": [ 194 | "code" 195 | ] 196 | }, 197 | { 198 | "login": "Donnevtis", 199 | "name": "Donnevtis", 200 | "avatar_url": "https://avatars.githubusercontent.com/u/38441204?v=4", 201 | "profile": "https://github.com/Donnevtis", 202 | "contributions": [ 203 | "ideas" 204 | ] 205 | }, 206 | { 207 | "login": "agent-bo-007", 208 | "name": "agent-bo-007", 209 | "avatar_url": "https://avatars.githubusercontent.com/u/78845669?v=4", 210 | "profile": "https://github.com/agent-bo-007", 211 | "contributions": [ 212 | "code" 213 | ] 214 | }, 215 | { 216 | "login": "daniluk4000", 217 | "name": "Danila Rodichkin", 218 | "avatar_url": "https://avatars.githubusercontent.com/u/10450717?v=4", 219 | "profile": "http://dk4000.pro", 220 | "contributions": [ 221 | "code" 222 | ] 223 | } 224 | ], 225 | "contributorsPerLine": 7, 226 | "projectName": "vue-yandex-map", 227 | "projectOwner": "PNKBizz", 228 | "repoType": "github", 229 | "repoHost": "https://github.com", 230 | "skipCi": true 231 | } 232 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "root": true, 3 | "env": { 4 | "node": true 5 | }, 6 | "extends": [ 7 | "plugin:vue/recommended", 8 | "plugin:jest/recommended", 9 | "@vue/airbnb" 10 | ], 11 | "globals": { 12 | "ymaps": "readonly" 13 | }, 14 | "rules": { 15 | "no-console": 0, 16 | "import/no-unresolved": 0, 17 | "import/extensions": 0, 18 | "import/prefer-default-export": 0, 19 | "no-param-reassign": 0, 20 | "consistent-return": 0, 21 | "no-plusplus": 0, 22 | "prefer-destructuring": 0, 23 | "vue/max-attributes-per-line": ['error', { 24 | singleline: 4, 25 | multiline: { max: 1, allowFirstLine: false }, 26 | }], 27 | "vue/no-v-html": 0, 28 | "vue/require-default-prop": 0, 29 | 30 | }, 31 | "parserOptions": { 32 | "parser": "babel-eslint" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: pnkbizz 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: NPM Publish 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 16 15 | - run: npm install 16 | - run: npm run build 17 | - uses: JS-DevTools/npm-publish@v1 18 | with: 19 | token: ${{ secrets.NPM_TOKEN }} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | .idea/ 7 | vue-yandex-maps.js 8 | .vscode/ 9 | package-lock.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pavel Galkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![All Contributors](https://img.shields.io/badge/all_contributors-24-orange.svg?style=flat-square)](#contributors-) 4 | 5 | [![npm](https://img.shields.io/npm/v/vue-yandex-maps.svg)](https://www.npmjs.com/package/vue-yandex-maps) 6 | [![GitHub issues](https://img.shields.io/github/issues/PNKBizz/vue-yandex-map.svg)](https://github.com/PNKBizz/vue-yandex-map/issues) 7 | [![GitHub closed issues](https://img.shields.io/github/issues-closed/PNKBizz/vue-yandex-map.svg)](https://github.com/PNKBizz/vue-yandex-map) 8 | [![npm](https://img.shields.io/npm/dm/vue-yandex-maps.svg)](https://www.npmjs.com/package/vue-yandex-maps) 9 | [![GitHub license](https://img.shields.io/github/license/PNKBizz/vue-yandex-map.svg)](https://github.com/PNKBizz/vue-yandex-map/blob/master/LICENSE) 10 | [![GitHub stars](https://img.shields.io/github/stars/PNKBizz/vue-yandex-map.svg?style=social)](https://github.com/PNKBizz/vue-yandex-map/stargazers) 11 | 12 | # vue-yandex-maps 13 | 14 | ## Version 2.0 (Maps 3.0) 15 | Version 2.0 with Yandex Maps 3.0 has been released. It's compatible with all of Vue 2, 3, and Nuxt and comes with full official TS support. 16 | 17 | It is highly recommended to use Version 2.0 instead of 0.xx/1.xx. 18 | 19 | Please view [version 2.0 documentation](https://yandex-maps-unofficial.github.io/vue-yandex-maps/). 20 | 21 | ## Version 0.11.x (Vue2) / 0.12.x (Vue 3) 22 | 23 | Latest version is only compatible with Vue 2.x
24 | Version for Vue 3 available within `0.12` version range. 25 | 26 | ``` 27 | npm install vue-yandex-maps@~0.12 28 | ``` 29 | 30 | Documentation: [RU](https://vue-yandex-maps.github.io/), [EN](https://vue-yandex-maps.github.io/en/) 31 | 32 | ## Contributors ✨ 33 | 34 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |

Wormaster

💻

Nikitenko Andrey

💻

Kamil

💻

Alexander Koval

💻

alex

💻

Антон Пинегин

💻

Vadim Malykhin

💻

Dmitriy

💻

VanishMax

💻

Rasim Demirbay

💻

Andrei Detenkov

🌍

CSSKing

💻

MrSwylet

🤔

Орлов Дмитрий

🤔

windstep

🤔

antoinematyja

🤔

alxnkt


Sergey Leleko


nikolawan


Alexander Sokolov

💻

Kirill Ivanov

💻

Donnevtis

🤔

agent-bo-007

💻

Danila Rodichkin

💻
73 | 74 | 75 | 76 | 77 | 78 | 79 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 80 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [['@babel/preset-env', { modules: false }]], 3 | env: { 4 | test: { 5 | presets: [['@babel/preset-env', { targets: { node: 'current' } }]], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:8080" 3 | } 4 | -------------------------------------------------------------------------------- /cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } -------------------------------------------------------------------------------- /cypress/integration/tests.js: -------------------------------------------------------------------------------- 1 | describe('Check functionality', () => { 2 | it('maps should load', () => { 3 | cy.visit('/'); 4 | 5 | cy.get('.passedMap1 input[value="loaded"]') 6 | .should('be.checked'); 7 | 8 | cy.get('.passedMap2 input[value="loaded"]') 9 | .should('be.checked'); 10 | 11 | cy.get('.passedMap3 input[value="loaded"]') 12 | .should('be.checked'); 13 | }); 14 | 15 | it('markers should be edit', () => { 16 | cy.get('#changeButton') 17 | .click(); 18 | 19 | cy.get('.passedMap1 input[value="edited"]') 20 | .should('be.checked'); 21 | 22 | cy.get('.passedMap2 input[value="edited"]') 23 | .should('be.checked'); 24 | 25 | cy.get('.passedMap3 input[value="edited"]') 26 | .should('be.checked'); 27 | }); 28 | 29 | it('markers should be delete', () => { 30 | cy.get('#filterButton') 31 | .click(); 32 | 33 | cy.get('.passedMap1 input[value="filtered"]') 34 | .should('be.checked'); 35 | 36 | cy.get('.passedMap2 input[value="filtered"]') 37 | .should('be.checked'); 38 | 39 | cy.get('.passedMap3 input[value="filtered"]') 40 | .should('be.checked'); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | module.exports = (on, config) => { 15 | // `on` is used to hook into various events Cypress emits 16 | // `config` is the resolved Cypress config 17 | } 18 | -------------------------------------------------------------------------------- /cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /cypress/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -e 4 | npm run docs:build 5 | cd docs/.vuepress/dist 6 | 7 | git init 8 | git add -A 9 | git commit -m 'deploy' 10 | 11 | git push -f git@github.com:vue-yandex-maps/vue-yandex-maps.github.io.git master 12 | 13 | cd - -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | themeConfig: { 3 | repo: 'PNKBizz/vue-yandex-map', 4 | docsDir: 'docs', 5 | editLinks: true, 6 | locales: { 7 | '/': { 8 | selectText: 'Язык', 9 | title: 'Vue-yandex-maps', 10 | description: 'Я.Карты для Vue JS', 11 | nav: [ 12 | { text: 'v0.x', items: [{ text: 'v1.x', link: 'https://vue-yandex-maps.github.io/new-docs/' }, { text: 'v2.x', link: 'https://yandex-maps-unofficial.github.io/vue-yandex-maps/' }] }, 13 | { text: 'Руководство', link: '/guide/' }, 14 | { text: 'Примеры', link: '/examples/' }, 15 | { text: 'API Я.Карт', link: 'https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/' }, 16 | ], 17 | sidebar: { 18 | '/guide/': [ 19 | '', 20 | 'Map', 21 | 'Marker' 22 | ] 23 | } 24 | }, 25 | '/en/': { 26 | selectText: 'Language', 27 | title: 'Vue-yandex-maps', 28 | description: 'Yandex map component for Vue JS', 29 | nav: [ 30 | { text: 'v0.x', items: [{ text: 'v1.x', link: 'https://vue-yandex-maps.github.io/new-docs/' }, { text: 'v2.x', link: 'https://yandex-maps-unofficial.github.io/vue-yandex-maps/' }] }, 31 | { text: 'Guide', link: '/en/guide/' }, 32 | { text: 'Examples', link: '/en/examples/' }, 33 | { text: 'YandexMap API ', link: 'https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/' }, 34 | ], 35 | sidebar: { 36 | '/en/guide/': [ 37 | '', 38 | 'Map', 39 | 'Marker' 40 | ] 41 | } 42 | } 43 | } 44 | }, 45 | locales: { 46 | '/': { 47 | lang: 'ru-RU', 48 | title: 'Vue-yandex-maps', 49 | description: 'Документация на русском' 50 | }, 51 | '/en/': { 52 | lang: 'en-US', 53 | title: 'Vue-yandex-maps', 54 | description: 'Documentation on english' 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /docs/.vuepress/public/examples/custom-balloon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/docs/.vuepress/public/examples/custom-balloon.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/examples/custom-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/docs/.vuepress/public/examples/custom-icon.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/docs/.vuepress/public/hero.jpg -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /hero.jpg 4 | actionText: Документация → 5 | actionLink: /guide/ 6 | footer: MIT Licensed 7 | --- -------------------------------------------------------------------------------- /docs/en/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /hero.jpg 4 | actionText: Documentation → 5 | actionLink: /en/guide/ 6 | footer: MIT Licensed 7 | --- -------------------------------------------------------------------------------- /docs/en/examples/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Examples of using and setting the map 6 | 7 | ## Move the marker by click 8 | 9 | <<< @/docs/examples/base/template.html 10 | <<< @/docs/examples/base/script.js 11 | 15 | 16 | ## Custom icon 17 | 18 | <<< @/docs/examples/custom-icon/template.html 19 | <<< @/docs/examples/custom-icon/script.js 20 | 24 | 25 | ## Custom balloon 26 | 27 | <<< @/docs/examples/custom-balloon/template.html 28 | <<< @/docs/examples/custom-balloon/script.js 29 | <<< @/docs/examples/custom-balloon/style.css 30 | 34 | 35 | ## Custom cluster balloon 36 | 37 | <<< @/docs/examples/custom-cluster/template.html 38 | <<< @/docs/examples/custom-cluster/script.js 39 | 43 | 44 | ## Balloon slot in marker 45 | 46 | <<< @/docs/examples/balloon-slot/template.html 47 | <<< @/docs/examples/balloon-slot/script.js 48 | 52 | 53 | ## How to use loadYmaps 54 | 55 | <<< @/docs/examples/load-ymap/script.js -------------------------------------------------------------------------------- /docs/en/guide/Map.md: -------------------------------------------------------------------------------- 1 | # Map 2 | After installation, registration and plugged the component you can use `` and work with a map. All parameters of the map are set via attributes. You can use `map-was-initialized` event to get an access to [map instance](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Map-docpage/) for work directly with [YandexMap API](https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/). Link to the map instance will be transmitted as payload of event.
3 | 4 | You can assign a class to parent element of map via attribute `ymap-class`. If this attribute is not specified the element will be assign an attribute `style="width: 100%; height: 100%;"`.
5 | 6 | All markers are added to the map via `GeoObjectCollection` by default, but if there is a huge count of markers, the map rendering will take a lof of time even when markers grouping to clusters. In this case, it is recommended to use `ObjectManager` and assign the attribute of map `useObjectManager`, but then you lose the opportunity to listen events by each marker.
7 | 8 | The attributes `coords`, `bounds` and `zoom` are observable. The map is react if these attributes are changing. 9 | 10 | ## Events 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
Event namePayload
map-was-initializedLink to map instance
actionend 27 | map event 28 |
balloonclose
balloonopen
boundschange
click
contextmenu
dblclick
destroy
hintclose
hintopen
optionschange
sizechange
typechange
68 | 69 | ## Attributes 70 | 71 | | Attribute | Type | Description | 72 | | ----- | ----- | ----- | 73 | | settings | Object | Settings of map. API Key, language and version. | 74 | | coords | Array | Map center coordinates. [ lat, lng ]. May use with `.sync`. *Required* | 75 | | map-events | Array | Native events, which map emits. If not provided, map will be emit all events, from section [Events](#events) | All | 76 | | zoom | Number | Zoom map value (from 0 to 19). May use with `.sync`. *Default: 18*. | 77 | | bounds | Array | Coordinates of the left bottom and right top corners of the map. If defined, `coords` and `center` are ignored. May use with `.sync`. | 78 | | [cluster-options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/ClusterPlacemark-docpage/#param-options) | Object | An object where the keys are the names of the clusters, and the values are the objects of options these clusters. In options you can point field `layout` (type `String`) for HTML template for `balloonItemContentLayout`, field `clusterIconContentLayout` (type `String`) for cluster icon customization and field `clusterBalloonLayout` (type `String`) for cluster balloon customization: [Custom Balloon example](https://tech.yandex.ru/maps/jsbox/2.1/cluster_custom_balloon_content_layout). There is also `createCluster` field for overriding default creating cluster function (field `use-object-manager` have to be turned off).| 79 | | cluster-callbacks | Object | An object where the keys are the names of the clusters, and the values are the objects of events these clusters, e.g. `{ clusterName: { click: function() {...}, contextmenu: anotherFunction } }` | 80 | | [behaviors](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/map.behavior.Manager-docpage/#param-behaviors) | Array | Array of connected map behaviors. All other values are considered off.| 81 | | [controls](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/control.Manager-docpage/#add-param-control) | Array | Array of connected map controls. All other values are considered offth.| 82 | | detailed-controls | Object | An object where the keys are the elements of map control, and the values are the objects of element settings. Designed for fine setting of control elements. | 83 | | map-type | String | Map type. Valid values: `map, satellite, hybrid`. *Default: map*. | 84 | | scroll-zoom | Boolean | Set `false` to disable map zoom on the page when you are scrolling. *Default: true* | 85 | | placemarks | Array of Objects | **Deprecated**. Use marker component | 86 | | use-object-manager | Boolean | Set `true` for use Object Manager. Used if there is huge count of markers on the map. *Default: false* | 87 | | object-manager-clusterize | Boolean | Clustering with Object Manager. *Default: true* | 88 | | ymap-class | String | Defines class for element, where rendering the map instance. If the attribute is not defined, the element uses style: `width: 100%; height: 100%;` | 89 | | init-without-markers | Boolean | Set to `false` for prevent init and render map if there are no markers on the map. Default: `true` | 90 | | show-all-markers | Boolean | Set to `true` to initialize map with all markers inside map bounds. Default: `false` | 91 | | use-html-in-layout | Boolean | Set to `true` to define balloon properties as html. Default: `false` | 92 | | [options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Map-docpage/#Map__param-options) | Object | Map options. | 93 | | balloon-component | Vue Component | Allow to use Vue Component as balloon. Need to activate [runtimeCompiler](https://cli.vuejs.org/config/#runtimecompiler). **Vue 2 only**| 94 | -------------------------------------------------------------------------------- /docs/en/guide/Marker.md: -------------------------------------------------------------------------------- 1 | # Marker 2 | 3 | You can define map markers by using component ``. 4 | 5 | ::: danger Attention! 6 | Since version `0.10` you can define markers through `ymap-marker` only. Map attribute `placemarks` not supported 7 | ::: 8 | 9 | ::: tip Take a look, 10 | For each marker you need to add property `markerId` 11 | ::: 12 | 13 | You can indicate marker type by using attribute `marker-type`. Allowable values: 14 | * Placemark 15 | * Polyline 16 | * Rectangle 17 | * Polygon 18 | * Circle 19 | 20 | ## Events 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
Event namePayload
balloonclose 33 | marker event 34 |
balloonopen
click
contextmenu
dblclick
drag
dragend
dragstart
hintclose
hintopen
mouseenter
mouseleave
71 | 72 | ::: danger Attention! 73 | Since version `0.10` attribute `callbacks` not supported. You can listen component events. 74 | ::: 75 | 76 | ## Attributes 77 | 78 | | Attribute | Type | Description | Marker-types | 79 | | ----- | ----- | ----- | ----- | 80 | | marker-id | String, Number | Marker id. `Required` || 81 | | marker-type | String | Marker type. Default: `Placemark` || 82 | | coords | Array [ latitude, longitude ] | Marker's coordinates or circle center. `Required` | Placemark, Circle | 83 | | coords | Array of arrays [ [latitude, longitude], [...] ] | Coordinates of tops. `Required` | Rectangle, Polyline | 84 | | coords | Array of two arrays of coordinates arrays (first for outer contour, second for inner) [ [[latitude, longitude], [...]], [[...], [...]] ] | Coordinates of tops. `Required` | Polygon | 85 | | marker-events | Array | Native events, which marker emits. If not provided, marker will be emit all events, from section [Events](#events) | All | 86 | | hint-content | String | Content of tip | All | 87 | | balloon | Object | Balloon properties: header, body, footer | All | 88 | | [icon](#icons) | Object | Marker's icon | Placemark | 89 | | marker-fill | Object | Fill properties: enabled, color, opacity, imageHref | Polygon, Rectangle, Circle | 90 | | marker-stroke | Object | Border properties: color, opacity, width, style | Polygon, Rectangle, Circle, Polyline | 91 | | circle-radius | Number | Radius of the circle in meters. Default: `1000`. | Circle | 92 | | cluster-name | String | Cluster name to grouping of markers | All | 93 | | properties | Object | [Marker settings](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-feature.properties) | All | 94 | | options | Object | [Marker options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-options) | All | 95 | | [balloonTemplate](/en/examples/#custom-cluster-balloon) | String | HTML Template for balloon | All | 96 | | balloon-component-props | Object | Props object for balloon. _Use only for balloonComponent_ | All | 97 | 98 | ## Slots 99 | 100 | You may to define balloon template through `balloon` slot in marker. Also you may place your custom component into this slot, but keep in mind that balloon only render view of this component and discard any logic. If you need to add some user interactive (eg handle button click), you may to listen event `balloonopen` and bind any handlers to your balloon elements. Don't forget to delete these handlers on `balloonclose`. [Example](/en/examples/#balloon-slot-in-marker) 101 | Also you may define balloon layout through `balloonLayout` slot in marker. It's rewrite default yandex layout for balloon. Be careful, if you use `balloonLayout` slot, `balloon` slot will be ignored 102 | 103 | # Icons 104 | 105 | You can define settings of marker icons through fields: color (default: 'blue'), content, glyph. Property `glyph` has priority higher then `content`. [List of colours and icons](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/option.presetStorage-docpage/). In this case you get classical view of marker. 106 | 107 | You can also define your personal icon for marker. In this case the object of settings should be as follows: 108 | 109 | ```JavaScript 110 | { 111 | layout: 'default#image', 112 | imageHref: markerIcon, // address of image or data:image/svg+xml;base64 113 | imageSize: [43, 55], // icon size в px 114 | imageOffset: [-22, -55] // offset в px 115 | } 116 | 117 | ``` 118 | -------------------------------------------------------------------------------- /docs/en/guide/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ::: danger Important! 4 | This version is deprecated. LTS version [here](https://github.com/yandex-maps-unofficial/vue-yandex-maps) 5 | ::: 6 | 7 | You can easily plug Yandex map in your project with this custom component and you available minimal part of functionality right now from the "box". However If you want to use full functionality of [YandexMap API](https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/), you need apply to [map instance](https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/) directly. 8 | 9 | 10 | ## Installing 11 | 12 | Using npm 13 | 14 | ```Bash 15 | npm install vue-yandex-maps 16 | ``` 17 | 18 | Using yarn 19 | ```Bash 20 | yarn add vue-yandex-maps 21 | ``` 22 | 23 | After that you can define settings of component: 24 | * [API key](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/load-docpage/) 25 | * [Language](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/localization-docpage/) 26 | * [Procedure of assignment geographic coords](https://tech.yandex.ru/maps/jsapi/doc/2.1/dg/concepts/load-docpage/#load__coordorder) 27 | * [Yandex Maps for Business usage](https://yandex.com/dev/maps/commercial/) 28 | * Yandex map version 29 | 30 | These settings are optional and below you can see default options: 31 | 32 | ```JavaScript 33 | const settings = { 34 | apiKey: '', 35 | suggestApiKey: '', 36 | lang: 'ru_RU', 37 | coordorder: 'latlong', 38 | enterprise: false, 39 | version: '2.1' 40 | } 41 | ``` 42 | 43 | At this moment you can use these settings when you will be registration the component. 44 | 45 | ## Registration 46 | 47 | ### Global 48 | ```JavaScript 49 | import YmapPlugin from 'vue-yandex-maps' 50 | 51 | Vue.use(YmapPlugin, settings) 52 | ``` 53 | 54 | ### Local 55 | 56 | ```JavaScript 57 | import { yandexMap, ymapMarker } from 'vue-yandex-maps' 58 | 59 | export default { 60 | components: { yandexMap, ymapMarker } 61 | // other options 62 | } 63 | 64 | ``` 65 | ```HTML 66 | 67 | 68 | 69 | ``` 70 | 71 | ### Nuxt module 72 | 73 | Add file `ymapPlugin.js` into `plugins` directory. 74 | 75 | ```JavaScript 76 | import Vue from 'vue' 77 | import YmapPlugin from 'vue-yandex-maps' 78 | 79 | const settings = { ... } // plugin settings 80 | 81 | Vue.use(YmapPlugin, settings); 82 | ``` 83 | 84 | Add existed plugin in plugin section `nuxt.config.js` 85 | 86 | ```JavaScript 87 | { 88 | plugins: [ 89 | { src: '~/plugins/ymapPlugin.js', mode: 'client' } 90 | ] 91 | } 92 | ``` 93 | 94 | ### Ymaps Loader 95 | 96 | If you need to use global variable `ymaps` separately from map component (e.g. for geocoder), just import loader. You may to define settings (see above) and `debug` option (`false` by default). Note that loader function is asynchronous. 97 | 98 | ```JavaScript 99 | import { loadYmap } from 'vue-yandex-maps' 100 | 101 | export default { 102 | async mounted() { 103 | await loadYmap({ ...settings, debug: true }); 104 | // here you may use ymaps 105 | } 106 | } 107 | ``` 108 | 109 | ### CDN 110 | 111 | You can use plugin directly via link [https://unpkg.com/vue-yandex-maps](https://unpkg.com/vue-yandex-maps). The plugin will be install automatically if you use Vue JS. It could be useful when you use [Code Pen](https://codepen.io/PNKBizz/pen/WMRwyM) 112 | -------------------------------------------------------------------------------- /docs/examples/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Примеры использования и настройки карты 6 | 7 | ## Перемещение маркера по клику 8 | 9 | <<< @/docs/examples/base/template.html 10 | <<< @/docs/examples/base/script.js 11 | 15 | 16 | ## Кастомная иконка 17 | 18 | <<< @/docs/examples/custom-icon/template.html 19 | <<< @/docs/examples/custom-icon/script.js 20 | 24 | 25 | ## Кастомный темплейт балуна 26 | 27 | <<< @/docs/examples/custom-balloon/template.html 28 | <<< @/docs/examples/custom-balloon/script.js 29 | <<< @/docs/examples/custom-balloon/style.css 30 | 34 | 35 | ## Кастомный балун кластера 36 | 37 | <<< @/docs/examples/custom-cluster/template.html 38 | <<< @/docs/examples/custom-cluster/script.js 39 | 43 | 44 | ## Использование слота балуна в маркере 45 | 46 | <<< @/docs/examples/balloon-slot/template.html 47 | <<< @/docs/examples/balloon-slot/script.js 48 | 52 | 53 | ## Использование loadYmaps 54 | 55 | <<< @/docs/examples/load-ymap/script.js 56 | -------------------------------------------------------------------------------- /docs/examples/balloon-slot/script.js: -------------------------------------------------------------------------------- 1 | Vue.component('my-component', { 2 | template: '', 3 | }); 4 | 5 | export default { 6 | data: () => ({ 7 | coords: [ 8 | 54.82896654088406, 9 | 39.831893822753904, 10 | ], 11 | }), 12 | methods: { 13 | bindListener() { 14 | document.getElementById('btn').addEventListener('click', this.handler); 15 | }, 16 | unbindListener() { 17 | document.getElementById('btn').removeEventListener('click', this.handler); 18 | }, 19 | handler() { 20 | alert('Whoo-Ha!'); 21 | }, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /docs/examples/balloon-slot/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/examples/base/script.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | coords: [ 4 | 54.82896654088406, 5 | 39.831893822753904, 6 | ], 7 | }), 8 | methods: { 9 | onClick(e) { 10 | this.coords = e.get('coords'); 11 | }, 12 | }, 13 | }; 14 | -------------------------------------------------------------------------------- /docs/examples/base/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/examples/custom-balloon/script.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | coords: [54, 39], 4 | }), 5 | computed: { 6 | balloonTemplate() { 7 | return ` 8 |

Hi, everyone!

9 |

I am here: ${this.coords}

10 | 11 | ` 12 | } 13 | }, 14 | methods: { 15 | onClick(e) { 16 | this.coords = e.get('coords'); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /docs/examples/custom-balloon/style.css: -------------------------------------------------------------------------------- 1 | .red { 2 | color: red; 3 | } -------------------------------------------------------------------------------- /docs/examples/custom-balloon/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/examples/custom-cluster/script.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | coords: [54, 39], 4 | zoom: 10, 5 | clusterOptions: { 6 | 1: { 7 | clusterDisableClickZoom: true, 8 | clusterOpenBalloonOnClick: true, 9 | clusterBalloonLayout: [ 10 | '', 15 | ].join(''), 16 | }, 17 | }, 18 | }), 19 | }; 20 | -------------------------------------------------------------------------------- /docs/examples/custom-cluster/template.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /docs/examples/custom-icon/script.js: -------------------------------------------------------------------------------- 1 | export default { 2 | data: () => ({ 3 | coords: [54, 39], 4 | markerIcon: { 5 | layout: 'default#imageWithContent', 6 | imageHref: 'https://image.flaticon.com/icons/png/512/33/33447.png', 7 | imageSize: [43, 43], 8 | imageOffset: [0, 0], 9 | content: '123 v12', 10 | contentOffset: [0, 15], 11 | contentLayout: '
$[properties.iconContent]
' 12 | } 13 | }) 14 | } -------------------------------------------------------------------------------- /docs/examples/custom-icon/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/examples/load-ymap/script.js: -------------------------------------------------------------------------------- 1 | import { loadYmap } from 'vue-yandex-maps'; 2 | 3 | export default { 4 | async mounted() { 5 | const settings = { lang: 'en_US' }; 6 | await loadYmap(settings); 7 | console.log(ymaps); // здесь доступен весь функционал ymaps 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /docs/guide/Map.md: -------------------------------------------------------------------------------- 1 | # Карта 2 | После подключения плагина вы можете использовать компонент `` для работы с картой. Параметры карты задаются через атрибуты. Вы можете получить доступ к [инстансу карты](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Map-docpage/) для работы напрямую с [API Я.Карт](https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/), слушая событие `map-was-initialized`. Ссылка на инстанс будет передана как payload события.
3 | 4 | Вы можете задать класс элементу, в котором непосредственно находится карта через аттрибут `ymap-class`. Если этот атрибут не задан - элементу присваивается аттрибут `style="width: 100%; height: 100%;"`.
5 | 6 | По умолчанию маркеры добавляются на карту через `GeoObjectCollection`, но при большом количестве маркеров отрисовка карты может занимать продолжительное время даже при группировке маркеров в кластеры. В таком случае рекомендуется использовать `ObjectManager`, указав атрибут карты `useObjectManager`. Но в этом случае вы теряете возможность слушать события у каждого отдельного маркера.
7 | 8 | Атрибуты карты `coords`, `bounds` и `zoom` являются наблюдаемыми. Карта реагирует на их изменения. 9 | 10 | ## Events 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
Event namePayload
map-was-initializedСсылка на инстанс карты
actionend 27 | map event 28 |
balloonclose
balloonopen
boundschange
click
contextmenu
dblclick
destroy
hintclose
hintopen
optionschange
sizechange
typechange
68 | 69 | ## Attributes 70 | 71 | | Attribute | Type | Description | 72 | | ----- | ----- | ----- | 73 | | settings | Object | Настройки карты. API Key, язык и версия. | 74 | | coords | Array | Координаты центра карты. [ lat, lng ]. Может принимать модификатор `.sync`. *Required* | 75 | | map-events | Array | Нативные события (события Я.Карт), которые эмитит карта. Если не задано, то карта будет эмитить все события, перечисленные в секции [Events](#events) | 76 | | zoom | Number | Значение зума карты (от 0 до 19). Может принимать модификатор `.sync`. *Default: 18*. | 77 | | bounds | Array | Координаты левого нижнего и правого верхнего углов карты. Если аттрибут задан, то значения `coords` и `center` игнорируются. Может принимать модификатор `.sync`. | 78 | | [cluster-options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/ClusterPlacemark-docpage/#param-options) | Object | Объект, где ключами являются имена кластеров, а значениями - объекты опций этих кластеров. Объект принимает поле `layout` (тип `String`) со строковым представлением HTML темплейта для `balloonItemContentLayout`, поле `clusterIconContentLayout` (тип `String`) для кастомизации иконки кластера и поле `clusterBalloonLayout` (тип `String`) для кастомизации балуна кластера: [Custom Balloon example](https://tech.yandex.ru/maps/jsbox/2.1/cluster_custom_balloon_content_layout). Также здесь можно передать переопределенную функцию `createCluster` для добавления своей логики при создание кластеров (опция `use-object-manager` при этом должна быть отключена).| 79 | | cluster-callbacks | Object | Объект, где ключами являются имена кластеров, а значениями - объекты событий этих кластеров, напр. `{ clusterName: { click: function() {...}, contextmenu: anotherFunction } }` | 80 | | [behaviors](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/map.behavior.Manager-docpage/#param-behaviors) | Array | Массив подключенных поведений карты. Все остальные значения считаются выключенными.| 81 | | [controls](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/control.Manager-docpage/#add-param-control) | Array | Массив подключенных элементов управления картой. Все остальные значения считаются выключенными.| 82 | | detailed-controls | Object | Объект, где ключами являются элементы управления картой, а значениями - объекты настроект элемента. Предназначен для тонкой настройки элементов управления. | 83 | | map-type | String | Тип карты. Допустимые значения: `map, satellite, hybrid`. *Default: map*. | 84 | | scroll-zoom | Boolean | Установите в значение `false`, чтобы при прокрутке страницы у карты не срабатывал зум. *Default: true* | 85 | | placemarks | Array of Objects | **Deprecated**. Используйте компонент маркера | 86 | | use-object-manager | Boolean | Установите в значение `true` для использования Object Mananger. Используйте при большом количестве маркеров на карте. *Default: false* | 87 | | object-manager-clusterize | Boolean | Кластеризация при использовании Object Mananger. *Default: true* | 88 | | ymap-class | String | Определяет класс для элемента, где рендерится инстанс карты. Если аттрибут не определен - элемент использует стиль: `width: 100%; height: 100%;` | 89 | | init-without-markers | Boolean | Установите значение в `false`, чтобы карта не отображалась при отсутствии маркеров. Default: `true` | 90 | | show-all-markers | Boolean | Установите значение в `true`, чтобы границы карты при инициализации вмещали все маркеры. Default: `false` | 91 | | use-html-in-layout | Boolean | Установите значение в `true`, чтобы передавать в поля в балун в виде html-разметки. Default: `false` | 92 | | [options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Map-docpage/#Map__param-options) | Object | Опции карты | 93 | | balloon-component | Vue Component | Позволяет использовать компонент Vue в качестве балуна. Для работы необходима активация [runtimeCompiler](https://cli.vuejs.org/config/#runtimecompiler). **Только для Vue 2**| 94 | -------------------------------------------------------------------------------- /docs/guide/Marker.md: -------------------------------------------------------------------------------- 1 | # Маркер 2 | 3 | Вы можете задать маркеры для карты, используя компонент ``. 4 | 5 | ::: danger Важно! 6 | Начиная с версии `0.10` маркеры можно задавать только используя компонент `ymap-marker`. Атрибут карты `placemarks` не поддерживается. 7 | ::: 8 | 9 | ::: tip Обратите внимание 10 | Для каждого маркера является обязательным указание свойста `markerId` 11 | ::: 12 | 13 | Вы можете указать тип маркера, используя атрибут `marker-type`. Допустимые значения: 14 | * Placemark 15 | * Polyline 16 | * Rectangle 17 | * Polygon 18 | * Circle 19 | 20 | ## Events 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
Event namePayload
balloonclose 33 | marker event 34 |
balloonopen
click
contextmenu
dblclick
drag
dragend
dragstart
hintclose
hintopen
mouseenter
mouseleave
71 | 72 | ::: danger Важно! 73 | Начиная с версии `0.10` атрибут `callbacks` не поддерживается. Слушайте события у компонента. 74 | ::: 75 | 76 | ## Attributes 77 | 78 | | Attribute | Type | Description | Marker-types | 79 | | ----- | ----- | ----- | ----- | 80 | | marker-id | String, Number | Id маркера. `Required` || 81 | | marker-type | String | Тип маркера. Default: `Placemark` || 82 | | coords | Array [ latitude, longitude ] | Координаты маркера или центр круга. `Required` | Placemark, Circle | 83 | | coords | Array of arrays [ [latitude, longitude], [...] ] | Координаты вершин. `Required` | Rectangle, Polyline | 84 | | coords | Array of two arrays of coordinates arrays (first for outer contour, second for inner) [ [[latitude, longitude], [...]], [[...], [...]] ] | Координаты вершин. `Required` | Polygon | 85 | | marker-events | Array | Нативные события (события Я.Карт), которые эмитит маркер. Если не задано, то маркер будет эмитить все события, перечисленные в секции [Events](#events) | All | 86 | | hint-content | String | Содержимое подсказки | All | 87 | | balloon | Object | Свойства балуна: header, body, footer | All | 88 | | [icon](#icons) | Object | Иконка маркера | Placemark | 89 | | marker-fill | Object | Свойства заливки: enabled, color, opacity, imageHref | Polygon, Rectangle, Circle | 90 | | marker-stroke | Object | Свойства обводки: color, opacity, width, style | Polygon, Rectangle, Circle, Polyline | 91 | | circle-radius | Number | Радиус окружности в метрах. Default: `1000`. | Circle | 92 | | cluster-name | String | Имя кластера для группировки маркеров | All | 93 | | properties | Object | [Свойства маркера](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-feature.properties) | All | 94 | | options | Object | [Опции маркера](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-options) | All | 95 | | [balloon-template](/examples/#кастомный-темпnейт-баnуна) | String | HTML Template for balloon | All | 96 | | balloon-component-props | Object | Объект пропсов для балуна. _Только при инициализации балуна через balloonComponent_ | All | 97 | 98 | ## Slots 99 | 100 | Вы можете передать темплейт балуна для маркера, используя слот `balloon`. Вы также можете поместить в этот слот компонент, но имейте ввиду, что в балун передается только представление компонента, его визуальная часть. Если вы хотите использовать какую-то логику (например действие по нажатию на кнопку внутри балуна), то вы можете использовать событие маркера `balloonopen` и навешивать любые обработчики на элементы вашего балуна. Не забудьте удалить обработчики при наступлении события `balloonclose`. [Пример](/examples/#испоnьзование-сnота-баnуна-в-маркере) 101 | Также Вы можете определить макет балуна через слот `balloonLayout` в маркере. Содержимое данного слота заменит содержание стандартного макета для балуна. Будьте осторожны, если вы используете слот `balloonLayout`, слот `balloon` будет игнорироваться. 102 | 103 | ## Icons 104 | 105 | Вы можете задать настройки иконки маркера следующими полями: color (default: 'blue'), content, glyph. Свойство `glyph` имеет более высокий приоритете, чем `content`. [Список цветов и иконок](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/option.presetStorage-docpage/). В этом случае вы получаете классический вид маркера. 106 | 107 | Вы можете также задать вашу собственную иконку для маркера. В этом случае объект настроек должен выглядеть следующим образом: 108 | 109 | ```JavaScript 110 | { 111 | layout: 'default#image', // 'default#imageWithContent' для использования с контентом 112 | imageHref: markerIcon, // адрес изображения или data:image/svg+xml;base64 113 | imageSize: [43, 55], // размер иконки в px 114 | imageOffset: [-22, -55], // смещение иконки в px, 115 | /* Следующие поля актуальны для layout: 'default#imageWithContent' */ 116 | content: 'some content here', // содержимое контента 117 | contentOffset: [-22, -55], // смещение контента в px, 118 | contentLayout: '
$[properties.iconContent]
' // строковый HTML шаблон для контента 119 | } 120 | 121 | ``` 122 | 123 | [Пример использования](/examples/#кастомная-иконка) 124 | -------------------------------------------------------------------------------- /docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Введение 2 | 3 | ::: danger Важно! 4 | Эта версия пакета больше не поддерживается. Актуальная версия [здесь](https://github.com/yandex-maps-unofficial/vue-yandex-maps) 5 | ::: 6 | 7 | Компонент позволяет без усилий подключить Я.Карты в проект и дает необходимый минимум функционала "из коробки". Однако, вы можете пользоваться всей мощью [API Я.Карт](https://tech.yandex.ru/maps/doc/jsapi/2.1/quick-start/index-docpage/), обращаясь напрямую к [инстансу карты](/guide/Map.html). 8 | 9 | ## Подключение 10 | 11 | Подключите компонент, используя ваш пакетный менеджер 12 | 13 | ```Bash 14 | npm install vue-yandex-maps 15 | ``` 16 | 17 | После этого вы можете определить настройки подключения компонента: 18 | * [Индивидуальный ключ API](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/load-docpage/) 19 | * [Используемый язык](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/localization-docpage/) 20 | * [Порядок задания географических координат](https://tech.yandex.ru/maps/jsapi/doc/2.1/dg/concepts/load-docpage/#load__coordorder) 21 | * [Использование коммерческой версии Я.Карт](https://yandex.ru/dev/maps/commercial/doc/concepts/about-enterprise.html) 22 | * Версия Я.Карт 23 | 24 | Эти настройки являются опциональными, значения по умолчанию указаны ниже. 25 | 26 | ```JavaScript 27 | const settings = { 28 | apiKey: '', 29 | suggestApiKey: '', 30 | lang: 'ru_RU', 31 | coordorder: 'latlong', 32 | enterprise: false, 33 | version: '2.1' 34 | } 35 | ``` 36 | 37 | Теперь вы можете использовать эти настройки при регистрации вашего компонента. 38 | 39 | ## Регистрация компонента 40 | 41 | ### Глобальная 42 | 43 | ```JavaScript 44 | import YmapPlugin from 'vue-yandex-maps' 45 | 46 | Vue.use(YmapPlugin, settings) 47 | ``` 48 | 49 | ### Локальная 50 | 51 | ```JavaScript 52 | import { yandexMap, ymapMarker } from 'vue-yandex-maps' 53 | 54 | export default { 55 | components: { yandexMap, ymapMarker } 56 | // other options 57 | } 58 | 59 | ``` 60 | ```HTML 61 | 62 | 63 | 64 | ``` 65 | 66 | ### Nuxt module 67 | 68 | Добавьте в директорию `plugins` файл `ymapPlugin.js` со следующим содержанием 69 | 70 | ```JavaScript 71 | import Vue from 'vue' 72 | import YmapPlugin from 'vue-yandex-maps' 73 | 74 | const settings = { ... } // настройки плагина 75 | 76 | Vue.use(YmapPlugin, settings); 77 | ``` 78 | 79 | Добавьте созданный плагин в секцию плагинов файла `nuxt.config.js` 80 | 81 | ```JavaScript 82 | { 83 | plugins: [ 84 | { src: '~/plugins/ymapPlugin.js', mode: 'client' } 85 | ] 86 | } 87 | ``` 88 | 89 | ### Ymaps Loader 90 | 91 | Если вам нужно использовать глобальную переменную `ymaps` отдельно от компонента карт (геокодер и др.), просто импортируйте лоадер. Вы можете задать настройки, описанные выше, а также указать параметр `debug` (по умолчанию - `false`). Учтите, что функция загрузчика асинхронная. 92 | 93 | ```JavaScript 94 | import { loadYmap } from 'vue-yandex-maps' 95 | 96 | export default { 97 | async mounted() { 98 | await loadYmap({ ...settings, debug: true }); 99 | // здесь доступна переменная ymaps 100 | } 101 | } 102 | ``` 103 | 104 | ### CDN 105 | 106 | Вы можете подключить плагин напрямую, используя ссылку [https://unpkg.com/vue-yandex-maps](https://unpkg.com/vue-yandex-maps). Установка будет произведена автоматически при обнаружении Vue JS. Это может быть полезно при использовании [Code Pen](https://codepen.io/PNKBizz/pen/WMRwyM) 107 | -------------------------------------------------------------------------------- /examples/Cypress/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "root": true, 3 | "env": { 4 | "node": true 5 | }, 6 | "extends": [ 7 | "plugin:vue/recommended", 8 | "plugin:jest/recommended", 9 | "@vue/airbnb" 10 | ], 11 | "globals": { 12 | "ymaps": "readonly" 13 | }, 14 | "rules": { 15 | "no-console": 0, 16 | "import/no-unresolved": 0, 17 | "import/extensions": 0, 18 | "import/prefer-default-export": 0, 19 | "no-param-reassign": 0, 20 | "consistent-return": 0, 21 | "no-plusplus": 0, 22 | "prefer-destructuring": 0, 23 | "vue/max-attributes-per-line": ['error', { 24 | singleline: 4, 25 | multiline: { max: 1, allowFirstLine: false }, 26 | }], 27 | "vue/no-v-html": 0, 28 | "vue/require-default-prop": 0, 29 | }, 30 | "parserOptions": { 31 | "parser": "babel-eslint" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/Cypress/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /examples/Cypress/README.md: -------------------------------------------------------------------------------- 1 | # cypress 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Run your tests 19 | ``` 20 | npm run test 21 | ``` 22 | 23 | ### Lints and fixes files 24 | ``` 25 | npm run lint 26 | ``` 27 | 28 | ### Customize configuration 29 | See [Configuration Reference](https://cli.vuejs.org/config/). 30 | -------------------------------------------------------------------------------- /examples/Cypress/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset', 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /examples/Cypress/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cypress", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.3.2", 12 | "vue": "^2.6.10", 13 | "vue-yandex-maps": "^0.10.0" 14 | }, 15 | "devDependencies": { 16 | "@vue/cli-plugin-babel": "^4.0.0", 17 | "@vue/cli-plugin-eslint": "^4.0.0", 18 | "@vue/cli-service": "^4.0.0", 19 | "babel-eslint": "^10.0.3", 20 | "eslint": "^5.16.0", 21 | "eslint-plugin-vue": "^5.0.0", 22 | "vue-template-compiler": "^2.6.10" 23 | }, 24 | "postcss": { 25 | "plugins": { 26 | "autoprefixer": {} 27 | } 28 | }, 29 | "browserslist": [ 30 | "> 1%", 31 | "last 2 versions" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /examples/Cypress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/examples/Cypress/public/favicon.ico -------------------------------------------------------------------------------- /examples/Cypress/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | cypress 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/Cypress/src/App.vue: -------------------------------------------------------------------------------- 1 | 87 | 88 | 167 | 168 | 192 | -------------------------------------------------------------------------------- /examples/Cypress/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | 4 | Vue.config.productionTip = false; 5 | 6 | new Vue({ 7 | render: h => h(App), 8 | }).$mount('#app'); 9 | -------------------------------------------------------------------------------- /examples/Cypress/src/markers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "3fcb98b9-dd4c-4b37-af34-9a86b50ad11e", 4 | "coords": [ 5 | "33.82", 6 | "53.95" 7 | ], 8 | "clusterName": 1 9 | }, 10 | { 11 | "id": "84aee8c2-bb23-47f4-9830-691fff095b85", 12 | "coords": [ 13 | "33.79", 14 | "53.81" 15 | ], 16 | "clusterName": 3 17 | }, 18 | { 19 | "id": "80a9635a-db22-42ec-9d61-8f60f8f1ffaf", 20 | "coords": [ 21 | "33.77", 22 | "53.31" 23 | ], 24 | "clusterName": 1 25 | }, 26 | { 27 | "id": "5512f1fd-1521-4bca-a4e1-f4f99cfec782", 28 | "coords": [ 29 | "33.37", 30 | "53.97" 31 | ], 32 | "clusterName": 1 33 | }, 34 | { 35 | "id": "1de139bb-baf5-42e7-a5e8-8b7e781c138a", 36 | "coords": [ 37 | "33.79", 38 | "53.81" 39 | ], 40 | "clusterName": 2 41 | }, 42 | { 43 | "id": "7f5d9ab9-20e1-41ff-96e3-197868b2db18", 44 | "coords": [ 45 | "33.16", 46 | "53.95" 47 | ], 48 | "clusterName": 1 49 | }, 50 | { 51 | "id": "f5834d02-9892-422d-86fa-3b71b6712ca4", 52 | "coords": [ 53 | "33.38", 54 | "53.45" 55 | ], 56 | "clusterName": 2 57 | }, 58 | { 59 | "id": "2a48a160-ebcf-4cad-8f14-a8077a0cb903", 60 | "coords": [ 61 | "33.74", 62 | "53.92" 63 | ], 64 | "clusterName": 3 65 | }, 66 | { 67 | "id": "d5313f8d-d2de-416c-9703-5df19c0ad5db", 68 | "coords": [ 69 | "33.84", 70 | "53.89" 71 | ], 72 | "clusterName": 1 73 | }, 74 | { 75 | "id": "79c41b36-dc76-4e8e-b1a6-4fcf6b45e3e4", 76 | "coords": [ 77 | "33.69", 78 | "53.74" 79 | ], 80 | "clusterName": 3 81 | }, 82 | { 83 | "id": "a37a9989-0e28-4565-b761-1101d14a5a7b", 84 | "coords": [ 85 | "33.44", 86 | "53.36" 87 | ], 88 | "clusterName": 1 89 | }, 90 | { 91 | "id": "f9bf2d3d-d241-4759-add3-0b8ea4fdd4cb", 92 | "coords": [ 93 | "33.54", 94 | "53.91" 95 | ], 96 | "clusterName": 2 97 | }, 98 | { 99 | "id": "653eb7f6-f474-4f12-baac-a64d04b9bfab", 100 | "coords": [ 101 | "33.44", 102 | "53.48" 103 | ], 104 | "clusterName": 1 105 | }, 106 | { 107 | "id": "80c385fb-ed6b-4c10-bdfd-7109aa3ad943", 108 | "coords": [ 109 | "33.36", 110 | "53.22" 111 | ], 112 | "clusterName": 1 113 | }, 114 | { 115 | "id": "490ac17c-9a49-4d8d-85ea-c262990e4034", 116 | "coords": [ 117 | "33.2", 118 | "53.62" 119 | ], 120 | "clusterName": 2 121 | }, 122 | { 123 | "id": "1f4378ff-e5f7-418f-b20a-f41d72ff104a", 124 | "coords": [ 125 | "33.79", 126 | "53.57" 127 | ], 128 | "clusterName": 1 129 | }, 130 | { 131 | "id": "7af01f15-71c6-48f8-a6a1-f407ff77920c", 132 | "coords": [ 133 | "33.55", 134 | "53.23" 135 | ], 136 | "clusterName": 3 137 | }, 138 | { 139 | "id": "71b3c4a8-b29d-4e12-9a07-341749eb8276", 140 | "coords": [ 141 | "33.64", 142 | "53.52" 143 | ], 144 | "clusterName": 1 145 | }, 146 | { 147 | "id": "074d88a7-73f5-4fbf-814e-2838b75e4d7a", 148 | "coords": [ 149 | "33.26", 150 | "53.28" 151 | ], 152 | "clusterName": 3 153 | }, 154 | { 155 | "id": "b4282550-4ba4-4fa6-9f42-10f3cd85b5e1", 156 | "coords": [ 157 | "33.72", 158 | "53.42" 159 | ], 160 | "clusterName": 3 161 | } 162 | ] -------------------------------------------------------------------------------- /examples/Nuxt/.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /examples/Nuxt/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | -------------------------------------------------------------------------------- /examples/Nuxt/README.md: -------------------------------------------------------------------------------- 1 | # nuxt 2 | 3 | > Yandex Maps Nuxt example 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | $ npm install 10 | 11 | # serve with hot reload at localhost:3000 12 | $ npm run dev 13 | 14 | # build for production and launch server 15 | $ npm run build 16 | $ npm start 17 | 18 | # generate static project 19 | $ npm run generate 20 | ``` 21 | 22 | For detailed explanation on how things work, checkout [Nuxt.js docs](https://nuxtjs.org). 23 | -------------------------------------------------------------------------------- /examples/Nuxt/assets/README.md: -------------------------------------------------------------------------------- 1 | # ASSETS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked). 8 | -------------------------------------------------------------------------------- /examples/Nuxt/components/Logo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 80 | -------------------------------------------------------------------------------- /examples/Nuxt/components/README.md: -------------------------------------------------------------------------------- 1 | # COMPONENTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | The components directory contains your Vue.js Components. 6 | 7 | _Nuxt.js doesn't supercharge these components._ 8 | -------------------------------------------------------------------------------- /examples/Nuxt/layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /examples/Nuxt/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 56 | -------------------------------------------------------------------------------- /examples/Nuxt/middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /examples/Nuxt/nuxt.config.js: -------------------------------------------------------------------------------- 1 | import pkg from './package'; 2 | 3 | export default { 4 | mode: 'universal', 5 | 6 | /* 7 | ** Headers of the page 8 | */ 9 | head: { 10 | title: pkg.name, 11 | meta: [ 12 | { charset: 'utf-8' }, 13 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 14 | { hid: 'description', name: 'description', content: pkg.description } 15 | ], 16 | link: [ 17 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } 18 | ] 19 | }, 20 | 21 | /* 22 | ** Customize the progress-bar color 23 | */ 24 | loading: { color: '#fff' }, 25 | 26 | /* 27 | ** Global CSS 28 | */ 29 | css: [ 30 | ], 31 | 32 | /* 33 | ** Plugins to load before mounting the App 34 | */ 35 | plugins: [ 36 | { src: '~/plugins/ymapPlugin.js', mode: 'client' }, 37 | ], 38 | 39 | /* 40 | ** Nuxt.js modules 41 | */ 42 | modules: [ 43 | ], 44 | 45 | /* 46 | ** Build configuration 47 | */ 48 | build: { 49 | /* 50 | ** You can extend webpack config here 51 | */ 52 | extend(config, ctx) { 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/Nuxt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt", 3 | "version": "1.0.0", 4 | "description": "Yandex Maps Nuxt example", 5 | "author": "Pavel Galkin", 6 | "private": true, 7 | "scripts": { 8 | "dev": "nuxt", 9 | "build": "nuxt build", 10 | "start": "nuxt start", 11 | "generate": "nuxt generate" 12 | }, 13 | "dependencies": { 14 | "cross-env": "^5.2.0", 15 | "nuxt": "^2.4.0", 16 | "vue-yandex-maps": "^0.8.4" 17 | }, 18 | "devDependencies": { 19 | "nodemon": "^1.18.9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/Nuxt/pages/README.md: -------------------------------------------------------------------------------- 1 | # PAGES 2 | 3 | This directory contains your Application Views and Routes. 4 | The framework reads all the `*.vue` files inside this directory and creates the router of your application. 5 | 6 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing). 7 | -------------------------------------------------------------------------------- /examples/Nuxt/pages/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | 24 | 29 | -------------------------------------------------------------------------------- /examples/Nuxt/plugins/README.md: -------------------------------------------------------------------------------- 1 | # PLUGINS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains Javascript plugins that you want to run before mounting the root Vue.js application. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins). 8 | -------------------------------------------------------------------------------- /examples/Nuxt/plugins/ymapPlugin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import YmapPlugin from 'vue-yandex-maps' 3 | 4 | const settings = { 5 | lang: 'ru_RU' 6 | } 7 | 8 | Vue.use(YmapPlugin, settings); -------------------------------------------------------------------------------- /examples/Nuxt/static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /examples/Nuxt/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/examples/Nuxt/static/favicon.ico -------------------------------------------------------------------------------- /examples/Nuxt/store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /examples/Vue/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | package-lock.json 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | 15 | # Editor directories and files 16 | .idea 17 | .vscode 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | -------------------------------------------------------------------------------- /examples/Vue/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Run your tests 19 | ``` 20 | npm run test 21 | ``` 22 | 23 | ### Lints and fixes files 24 | ``` 25 | npm run lint 26 | ``` 27 | 28 | ### Customize configuration 29 | See [Configuration Reference](https://cli.vuejs.org/config/). 30 | -------------------------------------------------------------------------------- /examples/Vue/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /examples/Vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve --skip-plugins @vue/cli-plugin-eslint", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "core-js": "^2.6.5", 11 | "vue": "^2.6.10", 12 | "vue-yandex-maps": "^0.8.4" 13 | }, 14 | "devDependencies": { 15 | "@vue/cli-plugin-babel": "^3.7.0", 16 | "@vue/cli-service": "^3.7.0", 17 | "vue-template-compiler": "^2.5.21" 18 | }, 19 | "postcss": { 20 | "plugins": { 21 | "autoprefixer": {} 22 | } 23 | }, 24 | "browserslist": [ 25 | "> 1%", 26 | "last 2 versions" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /examples/Vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/examples/Vue/public/favicon.ico -------------------------------------------------------------------------------- /examples/Vue/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | example 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/Vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | 35 | 53 | -------------------------------------------------------------------------------- /examples/Vue/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import ymapPlugin from '../../../src'; 4 | 5 | Vue.config.productionTip = false; 6 | Vue.use(ymapPlugin); 7 | 8 | new Vue({ 9 | render: h => h(App), 10 | }).$mount('#app'); 11 | -------------------------------------------------------------------------------- /examples/cdn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 20 | 21 | 22 |
23 | 27 | 30 | 33 | 41 | 42 | 43 | 46 |
47 | 80 | 81 | -------------------------------------------------------------------------------- /examples/vue3/.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /examples/vue3/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/vue3/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /examples/vue3/README.md: -------------------------------------------------------------------------------- 1 | # vue3 2 | 3 | ## Project setup 4 | ``` 5 | yarn install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | yarn serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | yarn build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | yarn lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /examples/vue3/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /examples/vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve --skip-plugins @vue/cli-plugin-eslint", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "core-js": "^3.6.5", 12 | "vue": "^3.0.0" 13 | }, 14 | "devDependencies": { 15 | "@vue/cli-plugin-babel": "~4.5.0", 16 | "@vue/cli-plugin-eslint": "~4.5.0", 17 | "@vue/cli-service": "~4.5.0", 18 | "@vue/compiler-sfc": "^3.0.0", 19 | "babel-eslint": "^10.1.0", 20 | "eslint": "^6.7.2", 21 | "eslint-plugin-vue": "^7.0.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/vue3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yandex-maps-unofficial/vue-yandex-map/00724e276baf643e782d5b33d433f4782b5fcd5f/examples/vue3/public/favicon.ico -------------------------------------------------------------------------------- /examples/vue3/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /examples/vue3/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import ymapPlugin from '../../../dist/vue-yandex-maps.esm.js'; 4 | 5 | const app = createApp(App) 6 | 7 | app.use(ymapPlugin) 8 | app.mount('#app') 9 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleFileExtensions: [ 3 | "js", 4 | "json", 5 | "vue" 6 | ], 7 | transform: { 8 | ".*\\.(vue)$": "vue-jest", 9 | "^.+\\.js$": "/node_modules/babel-jest" 10 | }, 11 | moduleNameMapper: { 12 | "^@/(.*)$": "/src/$1" 13 | }, 14 | globals: { 15 | MutationObserver: class { 16 | constructor(callback) {} 17 | disconnect() {} 18 | observe(element, initObject) {} 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | cypress: 2 | gnome-terminal --tab -- sh -c "npm run serve --prefix examples/Cypress; bash" 3 | npx cypress open 4 | 5 | .PHONY: cypress -------------------------------------------------------------------------------- /nuxt/index.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path'); 2 | 3 | module.exports = function nuxtVueYandexMaps(options) { 4 | this.addPlugin({ 5 | src: resolve(__dirname, 'plugin.js'), 6 | fileName: 'vue-yandex-maps.js', 7 | options, 8 | ssr: false, 9 | }); 10 | }; 11 | 12 | module.exports.meta = require('../package.json'); 13 | -------------------------------------------------------------------------------- /nuxt/plugin.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import YmapPlugin from 'vue-yandex-maps'; 3 | 4 | Vue.use(YmapPlugin, <%= serialize(options) %>); 5 | -------------------------------------------------------------------------------- /old-docs.md: -------------------------------------------------------------------------------- 1 | 2 | # vue-yandex-maps 3 | 4 | vue-yandex-maps is a plugin for vue.js that adds yandex-map custom element. 5 | 6 | # Install 7 | 8 | ```Bash 9 | npm install vue-yandex-maps --save 10 | ``` 11 | 12 | # Register component 13 | 14 | You may define config for map: 15 | * `apiKey: String` // '' by default [Documentation](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/load-docpage/) 16 | * `lang: String` // 'ru_RU' by default [Available langs](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/localization-docpage/) 17 | * `version: String` // '2.1' by default 18 | 19 | ```JavaScript 20 | const settings = { // you may define your apiKey, lang and version or skip this. 21 | apiKey: 'xxx', 22 | lang: 'ru_RU', 23 | version: '2.1' 24 | } 25 | ``` 26 | ### Register globally 27 | ```JavaScript 28 | import YmapPlugin from 'vue-yandex-maps' 29 | Vue.use(YmapPlugin, settings) 30 | ``` 31 | ### Or for a single instance 32 | ```JavaScript 33 | import { yandexMap, ymapMarker } from 'vue-yandex-maps' 34 | new Vue({ 35 | components: { yandexMap, ymapMarker } 36 | }) 37 | 38 | ``` 39 | ```HTML 40 | 43 | 44 | 45 | ``` 46 | 47 | ### Nuxt module 48 | 49 | Add `vue-yandex-maps/nuxt` to modules section of `nuxt.config.js` 50 | 51 | ```JavaScript 52 | { 53 | modules: [ 54 | ['vue-yandex-maps/nuxt', settings] 55 | ] 56 | } 57 | ``` 58 | 59 | ### Direct include 60 | 61 | You can use the CDN: https://unpkg.com/vue-yandex-maps, `yandexMap` is exposed to `window` and will automatically install itself. It might be useful for [Code Pen](https://codepen.io/PNKBizz/pen/WMRwyM) 62 | 63 | ## Usage 64 | 65 | Use `` tag to enable the map instance and use attributes to define map options. 66 | 67 | `` has a class `ymap-container` and child element, where rendering map instance. Child class you may define through map attribute `ymap-class`. If you doesn't define this class - child element will have `style` attribute with `width: 100%; height: 100%;` 68 | 69 | If you have a lot of markers on your map i strongly recommend you to use map attribute `useObjectManager`. But in this case you can't set callbacks to your markers through marker attribute `callbacks`. 70 | 71 | You may define placemarks on your map by using `` tag or set an array of objects with placemark options through `` attribute `placemarks` ([interface description](https://tech.yandex.ru/maps/doc/jsapi/2.0/ref/reference/GeoObject-docpage/)). You also can use both methods together.
72 | You must define `markerId` for every marker on your map in any case fo setting (through map attribute `placemarks` or using `ymap-marker` components).
73 | The Map instance rerender when changed array with markers or marker properties if marker is a component.
74 | Also map watch property `coords` and react without rerender, when it changed. 75 | 76 | Type of marker in `marker-type` attribute can be: 77 | 78 | * Placemark 79 | * Polyline 80 | * Rectangle 81 | * Polygon 82 | * Circle 83 | 84 | ```HTML 85 | 98 | 99 | 108 | 109 | 118 | 119 | 129 | 130 | 131 | ``` 132 | 133 | ```JavaScript 134 | 135 | data() { 136 | return { 137 | placemarks: [ 138 | { 139 | coords: [54.8, 39.8], 140 | properties: {}, // define properties here 141 | options: {}, // define options here 142 | clusterName: "1", 143 | balloonTemplate: '
"Your custom template"
' 144 | callbacks: { click: function() {} } 145 | } 146 | ] 147 | } 148 | } 149 | 150 | ``` 151 | 152 | # Events 153 | 154 | ## Map events 155 | 156 | | Event name | Payload | 157 | | ----- | ----- | 158 | | 'click' | [map event](https://tech.yandex.ru/maps/doc/jsapi/2.1/dg/concepts/events-docpage/) | 159 | | 'map-was-initialized' | Link to map instance | 160 | 161 | # Attributes 162 | 163 | ## Map attributes 164 | 165 | | Attribute | Type | Description | 166 | | ----- | ----- | ----- | 167 | | settings | Object | Map settings. You may define your apiKey, lang and version or skip this. | 168 | | coords | Array [ latitude, longtitude ] | Coordinates of map center. Required | 169 | | zoom | Number | Zoom of map (from 0 to 19). Default: `18`. | 170 | | cluster-options | Object | Map, where key is a name of cluster and value is an object of cluster options. Also you may set field 'layout' (type `String`) in cluster options object with HTML Template for balloonItemContentLayout. [Cluster option](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/ClusterPlacemark-docpage/#param-options) | 171 | | cluster-callbacks | Object | Map, where key is a name of cluster and value is an object, where key is an event name and value is a callback function, e.g. { click: function() {...}, contextmenu: anotherFunction } | 172 | | behaviors | Array | Array of enabled map behaviors. All another will be disabled. [Behaviors](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/map.behavior.Manager-docpage/#param-behaviors) | 173 | | controls | Array | Array of enabled map controls. All another will be disabled. [Controls](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/control.Manager-docpage/#add-param-control) | 174 | | detailed-controls | Object | Map, where key is a name of control and value is an object of control options. | 175 | | map-type | String | Map type. Possible types: `map, satellite, hybrid`. Default: `map`. | 176 | | scroll-zoom | Boolean | Set to `false` to disable zoom map on scroll page. Default: `true` | 177 | | zoom-control | Object | Configs for zoomControl of the map. [More](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/control.ZoomControl-docpage/) | 178 | | placemarks | Array of Objects | Array of config objects with fields: coordinates ([lat, lng]), properties, options. [More](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Placemark-docpage/) | 179 | | use-object-manager | Boolean | Set to `true` to use Object Mananger in map. Default: `false` | 180 | | object-manager-clusterize | Boolean | Defines using clusterize in Object Mananger. Default: `true` | 181 | | ymap-class | String | Defines class for element, where rendering map instance. If not defined - element use style: `width: 100%; height: 100%;` | 182 | | init-without-markers | Boolean | Set to `false` to prevent map initialization if there is no markers. Default: `true` | 183 | | options | Object | [Map options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/Map-docpage/#Map__param-options) | 184 | 185 | ## Marker attributes 186 | 187 | | Attribute | Type | Description | Marker-types | 188 | | ----- | ----- | ----- | ----- | 189 | | marker-id | String, Number | Marker Id. `Required` || 190 | | marker-type | String | Type of marker || 191 | | coords | Array [ latitude, longtitude ] | Coordinates of point or circle center. `Required` | Placemark, Circle | 192 | | coords | Array of arrays [ [latitude, longtitude], [...] ] | Coordinates of shape corners. `Required` | Rectangle, Polyline | 193 | | coords | Array of two arrays of coordinates arrays (first for outer contour, second for inner) [ [[latitude, longtitude], [...]], [[...], [...]] ] | Coordinates of shape corners. Required | Polygon | 194 | | hint-content | String | Tooltip content | All | 195 | | balloon | Object | Balloon content object with three properties: header, body, footer | All | 196 | | icon | Object | [About icons](#icons) | Placemark | 197 | | marker-fill | Object | Fill properties object with four properties: enabled, color, opacity, imageHref | Polygon, Rectangle, Circle | 198 | | marker-stroke | Object | Stroke properties object with four properties: color, opacity, width, style | Polygon, Rectangle, Circle, Polyline | 199 | | circle-radius | Number | Radius of circle in meters. Default: `1000`. | Circle | 200 | | cluster-name | String | Attribute for grouping markers in clusters | All | 201 | | properties | Object | Object with marker [properties](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-feature.properties) | All | 202 | | options | Object | Object with marker [options](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#param-options) | All | 203 | | callbacks | Object | Object, where key is an event name and value is a callback function, e.g. { click: function() {...}, contextmenu: anotherFunction }. [Events list](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/GeoObject-docpage/#events-summary) | All | 204 | | [balloonTemplate](#balloon-template) | String | HTML Template for balloon | All | 205 | 206 | # Icons 207 | 208 | You may define icon attribute as object with three properties: color (default value is 'blue'), content, glyph. Glyph property have higher priority than content. [List of colors and icons](https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/option.presetStorage-docpage/). In this way you get classic placemark. 209 | 210 | Or you may define it as a placemark with custom icon. In this case you need to set the object of the following form: 211 | 212 | ```JavaScript 213 | { 214 | layout: 'default#image', 215 | imageHref: markerIcon, 216 | imageSize: [43, 55], 217 | imageOffset: [-22, -55] 218 | } 219 | 220 | ``` 221 | 222 | If you need to use it with content, just change the layout as `default#imageWithContent` 223 | 224 | where `markerIcon`: data or computed path to image or data:image/svg+xml;base64, `imageSize`: size of icon in px, `imageOffset`: icon offset in px 225 | 226 | # Balloon Template 227 | 228 | You can define your own template for balloon. 229 | 230 | ```HTML 231 | 234 | 239 | 240 | 241 | ``` 242 | 243 | ```JavaScript 244 | computed: { 245 | balloonTemplate() { 246 | return ` 247 |

Hi, everyone!

248 |

I am here: ${this.coords}

249 | 250 | ` 251 | } 252 | } 253 | 254 | ``` 255 | 256 | ```CSS 257 | .red { 258 | color: red; 259 | } 260 | 261 | ``` 262 | 263 | # License 264 | 265 | MIT 266 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-yandex-maps", 3 | "version": "0.11.18", 4 | "description": "Yandex Maps component for VueJS.", 5 | "main": "dist/vue-yandex-maps.umd.js", 6 | "module": "dist/vue-yandex-maps.esm.js", 7 | "unpkg": "dist/vue-yandex-maps.min.js", 8 | "scripts": { 9 | "build": "rollup -c", 10 | "docs:build": "vuepress build docs", 11 | "docs:dev": "vuepress dev docs", 12 | "lint": "eslint ./src/* --fix", 13 | "test": "jest" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/PNKBizz/vue-yandex-map.git" 18 | }, 19 | "keywords": [ 20 | "yandex-maps", 21 | "maps", 22 | "vue" 23 | ], 24 | "author": "bizz.gc@gmail.com", 25 | "license": "MIT", 26 | "devDependencies": { 27 | "@babel/cli": "^7.2.3", 28 | "@babel/core": "^7.2.2", 29 | "@babel/polyfill": "^7.2.5", 30 | "@babel/preset-env": "^7.2.3", 31 | "@vue/cli-service": "^3.12.0", 32 | "@vue/eslint-config-airbnb": "^4.0.0", 33 | "@vue/test-utils": "^1.0.0-beta.29", 34 | "babel-eslint": "^10.0.1", 35 | "babel-jest": "^24.9.0", 36 | "eslint": "^5.8.0", 37 | "eslint-plugin-jest": "^22.19.0", 38 | "eslint-plugin-vue": "^5.0.0", 39 | "jest": "^24.9.0", 40 | "rollup": "^1.1.0", 41 | "rollup-plugin-babel": "^4.3.0", 42 | "rollup-plugin-terser": "^4.0.4", 43 | "rollup-plugin-uglify": "^6.0.2", 44 | "vue-jest": "^3.0.5", 45 | "vuepress": "^1.9.7" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import { terser } from 'rollup-plugin-terser'; 3 | import { uglify } from 'rollup-plugin-uglify'; 4 | import pkg from './package.json'; 5 | 6 | export default [ 7 | { 8 | input: 'src/index.js', 9 | output: { 10 | name: 'vue-yandex-maps', 11 | file: pkg.module, 12 | format: 'es', 13 | exports: 'named', 14 | globals: { vue: 'vue' }, 15 | }, 16 | plugins: [ 17 | babel({ 18 | exclude: 'node_modules/**', 19 | }), 20 | terser(), 21 | ], 22 | }, 23 | { 24 | input: 'src/index.js', 25 | output: { 26 | name: 'vue-yandex-maps', 27 | file: pkg.main, 28 | format: 'umd', 29 | exports: 'named', 30 | globals: { vue: 'vue' }, 31 | }, 32 | plugins: [ 33 | babel({ 34 | exclude: 'node_modules/**', 35 | }), 36 | uglify(), 37 | ], 38 | }, 39 | { 40 | input: 'src/index.js', 41 | output: { 42 | name: 'vue-yandex-maps', 43 | file: pkg.unpkg, 44 | format: 'iife', 45 | exports: 'named', 46 | extend: true, 47 | globals: { vue: 'vue' }, 48 | }, 49 | plugins: [ 50 | babel({ 51 | exclude: 'node_modules/**', 52 | }), 53 | uglify(), 54 | ], 55 | }, 56 | ]; 57 | -------------------------------------------------------------------------------- /src/Marker.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | import * as utils from './utils'; 3 | 4 | const MARKER_TYPES = [ 5 | 'placemark', 6 | 'polyline', 7 | 'rectangle', 8 | 'polygon', 9 | 'circle', 10 | ]; 11 | 12 | const defaultMarkerEvents = [ 13 | 'balloonclose', 14 | 'balloonopen', 15 | 'click', 16 | 'contextmenu', 17 | 'dblclick', 18 | 'drag', 19 | 'dragend', 20 | 'dragstart', 21 | 'hintclose', 22 | 'hintopen', 23 | 'mouseenter', 24 | 'mouseleave', 25 | ]; 26 | 27 | export default { 28 | inject: ['useObjectManager', 'addMarker', 'deleteMarker', 'compareValues', 'makeComponentBalloonTemplate'], 29 | props: { 30 | coords: Array, 31 | hintContent: String, 32 | icon: Object, 33 | balloon: Object, 34 | markerType: { 35 | type: String, 36 | validator(val) { 37 | return MARKER_TYPES.includes(val.toLowerCase()); 38 | }, 39 | default: 'placemark', 40 | }, 41 | markerFill: Object, 42 | markerStroke: Object, 43 | clusterName: [String, Number], 44 | circleRadius: { 45 | validator(val) { 46 | return !Number.isNaN(val); 47 | }, 48 | default: 1000, 49 | }, 50 | balloonTemplate: String, 51 | markerId: { 52 | type: [String, Number], 53 | required: true, 54 | }, 55 | properties: Object, 56 | options: Object, 57 | balloonComponentProps: { 58 | type: Object, 59 | default: () => ({}), 60 | }, 61 | markerEvents: { 62 | type: Array, 63 | default: () => [], 64 | }, 65 | }, 66 | data: () => ({ unwatchArr: [] }), 67 | render(h) { 68 | return h('div', [ 69 | this.$slots.balloon && h('div', { style: 'display: none;' }, [this.$slots.balloon]), 70 | this.$slots.balloonLayout && h('div', { style: 'display: none;' }, [this.$slots.balloonLayout]) 71 | ]); 72 | }, 73 | mounted() { 74 | Object.keys(this.$props).forEach((prop) => { 75 | if (prop === 'balloonComponentProps') return; 76 | this.unwatchArr.push(this.$watch( 77 | prop, 78 | (newVal, oldVal) => this.compareValues({ 79 | newVal, 80 | oldVal, 81 | marker: this.defineMarker(), 82 | }), 83 | )); 84 | }); 85 | 86 | this.addMarker(this.defineMarker()); 87 | }, 88 | methods: { 89 | defineMarker() { 90 | const marker = { 91 | markerId: this.markerId, 92 | markerType: this.markerType || 'placemark', 93 | coords: utils.setCoordsToNumeric(this.coords), 94 | hintContent: this.hintContent, 95 | markerFill: this.markerFill, 96 | circleRadius: +this.circleRadius, 97 | clusterName: this.clusterName, 98 | markerStroke: this.markerStroke, 99 | balloon: this.balloon, 100 | properties: this.properties, 101 | options: this.options, 102 | balloonOptions: {}, 103 | }; 104 | 105 | let balloonContentLayout = null; 106 | let balloonLayout = null; 107 | 108 | if (this.balloonTemplate) { 109 | balloonContentLayout = ymaps.templateLayoutFactory 110 | .createClass(this.balloonTemplate); 111 | } 112 | 113 | if (this.$slots.balloon) { 114 | balloonContentLayout = ymaps.templateLayoutFactory 115 | .createClass(this.$slots.balloon[0].elm.outerHTML); 116 | } 117 | 118 | if (this.$slots.balloonLayout) { 119 | balloonLayout = ymaps.templateLayoutFactory 120 | .createClass(this.$slots.balloonLayout[0].elm.outerHTML); 121 | } 122 | 123 | if (this.makeComponentBalloonTemplate) { 124 | balloonContentLayout = this.makeComponentBalloonTemplate(this, marker); 125 | } 126 | 127 | if (balloonContentLayout != null) { 128 | marker.balloonOptions.balloonContentLayout = balloonContentLayout; 129 | } 130 | 131 | if (balloonLayout != null) { 132 | marker.balloonOptions.balloonLayout = balloonLayout; 133 | } 134 | 135 | if (this.icon && ['default#image', 'default#imageWithContent'].includes(this.icon.layout)) { 136 | marker.iconContent = this.icon.content; 137 | marker.iconLayout = this.icon.layout; 138 | marker.iconImageHref = this.icon.imageHref; 139 | marker.iconImageSize = this.icon.imageSize; 140 | marker.iconImageOffset = this.icon.imageOffset; 141 | marker.iconContentOffset = this.icon.contentOffset; 142 | if (this.icon.contentLayout && typeof this.icon.contentLayout === 'string') { 143 | marker.iconContentLayout = ymaps.templateLayoutFactory 144 | .createClass(this.icon.contentLayout); 145 | } 146 | } else { 147 | marker.icon = this.icon; 148 | } 149 | 150 | const markerType = utils.createMarkerType(marker.markerType, this.useObjectManager); 151 | const initialProps = { 152 | hintContent: marker.hintContent, 153 | iconContent: marker.icon ? marker.icon.content : marker.iconContent, 154 | markerId: marker.markerId, 155 | }; 156 | 157 | const balloonProps = marker.balloon ? { 158 | balloonContentHeader: marker.balloon.header, 159 | balloonContentBody: marker.balloon.body, 160 | balloonContentFooter: marker.balloon.footer, 161 | } : {}; 162 | 163 | const properties = Object.assign(initialProps, balloonProps, marker.properties); 164 | 165 | const iconOptions = marker.iconLayout ? { 166 | iconLayout: marker.iconLayout, 167 | iconImageHref: marker.iconImageHref, 168 | iconImageSize: marker.iconImageSize, 169 | iconImageOffset: marker.iconImageOffset, 170 | iconContentOffset: marker.iconContentOffset, 171 | iconContentLayout: marker.iconContentLayout, 172 | } : { preset: marker.icon && `islands#${utils.getIconPreset(marker)}Icon` }; 173 | 174 | const strokeOptions = marker.markerStroke ? { 175 | strokeColor: marker.markerStroke.color || '0066ffff', 176 | strokeOpacity: parseFloat(marker.markerStroke.opacity) >= 0 177 | ? parseFloat(marker.markerStroke.opacity) : 1, 178 | strokeStyle: marker.markerStroke.style, 179 | strokeWidth: parseFloat(marker.markerStroke.width) >= 0 180 | ? parseFloat(marker.markerStroke.width) : 1, 181 | } : {}; 182 | 183 | const fillOptions = marker.markerFill ? { 184 | fill: marker.markerFill.enabled || true, 185 | fillColor: marker.markerFill.color || '0066ff99', 186 | fillOpacity: parseFloat(marker.markerFill.opacity) >= 0 187 | ? parseFloat(marker.markerFill.opacity) : 1, 188 | fillImageHref: marker.markerFill.imageHref || '', 189 | } : {}; 190 | 191 | const options = Object.assign( 192 | iconOptions, 193 | strokeOptions, 194 | fillOptions, 195 | marker.balloonOptions, 196 | marker.options, 197 | ); 198 | 199 | if (markerType === 'Circle') { 200 | marker.coords = [marker.coords, marker.circleRadius]; 201 | } 202 | 203 | const obj = { 204 | properties, 205 | options, 206 | markerType, 207 | coords: marker.coords, 208 | clusterName: marker.clusterName, 209 | }; 210 | 211 | const mapMarker = utils.createMarker(obj, this.useObjectManager, this.$emit); 212 | if (!this.useObjectManager) { 213 | const events = this.markerEvents.length ? this.markerEvents : defaultMarkerEvents; 214 | events.forEach(_ => mapMarker.events.add(_, e => this.$emit(_, e))); 215 | } 216 | return mapMarker; 217 | }, 218 | }, 219 | beforeDestroy() { 220 | this.unwatchArr.forEach(f => f()); 221 | this.deleteMarker(this.markerId); 222 | }, 223 | }; 224 | -------------------------------------------------------------------------------- /src/YMap.js: -------------------------------------------------------------------------------- 1 | import * as utils from './utils'; 2 | 3 | const { emitter } = utils; 4 | 5 | const defaultMapEvents = [ 6 | 'actionend', 7 | 'balloonclose', 8 | 'balloonopen', 9 | 'click', 10 | 'contextmenu', 11 | 'dblclick', 12 | 'destroy', 13 | 'hintclose', 14 | 'hintopen', 15 | 'optionschange', 16 | 'sizechange', 17 | 'typechange', 18 | ]; 19 | 20 | export default { 21 | pluginOptions: {}, 22 | provide() { 23 | let deletedMarkers = []; 24 | let changedMarkers = []; 25 | let deleteMarkerWithTimeout; 26 | let changeMarkersWithTimeout; 27 | const deleteMarker = (id) => { 28 | if (!this.myMap.geoObjects) return; 29 | deletedMarkers.push(id); 30 | if (deleteMarkerWithTimeout) clearTimeout(deleteMarkerWithTimeout); 31 | deleteMarkerWithTimeout = setTimeout(() => { 32 | this.deleteMarkers(deletedMarkers); 33 | deletedMarkers = []; 34 | }, 0); 35 | }; 36 | const compareValues = ({ newVal, oldVal, marker }) => { 37 | if (utils.objectComparison(newVal, oldVal)) { return; } 38 | changedMarkers.push(marker); 39 | if (changeMarkersWithTimeout) { clearTimeout(changeMarkersWithTimeout); } 40 | changeMarkersWithTimeout = setTimeout(() => { 41 | this.setMarkers(changedMarkers); 42 | changedMarkers = []; 43 | }, 0); 44 | }; 45 | 46 | let makeComponentBalloonTemplate; 47 | 48 | if (this.balloonComponent != null) { 49 | makeComponentBalloonTemplate = utils.makeComponentBalloonTemplate(this.balloonComponent); 50 | } 51 | 52 | return { 53 | useObjectManager: this.useObjectManager, 54 | addMarker: this.addMarker, 55 | deleteMarker, 56 | compareValues, 57 | makeComponentBalloonTemplate, 58 | }; 59 | }, 60 | data() { 61 | return { 62 | ymapId: `yandexMap${Math.round(Math.random() * 100000)}`, 63 | style: this.ymapClass ? '' : 'width: 100%; height: 100%;', 64 | isReady: false, 65 | debounce: null, 66 | }; 67 | }, 68 | props: { 69 | coords: { 70 | type: Array, 71 | required: true, 72 | }, 73 | zoom: { 74 | validator(val) { 75 | return !Number.isNaN(val); 76 | }, 77 | default: 18, 78 | }, 79 | bounds: Array, 80 | clusterOptions: { 81 | type: Object, 82 | default: () => ({}), 83 | }, 84 | clusterCallbacks: { 85 | type: Object, 86 | default: () => ({}), 87 | }, 88 | behaviors: { 89 | type: Array, 90 | default: () => ['default'], 91 | }, 92 | controls: { 93 | type: Array, 94 | default: () => ['default'], 95 | validator(val) { 96 | return utils.controlsTypeValidator(val); 97 | }, 98 | }, 99 | detailedControls: { 100 | type: Object, 101 | validator(val) { 102 | const controls = Object.keys(val); 103 | return utils.controlsTypeValidator(controls); 104 | }, 105 | }, 106 | scrollZoom: { 107 | type: Boolean, 108 | default: true, 109 | }, 110 | mapType: { 111 | type: String, 112 | default: 'map', 113 | validator(val) { 114 | return ['map', 'satellite', 'hybrid'].includes(val); 115 | }, 116 | }, 117 | placemarks: { 118 | type: Array, 119 | default() { 120 | return []; 121 | }, 122 | }, 123 | useObjectManager: { 124 | type: Boolean, 125 | default: false, 126 | }, 127 | objectManagerClusterize: { 128 | type: Boolean, 129 | default: true, 130 | }, 131 | ymapClass: String, 132 | initWithoutMarkers: { 133 | type: Boolean, 134 | default: true, 135 | }, 136 | debug: { 137 | type: Boolean, 138 | default: false, 139 | }, 140 | settings: { 141 | type: Object, 142 | default: () => ({}), 143 | }, 144 | options: { 145 | type: Object, 146 | default: () => ({}), 147 | }, 148 | mapEvents: { 149 | type: Array, 150 | default: () => [], 151 | }, 152 | showAllMarkers: Boolean, 153 | disablePan: Boolean, 154 | balloonComponent: { 155 | type: [Object, Function], 156 | default: () => null, 157 | }, 158 | useHtmlInLayout: Boolean, 159 | }, 160 | computed: { 161 | coordinates() { 162 | return this.coords.map(item => +item); 163 | }, 164 | }, 165 | methods: { 166 | init() { 167 | this.myMap = {}; 168 | this.markers = []; 169 | 170 | // if ymap isn't initialized or have no markers; 171 | if (!window.ymaps 172 | || !ymaps.GeoObjectCollection 173 | || (!this.initWithoutMarkers && !this.$slots.default && !this.placemarks.length) 174 | || (!document.getElementById(this.ymapId)) 175 | ) return; 176 | 177 | this.$emit('map-initialization-started'); 178 | 179 | this.myMap = new ymaps.Map(this.ymapId, { 180 | center: this.coordinates, 181 | zoom: +this.zoom, 182 | bounds: this.bounds, 183 | behaviors: this.behaviors, 184 | controls: this.controls, 185 | type: `yandex#${this.mapType}`, 186 | }, this.options); 187 | const events = this.mapEvents.length ? this.mapEvents : defaultMapEvents; 188 | events.forEach(_ => this.myMap.events.add(_, e => this.$emit(_, e))); 189 | this.myMap.events.add('boundschange', (e) => { 190 | const { originalEvent: { newZoom, newCenter, newBounds } } = e; 191 | this.$emit('boundschange', e); 192 | this.$emit('update:zoom', newZoom); 193 | this.$emit('update:coords', newCenter); 194 | this.$emit('update:bounds', newBounds); 195 | }); 196 | if (this.detailedControls) { 197 | const controls = Object.keys(this.detailedControls); 198 | controls.forEach((controlName) => { 199 | this.myMap.controls.remove(controlName); 200 | this.myMap.controls.add(controlName, this.detailedControls[controlName]); 201 | }); 202 | } 203 | if (this.scrollZoom === false) { 204 | this.myMap.behaviors.disable('scrollZoom'); 205 | } 206 | 207 | this.isReady = true; 208 | 209 | this.$emit('map-was-initialized', this.myMap); 210 | }, 211 | addMarker(marker) { 212 | this.markers.push(marker); 213 | if (this.debounce) clearTimeout(this.debounce); 214 | this.debounce = setTimeout(() => { 215 | this.setMarkers(this.markers); 216 | }, 0); 217 | }, 218 | setMarkers(markers) { 219 | const config = { 220 | options: this.clusterOptions, 221 | callbacks: this.clusterCallbacks, 222 | map: this.myMap, 223 | useObjectManager: this.useObjectManager, 224 | objectManagerClusterize: this.objectManagerClusterize, 225 | useHtmlInLayout: this.useHtmlInLayout, 226 | }; 227 | if (this.markers !== markers) { 228 | const ids = markers.map(_ => (this.useObjectManager ? _.id : _.properties.get('markerId'))); 229 | this.deleteMarkers(ids); 230 | utils.addToMap(markers, config); 231 | this.$emit('markers-was-change', ids); 232 | } else utils.addToMap(markers, config); 233 | this.markers = []; 234 | if (this.showAllMarkers) { 235 | this.myMap.setBounds(this.myMap.geoObjects.getBounds()); 236 | } 237 | }, 238 | deleteMarkers(deletedMarkersIds) { 239 | // geoObjects.each is not immutable, so: 240 | const geoObjects = []; 241 | this.myMap.geoObjects.each(geoObject => geoObjects.push(geoObject)); 242 | 243 | // and now - iterate & possibly delete 244 | geoObjects.forEach((collection) => { 245 | const removedMarkers = []; 246 | if (this.useObjectManager) { 247 | collection.remove(deletedMarkersIds); 248 | } else { 249 | const checkMarker = (marker) => { 250 | const markerId = marker.properties.get('markerId'); 251 | if (deletedMarkersIds.includes(markerId)) removedMarkers.push(marker); 252 | }; 253 | let length; 254 | if (collection.each) { 255 | collection.each(checkMarker); 256 | length = collection.getLength(); 257 | } else if (collection.getGeoObjects) { 258 | const markersArray = collection.getGeoObjects(); 259 | markersArray.forEach(checkMarker); 260 | length = markersArray.length; 261 | } 262 | if (length === 0 || length === removedMarkers.length) { 263 | this.myMap.geoObjects.remove(collection); 264 | } else if (removedMarkers.length) { 265 | removedMarkers.forEach(marker => collection.remove(marker)); 266 | } 267 | } 268 | }); 269 | this.$emit('markers-was-delete', deletedMarkersIds); 270 | }, 271 | }, 272 | watch: { 273 | coordinates(val) { 274 | if (!this.myMap) return; 275 | if (this.disablePan) { 276 | if (this.myMap.setCenter) this.myMap.setCenter(val); 277 | } else if (this.myMap.panTo && this.myMap.getZoom()) { 278 | this.myMap.panTo(val, { checkZoomRange: true }); 279 | } 280 | }, 281 | zoom() { 282 | if (this.myMap) this.myMap.setZoom(this.zoom); 283 | }, 284 | bounds(val) { 285 | if (this.myMap && this.myMap.setBounds) this.myMap.setBounds(val); 286 | }, 287 | }, 288 | render(h) { 289 | return h( 290 | 'section', 291 | { 292 | class: 'ymap-container', 293 | ref: 'mapContainer', 294 | }, 295 | [ 296 | h( 297 | 'div', 298 | { 299 | attrs: { 300 | id: this.ymapId, 301 | class: this.ymapClass, 302 | style: this.style, 303 | }, 304 | }, 305 | ), 306 | this.isReady && h( 307 | 'div', 308 | [ 309 | this.$slots.default, 310 | ], 311 | ), 312 | ], 313 | ); 314 | }, 315 | mounted() { 316 | if (this.$attrs['map-link'] || this.$attrs.mapLink) throw new Error('Vue-yandex-maps: Attribute mapLink is not supported. Use settings.'); 317 | 318 | if (this.placemarks && this.placemarks.length) throw new Error('Vue-yandex-maps: Attribute placemarks is not supported. Use marker component.'); 319 | 320 | this.mapObserver = new MutationObserver((() => { 321 | if (this.myMap.container) { 322 | this.myMap.container.fitToViewport(); 323 | } 324 | })); 325 | 326 | // Setup the observer 327 | const { mapContainer } = this.$refs; 328 | 329 | this.mapObserver.observe( 330 | mapContainer, 331 | { 332 | attributes: true, childList: true, characterData: true, subtree: false, 333 | }, 334 | ); 335 | 336 | if (emitter.scriptIsNotAttached) { 337 | const { debug } = this; 338 | const settings = { ...this.$options.pluginOptions, ...this.settings, debug }; 339 | utils.ymapLoader(settings); 340 | } 341 | if (emitter.ymapReady) { 342 | ymaps.ready(this.init); 343 | } else { 344 | emitter.$on('scriptIsLoaded', this.init); 345 | } 346 | }, 347 | beforeDestroy() { 348 | if (this.myMap && this.myMap.geoObjects) this.myMap.geoObjects.removeAll(); 349 | }, 350 | }; 351 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import YMapPlugin from './YMap'; 2 | import Marker from './Marker'; 3 | import { setupBalloonClass, ymapLoader } from './utils'; 4 | 5 | const install = (Vue, options = {}) => { 6 | if (install.installed) return; 7 | if (+Vue.version[0] === 3) { 8 | console.warn('Vue-yandex-maps: This version is only compatible with Vue 2.X. Please install vue-yandex-maps@next'); 9 | return; 10 | } 11 | install.installed = true; 12 | setupBalloonClass(Vue); 13 | YMapPlugin.pluginOptions = options; 14 | Vue.component('yandex-map', YMapPlugin); 15 | Vue.component('ymap-marker', Marker); 16 | }; 17 | 18 | YMapPlugin.install = install; 19 | 20 | if (typeof window !== 'undefined' && window.Vue) { 21 | window.Vue.use(YMapPlugin); 22 | } 23 | 24 | export const loadYmap = ymapLoader; 25 | export const yandexMap = YMapPlugin; 26 | export const ymapMarker = Marker; 27 | 28 | export default YMapPlugin; 29 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | export function addToMap(markers, { 2 | options, callbacks, map, useObjectManager, objectManagerClusterize, useHtmlInLayout, 3 | }) { 4 | const defaultLayout = useHtmlInLayout ? ` 5 |
6 |
7 |
8 | ` : ` 9 |
{{ properties.balloonContentHeader }}
10 |
{{ properties.balloonContentBody }}
11 |
{{ properties.balloonContentFooter }}
12 | `; 13 | const defaultClusterLayout = 'cluster#balloonTwoColumns'; 14 | 15 | const clusters = {}; 16 | const unclastered = []; 17 | markers.forEach((marker) => { 18 | if (!marker.clusterName) unclastered.push(marker); 19 | else { 20 | clusters[marker.clusterName] = clusters[marker.clusterName] 21 | ? [...clusters[marker.clusterName], marker] : [marker]; 22 | } 23 | }); 24 | 25 | Object.keys(clusters).forEach((clusterName) => { 26 | const clusterOptions = { ...options[clusterName] } || {}; 27 | const clusterCallbacks = callbacks[clusterName] || {}; 28 | const layout = clusterOptions.layout || defaultLayout; 29 | clusterOptions.clusterBalloonItemContentLayout = ymaps.templateLayoutFactory 30 | .createClass(layout); 31 | 32 | const balloonLayout = clusterOptions.clusterBalloonLayout || clusterOptions.clusterLayout; 33 | delete clusterOptions.clusterBalloonLayout; 34 | 35 | const clusterBalloonLayout = balloonLayout 36 | ? ymaps.templateLayoutFactory.createClass(balloonLayout) 37 | : clusterOptions.clusterBalloonContentLayout || defaultClusterLayout; 38 | clusterOptions.clusterBalloonContentLayout = clusterBalloonLayout; 39 | 40 | const { clusterIconContentLayout } = clusterOptions; 41 | clusterOptions.clusterIconContentLayout = clusterIconContentLayout 42 | && ymaps.templateLayoutFactory.createClass(clusterIconContentLayout); 43 | 44 | if (useObjectManager) { 45 | const ObjectManager = new ymaps.ObjectManager(Object.assign( 46 | { clusterize: objectManagerClusterize }, 47 | clusterOptions, 48 | )); 49 | Object.keys(clusterCallbacks).forEach((key) => { 50 | ObjectManager.clusters.events.add(key, clusterCallbacks[key]); 51 | }); 52 | ObjectManager.add(clusters[clusterName]); 53 | map.geoObjects.add(ObjectManager); 54 | } else { 55 | const clusterer = new ymaps.Clusterer(clusterOptions); 56 | Object.keys(clusterCallbacks).forEach((key) => { 57 | clusterer.events.add(key, clusterCallbacks[key]); 58 | }); 59 | 60 | if (clusterOptions.createCluster) { 61 | clusterer.createCluster = clusterOptions.createCluster; 62 | } 63 | 64 | clusterer.add(clusters[clusterName]); 65 | map.geoObjects.add(clusterer); 66 | } 67 | }); 68 | if (unclastered.length) { 69 | const unclasteredMarkers = useObjectManager 70 | ? new ymaps.ObjectManager({ clusterize: false }) : new ymaps.GeoObjectCollection(); 71 | unclastered.forEach(obj => unclasteredMarkers.add(obj)); 72 | map.geoObjects.add(unclasteredMarkers); 73 | } 74 | } 75 | 76 | export function setFirstLetterToUppercase(string) { 77 | return string.charAt(0).toUpperCase() + string.slice(1); 78 | } 79 | 80 | export function getIconPreset(marker) { 81 | const firstPart = marker.icon.color || 'blue'; 82 | let secondPart; 83 | if (marker.icon.glyph) { 84 | secondPart = setFirstLetterToUppercase(marker.icon.glyph); 85 | } else if (marker.icon.content) { 86 | secondPart = 'Stretchy'; 87 | } else { 88 | secondPart = ''; 89 | } 90 | return firstPart + secondPart; 91 | } 92 | 93 | export function setCoordsToNumeric(arr) { 94 | return arr.map(item => (Array.isArray(item) ? setCoordsToNumeric(item) : +item)); 95 | } 96 | 97 | export function objectComparison(first, second) { 98 | const cache = []; // кеш обьектов, для избежания рекурсии 99 | 100 | function inCache(f, s) { 101 | let i = cache.length; 102 | while (i--) { 103 | if ( 104 | (cache[i][0] === f || cache[i][0] === s) && (cache[i][1] === s || cache[i][1] === f) 105 | ) return true; 106 | } 107 | return false; 108 | } 109 | 110 | return (function eq(f, s) { 111 | if (f === s) return true; // сравниваем обычным образом 112 | if (f instanceof Date && s instanceof Date) return +f === +s; // время 113 | if (typeof f === 'function' && typeof s === 'function') return true; // функции не сравниваем 114 | if (typeof f !== 'object' || typeof s !== 'object') return false; // если хотябы один из аргументов не объект (положительный случай для необъектов рассмотрен выше) 115 | if (inCache(f, s)) return true; // есть в кеше 116 | cache.push([f, s]); // кешируем 117 | 118 | const keys = Object.keys(f); let 119 | i = keys.length; // получаем ключи 120 | if (Object.keys(s).length !== i) return false; // если количество ключей не совпадает 121 | while (i--) if (!eq(f[keys[i]], s[keys[i]])) return false; // рекурсивный вызов 122 | 123 | return true; 124 | }(first, second)); 125 | } 126 | 127 | class EventEmitter { 128 | constructor() { 129 | this.events = {}; 130 | this.ymapReady = false; 131 | this.scriptIsNotAttached = true; 132 | } 133 | 134 | $on(eventName, fn) { 135 | if (!this.events[eventName]) { 136 | this.events[eventName] = []; 137 | } 138 | 139 | this.events[eventName].push(fn); 140 | 141 | return () => { 142 | this.events[eventName] = this.events[eventName].filter(eventFn => fn !== eventFn); 143 | }; 144 | } 145 | 146 | $emit(eventName, data) { 147 | const event = this.events[eventName]; 148 | if (event) { 149 | event.forEach(fn => fn(data)); 150 | } 151 | } 152 | } 153 | 154 | export const emitter = new EventEmitter(); 155 | 156 | const CONTROL_TYPES = [ 157 | 'fullscreenControl', 158 | 'geolocationControl', 159 | 'routeEditor', 160 | 'rulerControl', 161 | 'searchControl', 162 | 'trafficControl', 163 | 'typeSelector', 164 | 'zoomControl', 165 | 'routeButtonControl', 166 | 'routePanelControl', 167 | 'smallMapDefaultSet', 168 | 'mediumMapDefaultSet', 169 | 'largeMapDefaultSet', 170 | ]; 171 | 172 | export function controlsTypeValidator(val) { 173 | return val.filter(control => ![...CONTROL_TYPES, 'default'].includes(control)).length === 0; 174 | } 175 | 176 | export function createMarkerType(val, useObjectManager) { 177 | const type = setFirstLetterToUppercase(val); 178 | if (!useObjectManager) return type; 179 | switch (type) { 180 | case 'Placemark': 181 | return 'Point'; 182 | case 'Polyline': 183 | return 'LineString'; 184 | default: 185 | return type; 186 | } 187 | } 188 | 189 | export function createMarker(object, useObjectManager) { 190 | const marker = useObjectManager ? { 191 | type: 'Feature', 192 | id: object.properties.markerId, 193 | geometry: { 194 | type: object.markerType, 195 | coordinates: object.coords, 196 | }, 197 | properties: object.properties, 198 | options: object.options, 199 | } : new ymaps[object.markerType](object.coords, object.properties, object.options); 200 | 201 | marker.clusterName = object.clusterName; 202 | 203 | return marker; 204 | } 205 | 206 | export function ymapLoader(settings = {}) { 207 | return new Promise((res, rej) => { 208 | if (window.ymaps) return res(); 209 | 210 | if (document.getElementById('vue-yandex-maps')) { 211 | emitter.$on('scriptIsLoaded', res); 212 | return; 213 | } 214 | 215 | const yandexMapScript = document.createElement('SCRIPT'); 216 | const { 217 | apiKey = '', 218 | suggestApiKey = '', 219 | lang = 'ru_RU', 220 | version = '2.1', 221 | coordorder = 'latlong', 222 | debug = false, 223 | enterprise = false, 224 | } = settings; 225 | const mode = debug ? 'debug' : 'release'; 226 | let settingsPart = `lang=${lang}${apiKey && `&apikey=${apiKey}`}&mode=${mode}&coordorder=${coordorder}`; 227 | if (suggestApiKey) settingsPart += `&suggest_apikey=${suggestApiKey}`; 228 | const link = `https://${enterprise ? 'enterprise.' : ''}api-maps.yandex.ru/${version}/?${settingsPart}`; 229 | yandexMapScript.setAttribute('src', link); 230 | yandexMapScript.setAttribute('async', ''); 231 | yandexMapScript.setAttribute('defer', ''); 232 | yandexMapScript.setAttribute('id', 'vue-yandex-maps'); 233 | document.head.appendChild(yandexMapScript); 234 | emitter.scriptIsNotAttached = false; 235 | yandexMapScript.onload = () => { 236 | ymaps.ready(() => { 237 | emitter.ymapReady = true; 238 | emitter.$emit('scriptIsLoaded'); 239 | res(); 240 | }); 241 | }; 242 | yandexMapScript.onerror = rej; 243 | }); 244 | } 245 | 246 | let idCounter = 1; 247 | let VueBalloonClass; 248 | 249 | export function setupBalloonClass(Vue) { 250 | if (typeof Vue.extend !== 'function') return; 251 | VueBalloonClass = Vue.extend({ 252 | props: ['marker', 'component'], 253 | template: '', 254 | }); 255 | } 256 | 257 | export function makeComponentBalloonTemplate(component) { 258 | let vueBalloon = null; 259 | const balloonId = `vue-balloon-${idCounter}`; 260 | 261 | idCounter += 1; 262 | 263 | return (markerComponent, markerData) => { 264 | const balloonContentLayout = ymaps.templateLayoutFactory.createClass(`
`, { 265 | build() { 266 | balloonContentLayout.superclass.build.call(this); 267 | 268 | vueBalloon = new VueBalloonClass({ 269 | parent: markerComponent.$root, 270 | data() { 271 | return { 272 | props: markerComponent.$props, 273 | listeners: markerComponent.$listeners, 274 | }; 275 | }, 276 | propsData: { 277 | marker: markerData, 278 | component, 279 | }, 280 | }); 281 | 282 | vueBalloon.$mount(`#${balloonId}`); 283 | }, 284 | clear() { 285 | vueBalloon.$destroy(); 286 | vueBalloon = null; 287 | balloonContentLayout.superclass.clear.call(this); 288 | }, 289 | }); 290 | 291 | return balloonContentLayout; 292 | }; 293 | } 294 | -------------------------------------------------------------------------------- /tests/test.test.js: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils'; 2 | import { yandexMap, ymapMarker } from '../src'; 3 | 4 | describe('Component', () => { 5 | const wrapper = mount(yandexMap, { 6 | propsData: { 7 | coords: [1, 1] 8 | } 9 | }); 10 | 11 | test('Map is a Vue instance', () => { 12 | expect(wrapper.isVueInstance()).toBe(true); 13 | }); 14 | 15 | test('Map is rendered', () => { 16 | expect(wrapper.contains('.ymap-container')).toBe(true); 17 | }); 18 | }); 19 | --------------------------------------------------------------------------------