mirror of
https://github.com/Viglino/ol-ext.git
synced 2025-12-08 19:26:29 +00:00
simplified publishing script and added sample (build dir) npm module from the project
This commit is contained in:
parent
77c3629704
commit
24b48bb277
@ -18,7 +18,7 @@ This page describes what you need to know to contribute code to OpenLayers as a
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Your contribution will be under our [license](LICENCE.md)
|
||||
Your contribution will be under our [license](LICENSE.md)
|
||||
as per [GitHub's terms of service](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license).
|
||||
|
||||
The CeCILL licence is a french BSD licence.
|
||||
|
||||
5
build/.npmignore
Normal file
5
build/.npmignore
Normal file
@ -0,0 +1,5 @@
|
||||
# ignore examples
|
||||
examples
|
||||
img
|
||||
# ignore doc pages
|
||||
doc/doc-pages
|
||||
29
build/CHANGELOG.md
Normal file
29
build/CHANGELOG.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Change log
|
||||
|
||||
## v1.1.3 2018-02-07
|
||||
This is the last v1 release.
|
||||
- Next release (v2) will use ES6 module syntax [#33](https://github.com/Viglino/ol3-ext/issues/33).
|
||||
- Switch to the `./dist/ol-ext.js` to keep on running on next version.
|
||||
|
||||
## v1.1.2 2017-12
|
||||
**change project name ol-ext is now ol-ext**
|
||||
- add doc-pages [#53](https://github.com/Viglino/ol3-ext/issues/53)
|
||||
- see [#65](https://github.com/Viglino/ol3-ext/issues/65)
|
||||
|
||||
## v1.0.0 2016-11-12
|
||||
see [#8](https://github.com/Viglino/ol3-ext/issues/8) and [#10](https://github.com/Viglino/ol3-ext/issues/10)
|
||||
- `ol.control.Toggle` inherits from `ol.control.Button` (this means you have to add the ol.control.Button.js to your pages).
|
||||
- Move subbar from `ol.control.Bar` to `ol.control.Toggle`.
|
||||
Instead of:
|
||||
```javascript
|
||||
var c = new ol.control.Toggle ();
|
||||
bar.addControl (c, subbar);
|
||||
```
|
||||
use:
|
||||
```javascript
|
||||
var c = new ol.control.Toggle ({ bar: subbar });
|
||||
bar.addControl (c);
|
||||
```
|
||||
- add `autoActive` option to `ol.control.Toggle` to auto activate the control when inserted in a subbar
|
||||
- add `autoDeactivate` option to `ol.control.Bar` to auto deactivate all controls in a subbar when desactivating it
|
||||
|
||||
32
build/CONTRIBUTING.md
Normal file
32
build/CONTRIBUTING.md
Normal file
@ -0,0 +1,32 @@
|
||||
# Contributing to ol-ext
|
||||
|
||||
Thanks for your interest in contributing to ol-ext.
|
||||
|
||||
## Submitting Bug Reports or Asking Questions
|
||||
|
||||
Please use the [GitHub issue tracker](https://github.com/Viglino/ol-ext/issues).
|
||||
Before creating a new issue, do a quick search to see if the problem has been reported already.
|
||||
|
||||
## Contributing Code
|
||||
|
||||
See [`DEVELOPING.md`](DEVELOPING.md) to learn how to get started developing.
|
||||
|
||||
Clone the repository and [pull requests](https://help.github.com/articles/using-pull-requests). Make sure
|
||||
that your pull request follows our pull request guidelines below before submitting it.
|
||||
|
||||
This page describes what you need to know to contribute code to OpenLayers as a developer.
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Your contribution will be under our [license](LICENCE.md)
|
||||
as per [GitHub's terms of service](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license).
|
||||
|
||||
The CeCILL licence is a french BSD licence.
|
||||
|
||||
## Pull request guidelines
|
||||
|
||||
Your pull request must:
|
||||
* Follow the naming convention in the [DEVELOPING.md](DEVELOPING.md)
|
||||
* Address a single issue or add a single item of functionality.
|
||||
* Use clear commit messages.
|
||||
* Be possible to merge automatically.
|
||||
77
build/DEVELOPING.md
Normal file
77
build/DEVELOPING.md
Normal file
@ -0,0 +1,77 @@
|
||||
# Developing
|
||||
|
||||
## Setting up development environment
|
||||
|
||||
You will obviously start by [forking](https://github.com/openlayers/openlayers/fork) the OpenLayers repository.
|
||||
|
||||
### Install the dependencies
|
||||
|
||||
Go in the project directory and run the `npm install` that wil install the dependencies in the local node_modules folder.
|
||||
|
||||
### Creating the distribution
|
||||
|
||||
Since v.2 the extensions are provided as ES6 modules.
|
||||
To be used in a web page you have to create the distribution.
|
||||
|
||||
Use the gulp command to create a distribution of the project into the `/dist` directory:
|
||||
````
|
||||
gulp
|
||||
````
|
||||
|
||||
To recreate the distribution on `js` file change, use the watch task
|
||||
````
|
||||
gulp watch
|
||||
````
|
||||
|
||||
|
||||
## Adding new extensions
|
||||
|
||||
To ensure the correct translation beetween the modules and the distribution on ol classes:
|
||||
- Export one class per file as default
|
||||
- Use the naming convention
|
||||
|
||||
### Naming convention
|
||||
|
||||
To ensure the correct translation beetween the modules and the distribution on ol classes, we use the follownig naming convention.
|
||||
|
||||
In Openlayers classes just replace the `point` by a `underscore`.
|
||||
- Thus the `ol.layer.Vector` class must be imported as `ol_layer_Vector`.
|
||||
- A new control `ol.control.MyControl` must be declared as `ol_control_MyControl`
|
||||
|
||||
The file name must reflect the name of the extension and should be placed in the src directory corresponding to its namespace.
|
||||
Thus `ol_control_MyControl`must be created in the `./src/control/MyControl.js` file and can be used in a webpack as:
|
||||
````javascript
|
||||
import ol_control_MyControl from 'ol-ext/control/MyControl';
|
||||
````
|
||||
|
||||
Example:
|
||||
````javascript
|
||||
// Import ol classes
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
// Create my control
|
||||
var ol_control_MyControl = function(options) {
|
||||
ol_control_Control.call(this,options);
|
||||
}
|
||||
ol.inherits(ol_control_MyControl, ol_control_Control);
|
||||
|
||||
// Export my control
|
||||
export default ol_control_MyControl
|
||||
|
||||
````
|
||||
|
||||
|
||||
## Building the documentation:
|
||||
|
||||
The documentation use [gulp-jsdoc3](https://www.npmjs.com/package/gulp-jsdoc3) to create the doc.
|
||||
|
||||
1. install the gulp-jsdoc3 project at the root directory:
|
||||
````
|
||||
npm install gulp-jsdoc3
|
||||
````
|
||||
2. then run the gulp command to create the doc in the [doc/doc-pages](http://viglino.github.io/ol-ext/doc/doc-pages/) directory:
|
||||
````
|
||||
gulp doc
|
||||
````
|
||||
|
||||
44
build/LICENCE.md
Normal file
44
build/LICENCE.md
Normal file
@ -0,0 +1,44 @@
|
||||
# LICENCE
|
||||
|
||||
ol-ext (c) 2016-2018 - Jean-Marc Viglino, IGN-France
|
||||
|
||||
[ol-ext](https://github.com/Viglino/ol-ext) is licenced under the French Opensource **BSD** compatible CeCILL-B FREE SOFTWARE LICENSE.
|
||||
|
||||
Some resources (mapping services and API) used in this sofware may have a specific license.
|
||||
You must check before use.
|
||||
|
||||
Full text license in English: http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt
|
||||
Full text license in French: http://www.cecill.info/licences/Licence_CeCILL-C_V1-fr.txt
|
||||
|
||||
## CeCILL-B FREE SOFTWARE LICENSE AGREEMENT :
|
||||
|
||||
This Agreement is an open source software license intended to give users
|
||||
significant freedom to modify and redistribute the software licensed
|
||||
hereunder.
|
||||
|
||||
The exercising of this freedom is conditional upon a strong obligation
|
||||
of giving credits for everybody that distributes a software
|
||||
incorporating a software ruled by the current license so as all
|
||||
contributions to be properly identified and acknowledged.
|
||||
|
||||
In consideration of access to the source code and the rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors only have limited liability.
|
||||
|
||||
In this respect, the risks associated with loading, using, modifying
|
||||
and/or developing or reproducing the software by the user are brought to
|
||||
the user's attention, given its Free Software status, which may make it
|
||||
complicated to use, with the result that its use is reserved for
|
||||
developers and experienced professionals having in-depth computer
|
||||
knowledge. Users are therefore encouraged to load and test the
|
||||
suitability of the software as regards their requirements in conditions
|
||||
enabling the security of their systems and/or data to be ensured and,
|
||||
more generally, to use and operate it in the same conditions of
|
||||
security. This Agreement may be freely reproduced and published,
|
||||
provided it is not altered, and that no provisions are either added or
|
||||
removed herefrom.
|
||||
|
||||
This Agreement may apply to any or all software for which the holder of
|
||||
the economic rights decides to submit the use thereof to its provisions.
|
||||
|
||||
90
build/README.md
Normal file
90
build/README.md
Normal file
@ -0,0 +1,90 @@
|
||||
# ol-ext
|
||||
*Cool extensions for [OpenLayers](https://github.com/openlayers/openlayers) (ol)*.
|
||||
|
||||
[ol-ext](https://github.com/Viglino/ol-ext) is a set of extensions, controls, interactions to use with Openlayers.
|
||||
[View live examples online](http://viglino.github.io/ol-ext/) or the [API documentation](http://viglino.github.io/ol-ext/doc/doc-pages/).
|
||||
|
||||
### ! ol3-ext is now [ol-ext](https://github.com/Viglino/ol-ext) !
|
||||
ol3-ext has been renamed to ol-ext and is [now available on NPM](https://www.npmjs.com/package/ol-ext): **update your bookmark and your code**.
|
||||
|
||||
**Keywords:** CSS popup,
|
||||
Font Awesome symbol renderer,
|
||||
charts for statistical map (pie/bar),
|
||||
layer switcher,
|
||||
wikipedia layer,
|
||||
animations
|
||||
|
||||
> [
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
](http://viglino.github.io/ol-ext/)
|
||||
|
||||
## Getting Started
|
||||
|
||||
## using ol-ext in a web page
|
||||
|
||||
* Just download the [build script](dist) in the dist directory of the project.
|
||||
* If you just want to add a `<script>` tag to test things out, you can link directly to the builds from the github rawgit (not recommended in production):
|
||||
````html
|
||||
<!-- jQuery -->
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<!-- Openlayers -->
|
||||
<link rel="stylesheet" href="https://openlayers.org/en/master/css/ol.css" />
|
||||
<script type="text/javascript" src="https://openlayers.org/en/latest/build/ol.js"></script>
|
||||
|
||||
<!-- OL-ext -->
|
||||
<link rel="stylesheet" href="https://cdn.rawgit.com/Viglino/ol-ext/master/dist/ol-ext.min.css" />
|
||||
<script type="text/javascript" src="https://cdn.rawgit.com/Viglino/ol-ext/master/dist/ol-ext.min.js"></script>
|
||||
````
|
||||
* Use npm [ol-ext package](https://www.npmjs.com/package/ol-ext) and link to the node_modules directory:
|
||||
````
|
||||
npm install ol-ext
|
||||
````
|
||||
|
||||
## using ol-ext in a webpack
|
||||
|
||||
Visit the [this repository](https://github.com/darkscript/ol-ol-ext-webpack-example) for a good example of working with ol-ext npm version and bundler (webpack)
|
||||
|
||||
## Documentation
|
||||
|
||||
Check out the [hosted examples](http://viglino.github.io/ol-ext/) or the [API documentation](http://viglino.github.io/ol-ext/doc/doc-pages/).
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see our [contributing guidelines](https://github.com/Viglino/ol-ext/blob/master/CONTRIBUTING.md) if you're interested in getting involved.
|
||||
|
||||
## Bugs
|
||||
|
||||
Please use the [GitHub issue tracker](https://github.com/Viglino/ol-ext/issues) for all bugs and feature requests. Before creating a new issue, do a quick search to see if the problem has been reported already.
|
||||
|
||||
## Licence
|
||||
|
||||
ol-ext is licenced under the French Opensource **BSD** compatible CeCILL-B FREE SOFTWARE LICENSE.
|
||||
(c) 2016-2017 - Jean-Marc Viglino
|
||||
|
||||
Some resources (mapping services and API) used in this sofware may have a specific license.
|
||||
You must check before use.
|
||||
|
||||
> [Full text license in English](http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt)
|
||||
> [Full text license in French](http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.txt)
|
||||
|
||||
For convenience you can use the BSD licence instead when publish content to webpack.
|
||||
11
build/composer.json
Normal file
11
build/composer.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "viglino/ol-ext",
|
||||
"description": "Cool extensions for OpenLayers (ol)",
|
||||
"license": "CeCILL-B",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-Marc Viglino",
|
||||
"email": "jean-marc.viglino@ign.fr"
|
||||
}
|
||||
]
|
||||
}
|
||||
263
build/control/Bar.css
Normal file
263
build/control/Bar.css
Normal file
@ -0,0 +1,263 @@
|
||||
/* Bar style */
|
||||
.ol-control.ol-bar
|
||||
{ left: 50%;
|
||||
min-height: 1em;
|
||||
min-width: 1em;
|
||||
position: absolute;
|
||||
top: 0.5em;
|
||||
transform: translate(-50%,0);
|
||||
-webkit-transform: translate(-50%,0);
|
||||
}
|
||||
|
||||
/* Hide subbar when not inserted in a parent bar */
|
||||
.ol-control.ol-toggle .ol-option-bar
|
||||
{ display: none;
|
||||
}
|
||||
|
||||
/* Default position for controls */
|
||||
.ol-control.ol-bar .ol-bar
|
||||
{ position: static;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control
|
||||
{ position: relative;
|
||||
top: auto;
|
||||
left:auto;
|
||||
right:auto;
|
||||
bottom: auto;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
transform: none;
|
||||
-webkit-transform: none;
|
||||
}
|
||||
.ol-control.ol-bar .ol-bar
|
||||
{ position: static;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control button
|
||||
{ margin:2px 1px;
|
||||
}
|
||||
|
||||
/* Positionning */
|
||||
.ol-control.ol-bar.ol-left
|
||||
{ left: 0.5em;
|
||||
top: 50%;
|
||||
transform: translate(0px, -50%);
|
||||
}
|
||||
.ol-control.ol-bar.ol-left .ol-control
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-right
|
||||
{ left: auto;
|
||||
right: 0.5em;
|
||||
top: 50%;
|
||||
transform: translate(0px, -50%);
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-control
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-bottom
|
||||
{ top: auto;
|
||||
bottom: 0.5em;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-top.ol-left,
|
||||
.ol-control.ol-bar.ol-top.ol-right
|
||||
{ top: 4.5em;
|
||||
transform:none;
|
||||
}
|
||||
.ol-touch .ol-control.ol-bar.ol-top.ol-left,
|
||||
.ol-touch .ol-control.ol-bar.ol-top.ol-right
|
||||
{ top: 5.5em;
|
||||
}
|
||||
.ol-control.ol-bar.ol-bottom.ol-left,
|
||||
.ol-control.ol-bar.ol-bottom.ol-right
|
||||
{ top: auto;
|
||||
bottom: 0.5em;
|
||||
transform:none;
|
||||
}
|
||||
|
||||
/* Group buttons */
|
||||
.ol-control.ol-bar.ol-group
|
||||
{ margin: 1px 1px 1px 0;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-group,
|
||||
.ol-control.ol-bar.ol-left .ol-group
|
||||
{ margin: 1px 1px 0 1px;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-group button
|
||||
{ border-radius:0;
|
||||
margin: 0 0 0 1px;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right.ol-group button,
|
||||
.ol-control.ol-bar.ol-left.ol-group button,
|
||||
.ol-control.ol-bar.ol-right .ol-group button,
|
||||
.ol-control.ol-bar.ol-left .ol-group button
|
||||
{ margin: 0 0 1px 0;
|
||||
}
|
||||
.ol-control.ol-bar.ol-group .ol-control:first-child > button
|
||||
{ border-radius: 5px 0 0 5px;
|
||||
}
|
||||
.ol-control.ol-bar.ol-group .ol-control:last-child > button
|
||||
{ border-radius: 0 5px 5px 0;
|
||||
}
|
||||
.ol-control.ol-bar.ol-left.ol-group .ol-control:first-child > button,
|
||||
.ol-control.ol-bar.ol-right.ol-group .ol-control:first-child > button,
|
||||
.ol-control.ol-bar.ol-left .ol-group .ol-control:first-child > button,
|
||||
.ol-control.ol-bar.ol-right .ol-group .ol-control:first-child > button
|
||||
{ border-radius: 5px 5px 0 0;
|
||||
}
|
||||
.ol-control.ol-bar.ol-left.ol-group .ol-control:last-child > button,
|
||||
.ol-control.ol-bar.ol-right.ol-group .ol-control:last-child > button,
|
||||
.ol-control.ol-bar.ol-left .ol-group .ol-control:last-child > button,
|
||||
.ol-control.ol-bar.ol-right .ol-group .ol-control:last-child > button
|
||||
{ border-radius: 0 0 5px 5px;
|
||||
}
|
||||
|
||||
/* */
|
||||
.ol-control.ol-bar .ol-rotate
|
||||
{ opacity:1;
|
||||
visibility: visible;
|
||||
}
|
||||
.ol-control.ol-bar .ol-rotate button
|
||||
{ display: block
|
||||
}
|
||||
|
||||
/* Active buttons */
|
||||
.ol-control.ol-bar .ol-toggle.ol-active > button
|
||||
{ background: rgba(60, 136, 0, 0.7)
|
||||
}
|
||||
.ol-control.ol-bar .ol-toggle.ol-active button:hover
|
||||
{ background: rgba(60, 136, 0, 0.7)
|
||||
}
|
||||
.ol-control.ol-toggle button:disabled
|
||||
{ background: rgba(0,60,136,.3);
|
||||
}
|
||||
|
||||
/* Subbar toolbar */
|
||||
.ol-control.ol-bar .ol-control.ol-option-bar
|
||||
{ display: none;
|
||||
position:absolute;
|
||||
top:100%;
|
||||
left:0;
|
||||
margin: 5px 0;
|
||||
border-radius: 0;
|
||||
background: rgba(255,255,255, 0.8);
|
||||
/* border: 1px solid rgba(0, 60, 136, 0.5); */
|
||||
box-shadow: 0 0 0 1px rgba(0, 60, 136, 0.5), 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.ol-control.ol-bar .ol-option-bar:before
|
||||
{ content: "";
|
||||
border: 0.5em solid transparent;
|
||||
border-color: transparent transparent rgba(0, 60, 136, 0.5);
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 0.3em;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar .ol-option-bar .ol-control
|
||||
{ display: table-cell;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control .ol-bar
|
||||
{ display: none;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control.ol-active > .ol-option-bar
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar .ol-control.ol-collapsed ul
|
||||
{ display: none;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar .ol-control.ol-text-button > button:hover,
|
||||
.ol-control.ol-bar .ol-control.ol-text-button > button
|
||||
{ background: none;
|
||||
color: rgba(0, 60, 136, 0.5);
|
||||
width: auto;
|
||||
min-width: 1.375em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar .ol-control.ol-text-button
|
||||
{ font-size:0.9em;
|
||||
border-left: 1px solid rgba(0, 60, 136, 0.8);
|
||||
border-radius: 0;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control.ol-text-button:first-child
|
||||
{ border-left:0;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control.ol-text-button button
|
||||
{ padding:0 0.3em;
|
||||
font-weight: normal;
|
||||
height:1.4em;
|
||||
}
|
||||
.ol-control.ol-bar .ol-control.ol-text-button button:hover
|
||||
{ color: rgba(0, 60, 136, 1);
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-bottom .ol-option-bar
|
||||
{ top: auto;
|
||||
bottom: 100%;
|
||||
}
|
||||
.ol-control.ol-bar.ol-bottom .ol-option-bar:before
|
||||
{ border-color: rgba(0, 60, 136, 0.5) transparent transparent ;
|
||||
bottom: auto;
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-left .ol-option-bar
|
||||
{ left:100%;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
margin: 0 5px;
|
||||
}
|
||||
.ol-control.ol-bar.ol-left .ol-option-bar:before
|
||||
{ border-color: transparent rgba(0, 60, 136, 0.5) transparent transparent;
|
||||
bottom: auto;
|
||||
right: 100%;
|
||||
left: auto;
|
||||
top: 0.3em;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar
|
||||
{ right:100%;
|
||||
left:auto;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
margin: 0 5px;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar:before
|
||||
{ border-color: transparent transparent transparent rgba(0, 60, 136, 0.5);
|
||||
bottom: auto;
|
||||
left: 100%;
|
||||
top: 0.3em;
|
||||
}
|
||||
|
||||
.ol-control.ol-bar.ol-left .ol-option-bar .ol-option-bar,
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar .ol-option-bar
|
||||
{ top: 100%;
|
||||
bottom: auto;
|
||||
left: 0.3em;
|
||||
right: auto;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar .ol-option-bar
|
||||
{ right: 0.3em;
|
||||
left: auto;
|
||||
}
|
||||
.ol-control.ol-bar.ol-left .ol-option-bar .ol-option-bar:before,
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar .ol-option-bar:before
|
||||
{ border-color: transparent transparent rgba(0, 60, 136, 0.5);
|
||||
bottom: 100%;
|
||||
top: auto;
|
||||
left: 0.3em;
|
||||
right: auto;
|
||||
}
|
||||
.ol-control.ol-bar.ol-right .ol-option-bar .ol-option-bar:before
|
||||
{ right: 0.3em;
|
||||
left: auto;
|
||||
}
|
||||
181
build/control/Bar.js
Normal file
181
build/control/Bar.js
Normal file
@ -0,0 +1,181 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** Control bar for OL3
|
||||
* The control bar is a container for other controls. It can be used to create toolbars.
|
||||
* Control bars can be nested and combined with ol.control.Toggle to handle activate/deactivate.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {String} options.className class of the control
|
||||
* @param {bool} options.group is a group, default false
|
||||
* @param {bool} options.toggleOne only one toggle control is active at a time, default false
|
||||
* @param {bool} options.autoDeactivate used with subbar to deactivate all control when top level control deactivate, default false
|
||||
* @param {Array<_ol_control_>} options.controls a list of control to add to the bar
|
||||
*/
|
||||
var ol_control_Bar = function(options)
|
||||
{ if (!options) options={};
|
||||
var element = $("<div>").addClass('ol-unselectable ol-control ol-bar');
|
||||
if (options.className) element.addClass(options.className);
|
||||
if (options.group) element.addClass('ol-group');
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
this.set('toggleOne', options.toggleOne);
|
||||
this.set('autoDeactivate', options.autoDeactivate);
|
||||
|
||||
this.controls_ = [];
|
||||
if (options.controls instanceof Array)
|
||||
{ for (var i=0; i<options.controls.length; i++)
|
||||
{ this.addControl(options.controls[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
ol.inherits(ol_control_Bar, ol_control_Control);
|
||||
|
||||
/** Set the control visibility
|
||||
* @param {boolean} b
|
||||
*/
|
||||
ol_control_Bar.prototype.setVisible = function (val) {
|
||||
if (val) $(this.element).show();
|
||||
else $(this.element).hide();
|
||||
}
|
||||
|
||||
/** Get the control visibility
|
||||
* @return {boolean} b
|
||||
*/
|
||||
ol_control_Bar.prototype.getVisible = function ()
|
||||
{ return ($(this.element).css('display') != 'none');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map instance the control is associated with
|
||||
* and add its controls associated to this map.
|
||||
* @param {_ol_Map_} map The map instance.
|
||||
*/
|
||||
ol_control_Bar.prototype.setMap = function (map)
|
||||
{ ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
for (var i=0; i<this.controls_.length; i++)
|
||||
{ var c = this.controls_[i];
|
||||
// map.addControl(c);
|
||||
c.setMap(map);
|
||||
}
|
||||
};
|
||||
|
||||
/** Get controls in the panel
|
||||
* @param {Array<_ol_control_>}
|
||||
*/
|
||||
ol_control_Bar.prototype.getControls = function ()
|
||||
{ return this.controls_;
|
||||
};
|
||||
|
||||
/** Set tool bar position
|
||||
* @param {top|left|bottom|right} pos
|
||||
*/
|
||||
ol_control_Bar.prototype.setPosition = function (pos)
|
||||
{ $(this.element).removeClass('ol-left ol-top ol-bottom ol-right');
|
||||
pos=pos.split ('-');
|
||||
for (var i=0; i<pos.length; i++)
|
||||
{ switch (pos[i])
|
||||
{ case 'top':
|
||||
case 'left':
|
||||
case 'bottom':
|
||||
case 'right':
|
||||
$(this.element).addClass ("ol-"+pos[i]);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Add a control to the bar
|
||||
* @param {_ol_control_} c control to add
|
||||
*/
|
||||
ol_control_Bar.prototype.addControl = function (c)
|
||||
{ this.controls_.push(c);
|
||||
c.setTarget(this.element);
|
||||
if (this.getMap())
|
||||
{ this.getMap().addControl(c);
|
||||
}
|
||||
// Activate and toogleOne
|
||||
c.on ('change:active', this.onActivateControl_, this);
|
||||
if (c.getActive && c.getActive())
|
||||
{ c.dispatchEvent({ type:'change:active', key:'active', oldValue:false, active:true });
|
||||
}
|
||||
};
|
||||
|
||||
/** Deativate all controls in a bar
|
||||
* @param {_ol_control_} except a control
|
||||
*/
|
||||
ol_control_Bar.prototype.deactivateControls = function (except)
|
||||
{ for (var i=0; i<this.controls_.length; i++)
|
||||
{ if (this.controls_[i] !== except && this.controls_[i].setActive)
|
||||
{ this.controls_[i].setActive(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ol_control_Bar.prototype.getActiveControls = function ()
|
||||
{ var active = [];
|
||||
for (var i=0, c; c=this.controls_[i]; i++)
|
||||
{ if (c.getActive && c.getActive()) active.push(c);
|
||||
}
|
||||
return active;
|
||||
}
|
||||
|
||||
/** Auto activate/deactivate controls in the bar
|
||||
* @param {boolean} b activate/deactivate
|
||||
*/
|
||||
ol_control_Bar.prototype.setActive = function (b)
|
||||
{ if (!b && this.get("autoDeactivate"))
|
||||
{ this.deactivateControls();
|
||||
}
|
||||
if (b)
|
||||
{ var ctrls = this.getControls();
|
||||
for (var i=0, sb; (sb = ctrls[i]); i++)
|
||||
{ if (sb.get("autoActivate")) sb.setActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Post-process an activated/deactivated control
|
||||
* @param {ol.event} e :an object with a target {_ol_control_} and active flag {bool}
|
||||
*/
|
||||
ol_control_Bar.prototype.onActivateControl_ = function (e)
|
||||
{ if (this.get('toggleOne'))
|
||||
{ if (e.active)
|
||||
{ var n;
|
||||
var ctrl = e.target;
|
||||
for (n=0; n<this.controls_.length; n++)
|
||||
{ if (this.controls_[n]===ctrl) break;
|
||||
}
|
||||
// Not here!
|
||||
if (n==this.controls_.length) return;
|
||||
this.deactivateControls (this.controls_[n]);
|
||||
}
|
||||
else
|
||||
{ // No one active > test auto activate
|
||||
if (!this.getActiveControls().length)
|
||||
{ for (var i=0, c; c=this.controls_[i]; i++)
|
||||
{ if (c.get("autoActivate"))
|
||||
{ c.setActive();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ol_control_Bar
|
||||
45
build/control/Button.js
Normal file
45
build/control/Button.js
Normal file
@ -0,0 +1,45 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
/** A simple push button control
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {String} options.className class of the control
|
||||
* @param {String} options.title title of the control
|
||||
* @param {String} options.html html to insert in the control
|
||||
* @param {function} options.handleClick callback when control is clicked (or use change:active event)
|
||||
*/
|
||||
var ol_control_Button = function(options)
|
||||
{ options = options || {};
|
||||
var element = $("<div>").addClass((options.className||"") + ' ol-button ol-unselectable ol-control');
|
||||
var self = this;
|
||||
|
||||
var bt = $("<button>").html(options.html || "")
|
||||
.attr('type','button')
|
||||
.attr('title', options.title)
|
||||
.on("click", function(e)
|
||||
{ if (e && e.preventDefault)
|
||||
{ e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
if (options.handleClick) options.handleClick.call(self, e);
|
||||
})
|
||||
.appendTo(element);
|
||||
// Try to get a title in the button content
|
||||
if (!options.title) bt.attr("title", bt.children().first().attr('title'));
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
if (options.title) this.set("title", options.title);
|
||||
};
|
||||
ol.inherits(ol_control_Button, ol_control_Control);
|
||||
|
||||
|
||||
export default ol_control_Button
|
||||
127
build/control/CanvasAttribution.js
Normal file
127
build/control/CanvasAttribution.js
Normal file
@ -0,0 +1,127 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Attribution from 'ol/control/attribution'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_color from 'ol/color'
|
||||
import ol_control_ScaleLine from 'ol/control/scaleline'
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* OpenLayers 3 Attribution Control integrated in the canvas (for jpeg/png export purposes).
|
||||
* @see http://www.kreidefossilien.de/webgis/dokumentation/beispiele/export-map-to-png-with-scale
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Attribution}
|
||||
* @param {Object=} options extend the ol_control_Attribution options.
|
||||
* @param {ol_style_Style} options.style option is usesd to draw the text.
|
||||
*/
|
||||
var ol_control_CanvasAttribution = function(options)
|
||||
{ if (!options) options = {};
|
||||
ol_control_Attribution.call(this, options);
|
||||
|
||||
// Draw in canvas
|
||||
this.isCanvas_ = !!options.canvas;
|
||||
|
||||
// Get style options
|
||||
if (!options) options={};
|
||||
if (!options.style) options.style = new ol_style_Style();
|
||||
this.setStyle (options.style);
|
||||
}
|
||||
ol.inherits(ol_control_CanvasAttribution, ol_control_Attribution);
|
||||
|
||||
/**
|
||||
* Draw attribution on canvas
|
||||
* @param {boolean} b draw the attribution on canvas.
|
||||
*/
|
||||
ol_control_CanvasAttribution.prototype.setCanvas = function (b)
|
||||
{ this.isCanvas_ = b;
|
||||
$(this.element).css("visibility", b ? "hidden":"visible");
|
||||
if (this.map_) this.map_.renderSync();
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the control style
|
||||
* @param {ol_style_Style} style
|
||||
*/
|
||||
ol_control_CanvasAttribution.prototype.setStyle = function (style)
|
||||
{ var text = style.getText();
|
||||
this.font_ = text ? text.getFont() : "10px Arial";
|
||||
var stroke = text ? text.getStroke() : null;
|
||||
var fill = text ? text.getFill() : null;
|
||||
this.fontStrokeStyle_ = stroke ? ol_color.asString(stroke.getColor()) : "#fff";
|
||||
this.fontFillStyle_ = fill ? ol_color.asString(fill.getColor()) : "#000";
|
||||
this.fontStrokeWidth_ = stroke ? stroke.getWidth() : 3;
|
||||
if (this.getMap()) this.getMap().render();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasAttribution.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawAttribution_, this);
|
||||
|
||||
ol_control_ScaleLine.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map) map.on('postcompose', this.drawAttribution_, this);
|
||||
this.map_ = map;
|
||||
|
||||
this.setCanvas (this.isCanvas_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw attribution in the final canvas
|
||||
* @private
|
||||
*/
|
||||
ol_control_CanvasAttribution.prototype.drawAttribution_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
if (!this.isCanvas_) return;
|
||||
|
||||
var text = "";
|
||||
$("li", this.element).each (function()
|
||||
{ if ($(this).css("display")!="none") text += (text ? " - ":"") + $(this).text();
|
||||
});
|
||||
|
||||
// Get size of the scale div
|
||||
var position = $(this.element).position();
|
||||
// Retina device
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
// Position if transform:scale()
|
||||
var container = $(this.getMap().getViewport()).parent();
|
||||
var scx = container.outerWidth() / container.get(0).getBoundingClientRect().width;
|
||||
var scy = container.outerHeight() / container.get(0).getBoundingClientRect().height;
|
||||
position.left *= scx;
|
||||
position.top *= scy;
|
||||
|
||||
position.right = position.left + $(this.element).outerWidth();
|
||||
position.bottom = position.top + $(this.element).outerHeight();
|
||||
|
||||
// Draw scale text
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = this.fontStrokeStyle_;
|
||||
ctx.fillStyle = this.fontFillStyle_;
|
||||
ctx.lineWidth = this.fontStrokeWidth_;
|
||||
ctx.textAlign = "right";
|
||||
ctx.textBaseline ="bottom";
|
||||
ctx.font = this.font_;
|
||||
ctx.strokeText(text, position.right, position.bottom);
|
||||
ctx.fillText(text, position.right, position.bottom);
|
||||
ctx.closePath();
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_control_CanvasAttribution
|
||||
138
build/control/CanvasScaleLine.js
Normal file
138
build/control/CanvasScaleLine.js
Normal file
@ -0,0 +1,138 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_ScaleLine from 'ol/control/scaleline'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* OpenLayers 3 Scale Line Control integrated in the canvas (for jpeg/png export purposes).
|
||||
* @see http://www.kreidefossilien.de/webgis/dokumentation/beispiele/export-map-to-png-with-scale
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_ScaleLine}
|
||||
* @param {Object=} options extend the ol_control_ScaleLine options.
|
||||
* @param {ol_style_Style} options.style used to draw the scale line (default is black/white, 10px Arial).
|
||||
*/
|
||||
var ol_control_CanvasScaleLine = function(options)
|
||||
{ ol_control_ScaleLine.call(this, options);
|
||||
|
||||
this.scaleHeight_ = 6;
|
||||
|
||||
// Get style options
|
||||
if (!options) options={};
|
||||
if (!options.style) options.style = new ol_style_Style();
|
||||
this.setStyle(options.style);
|
||||
}
|
||||
ol.inherits(ol_control_CanvasScaleLine, ol_control_ScaleLine);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasScaleLine.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawScale_, this);
|
||||
|
||||
ol_control_ScaleLine.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Add postcompose on the map
|
||||
if (map) map.on('postcompose', this.drawScale_, this);
|
||||
|
||||
// Hide the default DOM element
|
||||
this.$element = $(this.element).css("visibility","hidden");
|
||||
this.olscale = $(".ol-scale-line-inner", this.element);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the control style
|
||||
* @param {_ol_style_Style_} style
|
||||
*/
|
||||
ol_control_CanvasScaleLine.prototype.setStyle = function (style)
|
||||
{ var stroke = style.getStroke();
|
||||
this.strokeStyle_ = stroke ? ol_color.asString(stroke.getColor()) : "#000";
|
||||
this.strokeWidth_ = stroke ? stroke.getWidth() : 2;
|
||||
|
||||
var fill = style.getFill();
|
||||
this.fillStyle_ = fill ? ol_color.asString(fill.getColor()) : "#fff";
|
||||
|
||||
var text = style.getText();
|
||||
this.font_ = text ? text.getFont() : "10px Arial";
|
||||
stroke = text ? text.getStroke() : null;
|
||||
fill = text ? text.getFill() : null;
|
||||
this.fontStrokeStyle_ = stroke ? ol_color.asString(stroke.getColor()) : this.fillStyle_;
|
||||
this.fontStrokeWidth_ = stroke ? stroke.getWidth() : 3;
|
||||
this.fontFillStyle_ = fill ? ol_color.asString(fill.getColor()) : this.strokeStyle_;
|
||||
// refresh
|
||||
if (this.getMap()) this.getMap().render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw attribution in the final canvas
|
||||
* @private
|
||||
*/
|
||||
ol_control_CanvasScaleLine.prototype.drawScale_ = function(e)
|
||||
{ if ( this.$element.css("display")==="none" ) return;
|
||||
var ctx = e.context;
|
||||
|
||||
// Get size of the scale div
|
||||
var scalewidth = this.olscale.width();
|
||||
if (!scalewidth) return;
|
||||
var text = this.olscale.text();
|
||||
var position = this.$element.position();
|
||||
// Retina device
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
// Position if transform:scale()
|
||||
var container = $(this.getMap().getViewport()).parent();
|
||||
var scx = container.outerWidth() / container.get(0).getBoundingClientRect().width;
|
||||
var scy = container.outerHeight() / container.get(0).getBoundingClientRect().height;
|
||||
position.left *= scx;
|
||||
position.top *= scy;
|
||||
|
||||
// On top
|
||||
position.top += this.$element.height() - this.scaleHeight_;
|
||||
|
||||
// Draw scale text
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = this.fontStrokeStyle_;
|
||||
ctx.fillStyle = this.fontFillStyle_;
|
||||
ctx.lineWidth = this.fontStrokeWidth_;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline ="bottom";
|
||||
ctx.font = this.font_;
|
||||
ctx.strokeText(text, position.left+scalewidth/2, position.top);
|
||||
ctx.fillText(text, position.left+scalewidth/2, position.top);
|
||||
ctx.closePath();
|
||||
|
||||
// Draw scale bar
|
||||
position.top += 2;
|
||||
ctx.lineWidth = this.strokeWidth_;
|
||||
ctx.strokeStyle = this.strokeStyle_;
|
||||
var max = 4;
|
||||
var n = parseInt(text);
|
||||
while (n%10 === 0) n/=10;
|
||||
if (n%5 === 0) max = 5;
|
||||
for (var i=0; i<max; i++)
|
||||
{ ctx.beginPath();
|
||||
ctx.fillStyle = i%2 ? this.fillStyle_ : this.strokeStyle_;
|
||||
ctx.rect(position.left+i*scalewidth/max, position.top, scalewidth/max, this.scaleHeight_);
|
||||
ctx.stroke();
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_control_CanvasScaleLine
|
||||
155
build/control/CanvasTitle.js
Normal file
155
build/control/CanvasTitle.js
Normal file
@ -0,0 +1,155 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_color from 'ol/color'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
|
||||
/**
|
||||
* OpenLayers 3 Title Control integrated in the canvas (for jpeg/png export purposes).
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options extend the ol.control options.
|
||||
* @param {ol_style_Style} options.style style usesd to draw the title.
|
||||
*/
|
||||
var ol_control_CanvasTitle = function(options)
|
||||
{ if (!options) options={};
|
||||
|
||||
// Get style options
|
||||
if (!options.style) options.style = new ol_style_Style();
|
||||
this.setStyle(options.style);
|
||||
|
||||
// Initialize parent
|
||||
var elt = $("<div>").text(this.text_)
|
||||
.addClass("ol-title ol-unselectable")
|
||||
.css(
|
||||
{ font: this.font_,
|
||||
position: 'absolute',
|
||||
top:0, left:0, right:0,
|
||||
display: 'block',
|
||||
visibility: 'hidden'
|
||||
});
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: elt.get(0),
|
||||
target: options.target
|
||||
});
|
||||
}
|
||||
ol.inherits(ol_control_CanvasTitle, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawTitle_, this);
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map) map.on('postcompose', this.drawTitle_, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change the control style
|
||||
* @param {ol_style_Style} style
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.setStyle = function (style)
|
||||
{ var text = style.getText();
|
||||
this.font_ = text ? text.getFont() || "20px Arial" : "20px Arial";
|
||||
this.text_ = text ? text.getText() : "";
|
||||
var stroke = text ? text.getStroke() : null;
|
||||
var fill = text ? text.getFill() : null;
|
||||
this.strokeStyle_ = stroke ? ol_color.asString(stroke.getColor()) : "#fff";
|
||||
this.fillStyle_ = fill ? ol_color.asString(fill.getColor()) : "#000";
|
||||
if (this.element)
|
||||
{ $(this.element).text(this.text_).css ({font: this.font_});
|
||||
}
|
||||
// refresh
|
||||
if (this.getMap()) this.getMap().render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map title
|
||||
* @param {string} map title.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.setTitle = function (title)
|
||||
{ this.text_ = title;
|
||||
$(this.element).text(title);
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the map title
|
||||
* @param {string} map title.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.getTitle = function (title)
|
||||
{ return this.text_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set control visibility
|
||||
* @param {bool} b
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.setVisible = function (b)
|
||||
{ if (b) $(this.element).show();
|
||||
else $(this.element).hide();
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get control visibility
|
||||
* @return {bool}
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.getVisible = function (b)
|
||||
{ return ($(this.element).css('display') !== 'none');
|
||||
}
|
||||
|
||||
/** Draw scale line in the final canvas
|
||||
*/
|
||||
ol_control_CanvasTitle.prototype.drawTitle_ = function(e)
|
||||
{ if (!this.getVisible()) return;
|
||||
var ctx = e.context;
|
||||
|
||||
// Retina device
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
var w = ctx.canvas.width/ratio;
|
||||
var h = $(this.element).height();
|
||||
var position = { top:0, left:w/2 };
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = this.strokeStyle_;
|
||||
ctx.rect(0,0, w, h);
|
||||
ctx.fill();
|
||||
ctx.closePath();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = this.fillStyle_;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.font = this.font_;
|
||||
ctx.fillText(this.text_, position.left, position.top +h/2);
|
||||
ctx.closePath();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_control_CanvasTitle
|
||||
225
build/control/Cloud.js
Normal file
225
build/control/Cloud.js
Normal file
File diff suppressed because one or more lines are too long
181
build/control/Compass.js
Normal file
181
build/control/Compass.js
Normal file
@ -0,0 +1,181 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/**
|
||||
* Draw a compass on the map. The position/size of the control is defined in the css.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options. The style {_ol_style_Stroke_} option is usesd to draw the text.
|
||||
* @param {string} options.className class name for the control
|
||||
* @param {Image} options.image an image, default use the src option or a default image
|
||||
* @param {string} options.src image src, default use the image option or a default image
|
||||
* @param {boolean} options.rotateVithView rotate vith view (false to show watermark), default true
|
||||
* @param {_ol_style_Stroke_} options.style style to draw the lines, default draw no lines
|
||||
*/
|
||||
var ol_control_Compass = function(options)
|
||||
{ var self = this;
|
||||
if (!options) options = {};
|
||||
|
||||
// Initialize parent
|
||||
var elt = document.createElement("div");
|
||||
elt.className = "ol-compassctrl ol-unselectable ol-hidden" + (options.className ? " "+options.className : "");
|
||||
elt.style.position = "absolute";
|
||||
elt.style.visibility = "hidden";
|
||||
|
||||
ol_control_Control.call(this, { element: elt });
|
||||
|
||||
this.set('rotateVithView', options.rotateWithView!==false);
|
||||
// Style to draw the lines
|
||||
this.style = options.style;
|
||||
|
||||
// The image
|
||||
if (options.image)
|
||||
{ this.img_ = options.image;
|
||||
}
|
||||
else if (options.src)
|
||||
{ this.img_ = new Image();
|
||||
this.img_.onload = function(){ if (self.getMap()) self.getMap().renderSync(); }
|
||||
this.img_.src = options.src;
|
||||
}
|
||||
else this.img_ = this.defaultCompass_($(this.element).width(), this.style ? this.style.getColor():"");
|
||||
|
||||
// 8 angles
|
||||
this.da_ = [];
|
||||
for (var i=0; i<8; i++) this.da_[i] = [ Math.cos(Math.PI*i/8), Math.sin(Math.PI*i/8) ];
|
||||
};
|
||||
ol.inherits(ol_control_Compass, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Compass.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawCompass_, this);
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map) map.on('postcompose', this.drawCompass_, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a default image.
|
||||
* @param {number} s the size of the compass
|
||||
* @private
|
||||
*/
|
||||
ol_control_Compass.prototype.defaultCompass_ = function (s, color)
|
||||
{ var canvas = document.createElement('canvas');
|
||||
var ctx = canvas.getContext("2d");
|
||||
var s = canvas.width = canvas.height;
|
||||
var r = s/2;
|
||||
var r2 = 0.22*r;
|
||||
|
||||
function draw (r, r2)
|
||||
{ ctx.fillStyle = color ||"#963";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo (0,0);
|
||||
ctx.lineTo (r,0); ctx.lineTo (r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (-r,0); ctx.lineTo (-r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,r); ctx.lineTo (-r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,-r); ctx.lineTo (r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
function draw2 (r, r2)
|
||||
{ ctx.globalCompositeOperation = "destination-out";
|
||||
ctx.fillStyle = "#fff";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo (0,0);
|
||||
ctx.lineTo (r,0); ctx.lineTo (r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (-r,0); ctx.lineTo (-r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,r); ctx.lineTo (r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,-r); ctx.lineTo (-r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation="source-over";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo (0,0);
|
||||
ctx.lineTo (r,0); ctx.lineTo (r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (-r,0); ctx.lineTo (-r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,r); ctx.lineTo (r2,r2); ctx.moveTo (0,0);
|
||||
ctx.lineTo (0,-r); ctx.lineTo (-r2,-r2); ctx.moveTo (0,0);
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
ctx.translate(r,r);
|
||||
ctx.strokeStyle = color || "#963";
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.beginPath();
|
||||
ctx.arc (0,0, s*0.41, 0, 2*Math.PI);
|
||||
ctx.arc (0,0, s*0.44, 0, 2*Math.PI);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.rotate(Math.PI/4)
|
||||
draw (r*0.9, r2*0.8);
|
||||
draw2 (r*0.9, r2*0.8);
|
||||
|
||||
ctx.rotate(-Math.PI/4)
|
||||
draw (r, r2);
|
||||
draw2 (r, r2);
|
||||
|
||||
return canvas;
|
||||
};
|
||||
|
||||
/** Draw compass
|
||||
* @param {ol.event} e postcompose event
|
||||
* @private
|
||||
*/
|
||||
ol_control_Compass.prototype.drawCompass_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
// Retina device
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
var w = $(this.element).width();
|
||||
var h = $(this.element).height();
|
||||
var pos = $(this.element).position();
|
||||
|
||||
var compass = this.img_;
|
||||
var rot = e.frameState.viewState.rotation;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.translate(pos.left+w/2, pos.top+h/2);
|
||||
if (this.get('rotateVithView')) ctx.rotate(rot);
|
||||
/*
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
ctx.globalAlpha = this.opacity || 1;
|
||||
*/
|
||||
if (this.style)
|
||||
{ ctx.beginPath();
|
||||
ctx.strokeStyle = this.style.getColor();
|
||||
ctx.lineWidth = this.style.getWidth();
|
||||
var m = Math.max(canvas.width, canvas.height);
|
||||
for (var i=0; i<8; i++)
|
||||
{ ctx.moveTo (-this.da_[i][0]*m, -this.da_[i][1]*m);
|
||||
ctx.lineTo (this.da_[i][0]*m, this.da_[i][1]*m);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
if (compass.width)
|
||||
{ ctx.drawImage (compass, -w/2, -h/2, w, h);
|
||||
}
|
||||
|
||||
ctx.closePath();
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_control_Compass
|
||||
47
build/control/Disable.js
Normal file
47
build/control/Disable.js
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** A simple control to disable all actions on the map.
|
||||
* The control will create an invisible div over the map.
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {String} options.class class of the control
|
||||
* @param {String} options.html html code to insert in the control
|
||||
* @param {bool} options.on the control is on
|
||||
* @param {function} options.toggleFn callback when control is clicked
|
||||
*/
|
||||
var ol_control_Disable = function(options)
|
||||
{ var options = options||{};
|
||||
var element = $("<div>").addClass((options.calssName||"")+' ol-disable ol-unselectable ol-control');
|
||||
element.css({ top:0, left:0, right:0, bottom:0, "z-index":10000, background:"none", display:"none" });
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0)
|
||||
});
|
||||
}
|
||||
ol.inherits(ol_control_Disable, ol_control_Control);
|
||||
|
||||
/** Test if the control is on
|
||||
* @return {bool}
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Disable.prototype.isOn = function()
|
||||
{ return $(this.element).hasClass("ol-disable");
|
||||
}
|
||||
|
||||
/** Disable all action on the map
|
||||
* @param {bool} b, default false
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Disable.prototype.disableMap = function(b)
|
||||
{ if (b)
|
||||
{ $(this.element).addClass("ol-enable").show();
|
||||
}
|
||||
else
|
||||
{ $(this.element).removeClass("ol-enable").hide();
|
||||
}
|
||||
}
|
||||
|
||||
export default ol_control_Disable
|
||||
26
build/control/Gauge.css
Normal file
26
build/control/Gauge.css
Normal file
@ -0,0 +1,26 @@
|
||||
.ol-gauge
|
||||
{ top: 0.5em;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.ol-gauge > *
|
||||
{ display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.ol-gauge > span
|
||||
{
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.ol-gauge > div
|
||||
{ width: 200px;
|
||||
border: 1px solid rgba(0,60,136,.5);
|
||||
border-radius: 3px;
|
||||
padding:1px;
|
||||
}
|
||||
.ol-gauge button
|
||||
{ height: 0.8em;
|
||||
margin:0;
|
||||
max-width:100%;
|
||||
}
|
||||
57
build/control/Gauge.js
Normal file
57
build/control/Gauge.js
Normal file
@ -0,0 +1,57 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** A simple gauge control to display level information on the map.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {String} options.className class of the control
|
||||
* @param {String} options.title title of the control
|
||||
* @param {number} options.max maximum value, default 100;
|
||||
* @param {number} options.val the value, default 0
|
||||
*/
|
||||
var ol_control_Gauge = function(options)
|
||||
{ options = options || {};
|
||||
var element = $("<div>").addClass((options.className||"") + ' ol-gauge ol-unselectable ol-control');
|
||||
this.title_ = $("<span>").appendTo(element);
|
||||
this.gauge_ = $("<button>").attr('type','button').appendTo($("<div>").appendTo(element)).width(0);
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
this.setTitle(options.title);
|
||||
this.val(options.val);
|
||||
this.set("max", options.max||100);
|
||||
};
|
||||
ol.inherits(ol_control_Gauge, ol_control_Control);
|
||||
|
||||
/** Set the control title
|
||||
* @param {string} title
|
||||
*/
|
||||
ol_control_Gauge.prototype.setTitle = function(title)
|
||||
{ this.title_.html(title||"");
|
||||
if (!title) this.title_.hide();
|
||||
else this.title_.show();
|
||||
};
|
||||
|
||||
/** Set/get the gauge value
|
||||
* @param {number|undefined} v the value or undefined to get it
|
||||
* @return {number} the value
|
||||
*/
|
||||
ol_control_Gauge.prototype.val = function(v)
|
||||
{ if (v!==undefined)
|
||||
{ this.val_ = v;
|
||||
this.gauge_.css("width", (v/this.get('max')*100)+"%");
|
||||
}
|
||||
return this.val_;
|
||||
};
|
||||
|
||||
export default ol_control_Gauge
|
||||
79
build/control/GeoBookmark.css
Normal file
79
build/control/GeoBookmark.css
Normal file
@ -0,0 +1,79 @@
|
||||
.ol-control.ol-bookmark
|
||||
{ top: 0.5em;
|
||||
left: 3em;
|
||||
}
|
||||
.ol-control.ol-bookmark button
|
||||
{ position: relative;
|
||||
}
|
||||
.ol-control.ol-bookmark > button::before
|
||||
{ content: "";
|
||||
position: absolute;
|
||||
border-width: 10px 5px 4px;
|
||||
border-style: solid;
|
||||
border-color: #fff;
|
||||
border-bottom-color: transparent;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.ol-control.ol-bookmark > div
|
||||
{ display: none;
|
||||
min-width: 5em;
|
||||
}
|
||||
.ol-control.ol-bookmark input
|
||||
{ font-size: 0.9em;
|
||||
margin: 0.1em 0 ;
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
.ol-control.ol-bookmark ul
|
||||
{ margin:0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
min-width: 10em;
|
||||
}
|
||||
.ol-control.ol-bookmark li
|
||||
{ color: rgba(0,60,136,0.8);
|
||||
font-size: 0.9em;
|
||||
padding: 0 0.2em 0 0.5em;
|
||||
cursor: default;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.ol-control.ol-bookmark li:hover
|
||||
{ background-color: rgba(0,60,136,.5);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.ol-control.ol-bookmark > div button
|
||||
{ width: 1em;
|
||||
height: 0.8em;
|
||||
float: right;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
border-radius: 0;
|
||||
}
|
||||
.ol-control.ol-bookmark > div button:before
|
||||
{ content: "\2A2F";
|
||||
color: #936;
|
||||
font-size: 1.2em;
|
||||
line-height: 1em;
|
||||
border-radius: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.ol-bookmark ul li button,
|
||||
.ol-bookmark input
|
||||
{ display: none;
|
||||
}
|
||||
.ol-bookmark.ol-editable ul li button,
|
||||
.ol-bookmark.ol-editable input
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
179
build/control/GeoBookmark.js
Normal file
179
build/control/GeoBookmark.js
Normal file
@ -0,0 +1,179 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** Bookmark positions on ol maps.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fires add
|
||||
* @fires remove
|
||||
* @param {} options Geobookmark's options
|
||||
* @param {string} options.className default ol-bookmark
|
||||
* @param {string} options.placeholder input placeholder, default Add a new geomark...
|
||||
* @param {bool} options.editable enable modification, default true
|
||||
* @param {string} options.namespace a namespace to save the boolmark (if more than one on a page), default ol
|
||||
* @param {Array<any>} options.marks a list of default bookmarks:
|
||||
* @see [Geobookmark example](../../examples/map.control.geobookmark.html)
|
||||
* @example
|
||||
var bm = new GeoBookmark ({
|
||||
marks: {
|
||||
"Paris": {pos:_ol_proj_.transform([2.351828, 48.856578], 'EPSG:4326', 'EPSG:3857'), zoom:11, permanent: true },
|
||||
"London": {pos:_ol_proj_.transform([-0.1275,51.507222], 'EPSG:4326', 'EPSG:3857'), zoom:12}
|
||||
}
|
||||
});
|
||||
*/
|
||||
var ol_control_GeoBookmark = function(options) {
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
var element = document.createElement('div');
|
||||
if (options.target) {
|
||||
element.className = options.className || "ol-bookmark";
|
||||
} else {
|
||||
element.className = (options.className || "ol-bookmark") +
|
||||
" ol-unselectable ol-control ol-collapsed";
|
||||
element.addEventListener("mouseleave", function() {
|
||||
if (input !== document.activeElement) {
|
||||
menu.style.display = 'none';
|
||||
};
|
||||
});
|
||||
// Show bookmarks on click
|
||||
this.button = document.createElement('button');
|
||||
this.button.setAttribute('type', 'button');
|
||||
this.button.addEventListener('click', function(e) {
|
||||
menu.style.display = (menu.style.display === '' || menu.style.display === 'none' ? 'block': 'none');
|
||||
});
|
||||
element.appendChild(this.button);
|
||||
}
|
||||
// The menu
|
||||
var menu = document.createElement('div');
|
||||
element.appendChild(menu);
|
||||
var ul = document.createElement('ul');
|
||||
menu.appendChild(ul);
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("placeholder", options.placeholder || "Add a new geomark...")
|
||||
input.addEventListener("change", function(e) {
|
||||
var title = this.value;
|
||||
if (title) {
|
||||
self.addBookmark(title);
|
||||
this.value = '';
|
||||
self.dispatchEvent({
|
||||
type: "add",
|
||||
name: title
|
||||
});
|
||||
}
|
||||
menu.style.display = 'none';
|
||||
});
|
||||
input.addEventListener("blur", function() {
|
||||
menu.style.display = 'none';
|
||||
});
|
||||
menu.appendChild(input);
|
||||
|
||||
// Init
|
||||
ol_control_Control.call(this, {
|
||||
element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
this.on("propertychange", function(e) {
|
||||
if (e.key==='editable')
|
||||
{ element.className = element.className.replace(" ol-editable","");
|
||||
if (this.get('editable'))
|
||||
{ element.className += " ol-editable";
|
||||
}
|
||||
}
|
||||
console.log(e);
|
||||
}), this;
|
||||
|
||||
this.set("namespace", options.namespace || 'ol');
|
||||
this.set("editable", options.editable !== false);
|
||||
|
||||
// Set default bmark
|
||||
this.setBookmarks(localStorage[this.get('namespace')+"@bookmark"] ? null:options.marks);
|
||||
};
|
||||
ol.inherits(ol_control_GeoBookmark, ol_control_Control);
|
||||
|
||||
/** Set bookmarks
|
||||
* @param {} bmark a list of bookmarks, default retreave in the localstorage
|
||||
* @example
|
||||
bm.setBookmarks({
|
||||
"Paris": {pos:_ol_proj_.transform([2.351828, 48.856578], 'EPSG:4326', 'EPSG:3857'), zoom:11, permanent: true },
|
||||
"London": {pos:_ol_proj_.transform([-0.1275,51.507222], 'EPSG:4326', 'EPSG:3857'), zoom:12}
|
||||
});
|
||||
*/
|
||||
ol_control_GeoBookmark.prototype.setBookmarks = function(bmark) {
|
||||
if (!bmark) bmark = JSON.parse(localStorage[this.get('namespace')+"@bookmark"] || "{}");
|
||||
var modify = this.get("editable");
|
||||
var ul = this.element.querySelector("ul");
|
||||
var menu = this.element.querySelector("div");
|
||||
var self = this;
|
||||
|
||||
ul.innerHTML = '';
|
||||
for (var b in bmark) {
|
||||
var li = document.createElement('li');
|
||||
li.textContent = b;
|
||||
li.setAttribute('data-bookmark', JSON.stringify(bmark[b]));
|
||||
li.addEventListener('click', function() {
|
||||
var bm = JSON.parse(this.getAttribute("data-bookmark"));
|
||||
self.getMap().getView().setCenter(bm.pos);
|
||||
self.getMap().getView().setZoom(bm.zoom);
|
||||
menu.style.display = 'none';
|
||||
});
|
||||
ul.appendChild(li);
|
||||
if (modify && !bmark[b].permanent) {
|
||||
var button = document.createElement('button');
|
||||
button.setAttribute('data-name', b);
|
||||
button.setAttribute("title", "Suppr.");
|
||||
button.addEventListener('click', function(e) {
|
||||
self.removeBookmark(this.getAttribute("data-name"));
|
||||
self.dispatchEvent({ type: "remove", name: this.getAttribute("data-name") });
|
||||
e.stopPropagation();
|
||||
});
|
||||
li.appendChild(button);
|
||||
}
|
||||
}
|
||||
localStorage[this.get('namespace')+"@bookmark"] = JSON.stringify(bmark);
|
||||
};
|
||||
|
||||
/** Get Geo bookmarks
|
||||
* @return {any} a list of bookmarks : { BM1:{pos:ol.coordinates, zoom: integer}, BM2:{pos:ol.coordinates, zoom: integer} }
|
||||
*/
|
||||
ol_control_GeoBookmark.prototype.getBookmarks = function() {
|
||||
return JSON.parse(localStorage[this.get('namespace')+"@bookmark"] || "{}");
|
||||
};
|
||||
|
||||
/** Remove a Geo bookmark
|
||||
* @param {string} name
|
||||
*/
|
||||
ol_control_GeoBookmark.prototype.removeBookmark = function(name) {
|
||||
if (!name) {
|
||||
return;
|
||||
};
|
||||
var bmark = this.getBookmarks();
|
||||
delete bmark[name];
|
||||
this.setBookmarks(bmark);
|
||||
};
|
||||
|
||||
/** Add a new Geo bookmark (replace existing one if any)
|
||||
* @param {string} name name of the bookmark (display in the menu)
|
||||
* @param {_ol_coordinate_} position default current position
|
||||
* @param {number} zoom default current map zoom
|
||||
* @param {bool} permanent prevent from deletion, default false
|
||||
*/
|
||||
ol_control_GeoBookmark.prototype.addBookmark = function(name, position, zoom, permanent)
|
||||
{
|
||||
if (!name) return;
|
||||
var bmark = this.getBookmarks();
|
||||
// Don't override permanent bookmark
|
||||
if (bmark[name] && bmark[name].permanent) return;
|
||||
// Create or override
|
||||
bmark[name] = {
|
||||
pos: position || this.getMap().getView().getCenter(),
|
||||
zoom: zoom || this.getMap().getView().getZoom(),
|
||||
permanent: !!permanent
|
||||
};
|
||||
this.setBookmarks(bmark);
|
||||
};
|
||||
|
||||
export default ol_control_GeoBookmark
|
||||
124
build/control/Globe.css
Normal file
124
build/control/Globe.css
Normal file
@ -0,0 +1,124 @@
|
||||
.ol-control.ol-globe
|
||||
{ position: absolute;
|
||||
left: 0.5em;
|
||||
bottom: 0.5em;
|
||||
border-radius: 50%;
|
||||
opacity: 0.7;
|
||||
transform: scale(0.5);
|
||||
transform-origin: 0 100%;
|
||||
-webkit-transform: scale(0.5);
|
||||
-webkit-transform-origin: 0 100%;
|
||||
}
|
||||
.ol-control.ol-globe:hover
|
||||
{ opacity: 0.9;
|
||||
}
|
||||
|
||||
.ol-control.ol-globe .panel
|
||||
{ display:block;
|
||||
width:170px;
|
||||
height:170px;
|
||||
background-color:#fff;
|
||||
cursor: pointer;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 0 10px 5px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.ol-control.ol-globe .panel .ol-viewport
|
||||
{ border-radius: 50%;
|
||||
}
|
||||
|
||||
.ol-control.ol-globe .ol-pointer
|
||||
{ display: block;
|
||||
background-color: #fff;
|
||||
width:10px;
|
||||
height: 10px;
|
||||
border:10px solid red;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left:50%;
|
||||
transform: translate(-15px, -40px);
|
||||
-webkit-transform: translate(-15px, -40px);
|
||||
border-radius: 50%;
|
||||
z-index:1;
|
||||
transition: opacity 0.15s, top 0s, left 0s;
|
||||
-webkit-transition: opacity 0.15s, top 0s, left 0s;
|
||||
}
|
||||
.ol-control.ol-globe .ol-pointer.hidden
|
||||
{ opacity:0;
|
||||
transition: opacity 0.15s, top 3s, left 5s;
|
||||
-webkit-transition: opacity 0.15s, top 3s, left 5s;
|
||||
}
|
||||
|
||||
.ol-control.ol-globe .ol-pointer::before
|
||||
{ border-radius: 50%;
|
||||
box-shadow: 6px 6px 10px 5px #000;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 23px;
|
||||
width: 0;
|
||||
}
|
||||
.ol-control.ol-globe .ol-pointer::after
|
||||
{ content:"";
|
||||
width:0;
|
||||
height:0;
|
||||
display: block;
|
||||
position: absolute;
|
||||
border-width: 20px 10px 0;
|
||||
border-color: red transparent;
|
||||
border-style: solid;
|
||||
left: -50%;
|
||||
top: 100%;
|
||||
}
|
||||
|
||||
.ol-control.ol-globe .panel::before {
|
||||
border-radius: 50%;
|
||||
box-shadow: -20px -20px 80px 2px rgba(0, 0, 0, 0.7) inset;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
.ol-control.ol-globe .panel::after {
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 20px 7px rgba(255, 255, 255, 1);
|
||||
content: "";
|
||||
display: block;
|
||||
height: 0;
|
||||
left: 23%;
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
transform: rotate(-40deg);
|
||||
width: 20%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
.ol-control.ol-globe.ol-collapsed .panel
|
||||
{ display:none;
|
||||
}
|
||||
|
||||
.ol-control-top.ol-globe
|
||||
{ bottom: auto;
|
||||
top: 5em;
|
||||
transform-origin: 0 0;
|
||||
-webkit-transform-origin: 0 0;
|
||||
}
|
||||
.ol-control-right.ol-globe
|
||||
{ left: auto;
|
||||
right: 0.5em;
|
||||
transform-origin: 100% 100%;
|
||||
-webkit-transform-origin: 100% 100%;
|
||||
}
|
||||
.ol-control-right.ol-control-top.ol-globe
|
||||
{ left: auto;
|
||||
right: 0.5em;
|
||||
transform-origin: 100% 0;
|
||||
-webkit-transform-origin: 100% 0;
|
||||
}
|
||||
191
build/control/Globe.js
Normal file
191
build/control/Globe.js
Normal file
@ -0,0 +1,191 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_View from 'ol/view'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
//TODO: replace ol.animation.pan with new {ol_interaction_Interaction.pan}
|
||||
//import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
|
||||
/**
|
||||
* OpenLayers 3 lobe Overview Control.
|
||||
* The globe can rotate with map (follow.)
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {boolean} follow follow the map when center change, default false
|
||||
* @param {top|bottom-left|right} align position as top-left, etc.
|
||||
* @param {Array<ol.layer>} layers list of layers to display on the globe
|
||||
* @param {ol.style.Style | Array.<ol.style.Style> | undefined} style style to draw the position on the map , default a marker
|
||||
*/
|
||||
var ol_control_Globe = function(opt_options)
|
||||
{ var options = opt_options || {};
|
||||
var self = this;
|
||||
|
||||
// API
|
||||
var element;
|
||||
if (options.target)
|
||||
{ element = $("<div>");
|
||||
this.panel_ = $(options.target);
|
||||
}
|
||||
else
|
||||
{ element = $("<div>").addClass('ol-globe ol-unselectable ol-control');
|
||||
if (/top/.test(options.align)) element.addClass('ol-control-top');
|
||||
if (/right/.test(options.align)) element.addClass('ol-control-right');
|
||||
this.panel_ = $("<div>").addClass("panel")
|
||||
.appendTo(element);
|
||||
this.pointer_ = $("<div>").addClass("ol-pointer")
|
||||
.appendTo(element);
|
||||
|
||||
}
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
|
||||
|
||||
// http://openlayers.org/en/latest/examples/sphere-mollweide.html ???
|
||||
|
||||
// Create a globe map
|
||||
this.ovmap_ = new ol_Map(
|
||||
{ controls: new ol_Collection(),
|
||||
interactions: new ol_Collection(),
|
||||
target: this.panel_.get(0),
|
||||
view: new ol_View
|
||||
({ zoom: 0,
|
||||
center: [0,0]
|
||||
}),
|
||||
layers: options.layers
|
||||
});
|
||||
|
||||
setTimeout (function()
|
||||
{ self.ovmap_.updateSize();
|
||||
}, 0);
|
||||
|
||||
this.set('follow', options.follow || false);
|
||||
|
||||
// Cache extent
|
||||
this.extentLayer = new ol_layer_Vector(
|
||||
{ name: 'Cache extent',
|
||||
source: new ol_source_Vector(),
|
||||
style: options.style || [new ol_style_Style(
|
||||
{ image: new ol_style_Circle(
|
||||
{ fill: new ol_style_Fill({
|
||||
color: 'rgba(255,0,0, 1)'
|
||||
}),
|
||||
stroke: new ol_style_Stroke(
|
||||
{ width: 7,
|
||||
color: 'rgba(255,0,0, 0.8)'
|
||||
}),
|
||||
radius: 5
|
||||
})
|
||||
}
|
||||
)]
|
||||
})
|
||||
this.ovmap_.addLayer(this.extentLayer);
|
||||
};
|
||||
ol.inherits(ol_control_Globe, ol_control_Control);
|
||||
|
||||
|
||||
/**
|
||||
* Set the map instance the control associated with.
|
||||
* @param {ol.Map} map The map instance.
|
||||
*/
|
||||
ol_control_Globe.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().getView().un('propertychange', this.setView, this);
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map)
|
||||
{ map.getView().on('propertychange', this.setView, this);
|
||||
this.setView();
|
||||
}
|
||||
};
|
||||
|
||||
/** Set the globe center with the map center
|
||||
*/
|
||||
ol_control_Globe.prototype.setView = function()
|
||||
{ if (this.getMap() && this.get('follow'))
|
||||
{ this.setCenter(this.getMap().getView().getCenter());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Get globe map
|
||||
* @return {ol_Map}
|
||||
*/
|
||||
ol_control_Globe.prototype.getGlobe = function()
|
||||
{ return this.ovmap_;
|
||||
}
|
||||
|
||||
/** Show/hide the globe
|
||||
*/
|
||||
ol_control_Globe.prototype.show = function(b)
|
||||
{ if (b!==false) $(this.element).removeClass("ol-collapsed");
|
||||
else $(this.element).addClass("ol-collapsed");
|
||||
this.ovmap_.updateSize();
|
||||
}
|
||||
|
||||
/** Set position on the map
|
||||
* @param {top|bottom-left|right} align
|
||||
*/
|
||||
ol_control_Globe.prototype.setPosition = function(align)
|
||||
{ if (/top/.test(align)) $(this.element).addClass("ol-control-top");
|
||||
else $(this.element).removeClass("ol-control-top");
|
||||
if (/right/.test(align)) $(this.element).addClass("ol-control-right");
|
||||
else $(this.element).removeClass("ol-control-right");
|
||||
}
|
||||
|
||||
/** Set the globe center
|
||||
* @param {_ol_coordinate_} center the point to center to
|
||||
* @param {boolean} show true to show a pointer
|
||||
*/
|
||||
ol_control_Globe.prototype.setCenter = function (center, show)
|
||||
{ var self = this;
|
||||
this.pointer_.addClass("hidden");
|
||||
if (center)
|
||||
{ var map = this.ovmap_;
|
||||
var p = map.getPixelFromCoordinate(center);
|
||||
var h = $(this.element).height();
|
||||
if (map.getView().animate)
|
||||
{ setTimeout(function()
|
||||
{ self.pointer_.css({ 'top': Math.min(Math.max(p[1],0),h) , 'left': "50%" } )
|
||||
.removeClass("hidden");
|
||||
}, 800);
|
||||
map.getView().animate({ center: [center[0],0] });
|
||||
}
|
||||
//TODO: Old version (<3.20)
|
||||
else
|
||||
{ var pan = ol.animation.pan(
|
||||
{ duration: 800,
|
||||
source: map.getView().getCenter()
|
||||
});
|
||||
map.beforeRender(function(map, frameState)
|
||||
{ var b = pan(map, frameState);
|
||||
if (!b && show!==false)
|
||||
{ self.pointer_
|
||||
.css({ 'top': Math.min(Math.max(p[1],0),h) , 'left': "50%" } )
|
||||
.removeClass("hidden");
|
||||
}
|
||||
return b;
|
||||
});
|
||||
map.getView().setCenter([center[0],0]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ol_control_Globe
|
||||
294
build/control/Graticule.js
Normal file
294
build/control/Graticule.js
Normal file
@ -0,0 +1,294 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_proj_Projection from 'ol/proj/projection'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_style_Text from 'ol/style/text'
|
||||
import ol_proj from 'ol/proj'
|
||||
|
||||
/**
|
||||
* Draw a graticule on the map.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} _ol_control_ options.
|
||||
* - projection {ol.projectionLike} projection to use for the graticule, default EPSG:4326
|
||||
* - maxResolution {number} max resolution to display the graticule
|
||||
* - style {ol_style_Style} Style to use for drawing the graticule, default black.
|
||||
* - step {number} step beetween lines (in proj units), default 1
|
||||
* - stepCoord {number} show a coord every stepCoord, default 1
|
||||
* - spacing {number} spacing beetween lines (in px), default 40px
|
||||
* - borderWidth {number} width of the border (in px), default 5px
|
||||
* - margin {number} margin of the border (in px), default 0px
|
||||
*/
|
||||
var ol_control_Graticule = function(options)
|
||||
{ var self = this;
|
||||
if (!options) options = {};
|
||||
|
||||
// Initialize parent
|
||||
var elt = document.createElement("div");
|
||||
elt.className = "ol-graticule ol-unselectable ol-hidden";
|
||||
|
||||
ol_control_Control.call(this, { element: elt });
|
||||
|
||||
this.set('projection', options.projection || 'EPSG:4326');
|
||||
|
||||
// Use to limit calculation
|
||||
var p = new ol_proj_Projection({code:this.get('projection')});
|
||||
var m = p.getMetersPerUnit();
|
||||
this.fac = 1;
|
||||
while (m/this.fac>10)
|
||||
{ this.fac *= 10;
|
||||
}
|
||||
this.fac = 10000/this.fac;
|
||||
|
||||
this.set('maxResolution', options.maxResolution || Infinity);
|
||||
this.set('step', options.step || 0.1);
|
||||
this.set('stepCoord', options.stepCoord || 1);
|
||||
this.set('spacing', options.spacing || 40);
|
||||
this.set('margin', options.margin || 0);
|
||||
this.set('borderWidth', options.borderWidth || 5);
|
||||
this.set('stroke', options.stroke!==false);
|
||||
this.formatCoord = options.formatCoord || function(c){return c;};
|
||||
|
||||
if (options.style instanceof ol_style_Style) this.style = options.style;
|
||||
else this.style = new ol_style_Style(
|
||||
{ stroke: new ol_style_Stroke({ color:"#000", width:1 }),
|
||||
fill: new ol_style_Fill({ color: "#fff" }),
|
||||
text: new ol_style_Text(
|
||||
{ stroke: new ol_style_Stroke({ color:"#fff", width:2 }),
|
||||
fill: new ol_style_Fill({ color:"#000" }),
|
||||
})
|
||||
});
|
||||
};
|
||||
ol.inherits(ol_control_Graticule, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Graticule.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawGraticule_, this);
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map) map.on('postcompose', this.drawGraticule_, this);
|
||||
};
|
||||
|
||||
ol_control_Graticule.prototype.setStyle = function (style)
|
||||
{ this.style = style;
|
||||
};
|
||||
|
||||
ol_control_Graticule.prototype.getStyle = function (style)
|
||||
{ return style;
|
||||
};
|
||||
|
||||
ol_control_Graticule.prototype.drawGraticule_ = function (e)
|
||||
{ if (this.get('maxResolution')<e.frameState.viewState.resolution) return;
|
||||
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
var w = canvas.width/ratio;
|
||||
var h = canvas.height/ratio;
|
||||
|
||||
var proj = this.get('projection');
|
||||
|
||||
var map = this.getMap();
|
||||
var bbox =
|
||||
[ map.getCoordinateFromPixel([0,0]),
|
||||
map.getCoordinateFromPixel([w,0]),
|
||||
map.getCoordinateFromPixel([w,h]),
|
||||
map.getCoordinateFromPixel([0,h])
|
||||
];
|
||||
var xmax = -Infinity;
|
||||
var xmin = Infinity;
|
||||
var ymax = -Infinity;
|
||||
var ymin = Infinity;
|
||||
for (var i=0, c; c=bbox[i]; i++)
|
||||
{ bbox[i] = ol_proj.transform (c, map.getView().getProjection(), proj);
|
||||
xmax = Math.max (xmax, bbox[i][0]);
|
||||
xmin = Math.min (xmin, bbox[i][0]);
|
||||
ymax = Math.max (ymax, bbox[i][1]);
|
||||
ymin = Math.min (ymin, bbox[i][1]);
|
||||
}
|
||||
|
||||
var spacing = this.get('spacing');
|
||||
var step = this.get('step');
|
||||
var step2 = this.get('stepCoord');
|
||||
var borderWidth = this.get('borderWidth');
|
||||
var margin = this.get('margin');
|
||||
|
||||
// Limit max line draw
|
||||
var ds = (xmax-xmin)/step*spacing;
|
||||
if (ds>w)
|
||||
{ var dt = Math.round((xmax-xmin)/w*spacing /step);
|
||||
step *= dt;
|
||||
if (step>this.fac) step = Math.round(step/this.fac)*this.fac;
|
||||
}
|
||||
|
||||
xmin = (Math.floor(xmin/step))*step -step;
|
||||
ymin = (Math.floor(ymin/step))*step -step;
|
||||
xmax = (Math.floor(xmax/step))*step +2*step;
|
||||
ymax = (Math.floor(ymax/step))*step +2*step;
|
||||
|
||||
var extent = ol.proj.get(proj).getExtent();
|
||||
if (extent)
|
||||
{ if (xmin < extent[0]) xmin = extent[0];
|
||||
if (ymin < extent[1]) ymin = extent[1];
|
||||
if (xmax > extent[2]) xmax = extent[2]+step;
|
||||
if (ymax > extent[3]) ymax = extent[3]+step;
|
||||
}
|
||||
|
||||
var hasLines = this.style.getStroke() && this.get("stroke");
|
||||
var hasText = this.style.getText();
|
||||
var hasBorder = this.style.getFill();
|
||||
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.rect(margin, margin, w-2*margin, h-2*margin);
|
||||
ctx.clip();
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
var txt = {top:[],left:[],bottom:[], right:[]};
|
||||
|
||||
for (var x=xmin; x<xmax; x += step)
|
||||
{ var p0 = ol_proj.transform ([x, ymin], proj, map.getView().getProjection());
|
||||
p0 = map.getPixelFromCoordinate(p0);
|
||||
if (hasLines) ctx.moveTo(p0[0], p0[1]);
|
||||
var p = p0;
|
||||
for (var y=ymin+step; y<=ymax; y+=step)
|
||||
{ var p1 = ol_proj.transform ([x, y], proj, map.getView().getProjection());
|
||||
p1 = map.getPixelFromCoordinate(p1);
|
||||
if (hasLines) ctx.lineTo(p1[0], p1[1]);
|
||||
if (p[1]>0 && p1[1]<0) txt.top.push([x, p]);
|
||||
if (p[1]>h && p1[1]<h) txt.bottom.push([x,p]);
|
||||
p = p1;
|
||||
}
|
||||
}
|
||||
for (var y=ymin; y<ymax; y += step)
|
||||
{ var p0 = ol_proj.transform ([xmin, y], proj, map.getView().getProjection());
|
||||
p0 = map.getPixelFromCoordinate(p0);
|
||||
if (hasLines) ctx.moveTo(p0[0], p0[1]);
|
||||
var p = p0;
|
||||
for (var x=xmin+step; x<=xmax; x+=step)
|
||||
{ var p1 = ol_proj.transform ([x, y], proj, map.getView().getProjection());
|
||||
p1 = map.getPixelFromCoordinate(p1);
|
||||
if (hasLines) ctx.lineTo(p1[0], p1[1]);
|
||||
if (p[0]<0 && p1[0]>0) txt.left.push([y,p]);
|
||||
if (p[0]<w && p1[0]>w) txt.right.push([y,p]);
|
||||
p = p1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasLines)
|
||||
{ ctx.strokeStyle = this.style.getStroke().getColor();
|
||||
ctx.lineWidth = this.style.getStroke().getWidth();
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// Draw text
|
||||
if (hasText)
|
||||
{
|
||||
ctx.fillStyle = this.style.getText().getFill().getColor();
|
||||
ctx.strokeStyle = this.style.getText().getStroke().getColor();
|
||||
ctx.lineWidth = this.style.getText().getStroke().getWidth();
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'hanging';
|
||||
var tf;
|
||||
var offset = (hasBorder ? borderWidth : 0) + margin + 2;
|
||||
for (var i=0, t; t = txt.top[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2))
|
||||
{ tf = this.formatCoord(t[0]);
|
||||
ctx.strokeText(tf, t[1][0], offset);
|
||||
ctx.fillText(tf, t[1][0], offset);
|
||||
}
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
for (var i=0, t; t = txt.bottom[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2))
|
||||
{ tf = this.formatCoord(t[0]);
|
||||
ctx.strokeText(tf, t[1][0], h-offset);
|
||||
ctx.fillText(tf, t[1][0], h-offset);
|
||||
}
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'left';
|
||||
for (var i=0, t; t = txt.left[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2))
|
||||
{ tf = this.formatCoord(t[0]);
|
||||
ctx.strokeText(tf, offset, t[1][1]);
|
||||
ctx.fillText(tf, offset, t[1][1]);
|
||||
}
|
||||
ctx.textAlign = 'right';
|
||||
for (var i=0, t; t = txt.right[i]; i++) if (!(Math.round(t[0]/this.get('step'))%step2))
|
||||
{ tf = this.formatCoord(t[0]);
|
||||
ctx.strokeText(tf, w-offset, t[1][1]);
|
||||
ctx.fillText(tf, w-offset, t[1][1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw border
|
||||
if (hasBorder)
|
||||
{ var fillColor = this.style.getFill().getColor();
|
||||
var color, stroke;
|
||||
if (stroke = this.style.getStroke())
|
||||
{ color = this.style.getStroke().getColor();
|
||||
}
|
||||
else
|
||||
{ color = fillColor;
|
||||
fillColor = "#fff";
|
||||
}
|
||||
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = stroke ? stroke.getWidth() : 1;
|
||||
//
|
||||
for (var i=1; i<txt.top.length; i++)
|
||||
{ ctx.beginPath();
|
||||
ctx.rect(txt.top[i-1][1][0], margin, txt.top[i][1][0]-txt.top[i-1][1][0], borderWidth);
|
||||
ctx.fillStyle = Math.round(txt.top[i][0]/step)%2 ? color: fillColor;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
for (var i=1; i<txt.bottom.length; i++)
|
||||
{ ctx.beginPath();
|
||||
ctx.rect(txt.bottom[i-1][1][0], h-borderWidth-margin, txt.bottom[i][1][0]-txt.bottom[i-1][1][0], borderWidth);
|
||||
ctx.fillStyle = Math.round(txt.bottom[i][0]/step)%2 ? color: fillColor;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
for (var i=1; i<txt.left.length; i++)
|
||||
{ ctx.beginPath();
|
||||
ctx.rect(margin, txt.left[i-1][1][1], borderWidth, txt.left[i][1][1]-txt.left[i-1][1][1]);
|
||||
ctx.fillStyle = Math.round(txt.left[i][0]/step)%2 ? color: fillColor;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
for (var i=1; i<txt.right.length; i++)
|
||||
{ ctx.beginPath();
|
||||
ctx.rect(w-borderWidth-margin, txt.right[i-1][1][1], borderWidth, txt.right[i][1][1]-txt.right[i-1][1][1]);
|
||||
ctx.fillStyle = Math.round(txt.right[i][0]/step)%2 ? color: fillColor;
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = color;
|
||||
ctx.rect(margin,margin, borderWidth, borderWidth);
|
||||
ctx.rect(margin,h-borderWidth-margin, borderWidth,borderWidth);
|
||||
ctx.rect(w-borderWidth-margin,margin, borderWidth, borderWidth);
|
||||
ctx.rect(w-borderWidth-margin,h-borderWidth-margin, borderWidth,borderWidth);
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_control_Graticule
|
||||
38
build/control/GridReference.css
Normal file
38
build/control/GridReference.css
Normal file
@ -0,0 +1,38 @@
|
||||
.ol-gridreference
|
||||
{ background: #fff;
|
||||
border: 1px solid #000;
|
||||
overflow: auto;
|
||||
max-height: 100%;
|
||||
top:0;
|
||||
right:0;
|
||||
}
|
||||
.ol-gridreference input
|
||||
{ width:100%;
|
||||
}
|
||||
.ol-gridreference ul
|
||||
{ margin:0;
|
||||
padding:0;
|
||||
list-style: none;
|
||||
}
|
||||
.ol-gridreference li
|
||||
{ padding: 0 0.5em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ol-gridreference ul li:hover
|
||||
{ background-color: #ccc;
|
||||
}
|
||||
.ol-gridreference li.ol-title,
|
||||
.ol-gridreference li.ol-title:hover
|
||||
{ background:rgba(0,60,136,.5);
|
||||
color:#fff;
|
||||
cursor:default;
|
||||
}
|
||||
.ol-gridreference ul li .ol-ref
|
||||
{ margin-left: 0.5em;
|
||||
}
|
||||
.ol-gridreference ul li .ol-ref:before
|
||||
{ content:"(";
|
||||
}
|
||||
.ol-gridreference ul li .ol-ref:after
|
||||
{ content:")";
|
||||
}
|
||||
309
build/control/GridReference.js
Normal file
309
build/control/GridReference.js
Normal file
@ -0,0 +1,309 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_style_Text from 'ol/style/text'
|
||||
import ol_extent from 'ol/extent'
|
||||
|
||||
/**
|
||||
* Draw a grid reference on the map and add an index.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fires select
|
||||
* @param {Object=} Control options.
|
||||
* - style {ol_style_Style} Style to use for drawing the grid (stroke and text), default black.
|
||||
* - maxResolution {number} max resolution to display the graticule
|
||||
* - extent {ol.extent} extent of the grid, required
|
||||
* - size {ol.size} number of lines and cols, required
|
||||
* - margin {number} margin to display text (in px), default 0px
|
||||
* - source {ol.source.Vector} source to use for the index, default none (use setIndex to reset the index)
|
||||
* - property {string | function} a property to display in the index or a function that takes a feature and return the name to display in the index, default 'name'.
|
||||
* - sortFeatures {function|undefined} sort function to sort 2 features in the index, default sort on property option
|
||||
* - indexTitle {function|undefined} a function that takes a feature and return the title to display in the index, default the first letter of property option
|
||||
* - filterLabel {string} label to display in the search bar, default 'filter'
|
||||
*/
|
||||
var ol_control_GridReference = function(options)
|
||||
{ var self = this;
|
||||
if (!options) options = {};
|
||||
|
||||
// Initialize parent
|
||||
var elt = document.createElement("div");
|
||||
elt.className = (!options.target ? "ol-control ":"") +"ol-gridreference ol-unselectable "+(options.className||"");
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: elt,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
if (typeof (options.property)=='function') this.getFeatureName = options.property;
|
||||
if (typeof (options.sortFeatures)=='function') this.sortFeatures = options.sortFeatures;
|
||||
if (typeof (options.indexTitle)=='function') this.indexTitle = options.indexTitle;
|
||||
|
||||
// Set index using the source
|
||||
this.source_ = options.source;
|
||||
if (options.source)
|
||||
{ this.setIndex(options.source.getFeatures(), options);
|
||||
// reload on ready
|
||||
options.source.once('change',function(e)
|
||||
{ if (options.source.getState() === 'ready')
|
||||
{ this.setIndex(options.source.getFeatures(), options);
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
|
||||
// Options
|
||||
this.set('maxResolution', options.maxResolution || Infinity);
|
||||
this.set('extent', options.extent);
|
||||
this.set('size', options.size);
|
||||
this.set('margin', options.margin || 0);
|
||||
this.set('property', options.property || 'name');
|
||||
this.set('filterLabel', options.filterLabel || 'filter');
|
||||
|
||||
if (options.style instanceof ol_style_Style) this.style = options.style;
|
||||
else this.style = new ol_style_Style(
|
||||
{ stroke: new ol_style_Stroke({ color:"#000", width:1 }),
|
||||
text: new ol_style_Text(
|
||||
{ font: "bold 14px Arial",
|
||||
stroke: new ol_style_Stroke({ color:"#fff", width:2 }),
|
||||
fill: new ol_style_Fill({ color:"#000" }),
|
||||
})
|
||||
});
|
||||
};
|
||||
ol.inherits(ol_control_GridReference, ol_control_Control);
|
||||
|
||||
/** Returns the text to be displayed in the index
|
||||
* @param {ol.Feature} f the feature
|
||||
* @return {string} the text to be displayed in the index
|
||||
* @api
|
||||
*/
|
||||
ol_control_GridReference.prototype.getFeatureName = function (f)
|
||||
{ return f.get(this.get('property')||'name');
|
||||
};
|
||||
|
||||
/** Sort function
|
||||
* @param {ol.Feature} a first feature
|
||||
* @param {ol.Feature} b second feature
|
||||
* @return {Number} 0 if a==b, -1 if a<b, 1 if a>b
|
||||
* @api
|
||||
*/
|
||||
ol_control_GridReference.prototype.sortFeatures = function (a,b)
|
||||
{ return (this.getFeatureName(a) == this.getFeatureName(b)) ? 0 : (this.getFeatureName(a) < this.getFeatureName(b)) ? -1 : 1;
|
||||
};
|
||||
|
||||
/** Get the feature title
|
||||
* @param {ol.Feature} f
|
||||
* @return the first letter of the eature name (getFeatureName)
|
||||
* @api
|
||||
*/
|
||||
ol_control_GridReference.prototype.indexTitle = function (f)
|
||||
{ return this.getFeatureName(f).charAt(0);
|
||||
};
|
||||
|
||||
/** Display features in the index
|
||||
* @param { Array<ol.Feature> | ol.Collection<ol.Feature> } features
|
||||
*/
|
||||
ol_control_GridReference.prototype.setIndex = function (features)
|
||||
{ if (!this.getMap()) return;
|
||||
var self = this;
|
||||
if (features.getArray) features = features.getArray();
|
||||
features.sort ( function(a,b) { return self.sortFeatures(a,b); } );
|
||||
var elt = $(this.element).html("");
|
||||
|
||||
var search = $("<input>").attr('type', 'search')
|
||||
.attr('placeholder', this.get('filterLabel') || 'filter')
|
||||
.on('search keyup', function()
|
||||
{ var v = $(this).val().replace(/^\*/,'');
|
||||
// console.log(v)
|
||||
var r = new RegExp (v, 'i');
|
||||
$('li',ul).each(function()
|
||||
{ var self = $(this);
|
||||
if (self.hasClass('ol-title')) self.show();
|
||||
else
|
||||
{ if (r.test($('.ol-name',self).text())) self.show();
|
||||
else self.hide();
|
||||
}
|
||||
});
|
||||
$("li.ol-title", ul).each(function()
|
||||
{ var nextVisible = $(this).nextAll("li:visible").first()
|
||||
if (nextVisible.length && !nextVisible.hasClass('ol-title')) $(this).show();
|
||||
else $(this).hide();
|
||||
});
|
||||
})
|
||||
.appendTo(elt);
|
||||
|
||||
var ul = $("<ul>").appendTo(elt);
|
||||
var r, title;
|
||||
for (var i=0, f; f=features[i]; i++)
|
||||
{ r = this.getReference(f.getGeometry().getFirstCoordinate());
|
||||
if (r)
|
||||
{ var name = this.getFeatureName(f);
|
||||
var c = this.indexTitle(f);
|
||||
if (c != title)
|
||||
{ $("<li>").addClass('ol-title').text(c).appendTo(ul);
|
||||
}
|
||||
title = c;
|
||||
$("<li>").append($("<span>").addClass("ol-name").text(name))
|
||||
.append($("<span>").addClass("ol-ref").text(r))
|
||||
.data ('feature', f)
|
||||
.click(function()
|
||||
{ self.dispatchEvent({ type:"select", feature:$(this).data('feature') });
|
||||
})
|
||||
.appendTo(ul);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Get reference for a coord
|
||||
* @param {ol.coordinate} coords
|
||||
* @return {string} the reference
|
||||
*/
|
||||
ol_control_GridReference.prototype.getReference = function (coords)
|
||||
{ if (!this.getMap()) return;
|
||||
var extent = this.get('extent');
|
||||
var size = this.get('size');
|
||||
|
||||
var dx = Math.floor ( (coords[0] - extent[0]) / (extent[2]- extent[0]) * size[0] );
|
||||
if (dx<0 || dx>=size[0]) return "";
|
||||
var dy = Math.floor ( (extent[3] - coords[1]) / (extent[3]- extent[1]) * size[1] );
|
||||
if (dy<0 || dy>=size[1]) return "";
|
||||
return String.fromCharCode(65+dx)+dy;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_GridReference.prototype.setMap = function (map)
|
||||
{ var oldmap = this.getMap();
|
||||
if (oldmap) oldmap.un('postcompose', this.drawGrid_, this);
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
if (oldmap) oldmap.renderSync();
|
||||
|
||||
// Get change (new layer added or removed)
|
||||
if (map)
|
||||
{ map.on('postcompose', this.drawGrid_, this);
|
||||
if (this.source_) this.setIndex(this.source_.getFeatures());
|
||||
}
|
||||
};
|
||||
|
||||
/** Set style
|
||||
* @param {ol_style_Style} style
|
||||
*/
|
||||
ol_control_GridReference.prototype.setStyle = function (style)
|
||||
{ this.style = style;
|
||||
};
|
||||
|
||||
/** Get style
|
||||
* @return {ol_style_Style} style
|
||||
*/
|
||||
ol_control_GridReference.prototype.getStyle = function ()
|
||||
{ return style;
|
||||
};
|
||||
|
||||
/** Draw the grid
|
||||
* @param {ol.event} e postcompose event
|
||||
* @private
|
||||
*/
|
||||
ol_control_GridReference.prototype.drawGrid_ = function (e)
|
||||
{ if (this.get('maxResolution')<e.frameState.viewState.resolution) return;
|
||||
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
|
||||
var w = canvas.width/ratio;
|
||||
var h = canvas.height/ratio;
|
||||
|
||||
var extent = this.get('extent');
|
||||
var size = this.get('size');
|
||||
|
||||
var map = this.getMap();
|
||||
var ex = ol_extent.boundingExtent([map.getPixelFromCoordinate([extent[0],extent[1]]), map.getPixelFromCoordinate([extent[2],extent[3]])]);
|
||||
var p0 = [ex[0],ex[1]];
|
||||
var p1 = [ex[2],ex[3]];
|
||||
var dx = (p1[0]-p0[0])/size[0];
|
||||
var dy = (p1[1]-p0[1])/size[1];
|
||||
|
||||
ctx.save();
|
||||
var margin = this.get('margin');
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
ctx.strokeStyle = this.style.getStroke().getColor();
|
||||
ctx.lineWidth = this.style.getStroke().getWidth();
|
||||
|
||||
// Draw grid
|
||||
ctx.beginPath();
|
||||
for (var i=0; i<=size[0]; i++)
|
||||
{ ctx.moveTo(p0[0]+i*dx, p0[1]);
|
||||
ctx.lineTo(p0[0]+i*dx, p1[1]);
|
||||
}
|
||||
for (var i=0; i<=size[1]; i++)
|
||||
{ ctx.moveTo(p0[0], p0[1]+i*dy);
|
||||
ctx.lineTo(p1[0], p0[1]+i*dy);
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
// Draw text
|
||||
ctx.font = this.style.getText().getFont();
|
||||
ctx.fillStyle = this.style.getText().getFill().getColor();
|
||||
ctx.strokeStyle = this.style.getText().getStroke().getColor();
|
||||
var lw = ctx.lineWidth = this.style.getText().getStroke().getWidth();
|
||||
var spacing = margin +lw;
|
||||
ctx.textAlign = 'center';
|
||||
var letter, x, y;
|
||||
for (var i=0; i<size[0]; i++)
|
||||
{ letter = String.fromCharCode(65+i);
|
||||
x = p0[0]+i*dx+dx/2;
|
||||
y = p0[1]-spacing;
|
||||
if (y<0)
|
||||
{ y = spacing;
|
||||
ctx.textBaseline = 'hanging';
|
||||
}
|
||||
else ctx.textBaseline = 'alphabetic';
|
||||
ctx.strokeText(letter, x, y);
|
||||
ctx.fillText(letter, x, y);
|
||||
y = p1[1]+spacing;
|
||||
if (y>h)
|
||||
{ y = h-spacing;
|
||||
ctx.textBaseline = 'alphabetic';
|
||||
}
|
||||
else ctx.textBaseline = 'hanging';
|
||||
ctx.strokeText(letter, x, y);
|
||||
ctx.fillText(letter, x, y);
|
||||
}
|
||||
ctx.textBaseline = 'middle';
|
||||
for (var i=0; i<size[0]; i++)
|
||||
{ y = p0[1]+i*dy+dy/2;
|
||||
ctx.textAlign = 'right';
|
||||
x = p0[0] - spacing;
|
||||
if (x<0)
|
||||
{ x = spacing;
|
||||
ctx.textAlign = 'left';
|
||||
}
|
||||
else ctx.textAlign = 'right';
|
||||
ctx.strokeText(i, x, y);
|
||||
ctx.fillText(i, x, y);
|
||||
x = p1[0] + spacing;
|
||||
if (x>w)
|
||||
{ x = w-spacing;
|
||||
ctx.textAlign = 'right';
|
||||
}
|
||||
else ctx.textAlign = 'left';
|
||||
ctx.strokeText(i, x, y);
|
||||
ctx.fillText(i, x, y);
|
||||
}
|
||||
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_control_GridReference
|
||||
58
build/control/LayerPopup.css
Normal file
58
build/control/LayerPopup.css
Normal file
@ -0,0 +1,58 @@
|
||||
.ol-control.ol-layerswitcher-popup
|
||||
{ position: absolute;
|
||||
right: 0.5em;
|
||||
text-align: left;
|
||||
top: 3em;
|
||||
}
|
||||
.ol-control.ol-layerswitcher-popup .panel
|
||||
{ clear:both;
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-popup .panel
|
||||
{ list-style: none;
|
||||
padding: 0.25em;
|
||||
margin:0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-popup .panel ul
|
||||
{ list-style: none;
|
||||
padding: 0 0 0 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-popup.ol-collapsed .panel
|
||||
{ display:none;
|
||||
}
|
||||
.ol-layerswitcher-popup.ol-forceopen .panel
|
||||
{ display:block;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-popup button
|
||||
{ background-color: white;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
float: right;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-popup li
|
||||
{ color:#369;
|
||||
padding:0.25em 1em;
|
||||
font-family:"Trebuchet MS",Helvetica,sans-serif;
|
||||
cursor:pointer;
|
||||
}
|
||||
.ol-layerswitcher-popup li.ol-header
|
||||
{ display: none;
|
||||
}
|
||||
.ol-layerswitcher-popup li.select
|
||||
{ background:rgba(0, 60, 136, 0.7);
|
||||
color:#fff;
|
||||
}
|
||||
.ol-layerswitcher-popup li:hover
|
||||
{ background:rgba(0, 60, 136, 0.9);
|
||||
color:#fff;
|
||||
}
|
||||
56
build/control/LayerPopup.js
Normal file
56
build/control/LayerPopup.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_LayerSwitcher from './LayerSwitcher'
|
||||
|
||||
/**
|
||||
* OpenLayers 3 Layer Switcher Control.
|
||||
* @require jQuery
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_LayerSwitcher}
|
||||
* @param {Object=} options Control options.
|
||||
*/
|
||||
ol_control_LayerPopup = function(options)
|
||||
{ options = options || {};
|
||||
options.switcherClass="ol-layerswitcher-popup";
|
||||
if (options.mouseover!==false) options.mouseover=true;
|
||||
ol_control_LayerSwitcher.call(this, options);
|
||||
};
|
||||
ol.inherits(ol_control_LayerPopup, ol_control_LayerSwitcher);
|
||||
|
||||
/** Disable overflow
|
||||
*/
|
||||
ol_control_LayerPopup.prototype.overflow = function(){};
|
||||
|
||||
/** Render a list of layer
|
||||
* @param {elt} element to render
|
||||
* @layers {Array{ol.layer}} list of layer to show
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_LayerPopup.prototype.drawList = function(ul, layers)
|
||||
{ var self=this;
|
||||
|
||||
var setVisibility = function(e)
|
||||
{ e.preventDefault();
|
||||
var l = $(this).data("layer");
|
||||
self.switchLayerVisibility(l,layers);
|
||||
};
|
||||
|
||||
layers.forEach(function(layer)
|
||||
{ if (layer.get("displayInLayerSwitcher")!==false)
|
||||
{ var d = $("<li>").text(layer.get("title") || layer.get("name"))
|
||||
.data ('layer', layer)
|
||||
.click (setVisibility)
|
||||
.on ("touchstart", setVisibility)
|
||||
.appendTo(ul);
|
||||
if (self.testLayerVisibility(layer)) d.addClass("ol-layer-hidden");
|
||||
if (layer.getVisible()) d.addClass("select");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default ol_control_LayerPopup
|
||||
440
build/control/LayerSwitcher.css
Normal file
440
build/control/LayerSwitcher.css
Normal file
@ -0,0 +1,440 @@
|
||||
.ol-control.ol-layerswitcher
|
||||
{ position: absolute;
|
||||
right: 0.5em;
|
||||
text-align: left;
|
||||
top: 3em;
|
||||
max-height: calc(100% - 6em);
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ol-control.ol-layerswitcher .ol-switchertopdiv,
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv
|
||||
{ display: block
|
||||
}
|
||||
.ol-control.ol-layerswitcher.ol-collapsed .ol-switchertopdiv,
|
||||
.ol-control.ol-layerswitcher.ol-collapsed .ol-switcherbottomdiv
|
||||
{ display: none;
|
||||
}
|
||||
.ol-layerswitcher.ol-forceopen.ol-collapsed .ol-switchertopdiv,
|
||||
.ol-layerswitcher.ol-forceopen.ol-collapsed .ol-switcherbottomdiv
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
.ol-control.ol-layerswitcher .ol-switchertopdiv,
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv
|
||||
{ position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
height: 45px;
|
||||
background: #fff;
|
||||
z-index:2;
|
||||
opacity:1;
|
||||
cursor: pointer;
|
||||
border-top:2px solid transparent;
|
||||
border-bottom:2px solid #369;
|
||||
margin:0 2px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv
|
||||
{ top: auto;
|
||||
bottom: 0;
|
||||
height: 2em;
|
||||
border-top:2px solid #369;
|
||||
border-bottom:2px solid transparent;
|
||||
}
|
||||
.ol-control.ol-layerswitcher .ol-switchertopdiv:before,
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv:before
|
||||
{ content:"";
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top:50%;
|
||||
border:10px solid transparent;
|
||||
width:0;
|
||||
height:0;
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
opacity:0.8;
|
||||
}
|
||||
|
||||
.ol-control.ol-layerswitcher .ol-switchertopdiv:hover:before,
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv:hover:before
|
||||
{ opacity:1;
|
||||
}
|
||||
.ol-control.ol-layerswitcher .ol-switchertopdiv:before
|
||||
{ border-bottom-color: #369;
|
||||
border-top: 0;
|
||||
}
|
||||
.ol-control.ol-layerswitcher .ol-switcherbottomdiv:before
|
||||
{ border-top-color: #369;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.ol-control.ol-layerswitcher .panel
|
||||
{ background-color: #fff;
|
||||
border-radius: 0 0 2px 2px;
|
||||
clear: both;
|
||||
display: block; /* display:block to show panel on over */
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel
|
||||
{ list-style: none;
|
||||
padding: 0.5em 0.5em 0;
|
||||
margin:0;
|
||||
overflow: hidden;
|
||||
font-family: Tahoma,Geneva,sans-serif;
|
||||
font-size:0.9em;
|
||||
-webkit-transition: top 0.3s;
|
||||
transition: top 0.3s;
|
||||
position: relative;
|
||||
top:0;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel ul
|
||||
{ list-style: none;
|
||||
padding: 0 0 0 20px;
|
||||
overflow: hidden;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/** Customize checkbox
|
||||
*/
|
||||
.ol-layerswitcher input[type="radio"],
|
||||
.ol-layerswitcher input[type="checkbox"]
|
||||
{ display:none;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel li
|
||||
{ -weblit-transition: -webkit-transform 0.2s linear;
|
||||
transition: transform 0.2s linear;
|
||||
clear: both;
|
||||
display: block;
|
||||
#border:1px solid transparent;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* drag and drop */
|
||||
.ol-layerswitcher .panel li.drag
|
||||
{ opacity: 0.5;
|
||||
transform:scale(0.8);
|
||||
-webkit-transform:scale(0.8);
|
||||
}
|
||||
.ol-dragover
|
||||
{ background:rgba(51,102,153,0.5);
|
||||
opacity:0.8;
|
||||
}
|
||||
.ol-layerswitcher .panel li.forbidden,
|
||||
.forbidden .ol-layerswitcher-buttons div,
|
||||
.forbidden .layerswitcher-opacity div
|
||||
{ background:rgba(255,0,0,0.5);
|
||||
color:#f00!important;
|
||||
}
|
||||
|
||||
/* cursor management */
|
||||
.ol-layerswitcher.drag,
|
||||
.ol-layerswitcher.drag *
|
||||
{ cursor:not-allowed!important;
|
||||
cursor:no-drop!important;
|
||||
}
|
||||
.ol-layerswitcher.drag .panel li.dropover,
|
||||
.ol-layerswitcher.drag .panel li.dropover *
|
||||
{ cursor: pointer!important;
|
||||
cursor: n-resize!important;
|
||||
cursor: ns-resize!important;
|
||||
cursor: grab!important;
|
||||
cursor: grabbing!important;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel li.dropover
|
||||
{ background: rgba(51, 102, 153, 0.5);
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel li label
|
||||
{ display: inline-block;
|
||||
height: 1.4em;
|
||||
max-width: 12em;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0 0.2em 0 1.7em;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ol-layerswitcher [type="radio"] + label:before,
|
||||
.ol-layerswitcher [type="checkbox"] + label:before,
|
||||
.ol-layerswitcher [type="radio"]:checked + label:after,
|
||||
.ol-layerswitcher [type="checkbox"]:checked + label:after
|
||||
{ content: '';
|
||||
position: absolute;
|
||||
left: 0.1em; top: 0.1em;
|
||||
width: 1.2em; height: 1.2em;
|
||||
border: 2px solid #369;
|
||||
background: #fff;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
|
||||
.ol-layerswitcher [type="radio"] + label:before,
|
||||
.ol-layerswitcher [type="radio"] + label:after
|
||||
{ border-radius: 50%;
|
||||
}
|
||||
|
||||
.ol-layerswitcher [type="radio"]:checked + label:after
|
||||
{ background: #369 none repeat scroll 0 0;
|
||||
margin: 0.3em;
|
||||
width: 0.6em;
|
||||
height: 0.6em;
|
||||
}
|
||||
|
||||
.ol-layerswitcher [type="checkbox"]:checked + label:after
|
||||
{ background: transparent;
|
||||
border-width: 0 3px 3px 0;
|
||||
border-style: solid;
|
||||
border-color: #369;
|
||||
width: 0.7em;
|
||||
height: 1em;
|
||||
-webkit-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
left: 0.55em;
|
||||
top: -0.05em;
|
||||
box-shadow: 1px 0px 1px 1px #fff;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel li.ol-layer-hidden
|
||||
{ opacity: 0.6;
|
||||
}
|
||||
|
||||
.ol-layerswitcher.ol-collapsed .panel
|
||||
{ display:none;
|
||||
}
|
||||
.ol-layerswitcher.ol-forceopen .panel
|
||||
{ display:block;
|
||||
}
|
||||
|
||||
.ol-layerswitcher button
|
||||
{ background-color: white;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
float: right;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
z-index: 10;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-buttons
|
||||
{ display:block;
|
||||
float: right;
|
||||
text-align:right;
|
||||
}
|
||||
.ol-layerswitcher-buttons > div
|
||||
{ display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height:1em;
|
||||
width:1em;
|
||||
margin:2px;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .panel li > div
|
||||
{ display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* line break */
|
||||
.ol-layerswitcher .ol-separator
|
||||
{ display:block;
|
||||
width:0;
|
||||
height:0;
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerup
|
||||
{ float: right;
|
||||
height:2.5em;
|
||||
background-color: #369;
|
||||
opacity: 0.5;
|
||||
cursor: move;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerup:before,
|
||||
.ol-layerswitcher .layerup:after
|
||||
{ border-color: #fff transparent;
|
||||
border-style: solid;
|
||||
border-width: 0.4em 0.4em 0;
|
||||
content: "";
|
||||
height: 0;
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
left: 0.1em;
|
||||
width: 0;
|
||||
}
|
||||
.ol-layerswitcher .layerup:after
|
||||
{ border-width: 0 0.4em 0.4em;
|
||||
top:3px;
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerInfo
|
||||
{ background: #369;
|
||||
border-radius: 100%;
|
||||
}
|
||||
.ol-layerswitcher .layerInfo:before
|
||||
{ color: #fff;
|
||||
content: "i";
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
width: 1.25em;
|
||||
position:absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerTrash
|
||||
{ background: #369;
|
||||
}
|
||||
.ol-layerswitcher .layerTrash:before
|
||||
{ color: #fff;
|
||||
content: "\00d7";
|
||||
font-size:1em;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
line-height: 1em;
|
||||
margin: -0.5em 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerExtent
|
||||
{ background: #369;
|
||||
}
|
||||
.ol-layerswitcher .layerExtent:before
|
||||
{ border-right: 1px solid #fff;
|
||||
border-bottom: 1px solid #fff;
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
right: 2px;
|
||||
top: 6px;
|
||||
bottom: 3px;
|
||||
}
|
||||
.ol-layerswitcher .layerExtent:after
|
||||
{ border-left: 1px solid #fff;
|
||||
border-top: 1px solid #fff;
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 2px;
|
||||
right: 6px;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .expend-layers,
|
||||
.ol-layerswitcher .collapse-layers
|
||||
{ margin: 0 2px;
|
||||
}
|
||||
.ol-layerswitcher .expend-layers:before,
|
||||
.ol-layerswitcher .collapse-layers:before
|
||||
{ content:"";
|
||||
position:absolute;
|
||||
top:50%;
|
||||
left:0;
|
||||
margin-top:-2px;
|
||||
height:4px;
|
||||
width:100%;
|
||||
background:#369;
|
||||
}
|
||||
.ol-layerswitcher .expend-layers:after
|
||||
{ content:"";
|
||||
position:absolute;
|
||||
left:50%;
|
||||
top:0;
|
||||
margin-left:-2px;
|
||||
width:4px;
|
||||
height:100%;
|
||||
background:#369;
|
||||
}
|
||||
/*
|
||||
.ol-layerswitcher .collapse-layers:before
|
||||
{ content:"";
|
||||
position:absolute;
|
||||
border:0.5em solid #369;
|
||||
border-color: #369 transparent transparent;
|
||||
margin-top:0.25em;
|
||||
}
|
||||
.ol-layerswitcher .expend-layers:before
|
||||
{ content:"";
|
||||
position:absolute;
|
||||
border:0.5em solid #369;
|
||||
border-color: transparent transparent transparent #369 ;
|
||||
margin-left:0.25em;
|
||||
}
|
||||
*/
|
||||
|
||||
.ol-layerswitcher .layerswitcher-opacity
|
||||
{ position:relative;
|
||||
border: 1px solid #369;
|
||||
height: 3px;
|
||||
width: 120px;
|
||||
margin:5px 1em 10px 7px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 3px;
|
||||
background: #69c;
|
||||
background: -webkit-linear-gradient(left, rgba(0,60,136,0), rgba(0,60,136,0.6));
|
||||
background: linear-gradient(to right, rgba(0,60,136,0), rgba(0,60,136,0.6));
|
||||
cursor: pointer;
|
||||
box-shadow: 1px 1px 1px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerswitcher-opacity .layerswitcher-opacity-cursor,
|
||||
.ol-layerswitcher .layerswitcher-opacity .layerswitcher-opacity-cursor:before
|
||||
{ position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background: rgba(0,60,136,0.5);
|
||||
border-radius: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 1;
|
||||
}
|
||||
.ol-layerswitcher .layerswitcher-opacity .layerswitcher-opacity-cursor:before
|
||||
{ content: "";
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
height: 50%;
|
||||
}
|
||||
.ol-touch .ol-layerswitcher .layerswitcher-opacity .layerswitcher-opacity-cursor
|
||||
{ width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerswitcher-opacity-label {
|
||||
display:none;
|
||||
position: absolute;
|
||||
right: -2.5em;
|
||||
bottom: 5px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.ol-layerswitcher .layerswitcher-opacity-label::after {
|
||||
content:"%";
|
||||
}
|
||||
|
||||
.ol-layerswitcher .layerswitcher-progress
|
||||
{ display:block;
|
||||
margin:-4px 1em 2px 7px;
|
||||
width: 120px;
|
||||
}
|
||||
.ol-layerswitcher .layerswitcher-progress div
|
||||
{ background-color: #369;
|
||||
height:2px;
|
||||
display:block;
|
||||
width:0;
|
||||
}
|
||||
691
build/control/LayerSwitcher.js
Normal file
691
build/control/LayerSwitcher.js
Normal file
@ -0,0 +1,691 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_layer_Tile from 'ol/layer/tile'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_layer_VectorTile from 'ol/layer/vectortile'
|
||||
import ol_layer_Image from 'ol/layer/image'
|
||||
import ol_layer_Heatmap from 'ol/layer/heatmap'
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc OpenLayers 3 Layer Switcher Control.
|
||||
* @require jQuery
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} Control options.
|
||||
* @param {boolean} options.show_progress show a progress bar on tile layers, default false
|
||||
* - mouseover {boolean} show the panel on mouseover, default false
|
||||
* - reordering {boolean} allow layer reordering, default true
|
||||
* - trash {boolean} add a trash button to delete the layer, default false
|
||||
* - oninfo {function} callback on click on info button, if none no info button is shown
|
||||
* - extent {boolean} add an extent button to zoom to the extent of the layer
|
||||
* - onextent {function} callback when click on extent, default fits view to extent
|
||||
*
|
||||
* Layers attributes that control the switcher
|
||||
* - allwaysOnTop {boolean} true to force layer stay on top of the others while reordering, default false
|
||||
* - displayInLayerSwitcher {boolean} display in switcher, default true
|
||||
* - noSwitcherDelete {boolean} to prevent layer deletion (w. trash option), default false
|
||||
*/
|
||||
var ol_control_LayerSwitcher = function(opt_options)
|
||||
{ var options = opt_options || {};
|
||||
var self = this;
|
||||
this.dcount = 0;
|
||||
this.show_progress = options.show_progress;
|
||||
this.oninfo = (typeof (options.oninfo) == "function" ? options.oninfo: null);
|
||||
this.onextent = (typeof (options.onextent) == "function" ? options.onextent: null);
|
||||
this.hasextent = options.extent || options.onextent;
|
||||
this.hastrash = options.trash;
|
||||
this.reordering = (options.reordering!==false);
|
||||
|
||||
var element;
|
||||
if (options.target)
|
||||
{ element = $("<div>").addClass(options.switcherClass || "ol-layerswitcher");
|
||||
}
|
||||
else
|
||||
{ element = $("<div>").addClass((options.switcherClass || 'ol-layerswitcher') +' ol-unselectable ol-control ol-collapsed');
|
||||
|
||||
this.button = $("<button>")
|
||||
.attr('type','button')
|
||||
.on("touchstart", function(e)
|
||||
{ element.toggleClass("ol-collapsed");
|
||||
e.preventDefault();
|
||||
self.overflow();
|
||||
})
|
||||
.click (function()
|
||||
{ element.toggleClass("ol-forceopen").addClass("ol-collapsed");
|
||||
self.overflow();
|
||||
})
|
||||
.appendTo(element);
|
||||
if (options.mouseover)
|
||||
{ $(element).mouseleave (function(){ element.addClass("ol-collapsed"); })
|
||||
.mouseover(function(){ element.removeClass("ol-collapsed"); });
|
||||
}
|
||||
this.topv = $("<div>").addClass("ol-switchertopdiv")
|
||||
.click(function(){ self.overflow("+50%"); })
|
||||
.appendTo(element);
|
||||
this.botv = $("<div>").addClass("ol-switcherbottomdiv")
|
||||
.click(function(){ self.overflow("-50%"); })
|
||||
.appendTo(element);
|
||||
}
|
||||
this.panel_ = $("<ul>").addClass("panel")
|
||||
.appendTo(element);
|
||||
this.panel_.on ('mousewheel DOMMouseScroll onmousewheel', function(e)
|
||||
{ if (self.overflow(Math.max(-1, Math.min(1, (e.originalEvent.wheelDelta || -e.originalEvent.detail)))))
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
this.header_ = $("<li>").addClass("ol-header").appendTo(this.panel_);
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
// Enable jQuery dataTransfert
|
||||
// $.event.props.push('dataTransfer');
|
||||
this.target = options.target;
|
||||
|
||||
};
|
||||
ol.inherits(ol_control_LayerSwitcher, ol_control_Control);
|
||||
|
||||
|
||||
/** List of tips
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.tip =
|
||||
{ up: "up/down",
|
||||
down: "down",
|
||||
info: "informations...",
|
||||
extent: "zoom to extent",
|
||||
trash: "remove layer",
|
||||
plus: "expand/shrink"
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map instance the control is associated with.
|
||||
* @param {_ol_Map_} map The map instance.
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.setMap = function(map)
|
||||
{ ol_control_Control.prototype.setMap.call(this, map);
|
||||
this.drawPanel();
|
||||
|
||||
if (this.map_)
|
||||
{ this.map_.getLayerGroup().un('change', this.drawPanel, this);
|
||||
this.map_.un('moveend', this.viewChange, this);
|
||||
this.map_.un('change:size', this.overflow, this);
|
||||
// console.log("remove");
|
||||
}
|
||||
|
||||
this.map_ = map;
|
||||
// Get change (new layer added or removed)
|
||||
if (map)
|
||||
{ map.getLayerGroup().on('change', this.drawPanel, this);
|
||||
map.on('moveend', this.viewChange, this);
|
||||
map.on('change:size', this.overflow, this);
|
||||
}
|
||||
};
|
||||
|
||||
/** Add a custom header
|
||||
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.setHeader = function(html)
|
||||
{ this.header_.html(html);
|
||||
};
|
||||
|
||||
/** Calculate overflow and add scrolls
|
||||
* @param {Number} dir scroll direction -1|0|1|'+50%'|'-50%'
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.overflow = function(dir)
|
||||
{
|
||||
if (this.button)
|
||||
{ // Nothing to show
|
||||
if (this.panel_.css('display')=='none')
|
||||
{ $(this.element).css("height", "auto");
|
||||
return;
|
||||
}
|
||||
// Calculate offset
|
||||
var h = $(this.element).outerHeight();
|
||||
var hp = this.panel_.outerHeight();
|
||||
var dh = this.button.position().top + this.button.outerHeight(true);
|
||||
var top = this.panel_.position().top-dh;
|
||||
if (hp > h-dh)
|
||||
{ // Bug IE: need to have an height defined
|
||||
$(this.element).css("height", "100%");
|
||||
switch (dir)
|
||||
{ case 1: top += 2*$("li.visible .li-content",this.panel_).height(); break;
|
||||
case -1: top -= 2*$("li.visible .li-content",this.panel_).height(); break;
|
||||
case "+50%": top += Math.round(h/2); break;
|
||||
case "-50%": top -= Math.round(h/2); break;
|
||||
default: break;
|
||||
}
|
||||
// Scroll div
|
||||
if (top+hp <= h-3*dh/2)
|
||||
{ top = h-3*dh/2-hp;
|
||||
this.botv.hide();
|
||||
}
|
||||
else
|
||||
{ this.botv.css("display","");//show();
|
||||
}
|
||||
if (top >= 0)
|
||||
{ top = 0;
|
||||
this.topv.hide();
|
||||
}
|
||||
else
|
||||
{ this.topv.css("display","");
|
||||
}
|
||||
// Scroll ?
|
||||
this.panel_.css('top', top+"px");
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ $(this.element).css("height", "auto");
|
||||
this.panel_.css('top', "0px");
|
||||
this.botv.hide();
|
||||
this.topv.hide();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* On view change hide layer depending on resolution / extent
|
||||
* @param {ol.event} map The map instance.
|
||||
* @private
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.viewChange = function(e)
|
||||
{
|
||||
var map = this.map_;
|
||||
var res = this.map_.getView().getResolution();
|
||||
$("li", this.panel_).each(function()
|
||||
{ var l = $(this).data('layer');
|
||||
if (l)
|
||||
{ if (l.getMaxResolution()<=res || l.getMinResolution()>=res) $(this).addClass("ol-layer-hidden");
|
||||
else
|
||||
{ var ex0 = l.getExtent();
|
||||
if (ex0)
|
||||
{ var ex = map.getView().calculateExtent(map.getSize());
|
||||
if (!ol.extent.intersects(ex, ex0))
|
||||
{ $(this).addClass("ol-layer-hidden");
|
||||
}
|
||||
else $(this).removeClass("ol-layer-hidden");
|
||||
}
|
||||
else $(this).removeClass("ol-layer-hidden");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the panel control (prevent multiple draw due to layers manipulation on the map with a delay function)
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.drawPanel = function(e)
|
||||
{
|
||||
if (!this.getMap()) return;
|
||||
var self = this;
|
||||
// Multiple event simultaneously / draw once => put drawing in the event queue
|
||||
this.dcount++;
|
||||
setTimeout (function(){ self.drawPanel_(); }, 0);
|
||||
}
|
||||
|
||||
/** Delayed draw panel control
|
||||
* @private
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.drawPanel_ = function(e)
|
||||
{ if (--this.dcount || this.dragging_) return;
|
||||
$("li", this.panel_).not(".ol-header").remove();
|
||||
this.drawList (this.panel_, this.getMap().getLayers());
|
||||
}
|
||||
|
||||
/** Change layer visibility according to the baselayer option
|
||||
* @param {ol.layer}
|
||||
* @param {Array<ol.layer>} related layers
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.switchLayerVisibility = function(l, layers)
|
||||
{
|
||||
if (!l.get('baseLayer')) l.setVisible(!l.getVisible());
|
||||
else
|
||||
{ if (!l.getVisible()) l.setVisible(true);
|
||||
layers.forEach(function(li)
|
||||
{ if (l!==li && li.get('baseLayer') && li.getVisible()) li.setVisible(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if layer is on the map (depending on zoom and extent)
|
||||
* @param {ol.layer}
|
||||
* @return {boolean}
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.testLayerVisibility = function(layer)
|
||||
{
|
||||
if (this.map_)
|
||||
{ var res = this.map_.getView().getResolution();
|
||||
if (layer.getMaxResolution()<=res || layer.getMinResolution()>=res) return false;
|
||||
else
|
||||
{ var ex0 = layer.getExtent();
|
||||
if (ex0)
|
||||
{ var ex = this.map_.getView().calculateExtent(this.map_.getSize());
|
||||
return ol.extent.intersects(ex, ex0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/** Start ordering the list
|
||||
* @param {event} e drag event
|
||||
* @private
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.dragOrdering_ = function(e)
|
||||
{ var drag = e.data;
|
||||
switch (e.type)
|
||||
{ // Start ordering
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var pageY = e.pageY
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageY)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageY);
|
||||
drag =
|
||||
{ self: drag.self,
|
||||
elt: $(e.currentTarget).closest("li"),
|
||||
start: true,
|
||||
element: drag.self.element,
|
||||
panel: drag.self.panel_,
|
||||
pageY: pageY
|
||||
};
|
||||
drag.elt.parent().addClass('drag');
|
||||
$(document).on("mouseup mousemove touchend touchcancel touchmove", drag, drag.self.dragOrdering_);
|
||||
break;
|
||||
}
|
||||
// Stop ordering
|
||||
case 'touchcancel':
|
||||
case 'touchend':
|
||||
case 'mouseup':
|
||||
{ if (drag.target)
|
||||
{ // Get drag on parent
|
||||
var drop = drag.layer;
|
||||
var target = drag.target;
|
||||
if (drop && target)
|
||||
{ var collection ;
|
||||
if (drag.group) collection = drag.group.getLayers();
|
||||
else collection = drag.self.getMap().getLayers();
|
||||
var layers = collection.getArray();
|
||||
// Switch layers
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ if (layers[i]==drop)
|
||||
{ collection.removeAt (i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var j=0; j<layers.length; j++)
|
||||
{ if (layers[j]==target)
|
||||
{ if (i>j) collection.insertAt (j,drop);
|
||||
else collection.insertAt (j+1,drop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$("li",drag.elt.parent()).removeClass("dropover dropover-after dropover-before");
|
||||
drag.elt.removeClass("drag");
|
||||
drag.elt.parent().removeClass("drag");
|
||||
$(drag.element).removeClass('drag');
|
||||
if (drag.div) drag.div.remove();
|
||||
|
||||
$(document).off("mouseup mousemove touchend touchcancel touchmove", drag.self.dragOrdering_);
|
||||
break;
|
||||
}
|
||||
// Ordering
|
||||
case 'mousemove':
|
||||
case 'touchmove':
|
||||
{ // First drag (more than 2 px) => show drag element (ghost)
|
||||
var pageY = e.pageY
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageY)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageY);
|
||||
if (drag.start && Math.abs(drag.pageY - pageY) > 2)
|
||||
{ drag.start = false;
|
||||
drag.elt.addClass("drag");
|
||||
drag.layer = drag.elt.data('layer');
|
||||
drag.target = false;
|
||||
drag.group = drag.elt.parent().parent().data('layer');
|
||||
// Ghost div
|
||||
drag.div = $("<li>").appendTo(drag.panel);
|
||||
drag.div.css ({ position: "absolute", "z-index":10000, left:drag.elt.position().left, opacity:0.5 })
|
||||
.html($(drag.elt).html())
|
||||
.addClass("ol-dragover")
|
||||
.width(drag.elt.outerWidth())
|
||||
.height(drag.elt.height());
|
||||
$(drag.element).addClass('drag');
|
||||
}
|
||||
if (!drag.start)
|
||||
{ e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Ghost div
|
||||
drag.div.css ({ top:pageY - drag.panel.offset().top + drag.panel.scrollTop() +5 });
|
||||
|
||||
var li;
|
||||
if (e.pageX) li = $(e.target);
|
||||
else li = $(document.elementFromPoint(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY));
|
||||
if (li.hasClass("ol-switcherbottomdiv"))
|
||||
{ drag.self.overflow(-1);
|
||||
console.log('bottom')
|
||||
}
|
||||
else if (li.hasClass("ol-switchertopdiv"))
|
||||
{ drag.self.overflow(1);
|
||||
}
|
||||
if (!li.is("li")) li = li.closest("li");
|
||||
if (!li.hasClass('dropover')) $("li", drag.elt.parent()).removeClass("dropover dropover-after dropover-before");
|
||||
if (li.parent().hasClass('drag') && li.get(0) !== drag.elt.get(0))
|
||||
{ var target = li.data("layer");
|
||||
// Don't mix layer level
|
||||
if (target && !target.get("allwaysOnTop") == !drag.layer.get("allwaysOnTop"))
|
||||
{ li.addClass("dropover");
|
||||
li.addClass((drag.elt.position().top < li.position().top)?"dropover-after":"dropover-before");
|
||||
drag.target = target;
|
||||
}
|
||||
else
|
||||
{ drag.target = false;
|
||||
}
|
||||
drag.div.show();
|
||||
}
|
||||
else
|
||||
{ drag.target = false;
|
||||
if (li.get(0) === drag.elt.get(0)) drag.div.hide();
|
||||
else drag.div.show();
|
||||
}
|
||||
|
||||
if (!drag.target) drag.div.addClass("forbidden");
|
||||
else drag.div.removeClass("forbidden");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Change opacity on drag
|
||||
* @param {event} e drag event
|
||||
* @private
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.dragOpacity_ = function(e)
|
||||
{ var drag = e.data;
|
||||
switch (e.type)
|
||||
{ // Start opacity
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
drag.start = e.pageX
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageX)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageX);
|
||||
drag.elt = $(e.target);
|
||||
drag.layer = drag.elt.closest("li").data('layer')
|
||||
drag.self.dragging_ = true;
|
||||
$(document).on("mouseup touchend mousemove touchmove touchcancel", drag, drag.self.dragOpacity_);
|
||||
break;
|
||||
}
|
||||
// Stop opacity
|
||||
case 'touchcancel':
|
||||
case 'touchend':
|
||||
case 'mouseup':
|
||||
{ $(document).off("mouseup touchend mousemove touchmove touchcancel", drag.self.dragOpacity_);
|
||||
drag.layer.setOpacity(drag.opacity);
|
||||
drag.elt.parent().next().text(Math.round(drag.opacity*100));
|
||||
drag.self.dragging_ = false;
|
||||
drag = false;
|
||||
break;
|
||||
}
|
||||
// Move opcaity
|
||||
default:
|
||||
{ var x = e.pageX
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageX)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageX);
|
||||
var dx = Math.max ( 0, Math.min( 1, (x - drag.elt.parent().offset().left) / drag.elt.parent().width() ));
|
||||
drag.elt.css("left", (dx*100)+"%");
|
||||
drag.elt.parent().next().text(Math.round(drag.opacity*100));
|
||||
drag.opacity = dx;
|
||||
drag.layer.setOpacity(dx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Render a list of layer
|
||||
* @param {elt} element to render
|
||||
* @layers {Array{ol.layer}} list of layer to show
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.drawList = function(ul, collection)
|
||||
{ var self = this;
|
||||
var layers = collection.getArray();
|
||||
var setVisibility = function(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var l = $(this).parent().parent().data("layer");
|
||||
self.switchLayerVisibility(l,collection);
|
||||
};
|
||||
function moveLayer (l, layers, inc)
|
||||
{
|
||||
for (var i=0; i<layers.getLength(); i++)
|
||||
{ if (layers.item(i) === l)
|
||||
{ layers.remove(l);
|
||||
layers.insertAt(i+inc, l);
|
||||
return true;
|
||||
}
|
||||
if (layers.item(i).getLayers && moveLayer (l, layers.item(i).getLayers(), inc)) return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
function moveLayerUp(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
moveLayer($(this).closest('li').data("layer"), self.map_.getLayers(), +1);
|
||||
};
|
||||
function moveLayerDown(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
moveLayer($(this).closest('li').data("layer"), self.map_.getLayers(), -1);
|
||||
};
|
||||
function onInfo(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
self.oninfo($(this).closest('li').data("layer"));
|
||||
};
|
||||
function zoomExtent(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (self.onextent) self.onextent($(this).closest('li').data("layer"));
|
||||
else self.map_.getView().fit ($(this).closest('li').data("layer").getExtent(), self.map_.getSize());
|
||||
};
|
||||
function removeLayer(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var li = $(this).closest("ul").parent();
|
||||
if (li.data("layer"))
|
||||
{ li.data("layer").getLayers().remove($(this).closest('li').data("layer"));
|
||||
if (li.data("layer").getLayers().getLength()==0 && !li.data("layer").get('noSwitcherDelete'))
|
||||
{ removeLayer.call($(".layerTrash", li), e);
|
||||
}
|
||||
}
|
||||
else self.map_.removeLayer($(this).closest('li').data("layer"));
|
||||
};
|
||||
|
||||
// Add the layer list
|
||||
for (var i=layers.length-1; i>=0; i--)
|
||||
{ var layer = layers[i];
|
||||
if (layer.get("displayInLayerSwitcher")===false) continue;
|
||||
|
||||
var li = $("<li>").addClass((layer.getVisible()?"visible ":" ")+(layer.get('baseLayer')?"baselayer":""))
|
||||
.data("layer",layer).appendTo(ul);
|
||||
|
||||
var layer_buttons = $("<div>").addClass("ol-layerswitcher-buttons").appendTo(li);
|
||||
|
||||
var d = $("<div>").addClass('li-content').appendTo(li);
|
||||
if (!this.testLayerVisibility(layer)) d.addClass("ol-layer-hidden");
|
||||
|
||||
// Visibility
|
||||
$("<input>")
|
||||
.attr('type', layer.get('baseLayer') ? 'radio' : 'checkbox')
|
||||
.attr("checked",layer.getVisible())
|
||||
.on ('click', setVisibility)
|
||||
.appendTo(d);
|
||||
// Label
|
||||
$("<label>").text(layer.get("title") || layer.get("name"))
|
||||
.attr('title', layer.get("title") || layer.get("name"))
|
||||
.on ('click', setVisibility)
|
||||
.attr('unselectable', 'on')
|
||||
.css('user-select', 'none')
|
||||
.on('selectstart', false)
|
||||
.appendTo(d);
|
||||
|
||||
// up/down
|
||||
if (this.reordering)
|
||||
{ if ( (i<layers.length-1 && (layer.get("allwaysOnTop") || !layers[i+1].get("allwaysOnTop")) )
|
||||
|| (i>0 && (!layer.get("allwaysOnTop") || layers[i-1].get("allwaysOnTop")) ) )
|
||||
{ $("<div>").addClass("layerup")
|
||||
.on ("mousedown touchstart", {self:this}, this.dragOrdering_ )
|
||||
.attr("title", this.tip.up)
|
||||
.appendTo(layer_buttons);
|
||||
}
|
||||
}
|
||||
|
||||
// Show/hide sub layers
|
||||
if (layer.getLayers)
|
||||
{ var nb = 0;
|
||||
layer.getLayers().forEach(function(l)
|
||||
{ if (l.get('displayInLayerSwitcher')!==false) nb++;
|
||||
});
|
||||
if (nb)
|
||||
{ $("<div>").addClass(layer.get("openInLayerSwitcher") ? "collapse-layers" : "expend-layers" )
|
||||
.click(function()
|
||||
{ var l = $(this).closest('li').data("layer");
|
||||
l.set("openInLayerSwitcher", !l.get("openInLayerSwitcher") )
|
||||
})
|
||||
.attr("title", this.tip.plus)
|
||||
.appendTo(layer_buttons);
|
||||
}
|
||||
}
|
||||
|
||||
// $("<div>").addClass("ol-separator").appendTo(layer_buttons);
|
||||
|
||||
// Info button
|
||||
if (this.oninfo)
|
||||
{ $("<div>").addClass("layerInfo")
|
||||
.on ('click', onInfo)
|
||||
.attr("title", this.tip.info)
|
||||
.appendTo(layer_buttons);
|
||||
}
|
||||
// Layer remove
|
||||
if (this.hastrash && !layer.get("noSwitcherDelete"))
|
||||
{ $("<div>").addClass("layerTrash")
|
||||
.on ('click', removeLayer)
|
||||
.attr("title", this.tip.trash)
|
||||
.appendTo(layer_buttons);
|
||||
}
|
||||
// Layer extent
|
||||
if (this.hasextent && layers[i].getExtent())
|
||||
{ var ex = layers[i].getExtent();
|
||||
if (ex.length==4 && ex[0]<ex[2] && ex[1]<ex[3])
|
||||
{ $("<div>").addClass("layerExtent")
|
||||
.on ('click', zoomExtent)
|
||||
.attr("title", this.tip.extent)
|
||||
.appendTo(layer_buttons);
|
||||
}
|
||||
}
|
||||
|
||||
// Progress
|
||||
if (this.show_progress && layer instanceof ol_layer_Tile)
|
||||
{ var p = $("<div>")
|
||||
.addClass("layerswitcher-progress")
|
||||
.appendTo(d);
|
||||
this.setprogress_(layer);
|
||||
layer.layerswitcher_progress = $("<div>").appendTo(p);
|
||||
}
|
||||
|
||||
// Opacity
|
||||
var opacity = $("<div>").addClass("layerswitcher-opacity")
|
||||
.on("click", function(e)
|
||||
{ e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var x = e.pageX
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageX)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageX);
|
||||
var dx = Math.max ( 0, Math.min( 1, (x - $(this).offset().left) / $(this).width() ));
|
||||
$(this).closest("li").data('layer').setOpacity(dx);
|
||||
})
|
||||
.appendTo(d);
|
||||
$("<div>").addClass("layerswitcher-opacity-cursor")
|
||||
.on("mousedown touchstart", { self: this }, self.dragOpacity_ )
|
||||
.css ('left', (layer.getOpacity()*100)+"%")
|
||||
.appendTo(opacity);
|
||||
// Percent
|
||||
$("<div>").addClass("layerswitcher-opacity-label")
|
||||
.text(Math.round(layer.getOpacity()*100))
|
||||
.appendTo(d);
|
||||
|
||||
// Layer group
|
||||
if (layer.getLayers)
|
||||
{ li.addClass('ol-layer-group');
|
||||
if (layer.get("openInLayerSwitcher")===true)
|
||||
{ this.drawList ($("<ul>").appendTo(li), layer.getLayers());
|
||||
}
|
||||
}
|
||||
else if (layer instanceof ol_layer_Vector) li.addClass('ol-layer-vector');
|
||||
else if (layer instanceof ol_layer_VectorTile) li.addClass('ol-layer-vector');
|
||||
else if (layer instanceof ol_layer_Tile) li.addClass('ol-layer-tile');
|
||||
else if (layer instanceof ol_layer_Image) li.addClass('ol-layer-image');
|
||||
else if (layer instanceof ol_layer_Heatmap) li.addClass('ol-layer-heatmap');
|
||||
}
|
||||
|
||||
if (ul==this.panel_) this.overflow();
|
||||
};
|
||||
|
||||
/** Handle progress bar for a layer
|
||||
* @private
|
||||
*/
|
||||
ol_control_LayerSwitcher.prototype.setprogress_ = function(layer)
|
||||
{
|
||||
if (!layer.layerswitcher_progress)
|
||||
{ var loaded = 0;
|
||||
var loading = 0;
|
||||
function draw()
|
||||
{ if (loading === loaded)
|
||||
{ loading = loaded = 0;
|
||||
layer.layerswitcher_progress.width(0);
|
||||
}
|
||||
else
|
||||
{ layer.layerswitcher_progress.css('width', (loaded / loading * 100).toFixed(1) + '%');
|
||||
}
|
||||
}
|
||||
layer.getSource().on('tileloadstart', function()
|
||||
{ loading++;
|
||||
draw();
|
||||
});
|
||||
layer.getSource().on('tileloadend', function()
|
||||
{ loaded++;
|
||||
draw();
|
||||
});
|
||||
layer.getSource().on('tileloaderror', function()
|
||||
{ loaded++;
|
||||
draw();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ol_control_LayerSwitcher
|
||||
100
build/control/LayerSwitcherImage.css
Normal file
100
build/control/LayerSwitcherImage.css
Normal file
@ -0,0 +1,100 @@
|
||||
.ol-control.ol-layerswitcher-image
|
||||
{ position: absolute;
|
||||
right: 0.5em;
|
||||
text-align: left;
|
||||
top: 1em;
|
||||
transition: all 0.2s ease 0s;
|
||||
-webkit-transition: all 0.2s ease 0s;
|
||||
}
|
||||
.ol-control.ol-layerswitcher-image.ol-collapsed
|
||||
{ top:3em;
|
||||
transition: none;
|
||||
-webkit-transition: none;
|
||||
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image .panel
|
||||
{ list-style: none;
|
||||
padding: 0.25em;
|
||||
margin:0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image .panel ul
|
||||
{ list-style: none;
|
||||
padding: 0 0 0 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image.ol-collapsed .panel
|
||||
{ display:none;
|
||||
}
|
||||
.ol-layerswitcher-image.ol-forceopen .panel
|
||||
{ display:block;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image button
|
||||
{ background-color: white;
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==");
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
float: right;
|
||||
height: 38px;
|
||||
width: 38px;
|
||||
display:none;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image.ol-collapsed button
|
||||
{ display:block;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image li
|
||||
{ border-radius: 4px;
|
||||
border: 3px solid transparent;
|
||||
box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);
|
||||
display: inline-block;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin:2px;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
cursor:pointer;
|
||||
}
|
||||
.ol-layerswitcher-image li.ol-layer-hidden
|
||||
{ opacity: 0.5;
|
||||
border-color:#555;
|
||||
}
|
||||
.ol-layerswitcher-image li.ol-header
|
||||
{ display: none;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image li img
|
||||
{ position:absolute;
|
||||
max-width:100%;
|
||||
}
|
||||
.ol-layerswitcher-image li.select
|
||||
{ border: 3px solid red;
|
||||
}
|
||||
|
||||
.ol-layerswitcher-image li p
|
||||
{ display:none;
|
||||
}
|
||||
.ol-layerswitcher-image li:hover p
|
||||
{ background-color: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
bottom: 0;
|
||||
display: block;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
height:1.2em;
|
||||
font-family:Verdana, Geneva, sans-serif;
|
||||
font-size:0.8em;
|
||||
}
|
||||
68
build/control/LayerSwitcherImage.js
Normal file
68
build/control/LayerSwitcherImage.js
Normal file
@ -0,0 +1,68 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_LayerSwitcher from './LayerSwitcher'
|
||||
|
||||
/**
|
||||
* @classdesc OpenLayers 3 Layer Switcher Control.
|
||||
* @require layer.getPreview
|
||||
* @require jQuery
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_LayerSwitcher}
|
||||
* @param {Object=} options Control options.
|
||||
*/
|
||||
var ol_control_LayerSwitcherImage = function(options)
|
||||
{ options = options || {};
|
||||
options.switcherClass="ol-layerswitcher-image";
|
||||
if (options.mouseover!==false) options.mouseover=true;
|
||||
ol_control_LayerSwitcher.call(this, options);
|
||||
};
|
||||
ol.inherits(ol_control_LayerSwitcherImage, ol_control_LayerSwitcher);
|
||||
|
||||
/** Render a list of layer
|
||||
* @param {elt} element to render
|
||||
* @layers {Array{ol.layer}} list of layer to show
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_LayerSwitcherImage.prototype.drawList = function(ul, layers)
|
||||
{ var self = this;
|
||||
|
||||
var setVisibility = function(e)
|
||||
{ e.preventDefault();
|
||||
var l = $(this).data("layer");
|
||||
self.switchLayerVisibility(l,layers);
|
||||
if (e.type=="touchstart") $(self.element).addClass("ol-collapsed");
|
||||
};
|
||||
|
||||
ul.css("height","auto");
|
||||
|
||||
layers.forEach(function(layer)
|
||||
{ if (layer.get("displayInLayerSwitcher")!==false)
|
||||
{ var prev = layer.getPreview ? layer.getPreview() : ["none"];
|
||||
var d = $("<li>").addClass("ol-imgcontainer")
|
||||
.data ('layer', layer)
|
||||
.click (setVisibility)
|
||||
.on ("touchstart", setVisibility);
|
||||
if (layer.getVisible()) d.addClass("select");
|
||||
for (var k=0; k<prev.length; k++)
|
||||
{ $("<img>").attr('src', prev[k])
|
||||
.appendTo(d);
|
||||
}
|
||||
$("<p>").text(layer.get("title") || layer.get("name")).appendTo(d);
|
||||
|
||||
if (self.testLayerVisibility(layer)) d.addClass("ol-layer-hidden");
|
||||
d.appendTo(ul);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/** Disable overflow
|
||||
*/
|
||||
ol_control_LayerSwitcherImage.prototype.overflow = function(){};
|
||||
|
||||
export default ol_control_LayerSwitcherImage
|
||||
117
build/control/Overlay.css
Normal file
117
build/control/Overlay.css
Normal file
@ -0,0 +1,117 @@
|
||||
.ol-overlay
|
||||
{ position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width:100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
padding: 1em;
|
||||
color: #fff;
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
opacity: 0;
|
||||
display: none;
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
-webkit-transition: all 0.5s;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
|
||||
.ol-overlay.slide-up
|
||||
{ transform: translateY(100%);
|
||||
-webkit-transform: translateY(100%);
|
||||
}
|
||||
.ol-overlay.slide-down
|
||||
{ -webkit-transform: translateY(-100%);
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
.ol-overlay.slide-left
|
||||
{ -webkit-transform: translateX(-100%);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
.ol-overlay.slide-right
|
||||
{ -webkit-transform: translateX(100%);
|
||||
transform: translateX(100%);
|
||||
}
|
||||
.ol-overlay.zoom
|
||||
{ top: 50%;
|
||||
left: 50%;
|
||||
opacity:0.5;
|
||||
-webkit-transform: translate(-50%,-50%) scale(0);
|
||||
transform: translate(-50%,-50%) scale(0);
|
||||
}
|
||||
.ol-overlay.zoomout
|
||||
{ -webkit-transform: scale(3);
|
||||
transform: scale(3);
|
||||
}
|
||||
.ol-overlay.zoomrotate
|
||||
{ top: 50%;
|
||||
left: 50%;
|
||||
opacity:0.5;
|
||||
-webkit-transform: translate(-50%,-50%) scale(0) rotate(360deg);
|
||||
transform: translate(-50%,-50%) scale(0) rotate(360deg);
|
||||
}
|
||||
.ol-overlay.stretch
|
||||
{ top: 50%;
|
||||
left: 50%;
|
||||
opacity:0.5;
|
||||
-webkit-transform: translate(-50%,-50%) scaleX(0);
|
||||
transform: translate(-50%,-50%) scaleX(0) ;
|
||||
}
|
||||
.ol-overlay.stretchy
|
||||
{ top: 50%;
|
||||
left: 50%;
|
||||
opacity:0.5;
|
||||
-webkit-transform: translate(-50%,-50%) scaleY(0);
|
||||
transform: translate(-50%,-50%) scaleY(0) ;
|
||||
}
|
||||
.ol-overlay.wipe
|
||||
{ opacity: 1;
|
||||
/* clip: must be set programmatically */
|
||||
/* clip-path: use % but not crossplatform (IE) */
|
||||
}
|
||||
.ol-overlay.flip
|
||||
{ -webkit-transform: perspective(600px) rotateY(180deg);
|
||||
transform: perspective(600px) rotateY(180deg);
|
||||
}
|
||||
.ol-overlay.card
|
||||
{ opacity: 0.5;
|
||||
-webkit-transform: translate(-80%, 100%) rotate(-0.5turn);
|
||||
transform: translate(-80%, 100%) rotate(-0.5turn);
|
||||
}
|
||||
.ol-overlay.book
|
||||
{ -webkit-transform: perspective(600px) rotateY(-180deg) scaleX(0.6);
|
||||
transform: perspective(600px) rotateY(-180deg) scaleX(0.6) ;
|
||||
-webkit-transform-origin: 10% 50%;
|
||||
transform-origin: 10% 50%;
|
||||
}
|
||||
.ol-overlay.book.visible
|
||||
{ -webkit-transform-origin: 10% 50%;
|
||||
transform-origin: 10% 50%;
|
||||
}
|
||||
|
||||
.ol-overlay.ol-visible
|
||||
{ opacity:1;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
-webkit-transform: none;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.ol-overlay .ol-closebox
|
||||
{ position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
cursor: pointer;
|
||||
z-index:1;
|
||||
}
|
||||
.ol-overlay .ol-closebox:before
|
||||
{ content: "\274c";
|
||||
display: block;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
119
build/control/Overlay.js
Normal file
119
build/control/Overlay.js
Normal file
@ -0,0 +1,119 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** Control overlay for OL3
|
||||
* The overlay control is a control that display an overlay over the map
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fire change:visible
|
||||
* @param {Object=} options Control options.
|
||||
* - className {String} class of the control
|
||||
* - hideOnClick {bool} hide the control on click, default false
|
||||
* - closeBox {bool} add a closeBox to the control, default false
|
||||
*/
|
||||
var ol_control_Overlay = function(options)
|
||||
{ if (!options) options={};
|
||||
|
||||
var element = $("<div>").addClass('ol-unselectable ol-overlay');
|
||||
if (options.className) element.addClass(options.className);
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
var self = this;
|
||||
if (options.hideOnClick) element.click(function(){self.hide();});
|
||||
|
||||
this.set("closeBox", options.closeBox);
|
||||
|
||||
this._timeout = false;
|
||||
this.setContent (options.content);
|
||||
};
|
||||
ol.inherits(ol_control_Overlay, ol_control_Control);
|
||||
|
||||
/** Set the content of the overlay
|
||||
* @param {string} html the html to display in the control (or a jQuery object)
|
||||
*/
|
||||
ol_control_Overlay.prototype.setContent = function (html)
|
||||
{ var self = this;
|
||||
if (html)
|
||||
{ var elt = $(this.element);
|
||||
elt.html(html);
|
||||
if (this.get("closeBox"))
|
||||
{ var cb = $("<div>").addClass("ol-closebox")
|
||||
.click(function(){self.hide();});
|
||||
elt.prepend(cb);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Set the control visibility
|
||||
* @param {string} html the html to display in the control (or a jQuery object)
|
||||
* @param {ol.coordinate} coord coordinate of the top left corner of the control to start from
|
||||
*/
|
||||
ol_control_Overlay.prototype.show = function (html, coord)
|
||||
{ var self = this;
|
||||
var elt = $(this.element).show();
|
||||
if (coord)
|
||||
{ this.center_ = this.getMap().getPixelFromCoordinate(coord);
|
||||
elt.css({"top":this.center_[1], "left":this.center_[0] });
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Do fix from hkollmann pull request
|
||||
this.center_ = false;
|
||||
elt.css({"top":"", "left":"" });
|
||||
}
|
||||
this.setContent(html);
|
||||
if (this._timeout) clearTimeout(this._timeout);
|
||||
this._timeout = setTimeout(function()
|
||||
{ elt.addClass("ol-visible")
|
||||
.css({ "top":"", "left":"" });
|
||||
self.dispatchEvent({ type:'change:visible', visible:true, element: self.element });
|
||||
}, 10);
|
||||
self.dispatchEvent({ type:'change:visible', visible:false, element: self.element });
|
||||
};
|
||||
|
||||
/** Set the control visibility hidden
|
||||
*/
|
||||
ol_control_Overlay.prototype.hide = function ()
|
||||
{ var elt = $(this.element).removeClass("ol-visible");
|
||||
if (this.center_)
|
||||
{ elt.css({"top":this.center_[1], "left":this.center_[0] })
|
||||
this.center_ = false;
|
||||
}
|
||||
if (this._timeout) clearTimeout(this._timeout);
|
||||
this._timeout = setTimeout(function(){ elt.hide(); }, 500);
|
||||
this.dispatchEvent({ type:'change:visible', visible:false, element: this.element });
|
||||
};
|
||||
|
||||
/** Toggle control visibility
|
||||
*/
|
||||
ol_control_Overlay.prototype.toggle = function ()
|
||||
{ if (this.getVisible()) this.hide();
|
||||
else this.show();
|
||||
}
|
||||
|
||||
/** Get the control visibility
|
||||
* @return {boolean} b
|
||||
*/
|
||||
ol_control_Overlay.prototype.getVisible = function ()
|
||||
{ return ($(this.element).css('display') != 'none');
|
||||
};
|
||||
|
||||
/** Change class name
|
||||
* @param {String} className
|
||||
*/
|
||||
ol_control_Overlay.prototype.setClass = function (className)
|
||||
{ var vis = $(this.element).hasClass("ol-visible");
|
||||
$(this.element).removeClass().addClass('ol-unselectable ol-overlay'+(vis?" ol-visible ":" ")+className);
|
||||
};
|
||||
|
||||
export default ol_control_Overlay
|
||||
59
build/control/Overview.css
Normal file
59
build/control/Overview.css
Normal file
@ -0,0 +1,59 @@
|
||||
.ol-control.ol-overview
|
||||
{ position: absolute;
|
||||
left: 0.5em;
|
||||
text-align: left;
|
||||
bottom: 0.5em;
|
||||
}
|
||||
|
||||
.ol-control.ol-overview .panel
|
||||
{ display:block;
|
||||
width:150px;
|
||||
height:150px;
|
||||
margin:2px;
|
||||
background-color:#fff;
|
||||
border:1px solid #369;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ol-overview:not(.ol-collapsed) button
|
||||
{ position:absolute;
|
||||
bottom:2px;
|
||||
left:2px;
|
||||
z-index:2;
|
||||
}
|
||||
|
||||
.ol-control.ol-overview.ol-collapsed .panel
|
||||
{ display:none;
|
||||
}
|
||||
|
||||
.ol-overview.ol-collapsed button:before
|
||||
{ content:'\00bb';
|
||||
}
|
||||
.ol-overview button:before
|
||||
{ content:'\00ab';
|
||||
}
|
||||
|
||||
|
||||
.ol-control-right.ol-overview
|
||||
{ left: auto;
|
||||
right: 0.5em;
|
||||
}
|
||||
.ol-control-right.ol-overview:not(.ol-collapsed) button
|
||||
{ left:auto;
|
||||
right:2px;
|
||||
}
|
||||
.ol-control-right.ol-overview.ol-collapsed button:before
|
||||
{ content:'\00ab';
|
||||
}
|
||||
.ol-control-right.ol-overview button:before
|
||||
{ content:'\00bb';
|
||||
}
|
||||
|
||||
.ol-control-top.ol-overview
|
||||
{ bottom: auto;
|
||||
top: 5em;
|
||||
}
|
||||
.ol-control-top.ol-overview:not(.ol-collapsed) button
|
||||
{ bottom:auto;
|
||||
top:2px;
|
||||
}
|
||||
308
build/control/Overview.js
Normal file
308
build/control/Overview.js
Normal file
@ -0,0 +1,308 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_geom_Polygon from 'ol/geom/polygon'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
import ol_easing from 'ol/easing'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_View from 'ol/view'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_Feature from 'ol/feature'
|
||||
|
||||
//TODO: replace ol.animation.pan with new {ol_interaction_Interaction.pan}
|
||||
//import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
|
||||
/**
|
||||
* OpenLayers 3 Layer Overview Control.
|
||||
* The overview can rotate with map.
|
||||
* Zoom levels are configurable.
|
||||
* Click on the overview will center the map.
|
||||
* Change width/height of the overview trough css.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {ol.ProjectionLike} options.projection The projection. Default is EPSG:3857 (Spherical Mercator).
|
||||
* @param {Number} options.minZoom default 0
|
||||
* @param {Number} options.maxZoom default 18
|
||||
* @param {boolean} options.rotation enable rotation, default false
|
||||
* @param {top|bottom-left|right} options.align position
|
||||
* @param {Array<ol.layer>} options.layers list of layers
|
||||
* @param {ol.style.Style | Array.<ol.style.Style> | undefined} options.style style to draw the map extent on the overveiw
|
||||
* @param {bool|elastic} options.panAnimation use animation to center map on click, default true
|
||||
*/
|
||||
var ol_control_Overview = function(options)
|
||||
{ options = options || {};
|
||||
var self = this;
|
||||
|
||||
// API
|
||||
this.minZoom = options.minZoom || 0;
|
||||
this.maxZoom = options.maxZoom || 18;
|
||||
this.rotation = options.rotation;
|
||||
|
||||
var element;
|
||||
if (options.target)
|
||||
{ element = $("<div>");
|
||||
this.panel_ = $(options.target);
|
||||
}
|
||||
else
|
||||
{ element = $("<div>").addClass('ol-overview ol-unselectable ol-control ol-collapsed');
|
||||
if (/top/.test(options.align)) element.addClass('ol-control-top');
|
||||
if (/right/.test(options.align)) element.addClass('ol-control-right');
|
||||
$("<button>").on("touchstart", function(e){ self.toggleMap(); e.preventDefault(); })
|
||||
.attr('type','button')
|
||||
.click (function(){self.toggleMap()})
|
||||
.appendTo(element);
|
||||
this.panel_ = $("<div>").addClass("panel")
|
||||
.appendTo(element);
|
||||
}
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
// Create a overview map
|
||||
this.ovmap_ = new ol_Map(
|
||||
{ controls: new ol_Collection(),
|
||||
interactions: new ol_Collection(),
|
||||
target: this.panel_.get(0),
|
||||
view: new ol_View
|
||||
({ zoom: 14,
|
||||
center: [270148, 6247782],
|
||||
projection: options.projection
|
||||
}),
|
||||
layers: options.layers
|
||||
});
|
||||
|
||||
this.oview_ = this.ovmap_.getView();
|
||||
|
||||
// Cache extent
|
||||
this.extentLayer = new ol_layer_Vector(
|
||||
{ name: 'Cache extent',
|
||||
source: new ol_source_Vector(),
|
||||
style: options.style || [new ol_style_Style(
|
||||
{ image: new ol_style_Circle(
|
||||
{ fill: new ol_style_Fill({
|
||||
color: 'rgba(255,0,0, 1)'
|
||||
}),
|
||||
stroke: new ol_style_Stroke(
|
||||
{ width: 7,
|
||||
color: 'rgba(255,0,0, 0.8)'
|
||||
}),
|
||||
radius: 5
|
||||
}),
|
||||
stroke: new ol_style_Stroke(
|
||||
{ width: 5,
|
||||
color: "rgba(255,0,0,0.8)"
|
||||
})
|
||||
}
|
||||
)]
|
||||
})
|
||||
this.ovmap_.addLayer(this.extentLayer);
|
||||
|
||||
/** Elastic bounce
|
||||
* @param {Int} bounce number of bounce
|
||||
* @param {Number} amplitude amplitude of the bounce [0,1]
|
||||
* @return {Number}
|
||||
*/
|
||||
ol_easing.bounceFn = function (bounce, amplitude)
|
||||
{ var a = (2*bounce+1) * Math.PI/2;
|
||||
var b = amplitude>0 ? -1/amplitude : -100;
|
||||
var c = - Math.cos(a) * Math.pow(2, b);
|
||||
return function(t)
|
||||
{ t = 1-Math.cos(t*Math.PI/2);
|
||||
return 1 + Math.abs( Math.cos(a*t) ) * Math.pow(2, b*t) + c*t;
|
||||
}
|
||||
}
|
||||
/** Elastic bounce
|
||||
* @param {Int} bounce number of bounce
|
||||
* @param {Number} amplitude amplitude of the bounce [0,1]
|
||||
* @return {Number}
|
||||
*/
|
||||
ol_easing.elasticFn = function (bounce, amplitude)
|
||||
{ var a = 3*bounce * Math.PI/2;
|
||||
var b = amplitude>0 ? -1/amplitude : -100;
|
||||
var c = Math.cos(a) * Math.pow(2, b);
|
||||
return function(t)
|
||||
{ t = 1-Math.cos(t*Math.PI/2);
|
||||
return 1 - Math.cos(a*t) * Math.pow(2, b*t) + c*t;
|
||||
}
|
||||
}
|
||||
|
||||
// Click on the preview center the map
|
||||
this.ovmap_.addInteraction (new ol_interaction_Pointer(
|
||||
{ handleDownEvent: function(evt)
|
||||
{ //TODO: Old version OL3
|
||||
if (ol.animation)
|
||||
{ var pan;
|
||||
if (options.panAnimation !==false)
|
||||
{ if (options.panAnimation=="elastic" || options.elasticPan)
|
||||
{ pan = ol.animation.pan(
|
||||
{ duration: 1000,
|
||||
easing: ol_easing.elasticFn(2,0.3),
|
||||
source: self.getMap().getView().getCenter()
|
||||
});
|
||||
}
|
||||
else
|
||||
{ pan = ol.animation.pan(
|
||||
{ duration: 300,
|
||||
source: self.getMap().getView().getCenter()
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
self.getMap().beforeRender(pan);
|
||||
self.getMap().getView().setCenter(evt.coordinate);
|
||||
}
|
||||
else
|
||||
{ if (options.panAnimation !==false)
|
||||
{ if (options.panAnimation=="elastic" || options.elasticPan)
|
||||
{ self.getMap().getView().animate(
|
||||
{ center: evt.coordinate,
|
||||
easing: ol_easing.elasticFn(2,0.3),
|
||||
duration: 1000
|
||||
});
|
||||
}
|
||||
else
|
||||
{ self.getMap().getView().animate(
|
||||
{ center: evt.coordinate,
|
||||
duration: 300
|
||||
});
|
||||
}
|
||||
}
|
||||
else self.getMap().getView().setCenter(evt.coordinate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
};
|
||||
ol.inherits(ol_control_Overview, ol_control_Control);
|
||||
|
||||
/** Get overview map
|
||||
* @return {ol.Map}
|
||||
*/
|
||||
ol_control_Overview.prototype.getOverviewMap = function()
|
||||
{ return this.ovmap_;
|
||||
}
|
||||
|
||||
/** Toggle overview map
|
||||
*/
|
||||
ol_control_Overview.prototype.toggleMap = function()
|
||||
{ $(this.element).toggleClass("ol-collapsed");
|
||||
this.ovmap_.updateSize();
|
||||
}
|
||||
|
||||
/** Set overview map position
|
||||
* @param {top|bottom-left|right}
|
||||
*/
|
||||
ol_control_Overview.prototype.setPosition = function(align)
|
||||
{ if (/top/.test(align)) $(this.element).addClass("ol-control-top");
|
||||
else $(this.element).removeClass("ol-control-top");
|
||||
if (/right/.test(align)) $(this.element).addClass("ol-control-right");
|
||||
else $(this.element).removeClass("ol-control-right");
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map instance the control associated with.
|
||||
* @param {ol.Map} map The map instance.
|
||||
*/
|
||||
ol_control_Overview.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().getView().un('propertychange', this.setView, this);
|
||||
}
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
if (map)
|
||||
{ map.getView().on('propertychange', this.setView, this);
|
||||
this.setView();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Calculate the extent of the map and draw it on the overview
|
||||
*/
|
||||
ol_control_Overview.prototype.calcExtent_ = function(extent)
|
||||
{ var map = this.getMap();
|
||||
if (!map) return;
|
||||
|
||||
var source = this.extentLayer.getSource();
|
||||
source.clear();
|
||||
var f = new ol_Feature();
|
||||
|
||||
var size = map.getSize();
|
||||
var resolution = map.getView().getResolution();
|
||||
var rotation = map.getView().getRotation();
|
||||
var center = map.getView().getCenter();
|
||||
if (!resolution) return;
|
||||
|
||||
var dx = resolution * size[0] / 2;
|
||||
var dy = resolution * size[1] / 2;
|
||||
var res2 = this.oview_.getResolution();
|
||||
if (dx/res2>5 || dy/res2>5)
|
||||
{ var cos = Math.cos(rotation);
|
||||
var sin = Math.sin(rotation);
|
||||
var i, x, y;
|
||||
extent=[[-dx,-dy],[-dx,dy],[dx,dy],[dx,-dy]];
|
||||
for (i = 0; i < 4; ++i)
|
||||
{ x = extent[i][0];
|
||||
y = extent[i][1];
|
||||
extent[i][0] = center[0] + x * cos - y * sin;
|
||||
extent[i][1] = center[1] + x * sin + y * cos;
|
||||
}
|
||||
f.setGeometry (new ol_geom_Polygon( [ extent ]));
|
||||
}
|
||||
else
|
||||
{ f.setGeometry (new ol_geom_Point( center ));
|
||||
}
|
||||
source.addFeature(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
ol_control_Overview.prototype.setView = function(e)
|
||||
{ if (!e)
|
||||
{ // refresh all
|
||||
this.setView({key:'rotation'});
|
||||
this.setView({key:'resolution'});
|
||||
this.setView({key:'center'});
|
||||
return;
|
||||
}
|
||||
// Set the view params
|
||||
switch (e.key)
|
||||
{ case 'rotation':
|
||||
if (this.rotation) this.oview_.setRotation(this.getMap().getView().getRotation());
|
||||
else if (this.oview_.getRotation()) this.oview_.setRotation(0);
|
||||
break;
|
||||
case 'center':
|
||||
{ var mapExtent = this.getMap().getView().calculateExtent(this.getMap().getSize());
|
||||
var extent = this.oview_.calculateExtent(this.ovmap_.getSize());
|
||||
if (mapExtent[0]<extent[0] || mapExtent[1]<extent[1]
|
||||
|| mapExtent[2]>extent[2] || mapExtent[3]>extent[3])
|
||||
{ this.oview_.setCenter(this.getMap().getView().getCenter());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'resolution':
|
||||
{ var z = Math.round(this.getMap().getView().getZoom()/2)*2-4;
|
||||
z = Math.min ( this.maxZoom, Math.max(this.minZoom, z) );
|
||||
this.oview_.setZoom(z);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
this.calcExtent_();
|
||||
}
|
||||
|
||||
export default ol_control_Overview
|
||||
14
build/control/Permalink.css
Normal file
14
build/control/Permalink.css
Normal file
@ -0,0 +1,14 @@
|
||||
.ol-permalink
|
||||
{ position: absolute;
|
||||
top:0.5em;
|
||||
right: 2.5em;
|
||||
}
|
||||
.ol-touch .ol-permalink
|
||||
{ right: 3em;
|
||||
}
|
||||
|
||||
.ol-permalink button
|
||||
{ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AcFBjYE1ZK03gAAAUlJREFUOMuVk71KA1EQhc/NaiP+gCRpFHwGBSFlCrFVfAsbwSJCBMv06QIGJOBziI3EYAgkjU8gIloIAasIn4WzMqx34zrN7J6de+6ZmbNSgQDSfADcATPgHbgCyvonSYv8KEzWdofegH3gwmG9Ikq67sAESFzNueHThTyiEIKAmr2OJCUhhO30Aou+5aUQU2Ik65K2JC1KegohPGfUBkmvksqShnntHEcGOs60NXHfjmKz6czZTsNqbhzW+muwY2ATWAWawCOwBgxcTfvnvCPxKx4Cy5bPgBWgauRpdL2ImNlGhp3MabETm8mh94nDk4yCNE5/KTGg7xxbyhYAG0AN2AEqURIDZ0a0Fxn+LXAPXDpzRqMk6cOedz1ubdYl1b6NHgZRJe72nuu/CdSBl+yKi/zZlTnbaeXOJIesClwDU+ATeEhtX5TkCwAWUyAsHH1QAAAAAElFTkSuQmCC');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
246
build/control/Permalink.js
Normal file
246
build/control/Permalink.js
Normal file
@ -0,0 +1,246 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_proj from 'ol/proj'
|
||||
|
||||
/**
|
||||
* Permalink Control.
|
||||
*
|
||||
* Add a `permalink`property to layers to be handled by the control (and added in the url).
|
||||
* The layer's permalink property is used to name the layer in the url.
|
||||
* The control must be added after all layer are inserted in the map to take them into acount.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} options
|
||||
* @param {bool} options.urlReplace replace url or not, default true
|
||||
* @param {integer} options.fixed number of digit in coords, default 6
|
||||
* @param {bool} options.anchor use "#" instead of "?" in href
|
||||
* @param {function} options.onclick a function called when control is clicked
|
||||
*/
|
||||
var ol_control_Permalink = function(opt_options)
|
||||
{ var options = opt_options || {};
|
||||
var self = this;
|
||||
|
||||
var button = document.createElement('button');
|
||||
this.replaceState_ = (options.urlReplace!==false);
|
||||
this.fixed_ = options.fixed || 6;
|
||||
this.hash_ = options.anchor ? "#" : "?";
|
||||
|
||||
function linkto()
|
||||
{ if (typeof(options.onclick) == 'function') options.onclick(self.getLink());
|
||||
else self.setUrlReplace(!self.replaceState_);
|
||||
}
|
||||
button.addEventListener('click', linkto, false);
|
||||
button.addEventListener('touchstart', linkto, false);
|
||||
|
||||
var element = document.createElement('div');
|
||||
element.className = (options.className || "ol-permalink") + " ol-unselectable ol-control";
|
||||
element.appendChild(button);
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
this.on ('change', this.viewChange_, this);
|
||||
|
||||
// Save search params
|
||||
this.search_ = {};
|
||||
var hash = document.location.hash || document.location.search;
|
||||
if (hash)
|
||||
{ hash = hash.replace(/(^#|^\?)/,"").split("&");
|
||||
for (var i=0; i<hash.length; i++)
|
||||
{ var t = hash[i].split("=");
|
||||
switch(t[0])
|
||||
{ case 'lon':
|
||||
case 'lat':
|
||||
case 'z':
|
||||
case 'r':
|
||||
case 'l': break;
|
||||
default: this.search_[t[0]] = t[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode permalink
|
||||
this.setPosition();
|
||||
};
|
||||
ol.inherits(ol_control_Permalink, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Set the map instance the control associated with.
|
||||
* @param {ol.Map} map The map instance.
|
||||
*/
|
||||
ol_control_Permalink.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().getLayerGroup().un('change', this.layerChange_, this);
|
||||
this.getMap().un('moveend', this.viewChange_, this);
|
||||
}
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
// Get change
|
||||
if (map)
|
||||
{ map.getLayerGroup().on('change', this.layerChange_, this);
|
||||
map.on('moveend', this.viewChange_, this);
|
||||
this.setPosition();
|
||||
}
|
||||
};
|
||||
|
||||
/** Get layer given a permalink name (permalink propertie in the layer)
|
||||
* @param {string} the permalink to search for
|
||||
* @param {Array<ol.layer>|undefined} an array of layer to search in
|
||||
* @return {ol.layer|false}
|
||||
*/
|
||||
ol_control_Permalink.prototype.getLayerByLink = function (id, layers)
|
||||
{ if (!layers && this.getMap()) layers = this.getMap().getLayers().getArray();
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ if (layers[i].get('permalink') == id) return layers[i];
|
||||
// Layer Group
|
||||
if (layers[i].getLayers)
|
||||
{ var li = this.getLayerByLink ( id, layers[i].getLayers().getArray() );
|
||||
if (li) return li;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Set map position according to the current link
|
||||
*/
|
||||
ol_control_Permalink.prototype.setPosition = function()
|
||||
{ var map = this.getMap();
|
||||
if (!map) return;
|
||||
|
||||
var hash = document.location.hash || document.location.search;
|
||||
if (!hash) return;
|
||||
|
||||
var param = {};
|
||||
hash = hash.replace(/(^#|^\?)/,"").split("&");
|
||||
for (var i=0; i<hash.length; i++)
|
||||
{ var t = hash[i].split("=");
|
||||
param[t[0]] = t[1];
|
||||
}
|
||||
var c = ol_proj.transform([Number(param.lon),Number(param.lat)], 'EPSG:4326', map.getView().getProjection());
|
||||
if (c[0] && c[1]) map.getView().setCenter(c);
|
||||
if (param.z) map.getView().setZoom(Number(param.z));
|
||||
if (param.r) map.getView().setRotation(Number(param.r));
|
||||
|
||||
if (param.l)
|
||||
{ var l = param.l.split("|");
|
||||
|
||||
// Reset layers
|
||||
function resetLayers(layers)
|
||||
{ if (!layers) layers = map.getLayers().getArray();
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ if (layers[i].get('permalink'))
|
||||
{ layers[i].setVisible(false);
|
||||
// console.log("hide "+layers[i].get('permalink'));
|
||||
}
|
||||
if (layers[i].getLayers)
|
||||
{ resetLayers (layers[i].getLayers().getArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
resetLayers();
|
||||
|
||||
for (var i=0; i<l.length; i++)
|
||||
{ var t = l[i].split(":");
|
||||
var li = this.getLayerByLink(t[0]);
|
||||
var op = Number(t[1]);
|
||||
if (li)
|
||||
{ li.setOpacity(op);
|
||||
li.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the parameters added to the url. The object can be changed to add new values.
|
||||
* @return {Object} a key value object added to the url as &key=value
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Permalink.prototype.getUrlParams = function()
|
||||
{ return this.search_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the permalink
|
||||
* @return {permalink}
|
||||
*/
|
||||
ol_control_Permalink.prototype.getLink = function()
|
||||
{ var map = this.getMap();
|
||||
var c = ol_proj.transform(map.getView().getCenter(), map.getView().getProjection(), 'EPSG:4326');
|
||||
var z = map.getView().getZoom();
|
||||
var r = map.getView().getRotation();
|
||||
var l = this.layerStr_;
|
||||
// Change anchor
|
||||
var anchor = "lon="+c[0].toFixed(this.fixed_)+"&lat="+c[1].toFixed(this.fixed_)+"&z="+z+(r?"&r="+(Math.round(r*10000)/10000):"")+(l?"&l="+l:"");
|
||||
|
||||
for (var i in this.search_) anchor += "&"+i+"="+this.search_[i];
|
||||
|
||||
//return document.location.origin+document.location.pathname+this.hash_+anchor;
|
||||
return document.location.protocol+"//"+document.location.host+document.location.pathname+this.hash_+anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable / disable url replacement (replaceSate)
|
||||
* @param {bool}
|
||||
*/
|
||||
ol_control_Permalink.prototype.setUrlReplace = function(replace)
|
||||
{ try{
|
||||
this.replaceState_ = replace;
|
||||
if (!replace)
|
||||
{ var s = "";
|
||||
for (var i in this.search_)
|
||||
{ s += (s==""?"?":"&") + i+"="+this.search_[i];
|
||||
}
|
||||
window.history.replaceState (null,null, document.location.origin+document.location.pathname+s);
|
||||
}
|
||||
else window.history.replaceState (null,null, this.getLink());
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On view change refresh link
|
||||
* @param {ol.event} The map instance.
|
||||
* @private
|
||||
*/
|
||||
ol_control_Permalink.prototype.viewChange_ = function()
|
||||
{ try{
|
||||
if (this.replaceState_) window.history.replaceState (null,null, this.getLink());
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
/**
|
||||
* Layer change refresh link
|
||||
* @param {ol.event} The map instance.
|
||||
* @private
|
||||
*/
|
||||
ol_control_Permalink.prototype.layerChange_ = function(e)
|
||||
{ // Get layers
|
||||
var l = "";
|
||||
function getLayers(layers)
|
||||
{ for (var i=0; i<layers.length; i++)
|
||||
{ if (layers[i].getVisible() && layers[i].get("permalink"))
|
||||
{ if (l) l += "|";
|
||||
l += layers[i].get("permalink")+":"+layers[i].get("opacity");
|
||||
}
|
||||
// Layer Group
|
||||
if (layers[i].getLayers) getLayers(layers[i].getLayers().getArray());
|
||||
}
|
||||
}
|
||||
getLayers(this.getMap().getLayers().getArray());
|
||||
this.layerStr_ = l;
|
||||
|
||||
this.viewChange_();
|
||||
}
|
||||
|
||||
export default ol_control_Permalink
|
||||
11
build/control/PirateMap.css
Normal file
11
build/control/PirateMap.css
Normal file
@ -0,0 +1,11 @@
|
||||
.pirate_back
|
||||
{ /** Image Chris Fiedler - CC0 - https://pixabay.com/fr/papier-vieux-texture-parchemin-1074136/ */
|
||||
/*TODO: check if the image relative path is good*/
|
||||
background-image: url("piratecontrol.jpg");
|
||||
}
|
||||
.pirate_compass
|
||||
{ background-image: url("piratecontrol.png");
|
||||
}
|
||||
.ol-pirate
|
||||
{ display:none;
|
||||
}
|
||||
242
build/control/PirateMap.js
Normal file
242
build/control/PirateMap.js
Normal file
@ -0,0 +1,242 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/** ol_control_PirateMap adds an old map effect on a canvas renderer.
|
||||
* It colors the map, adds a parchment texture and compass onto the map.
|
||||
* @param {Object}
|
||||
* - hue {ol.Color} color to set hue of the map, default #963
|
||||
* - saturation {Number} saturation of the hue color, default 0.6
|
||||
* - opacity {Number} opacity of the overimpose image, default 0.7
|
||||
*/
|
||||
var ol_control_PirateMap = function(options)
|
||||
{
|
||||
// deprecated
|
||||
console.error("ol_control_PirateMap is deprecated. Use a combination of ol.filter.Texture + ol.controlCompass + ol.control.Clip.\n"
|
||||
+"See http://viglino.github.io/ol-ext/examples/map.pirate.html")
|
||||
|
||||
options = options || {};
|
||||
var self = this;
|
||||
|
||||
this.asset = {};
|
||||
this.hue = (options.hue ? ol_color.asString(options.hue) : "#963");
|
||||
this.saturation = options.saturation || 0.6;
|
||||
this.opacity = options.opacity || 0.7;
|
||||
|
||||
// Get image in css
|
||||
this.asset.back = new Image();
|
||||
this.asset.back.onload = function(){ if (self.map_) self.map_.renderSync(); }
|
||||
var i = $("<img>").addClass("pirate_back").appendTo("body");
|
||||
this.asset.back.src = i.css("background-image").replace(/^url\(\"(.*)\"\)$/,"$1");
|
||||
i.remove();
|
||||
|
||||
this.asset.compass = new Image();
|
||||
this.asset.compass.onload = function(){ if (self.map_) self.map_.renderSync(); }
|
||||
var i = $("<img>").addClass("pirate_compass").appendTo("body");
|
||||
this.asset.compass.src = i.css("background-image").replace(/^url\(\"(.*)\"\)$/,"$1");
|
||||
i.remove();
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.className = "ol-pirate ol-unselectable ol-control";
|
||||
ol_control_Control.call(this,
|
||||
{ element: div,
|
||||
target: options.target
|
||||
});
|
||||
};
|
||||
|
||||
ol.inherits(ol_control_PirateMap, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_PirateMap.prototype.setMap = function (map)
|
||||
{ ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
if (this.map_)
|
||||
{ this.map_.un('precompose', this.drawMask_, this);
|
||||
this.map_.un('postcompose', this.drawPirate_, this);
|
||||
}
|
||||
|
||||
if (map)
|
||||
{ map.on('precompose', this.drawMask_, this);
|
||||
map.on('postcompose', this.drawPirate_, this);
|
||||
}
|
||||
this.map_ = map;
|
||||
};
|
||||
|
||||
(function() {
|
||||
|
||||
var crop = [[0.023, 0.957], [0, 0.463], [0.007, 0.42], [0.004, 0.397], [0.029, 0.383], [0.013, 0.383], [0.046, 0.367], [0.011, 0.371], [0.004, 0.349], [0.006, 0.297], [0.012, 0.265], [0.007, 0.246], [0.016, 0.191], [0.031, 0.191], [0.019, 0.171], [0.012, 0.1], [0.046, 0.001], [0.071, 0.012], [0.1, 0], [0.186, 0.01], [0.228, 0.008], [0.239, 0.022], [0.25, 0.009], [0.304, 0.002], [0.311, 0.027], [0.313, 0.007], [0.322, 0.064], [0.311, 0.101], [0.329, 0.055], [0.321, 0.018], [0.334, 0.01], [0.496, 0.009], [0.53, 0.019], [0.553, 0.01], [0.615, 0.014], [0.683, 0.03], [0.697, 0.019], [0.728, 0.027], [0.732, 0.066], [0.735, 0.012], [0.752, 0.006], [0.795, 0.014], [0.85, 0.007], [0.929, 0.013], [1, 0.204], [0.994, 0.324], [0.999, 0.393], [0.988, 0.464], [0.947, 0.46], [0.977, 0.47], [0.978, 0.479], [0.99, 0.489], [0.994, 0.572], [0.992, 0.669], [0.982, 0.673], [0.994, 0.689], [1, 0.716], [0.999, 0.81], [0.987, 0.816], [0.996, 0.83], [0.99, 0.894], [0.944, 1], [0.848, 0.993], [0.841, 0.97], [0.837, 0.993], [0.798, 0.981], [0.697, 0.98], [0.653, 0.986], [0.606, 0.981], [0.598, 0.968], [0.598, 0.941], [0.592, 0.982], [0.558, 0.988], [0.507, 0.983], [0.485, 0.988], [0.418, 0.978], [0.4, 0.969], [0.393, 0.98], [0.338, 0.984], [0.304, 0.977], [0.251, 0.984], [0.238, 0.979], [0.252, 0.915], [0.239, 0.969], [0.233, 0.953], [0.23, 0.984], [0.155, 0.971], [0.147, 0.957], [0.142, 0.974], [0.095, 0.976], [0.066, 0.98], [0.023, 0.957]];
|
||||
|
||||
ol_control_PirateMap.prototype.drawMask_ = function (event)
|
||||
{
|
||||
var ctx = event.context;
|
||||
var canvas = ctx.canvas;
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
|
||||
ctx.save();
|
||||
/*
|
||||
ctx.lineWidth = 5;
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.3)";
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(w*crop[0][0]+2, h*crop[0][1]+2);
|
||||
for (var i=1; i<crop.length; i++)
|
||||
ctx.lineTo(w*crop[i][0]+2, h*crop[i][1]+2);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
*/
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(w*crop[0][0], h*crop[0][1]);
|
||||
for (var i=1; i<crop.length; i++)
|
||||
ctx.lineTo(w*crop[i][0], h*crop[i][1]);
|
||||
|
||||
ctx.clip();
|
||||
};
|
||||
|
||||
/** Draw on the final canvas
|
||||
* @private
|
||||
*/
|
||||
function drawlines(ctx, cx, cy, m)
|
||||
{
|
||||
ctx.moveTo (cx+m, cy);
|
||||
ctx.lineTo(cx-m, cy);
|
||||
|
||||
ctx.moveTo (cx, cy+m);
|
||||
ctx.lineTo(cx, cy-m);
|
||||
|
||||
ctx.moveTo (cx+m, cy+m);
|
||||
ctx.lineTo(cx-m, cy-m);
|
||||
ctx.moveTo (cx+m, cy-m);
|
||||
ctx.lineTo(cx-m, cy+m);
|
||||
|
||||
ctx.moveTo (cx+m/2, cy-3*m/2);
|
||||
ctx.lineTo(cx-m/2, cy+3*m/2);
|
||||
ctx.moveTo (cx+m/2, cy+3*m/2);
|
||||
ctx.lineTo(cx-m/2, cy-3*m/2);
|
||||
|
||||
ctx.moveTo (cx+3*m/2, cy+m/2);
|
||||
ctx.lineTo(cx-3*m/2, cy-m/2);
|
||||
ctx.moveTo (cx+3*m/2, cy-m/2);
|
||||
ctx.lineTo(cx-3*m/2, cy+m/2);
|
||||
}
|
||||
|
||||
function drawCompass(ctx, compass, cx, cy, rot, sc, m)
|
||||
{ ctx.save();
|
||||
|
||||
ctx.translate(cx, cy);
|
||||
ctx.rotate(rot);
|
||||
|
||||
ctx.beginPath();
|
||||
drawlines(ctx, 0, 0, m*1.5)
|
||||
ctx.stroke();
|
||||
|
||||
if (sc)
|
||||
{ ctx.globalAlpha = 1;
|
||||
ctx.drawImage (compass, -compass.width/2*sc, -compass.height/2*sc, compass.width*sc, compass.height*sc);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
ol_control_PirateMap.prototype.drawPirate_ = function (event)
|
||||
{ if (!this.map_) return;
|
||||
var ctx = event.context;
|
||||
var canvas = ctx.canvas;
|
||||
var ratio = event.frameState.pixelRatio;
|
||||
var view = this.map_.getView();
|
||||
var img = this.asset.back;
|
||||
var compass = this.asset.compass;
|
||||
|
||||
var m = Math.max(canvas.width, canvas.height);
|
||||
var res = view.getResolution()/ratio;
|
||||
var rot = view.getRotation();
|
||||
|
||||
// Set back color hue
|
||||
ctx.save();
|
||||
|
||||
//ctx.scale(ratio, ratio);
|
||||
|
||||
ctx.globalCompositeOperation = "color";
|
||||
ctx.fillStyle = this.hue;
|
||||
ctx.globalAlpha = this.saturation;
|
||||
ctx.fillRect(0,0,canvas.width,canvas.height);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
// Draw back image
|
||||
ctx.save();
|
||||
|
||||
var ext = event.frameState.extent;
|
||||
var dx = ext[0]/res;
|
||||
var dy = ext[1]/res;
|
||||
dx = dx % img.width ;
|
||||
dy = img.height - dy % img.height;
|
||||
if (dx<0) dx += img.width;
|
||||
if (dy<0) dy += img.height;
|
||||
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
ctx.globalAlpha = this.opacity;
|
||||
|
||||
ctx.rotate(rot);
|
||||
|
||||
for (var i=-dx-m; i<m; i+=img.width)
|
||||
for (var j=-dy-m; j<m; j+=img.height)
|
||||
{ ctx.drawImage(img, i,j);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
// Draw compass
|
||||
ctx.save();
|
||||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle = this.hue;
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
ctx.globalAlpha = this.opacity;
|
||||
|
||||
drawCompass (ctx, compass, canvas.width*0.9, canvas.height*0.9, rot, ratio, m*1.5);
|
||||
drawCompass (ctx, compass, compass.width/2 + canvas.width*0.05, canvas.height*0.5, rot, 0.5*ratio, m*1.5);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
// Restore clip
|
||||
ctx.restore();
|
||||
|
||||
/** /
|
||||
ctx.save();
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.3)";
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
ctx.globalAlpha = 0.3;
|
||||
|
||||
var w=canvas.width;
|
||||
var h=canvas.height;
|
||||
|
||||
for (var lw=3; lw>0; lw--)
|
||||
{
|
||||
ctx.beginPath();
|
||||
ctx.lineWidth = 4*lw;
|
||||
ctx.moveTo(w*crop[0][0]+2, h*crop[0][1]+2);
|
||||
for (var i=1; i<crop.length; i++)
|
||||
ctx.lineTo(w*crop[i][0]+2, h*crop[i][1]+2);
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
/**/
|
||||
|
||||
}
|
||||
})();
|
||||
|
||||
export default ol_control_PirateMap
|
||||
102
build/control/Profil.css
Normal file
102
build/control/Profil.css
Normal file
@ -0,0 +1,102 @@
|
||||
.ol-control.ol-profil
|
||||
{ position: absolute;
|
||||
top: 0.5em;
|
||||
right: 3em;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ol-profil .ol-inner
|
||||
{ position: relative;
|
||||
padding: 0.5em;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.ol-control.ol-profil .ol-inner
|
||||
{ display: block;
|
||||
background-color: rgba(255,255,255,0.7);
|
||||
margin: 2.3em 2px 2px;
|
||||
}
|
||||
.ol-control.ol-profil.ol-collapsed .ol-inner
|
||||
{ display: none;
|
||||
}
|
||||
|
||||
.ol-profil canvas
|
||||
{ display: block;
|
||||
}
|
||||
.ol-profil button
|
||||
{ display: block;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAPCAYAAAALWoRrAAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgXCR4dn7j9TAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAz0lEQVQ4y7WTMU4CURRFz0xIpLUBEhdAY2tJYW1jaWlsXYVxDWyBhWCFCYugYgnDFPMOhTMJGf3AwHiqn/uTk5v/3gfAH6b0RH7sMiIe1Ts162z+q2lVVbd1XqijLuJk0zzP1/VxCGyApLgsy+HJphGx8DeFOm6L1bn6eVQaEW+m2amTRqx+1fkqKY2Ie0+zUx/U7WGYfNMsy57PmMMN8A1MWsWeUoPyivV8PWtPOzL7D+lYHfUtBXgHGLTCJfBxodD6k9Dsm8BLE17LobQ39nJC61aLVoVsAAAAAElFTkSuQmCC');
|
||||
}
|
||||
.ol-profil.ol-collapsed button
|
||||
{ position: static;
|
||||
}
|
||||
|
||||
.ol-profil .ol-profilbar,
|
||||
.ol-profil .ol-profilcursor
|
||||
{ position:absolute;
|
||||
pointer-events: none;
|
||||
width: 1px;
|
||||
display: none;
|
||||
}
|
||||
.ol-profil .ol-profilcursor
|
||||
{ width: 0;
|
||||
height: 0;
|
||||
}
|
||||
.ol-profil .ol-profilcursor:before
|
||||
{ content:"";
|
||||
pointer-events: none;
|
||||
display: block;
|
||||
margin: -2px;
|
||||
width:5px;
|
||||
height:5px;
|
||||
}
|
||||
.ol-profil .ol-profilbar,
|
||||
.ol-profil .ol-profilcursor:before
|
||||
{ background: red;
|
||||
}
|
||||
|
||||
.ol-profil table
|
||||
{ text-align: center;
|
||||
}
|
||||
|
||||
.ol-profil table span
|
||||
{ display: block;
|
||||
}
|
||||
|
||||
.ol-profilpopup
|
||||
{ background-color: rgba(255, 255, 255, 0.5);
|
||||
margin: 0.5em;
|
||||
padding: 0 0.5em;
|
||||
position: absolute;
|
||||
top:-1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ol-profilpopup.ol-left
|
||||
{ right:0;
|
||||
}
|
||||
|
||||
|
||||
.ol-profil table td
|
||||
{ padding: 0 2px;
|
||||
}
|
||||
|
||||
.ol-profil table .track-info
|
||||
{ display: table-row;
|
||||
}
|
||||
.ol-profil table .point-info
|
||||
{ display: none;
|
||||
}
|
||||
.ol-profil .over table .track-info
|
||||
{ display: none;
|
||||
}
|
||||
.ol-profil .over table .point-info
|
||||
{ display: table-row;
|
||||
}
|
||||
|
||||
.ol-profil p
|
||||
{ text-align: center;
|
||||
margin:0;
|
||||
}
|
||||
377
build/control/Profile.js
Normal file
377
build/control/Profile.js
Normal file
@ -0,0 +1,377 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_Sphere from 'ol/sphere'
|
||||
import ol_proj from 'ol/proj'
|
||||
|
||||
/**
|
||||
* @classdesc OpenLayers 3 Profil Control.
|
||||
* Draw a profil of a feature (with a 3D geometry)
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fires over, out, show
|
||||
* @param {Object=} _ol_control_ opt_options.
|
||||
*
|
||||
*/
|
||||
var ol_control_Profil = function(opt_options)
|
||||
{ var options = opt_options || {};
|
||||
this.info = options.info || ol_control_Profil.prototype.info;
|
||||
var self = this;
|
||||
|
||||
var element;
|
||||
if (options.target)
|
||||
{ element = $("<div>").addClass(options.className || "ol-profil");
|
||||
}
|
||||
else
|
||||
{ element = $("<div>").addClass((options.className || 'ol-profil') +' ol-unselectable ol-control ol-collapsed');
|
||||
this.button = $("<button>")
|
||||
.attr('type','button')
|
||||
.on("click touchstart", function(e)
|
||||
{ self.toggle();
|
||||
e.preventDefault();
|
||||
})
|
||||
.appendTo(element);
|
||||
}
|
||||
|
||||
var div = $("<div>").addClass("ol-inner").appendTo(element);
|
||||
div = $("<div>").css("position","relative").appendTo(div);
|
||||
|
||||
var ratio = this.ratio = 2;
|
||||
this.canvas_ = document.createElement('canvas');
|
||||
this.canvas_.width = (options.width || 300)*ratio;
|
||||
this.canvas_.height = (options.height || 150)*ratio;
|
||||
$(this.canvas_).css({
|
||||
"transform":"scale(0.5,0.5)", "transform-origin":"0 0",
|
||||
"-ms-transform":"scale(0.5,0.5)", "-ms-transform-origin":"0 0",
|
||||
"-webkit-transform":"scale(0.5,0.5)", "-webkit-transform-origin":"0 0",
|
||||
"transform":"scale(0.5,0.5)", "transform-origin":"0 0"
|
||||
});
|
||||
$("<div>").appendTo(div)
|
||||
.width (this.canvas_.width/ratio)
|
||||
.height (this.canvas_.height/ratio)
|
||||
.append(this.canvas_)
|
||||
.on("click mousemove", function(e){ self.onMove(e); });
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
// Offset in px
|
||||
this.margin_ = { top:10*ratio, left:40*ratio, bottom:30*ratio, right:10*ratio };
|
||||
if (!this.info.ytitle) this.margin_.left -= 20*ratio;
|
||||
if (!this.info.xtitle) this.margin_.bottom -= 20*ratio;
|
||||
|
||||
// Cursor
|
||||
this.bar_ = $("<div>").addClass("ol-profilbar")
|
||||
.css({top:(this.margin_.top/ratio)+"px", height:(this.canvas_.height-this.margin_.top-this.margin_.bottom)/ratio+"px" })
|
||||
.appendTo(div);
|
||||
this.cursor_ = $("<div>").addClass("ol-profilcursor")
|
||||
.appendTo(div);
|
||||
this.popup_ = $("<div>").addClass("ol-profilpopup")
|
||||
.appendTo(this.cursor_);
|
||||
|
||||
// Track information
|
||||
var t = $("<table cellpadding='0' cellspacing='0'>").appendTo(div).width(this.canvas_.width/ratio);
|
||||
var tr = $("<tr>").addClass("track-info").appendTo(t);
|
||||
$("<td>").html((this.info.zmin||"Zmin")+': <span class="zmin">').appendTo(tr);
|
||||
$("<td>").html((this.info.zmax||"Zmax")+': <span class="zmax">').appendTo(tr);
|
||||
$("<td>").html((this.info.distance||"Distance")+': <span class="dist">').appendTo(tr);
|
||||
$("<td>").html((this.info.time||"Time")+': <span class="time">').appendTo(tr);
|
||||
tr = $("<tr>").addClass("point-info").appendTo(t);
|
||||
$("<td>").html((this.info.altitude||"Altitude")+': <span class="z">').appendTo(tr);
|
||||
$("<td>").html((this.info.distance||"Distance")+': <span class="dist">').appendTo(tr);
|
||||
$("<td>").html((this.info.time||"Time")+': <span class="time">').appendTo(tr);
|
||||
|
||||
// Array of data
|
||||
this.tab_ = [];
|
||||
|
||||
// Show feature
|
||||
if (options.feature)
|
||||
{ this.setGeometry (options.feature);
|
||||
}
|
||||
};
|
||||
ol.inherits(ol_control_Profil, ol_control_Control);
|
||||
|
||||
/** Custom infos list
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.info =
|
||||
{ "zmin": "Zmin",
|
||||
"zmax": "Zmax",
|
||||
"ytitle": "Altitude (m)",
|
||||
"xtitle": "Distance (km)",
|
||||
"time": "Time",
|
||||
"altitude": "Altitude",
|
||||
"distance": "Distance"
|
||||
};
|
||||
|
||||
/** Show popup info
|
||||
* @param {string} info to display as a popup
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.popup = function(info)
|
||||
{ this.popup_.html(info);
|
||||
}
|
||||
|
||||
/** Mouse move over canvas
|
||||
*/
|
||||
ol_control_Profil.prototype.onMove = function(e)
|
||||
{ if (!this.tab_.length) return;
|
||||
var pos = $(this.canvas_).offset();
|
||||
var dx = e.pageX -pos.left;
|
||||
var dy = e.pageY -pos.top;
|
||||
var ratio = this.ratio;
|
||||
if (dx>this.margin_.left/ratio && dx<(this.canvas_.width-this.margin_.right)/ratio
|
||||
&& dy>this.margin_.top/ratio && dy<(this.canvas_.height-this.margin_.bottom)/ratio)
|
||||
{ this.bar_.css("left", dx+"px").show();
|
||||
var d = (dx*ratio-this.margin_.left)/this.scale_[0];
|
||||
var p0 = this.tab_[0];
|
||||
for (var i=1, p; p=this.tab_[i]; i++)
|
||||
{ if (p[0]>=d)
|
||||
{ if (d < (p[0]+p0[0])/2) p = p0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p) this.cursor_.css({
|
||||
left:dx+"px",
|
||||
top:(this.canvas_.height-this.margin_.bottom+p[1]*this.scale_[1]+this.dy_)/ratio+"px"
|
||||
}).show();
|
||||
else this.cursor_.hide();
|
||||
this.bar_.parent().addClass("over");
|
||||
$(".point-info .z", this.element).text(p[1]+"m");
|
||||
$(".point-info .dist", this.element).text((p[0]/1000).toFixed(1)+"km");
|
||||
$(".point-info .time", this.element).text(p[2]);
|
||||
if (dx>this.canvas_.width/ratio/2) this.popup_.addClass('ol-left');
|
||||
else this.popup_.removeClass('ol-left');
|
||||
this.dispatchEvent({ type:'over', click:e.type=="click", coord: p[3], time: p[2], distance: p[0] });
|
||||
}
|
||||
else
|
||||
{ if (this.bar_.parent().hasClass("over"))
|
||||
{ this.bar_.hide();
|
||||
this.cursor_.hide();
|
||||
this.bar_.parent().removeClass("over");
|
||||
this.dispatchEvent({ type:'out' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Show panel
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.show = function()
|
||||
{ $(this.element).removeClass("ol-collapsed");
|
||||
this.dispatchEvent({ type:'show', show: true });
|
||||
}
|
||||
/** Hide panel
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.hide = function()
|
||||
{ $(this.element).addClass("ol-collapsed");
|
||||
this.dispatchEvent({ type:'show', show: false });
|
||||
}
|
||||
/** Toggle panel
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.toggle = function()
|
||||
{ var b = $(this.element).toggleClass("ol-collapsed").hasClass("ol-collapsed");
|
||||
this.dispatchEvent({ type:'show', show: !b });
|
||||
}
|
||||
/** Is panel visible
|
||||
*/
|
||||
ol_control_Profil.prototype.isShown = function()
|
||||
{ return (!$(this.element).hasClass("ol-collapsed"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the geometry to draw the profil.
|
||||
* @param {ol.Feature|ol.geom} f the feature.
|
||||
* @param {Object=} options
|
||||
* - projection {ol.ProjectionLike} feature projection, default projection of the map
|
||||
* - zunit {m|km} default m
|
||||
* - unit {m|km} default km
|
||||
* - zmin {Number|undefined} default 0
|
||||
* - zmax {Number|undefined} default max Z of the feature
|
||||
* - graduation {Number|undefined} z graduation default 100
|
||||
* - amplitude {integer|undefined} amplitude of the altitude, default zmax-zmin
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.setGeometry = function(g, options)
|
||||
{ if (!options) options = {};
|
||||
if (g instanceof ol.Feature) g = g.getGeometry();
|
||||
var canvas = this.canvas_;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
ctx.clearRect(0,0, w, h);
|
||||
|
||||
// No Z
|
||||
if (!/Z/.test(g.getLayout())) return;
|
||||
// No time
|
||||
if(/M/.test(g.getLayout())) $(".time", this.element).parent().show();
|
||||
else $(".time", this.element).parent().hide();
|
||||
|
||||
// Coords
|
||||
var c = g.getCoordinates();
|
||||
switch (g.getType())
|
||||
{ case "LineString": break;
|
||||
case "MultiLineString": c = c[0]; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
// Distance beetween 2 coords
|
||||
var wgs84Sphere = new ol_Sphere(6378137);
|
||||
var proj = options.projection || this.getMap().getView().getProjection();
|
||||
function dist2d(p1,p2)
|
||||
{ return wgs84Sphere.haversineDistance(
|
||||
ol_proj.transform(p1, proj, 'EPSG:4326'),
|
||||
ol_proj.transform(p2, proj, 'EPSG:4326'));
|
||||
}
|
||||
|
||||
function getTime(t0, t1)
|
||||
{ if (!t0 || !t1) return "-"
|
||||
var dt = (t1-t0) / 60; // mn
|
||||
var ti = Math.trunc(dt/60);
|
||||
var mn = Math.trunc(dt-ti*60);
|
||||
return ti+"h"+(mn<10?"0":"")+mn+"mn";
|
||||
}
|
||||
|
||||
// Margin
|
||||
ctx.setTransform(1, 0, 0, 1, this.margin_.left, h-this.margin_.bottom);
|
||||
var ratio = this.ratio;
|
||||
|
||||
w -= this.margin_.right + this.margin_.left;
|
||||
h -= this.margin_.top + this.margin_.bottom;
|
||||
// Draw axes
|
||||
ctx.strokeStyle = "#000";
|
||||
ctx.lineWidth = 0.5*ratio;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,0); ctx.lineTo(0,-h);
|
||||
ctx.moveTo(0,0); ctx.lineTo(w, 0);
|
||||
ctx.stroke();
|
||||
|
||||
//
|
||||
var zmin=Infinity, zmax=-Infinity;
|
||||
var d, z, ti, t = this.tab_ = [];
|
||||
for (var i=0, p; p=c[i]; i++)
|
||||
{ z = p[2];
|
||||
if (z<zmin) zmin=z;
|
||||
if (z>zmax) zmax=z;
|
||||
if (i==0) d = 0;
|
||||
else d += dist2d(c[i-1], p);
|
||||
ti = getTime(c[0][3],p[3]);
|
||||
t.push ([d, z, ti, p]);
|
||||
}
|
||||
|
||||
// Info
|
||||
$(".track-info .zmin", this.element).text(zmin.toFixed(2)+"m");
|
||||
$(".track-info .zmax", this.element).text(zmax.toFixed(2)+"m");
|
||||
if (d>1000)
|
||||
{ $(".track-info .dist", this.element).text((d/1000).toFixed(1)+"km");
|
||||
}
|
||||
else
|
||||
{ $(".track-info .dist", this.element).text((d).toFixed(1)+"m");
|
||||
}
|
||||
$(".track-info .time", this.element).text(ti);
|
||||
|
||||
// Set graduation
|
||||
var grad = options.graduation || 100;
|
||||
while (true)
|
||||
{ zmax = Math.ceil(zmax/grad)*grad;
|
||||
zmin = Math.floor(zmin/grad)*grad;
|
||||
var nbgrad = (zmax-zmin)/grad;
|
||||
if (h/nbgrad < 15*ratio)
|
||||
{ grad *= 2;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
// Set amplitude
|
||||
if (typeof(options.zmin)=='number' && zmin > options.zmin) zmin = options.zmin;
|
||||
if (typeof(options.zmax)=='number' && zmax < options.zmax) zmax = options.zmax;
|
||||
var amplitude = options.amplitude;
|
||||
if (amplitude)
|
||||
{ zmax = Math.max (zmin + amplitude, zmax);
|
||||
}
|
||||
|
||||
// Scales lines
|
||||
var scx = w/d;
|
||||
var scy = -h/(zmax-zmin);
|
||||
var dy = this.dy_ = -zmin*scy;
|
||||
this.scale_ = [scx,scy];
|
||||
// Draw
|
||||
ctx.font = (10*ratio)+"px arial";
|
||||
ctx.textAlign = "right";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle="#000";
|
||||
// Scale Z
|
||||
ctx.beginPath();
|
||||
for (var i=zmin; i<=zmax; i+=grad)
|
||||
{ if (options.zunit!="km") ctx.fillText(i, -4*ratio, i*scy+dy);
|
||||
else ctx.fillText((i/1000).toFixed(1), -4*ratio, i*scy+dy);
|
||||
ctx.moveTo (-2*ratio, i*scy+dy);
|
||||
if (i!=0) ctx.lineTo (d*scx, i*scy+dy);
|
||||
else ctx.lineTo (0, i*scy+dy);
|
||||
}
|
||||
// Scale X
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
ctx.setLineDash([ratio,3*ratio]);
|
||||
var unit = options.unit ||"km";
|
||||
var step;
|
||||
if (d>1000)
|
||||
{ step = Math.round(d/1000)*100;
|
||||
if (step > 1000) step = Math.ceil(step/1000)*1000;
|
||||
}
|
||||
else
|
||||
{ unit = "m";
|
||||
if (d>100) step = Math.round(d/100)*10;
|
||||
else if (d>10) step = Math.round(d/10);
|
||||
else if (d>1) step = Math.round(d)/10;
|
||||
else step = d;
|
||||
}
|
||||
for (var i=0; i<=d; i+=step)
|
||||
{ var txt = (unit=="m") ? i : (i/1000);
|
||||
//if (i+step>d) txt += " "+ (options.zunits || "km");
|
||||
ctx.fillText(Math.round(txt*10)/10, i*scx, 4*ratio);
|
||||
ctx.moveTo (i*scx, 2*ratio); ctx.lineTo (i*scx, 0);
|
||||
}
|
||||
ctx.font = (12*ratio)+"px arial";
|
||||
ctx.fillText(this.info.xtitle.replace("(km)","("+unit+")"), w/2, 18*ratio);
|
||||
ctx.save();
|
||||
ctx.rotate(-Math.PI/2);
|
||||
ctx.fillText(this.info.ytitle, h/2, -this.margin_.left);
|
||||
ctx.restore();
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
//
|
||||
ctx.strokeStyle = "#369";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.setLineDash([]);
|
||||
ctx.beginPath();
|
||||
for (var i=0, p; p=t[i]; i++)
|
||||
{ if (i==0) ctx.moveTo(p[0]*scx,p[1]*scy+dy);
|
||||
else ctx.lineTo(p[0]*scx,p[1]*scy+dy);
|
||||
}
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
/** Get profil image
|
||||
* @param {string|undefined} type image format or 'canvas' to get the canvas image, default image/png.
|
||||
* @param {Number|undefined} encoderOptions between 0 and 1 indicating image quality image/jpeg or image/webp, default 0.92.
|
||||
* @return {string} requested data uri
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Profil.prototype.getImage = function(type, encoderOptions)
|
||||
{ if (type==="canvas") return this.canvas_;
|
||||
return this.canvas_.toDataURL(type, encoderOptions);
|
||||
}
|
||||
|
||||
export default ol_control_Profil
|
||||
65
build/control/Search.css
Normal file
65
build/control/Search.css
Normal file
@ -0,0 +1,65 @@
|
||||
.ol-search
|
||||
{ top: 0.5em;
|
||||
left: 3em;
|
||||
}
|
||||
.ol-touch .ol-search
|
||||
{ left: 3.5em;
|
||||
}
|
||||
.ol-search button
|
||||
{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAABPUlEQVQoU41SwXHCQAzUHh58eoUOIBWEDkI6oAToIKkg7iAuwakgpAIowXRACcnrzp6BzchjMx4wE/S6kW5XK60gvQghzJIkmVoqSZI9gJ9+/fINS5Cc1HX9QXIlIr/tpwcRyb33b7cIGnAIYQdg4pxbjcfj0nJ1Xc+Px+PGObdN03Q9RIAQwgpAnqbp7FKmjQGgJLlU1d2V7BjjRkQO3vvXIXarkyxVNbsCm2QR2Q0V7XOMMReRmfd+OQQubN6hYgs22ZtbnRcAtiRfLueqqmpJ8ovko6oeBq0KIWQA3gFkzrlmMafTaUEyI/mpqmbhVTRWWbRdbClPbeobQNES5KPRqOxs7DBn8K1DsAOKMZYApiTXqlrcDe4d0XN7jWeCfzt351tVle2iGalTcBd4gGDvvZ/fDe4RmCOFLe8Pr7mvEP2N9PQAAAAASUVORK5CYII=");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
background-size: 1em;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
float: left;
|
||||
}
|
||||
.ol-search input
|
||||
{ display: inline-block;
|
||||
border: 0;
|
||||
margin: 1px 1px 1px 2px;
|
||||
font-size: 1.14em;
|
||||
padding-left: 0.3em;
|
||||
height: 1.375em;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.1s;
|
||||
}
|
||||
.ol-touch .ol-search input,
|
||||
.ol-touch .ol-search ul
|
||||
{ font-size: 1.5em;
|
||||
}
|
||||
.ol-control.ol-search.ol-collapsed ul,
|
||||
.ol-control.ol-search.ol-collapsed input
|
||||
{ display: none;
|
||||
}
|
||||
|
||||
.ol-search ul
|
||||
{ list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: block;
|
||||
clear: both;
|
||||
cursor: pointer;
|
||||
max-width: 17em;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
/*
|
||||
.ol-control.ol-search ul
|
||||
{ position: absolute;
|
||||
background: #fff;
|
||||
box-shadow: 5px 5px 5px rgba(0,0,0,0.5);
|
||||
}
|
||||
*/
|
||||
.ol-control.ol-search ul li
|
||||
{ padding: 0.1em 0.5em;
|
||||
}
|
||||
.ol-search ul li
|
||||
{ white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.ol-search ul li.select,
|
||||
.ol-search ul li:hover
|
||||
{ background-color: rgba(0,60,136,.5);
|
||||
color: #fff;
|
||||
}
|
||||
197
build/control/Search.js
Normal file
197
build/control/Search.js
Normal file
@ -0,0 +1,197 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
/**
|
||||
* Search Control.
|
||||
* This is the base class for search controls. You can use it for simple custom search or as base to new class.
|
||||
* @see ol_control_SearchFeature
|
||||
* @see ol_control_SearchPhoton
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fires select
|
||||
* @fires change:input
|
||||
* @param {Object=} options
|
||||
* @param {string} options.className control class name
|
||||
* @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.
|
||||
* @param {string | undefined} options.label Text label to use for the search button, default "search"
|
||||
* @param {string | undefined} options.placeholder placeholder, default "Search..."
|
||||
* @param {number | undefined} options.typing a delay on each typing to start searching (ms) use -1 to prevent autocompletion, default 300.
|
||||
* @param {integer | undefined} options.minLength minimum length to start searching, default 1
|
||||
* @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10
|
||||
* @param {function} options.getTitle a function that takes a feature and return the name to display in the index.
|
||||
* @param {function} options.autocomplete a function that take a search string and callback function to send an array
|
||||
*/
|
||||
var ol_control_Search = function(options)
|
||||
{ var self = this;
|
||||
if (!options) options = {};
|
||||
if (options.typing == undefined) options.typing = 300;
|
||||
|
||||
var element;
|
||||
if (options.target)
|
||||
{ element = $("<div>").addClass((options.className||"")+ " ol-search");
|
||||
}
|
||||
else
|
||||
{ element = $("<div>").addClass((options.className||"") + ' ol-search ol-unselectable ol-control ol-collapsed');
|
||||
this.button = $("<button>")
|
||||
.attr('type','button')
|
||||
.attr('title',options.label||"search")
|
||||
.click (function()
|
||||
{ element.toggleClass("ol-collapsed");
|
||||
if (!element.hasClass("ol-collapsed"))
|
||||
{ $("input.search", element).focus();
|
||||
$('li', element).removeClass('select');
|
||||
}
|
||||
})
|
||||
.appendTo(element);
|
||||
}
|
||||
// Search input
|
||||
var tout, cur="";
|
||||
$("<input>").attr('type','search')
|
||||
.addClass("search")
|
||||
.attr('placeholder', options.placeholder||"Search...")
|
||||
.on('change', function(e)
|
||||
{ self.dispatchEvent({ type:"change:input", input:e, value:$(this).val() });
|
||||
})
|
||||
.on('keyup search cut paste input', function(e)
|
||||
{ // console.log(e.type+" "+e.key)
|
||||
var li = $("ul.autocomplete li.select", element);
|
||||
var val = $(this).val();
|
||||
// move up/down
|
||||
if (e.key=='ArrowDown' || e.key=='ArrowUp' || e.key=='Down' || e.key=='Up')
|
||||
{ li.removeClass('select');
|
||||
li = (/Down/.test(e.key)) ? li.next() : li.prev();
|
||||
if (li.length) li.addClass('select');
|
||||
else $("ul.autocomplete li",element).first().addClass('select');
|
||||
}
|
||||
// Clear input
|
||||
else if (e.type=='input' && !val)
|
||||
{ self.drawList_();
|
||||
}
|
||||
// Select in the list
|
||||
else if (li.length && (e.type=="search" || e.key =='Enter'))
|
||||
{ if (element.hasClass("ol-control")) $(this).blur();
|
||||
li.removeClass('select');
|
||||
cur = val;
|
||||
self.select(li.data('search'));
|
||||
}
|
||||
// Search / autocomplete
|
||||
else if ( (e.type=="search" || e.key =='Enter')
|
||||
|| (cur!=val && options.typing>=0))
|
||||
{ // current search
|
||||
cur = val;
|
||||
if (cur)
|
||||
{ // prevent searching on each typing
|
||||
if (tout) clearTimeout(tout);
|
||||
tout = setTimeout(function()
|
||||
{ if (cur.length >= self.get("minLength"))
|
||||
{ var s = self.autocomplete (cur, function(auto) { self.drawList_(auto); });
|
||||
if (s) self.drawList_(s);
|
||||
}
|
||||
else self.drawList_();
|
||||
}, options.typing);
|
||||
}
|
||||
else self.drawList_();
|
||||
}
|
||||
// Clear list selection
|
||||
else
|
||||
{ $("ul.autocomplete li", element).removeClass('select');
|
||||
}
|
||||
})
|
||||
.blur(function()
|
||||
{ setTimeout(function(){ element.addClass('ol-collapsed') }, 200);
|
||||
})
|
||||
.focus(function()
|
||||
{ element.removeClass('ol-collapsed')
|
||||
})
|
||||
.appendTo(element);
|
||||
// Autocomplete list
|
||||
$("<ul>").addClass('autocomplete').appendTo(element);
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element.get(0),
|
||||
target: options.target
|
||||
});
|
||||
|
||||
if (typeof (options.getTitle)=='function') this.getTitle = options.getTitle;
|
||||
if (typeof (options.autocomplete)=='function') this.autocomplete = options.autocomplete;
|
||||
|
||||
// Options
|
||||
this.set('minLength', options.minLength || 1);
|
||||
this.set('maxItems', options.maxItems || 10);
|
||||
|
||||
};
|
||||
ol.inherits(ol_control_Search, ol_control_Control);
|
||||
|
||||
/** Returns the text to be displayed in the menu
|
||||
* @param {any} f feature to be displayed
|
||||
* @return {string} the text to be displayed in the index, default f.name
|
||||
* @api
|
||||
*/
|
||||
ol_control_Search.prototype.getTitle = function (f)
|
||||
{ return f.name || "No title";
|
||||
};
|
||||
|
||||
/** Force search to refresh
|
||||
*/
|
||||
ol_control_Search.prototype.search = function ()
|
||||
{ $("input.search", this.element).trigger('search');
|
||||
};
|
||||
|
||||
/** Set the input value in the form (for initialisation purpose)
|
||||
* @param {string} value
|
||||
* @param {boolean} search to start a search
|
||||
* @api
|
||||
*/
|
||||
ol_control_Search.prototype.setInput = function (value, search)
|
||||
{ $("input.search",this.element).val(value);
|
||||
if (search) $("input.search",this.element).trigger("keyup");
|
||||
};
|
||||
|
||||
/** A ligne has been clicked in the menu > dispatch event
|
||||
* @param {any} f the feature, as passed in the autocomplete
|
||||
* @api
|
||||
*/
|
||||
ol_control_Search.prototype.select = function (f)
|
||||
{ this.dispatchEvent({ type:"select", search:f });
|
||||
};
|
||||
|
||||
/** Autocomplete function
|
||||
* @param {string} s search string
|
||||
* @param {function} cback a callback function that takes an array to display in the autocomplete field (for asynchronous search)
|
||||
* @return {Array|false} an array of search solutions or false if the array is send with the cback argument
|
||||
* @api
|
||||
*/
|
||||
ol_control_Search.prototype.autocomplete = function (s, cback)
|
||||
{ cback ([]);
|
||||
return false;
|
||||
};
|
||||
|
||||
/** Draw the list
|
||||
* @param {Array} auto an array of search result
|
||||
*/
|
||||
ol_control_Search.prototype.drawList_ = function (auto)
|
||||
{ var ul = $("ul.autocomplete", this.element).html("");
|
||||
if (!auto) return;
|
||||
var self = this;
|
||||
var max = Math.min (self.get("maxItems"),auto.length);
|
||||
for (var i=0; i<max; i++)
|
||||
{ if (!i || !self.equalFeatures(auto[i], auto[i-1])) {
|
||||
$("<li>").html(self.getTitle(auto[i]))
|
||||
.data('search', auto[i])
|
||||
.click(function(e)
|
||||
{ self.select($(this).data('search'));
|
||||
})
|
||||
.appendTo(ul);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ol_control_Search.prototype.equalFeatures = function (f1, f2) {
|
||||
return false;
|
||||
};
|
||||
|
||||
export default ol_control_Search
|
||||
60
build/control/SearchBAN.js
Normal file
60
build/control/SearchBAN.js
Normal file
@ -0,0 +1,60 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
import ol from 'ol'
|
||||
import ol_proj from 'ol/proj'
|
||||
import ol_control_SearchPhoton from "./SearchPhoton";
|
||||
|
||||
/**
|
||||
* Search places using the French National Base Address (BAN) API.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.control.Search}
|
||||
* @fires select
|
||||
* @param {Object=} Control options.
|
||||
* @param {string} options.className control class name
|
||||
* @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.
|
||||
* @param {string | undefined} options.label Text label to use for the search button, default "search"
|
||||
* @param {string | undefined} options.placeholder placeholder, default "Search..."
|
||||
* @param {number | undefined} options.typing a delay on each typing to start searching (ms), default 500.
|
||||
* @param {integer | undefined} options.minLength minimum length to start searching, default 3
|
||||
* @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10
|
||||
*
|
||||
* @param {string|undefined} options.url Url to BAN api, default "https://api-adresse.data.gouv.fr/search/"
|
||||
* @param {boolean} options.position Search, with priority to geo position, default false
|
||||
* @param {function} options.getTitle a function that takes a feature and return the text to display in the menu, default return label attribute
|
||||
* @see {@link https://adresse.data.gouv.fr/api/}
|
||||
*/
|
||||
var ol_control_SearchBAN = function(options)
|
||||
{ options = options || {};
|
||||
options.typing = options.typing || 500;
|
||||
options.url = options.url || "https://api-adresse.data.gouv.fr/search/";
|
||||
ol.control.SearchPhoton.call(this, options);
|
||||
};
|
||||
ol.inherits(ol_control_SearchBAN, ol_control_SearchPhoton);
|
||||
|
||||
/** Returns the text to be displayed in the menu
|
||||
* @param {ol.Feature} f the feature
|
||||
* @return {string} the text to be displayed in the index
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchBAN.prototype.getTitle = function (f) {
|
||||
var p = f.properties;
|
||||
return (p.label);
|
||||
};
|
||||
|
||||
/** A ligne has been clicked in the menu > dispatch event
|
||||
* @param {any} f the feature, as passed in the autocomplete
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchBAN.prototype.select = function (f){
|
||||
var c = f.geometry.coordinates;
|
||||
// Add coordinate to the event
|
||||
try {
|
||||
c = ol_proj.transform (f.geometry.coordinates, 'EPSG:4326', this.getMap().getView().getProjection());
|
||||
} catch(e) {};
|
||||
this.dispatchEvent({ type:"select", search:f, coordinate: c });
|
||||
};
|
||||
|
||||
export default ol_control_SearchBAN
|
||||
81
build/control/SearchFeature.js
Normal file
81
build/control/SearchFeature.js
Normal file
@ -0,0 +1,81 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Search from './Search'
|
||||
|
||||
/**
|
||||
* Search features.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Search}
|
||||
* @fires select
|
||||
* @param {Object=} Control options.
|
||||
* @param {string} options.className control class name
|
||||
* @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.
|
||||
* @param {string | undefined} options.label Text label to use for the search button, default "search"
|
||||
* @param {string | undefined} options.placeholder placeholder, default "Search..."
|
||||
* @param {number | undefined} options.typing a delay on each typing to start searching (ms), default 300.
|
||||
* @param {integer | undefined} options.minLength minimum length to start searching, default 1
|
||||
* @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10
|
||||
*
|
||||
* @param {string | undefined} options.property a property to display in the index, default 'name'.
|
||||
* @param {function} options.getTitle a function that takes a feature and return the name to display in the index, default return the property
|
||||
* @param {function | undefined} options.getSearchString a function that take a feature and return a text to be used as search string, default geTitle() is used as search string
|
||||
*/
|
||||
var ol_control_SearchFeature = function(options)
|
||||
{ if (!options) options = {};
|
||||
|
||||
ol_control_Search.call(this, options);
|
||||
|
||||
if (typeof(options.getSearchString)=="function") this.getSearchString = options.getSearchString;
|
||||
this.set('property', options.property||'name');
|
||||
|
||||
this.source_ = options.source;
|
||||
};
|
||||
ol.inherits(ol_control_SearchFeature, ol_control_Search);
|
||||
|
||||
/** Returns the text to be displayed in the menu
|
||||
* @param {ol.Feature} f the feature
|
||||
* @return {string} the text to be displayed in the index
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchFeature.prototype.getTitle = function (f)
|
||||
{ return f.get(this.get('property')||'name');
|
||||
};
|
||||
|
||||
/** Return the string to search in
|
||||
* @param {ol.Feature} f the feature
|
||||
* @return {string} the text to be used as search string
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchFeature.prototype.getSearchString = function (f)
|
||||
{ return this.getTitle(f);
|
||||
}
|
||||
|
||||
/** Autocomplete function
|
||||
* @param {string} s search string
|
||||
* @param {int} max max
|
||||
* @param {function} cback a callback function that takes an array of {name, feature} to display in the autocomplete fielad
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchFeature.prototype.autocomplete = function (s, cback)
|
||||
{ var result = [];
|
||||
// regexp
|
||||
s = s.replace(/^\*/,'');
|
||||
var rex = new RegExp(s, 'i');
|
||||
// The source
|
||||
var features = this.source_.getFeatures();
|
||||
var max = this.get('maxItems')
|
||||
for (var i=0, f; f=features[i]; i++)
|
||||
{ if (rex.test(this.getSearchString(f)))
|
||||
{ result.push(f);
|
||||
if ((--max)<=0) break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default ol_control_SearchFeature
|
||||
128
build/control/SearchPhoton.js
Normal file
128
build/control/SearchPhoton.js
Normal file
@ -0,0 +1,128 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
import ol from 'ol'
|
||||
import ol_proj from 'ol/proj'
|
||||
import ol_control_Search from './Search'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
|
||||
/**
|
||||
* Search places using the photon API.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Search}
|
||||
* @fires select
|
||||
* @param {Object=} Control options.
|
||||
* @param {string} options.className control class name
|
||||
* @param {Element | string | undefined} options.target Specify a target if you want the control to be rendered outside of the map's viewport.
|
||||
* @param {string | undefined} options.label Text label to use for the search button, default "search"
|
||||
* @param {string | undefined} options.placeholder placeholder, default "Search..."
|
||||
* @param {number | undefined} options.typing a delay on each typing to start searching (ms), default 1000.
|
||||
* @param {integer | undefined} options.minLength minimum length to start searching, default 3
|
||||
* @param {integer | undefined} options.maxItems maximum number of items to display in the autocomplete list, default 10
|
||||
*
|
||||
* @param {string|undefined} options.url Url to photon api, default "http://photon.komoot.de/api/"
|
||||
* @param {string|undefined} options.lang Force preferred language, default none
|
||||
* @param {boolean} options.position Search, with priority to geo position, default false
|
||||
* @param {function} options.getTitle a function that takes a feature and return the name to display in the index, default return street + name + contry
|
||||
*/
|
||||
var ol_control_SearchPhoton = function(options)
|
||||
{ options = options || {};
|
||||
delete options.autocomplete;
|
||||
options.minLength = options.minLength || 3;
|
||||
options.typing = options.typing || 800;
|
||||
ol_control_Search.call(this, options);
|
||||
this.set('lang', options.lang);
|
||||
this.set('position', options.position);
|
||||
// Handle Mix Content Warning
|
||||
// If the current connection is an https connection all other connections must be https either
|
||||
var url = options.url || "http://photon.komoot.de/api/";
|
||||
if (window.location.protocol === "https:") {
|
||||
var parser = document.createElement('a');
|
||||
parser.href = url;
|
||||
parser.protocol = window.location.protocol;
|
||||
url = parser.href;
|
||||
}
|
||||
this.set('url', url);
|
||||
};
|
||||
ol.inherits(ol_control_SearchPhoton, ol_control_Search);
|
||||
|
||||
/** Returns the text to be displayed in the menu
|
||||
* @param {ol.Feature} f the feature
|
||||
* @return {string} the text to be displayed in the index
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchPhoton.prototype.getTitle = function (f)
|
||||
{ var p = f.properties;
|
||||
return (p.housenumber||"")
|
||||
+ " "+(p.street || p.name || "")
|
||||
+ "<i>"
|
||||
+ " "+(p.postcode||"")
|
||||
+ " "+(p.city||"")
|
||||
+ " ("+p.country
|
||||
+ ")</i>";
|
||||
};
|
||||
|
||||
/** Autocomplete function11
|
||||
* @param {string} s search string
|
||||
* @param {function} cback a callback function that takes an array of {name, feature} to display in the autocomplete fielad
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchPhoton.prototype.autocomplete = function (s, cback)
|
||||
{ var data =
|
||||
{ q: s,
|
||||
lang: this.get('lang'),
|
||||
limit: this.get('maxItems')
|
||||
}
|
||||
// Handle position proirity
|
||||
if (this.get('position'))
|
||||
{ var view = this.getMap().getView();
|
||||
var pt = new ol_geom_Point(view.getCenter());
|
||||
pt = (pt.transform (view.getProjection(), "EPSG:4326")).getCoordinates();
|
||||
|
||||
data.lon = pt[0];
|
||||
data.lat = pt[1];
|
||||
}
|
||||
|
||||
var url = this.get('url');
|
||||
$.support.cors = true;
|
||||
$.ajax(url,
|
||||
{ dataType: "json",
|
||||
//crossDomain: true,
|
||||
data: data,
|
||||
success: function(r) {
|
||||
cback(r.features);
|
||||
},
|
||||
error: function() {
|
||||
console.log(url, arguments);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/** Prevent same feature to be drawn twice: test equality
|
||||
* @param {} f1 First feature to compare
|
||||
* @param {} f2 Second feature to compare
|
||||
* @return {boolean}
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchPhoton.prototype.equalFeatures = function (f1, f2) {
|
||||
return (this.getTitle(f1) === this.getTitle(f2)
|
||||
&& f1.geometry.coordinates[0] === f2.geometry.coordinates[0]
|
||||
&& f1.geometry.coordinates[1] === f2.geometry.coordinates[1]);
|
||||
};
|
||||
|
||||
/** A ligne has been clicked in the menu > dispatch event
|
||||
* @param {any} f the feature, as passed in the autocomplete
|
||||
* @api
|
||||
*/
|
||||
ol_control_SearchPhoton.prototype.select = function (f)
|
||||
{ var c = f.geometry.coordinates;
|
||||
// Add coordinate to the event
|
||||
try {
|
||||
c = ol_proj.transform (f.geometry.coordinates, 'EPSG:4326', this.getMap().getView().getProjection());
|
||||
} catch(e) {};
|
||||
this.dispatchEvent({ type:"select", search:f, coordinate: c });
|
||||
};
|
||||
|
||||
export default ol_control_SearchPhoton
|
||||
59
build/control/Swipe.css
Normal file
59
build/control/Swipe.css
Normal file
@ -0,0 +1,59 @@
|
||||
.ol-swipe
|
||||
{ position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.ol-swipe:before
|
||||
{ content: "";
|
||||
position: absolute;
|
||||
top: -5000px;
|
||||
bottom: -5000px;
|
||||
left: 50%;
|
||||
width: 4px;
|
||||
background: #fff;
|
||||
z-index:-1;
|
||||
transform: translate(-2px, 0);
|
||||
-webkit-transform: translate(-2px, 0);
|
||||
}
|
||||
.ol-swipe.horizontal:before
|
||||
{ left: -5000px;
|
||||
right: -5000px;
|
||||
top: 50%;
|
||||
bottom: auto;
|
||||
width: auto;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.ol-swipe,
|
||||
.ol-swipe button
|
||||
{ cursor: ew-resize;
|
||||
}
|
||||
.ol-swipe.horizontal,
|
||||
.ol-swipe.horizontal button
|
||||
{ cursor: ns-resize;
|
||||
}
|
||||
|
||||
.ol-swipe:after,
|
||||
.ol-swipe button:before,
|
||||
.ol-swipe button:after
|
||||
{ content: "";
|
||||
position: absolute;
|
||||
top: 25%;
|
||||
bottom: 25%;
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
background: rgba(255,255,255,0.8);
|
||||
transform: translate(-1px, 0);
|
||||
-webkit-transform: translate(-1px, 0);
|
||||
}
|
||||
.ol-swipe button:after
|
||||
{ transform: translateX(5px);
|
||||
-webkit-transform: translateX(5px);
|
||||
}
|
||||
.ol-swipe button:before
|
||||
{ transform: translateX(-7px);
|
||||
-webkit-transform: translateX(-7px);
|
||||
}
|
||||
215
build/control/Swipe.js
Normal file
215
build/control/Swipe.js
Normal file
@ -0,0 +1,215 @@
|
||||
/* Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/**
|
||||
* @classdesc OpenLayers 3 swipe Control.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @param {Object=} Control opt_options.
|
||||
* - layers {ol.layer} layer to swipe
|
||||
* - rightLayer {ol.layer} layer to swipe on right side
|
||||
* - className {string} control class name
|
||||
* - position {number} position propertie of the swipe [0,1], default 0.5
|
||||
* - orientation {vertical|horizontal} orientation propertie, default vertical
|
||||
*/
|
||||
var ol_control_Swipe = function(opt_options)
|
||||
{ var options = opt_options || {};
|
||||
var self = this;
|
||||
|
||||
var button = document.createElement('button');
|
||||
|
||||
var element = document.createElement('div');
|
||||
element.className = (options.className || "ol-swipe") + " ol-unselectable ol-control";
|
||||
element.appendChild(button);
|
||||
|
||||
$(element).on ("mousedown touchstart", this, this.move );
|
||||
|
||||
ol_control_Control.call(this,
|
||||
{ element: element
|
||||
});
|
||||
|
||||
this.layers = [];
|
||||
if (options.layers) this.addLayer(options.layers, false);
|
||||
if (options.rightLayers) this.addLayer(options.rightLayers, true);
|
||||
|
||||
this.on('propertychange', function()
|
||||
{ if (this.getMap()) this.getMap().renderSync();
|
||||
if (this.get('orientation') === "horizontal")
|
||||
{ $(this.element).css("top", this.get('position')*100+"%");
|
||||
$(this.element).css("left", "");
|
||||
}
|
||||
else
|
||||
{ if (this.get('orientation') !== "vertical") this.set('orientation', "vertical");
|
||||
$(this.element).css("left", this.get('position')*100+"%");
|
||||
$(this.element).css("top", "");
|
||||
}
|
||||
$(this.element).removeClass("horizontal vertical");
|
||||
$(this.element).addClass(this.get('orientation'));
|
||||
}, this);
|
||||
|
||||
this.set('position', options.position || 0.5);
|
||||
this.set('orientation', options.orientation || 'vertical');
|
||||
};
|
||||
ol.inherits(ol_control_Swipe, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Set the map instance the control associated with.
|
||||
* @param {_ol_Map_} map The map instance.
|
||||
*/
|
||||
ol_control_Swipe.prototype.setMap = function(map)
|
||||
{
|
||||
if (this.getMap())
|
||||
{ for (var i=0; i<this.layers.length; i++)
|
||||
{ var l = this.layers[i];
|
||||
if (l.right) l.layer.un('precompose', this.precomposeRight, this);
|
||||
else l.layer.un('precompose', this.precomposeLeft, this);
|
||||
l.layer.un('postcompose', this.postcompose, this);
|
||||
}
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ for (var i=0; i<this.layers.length; i++)
|
||||
{ var l = this.layers[i];
|
||||
if (l.right) l.layer.on('precompose', this.precomposeRight, this);
|
||||
else l.layer.on('precompose', this.precomposeLeft, this);
|
||||
l.layer.on('postcompose', this.postcompose, this);
|
||||
}
|
||||
map.renderSync();
|
||||
}
|
||||
};
|
||||
|
||||
/** @private
|
||||
*/
|
||||
ol_control_Swipe.prototype.isLayer_ = function(layer)
|
||||
{ for (var k=0; k<this.layers.length; k++)
|
||||
{ if (this.layers[k].layer === layer) return k;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
/** Add a layer to clip
|
||||
* @param {ol.layer|Array<ol.layer>} layer to clip
|
||||
* @param {bool} add layer in the right part of the map, default left.
|
||||
*/
|
||||
ol_control_Swipe.prototype.addLayer = function(layers, right)
|
||||
{ if (!(layers instanceof Array)) layers = [layers];
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{var l = layers[i];
|
||||
if (this.isLayer_(l)<0)
|
||||
{ this.layers.push({ layer:l, right:right });
|
||||
if (this.getMap())
|
||||
{ if (right) l.on('precompose', this.precomposeRight, this);
|
||||
else l.on('precompose', this.precomposeLeft, this);
|
||||
l.on('postcompose', this.postcompose, this);
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Remove a layer to clip
|
||||
* @param {ol.layer|Array<ol.layer>} layer to clip
|
||||
*/
|
||||
ol_control_Swipe.prototype.removeLayer = function(layers)
|
||||
{ if (!(layers instanceof Array)) layers = [layers];
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ var k = this.isLayer_(layers[i]);
|
||||
if (k >=0 && this.getMap())
|
||||
{ if (this.layers[k].right) layers[i].un('precompose', this.precomposeRight, this);
|
||||
else layers[i].un('precompose', this.precomposeLeft, this);
|
||||
layers[i].un('postcompose', this.postcompose, this);
|
||||
this.layers.splice(k,1);
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** @private
|
||||
*/
|
||||
ol_control_Swipe.prototype.move = function(e)
|
||||
{ var self = e.data;
|
||||
switch (e.type)
|
||||
{ case 'touchcancel':
|
||||
case 'touchend':
|
||||
case 'mouseup':
|
||||
{ self.isMoving = false;
|
||||
$(document).off ("mouseup mousemove touchend touchcancel touchmove", self.move );
|
||||
break;
|
||||
}
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
{ self.isMoving = true;
|
||||
$(document).on ("mouseup mousemove touchend touchcancel touchmove", self, self.move );
|
||||
}
|
||||
case 'mousemove':
|
||||
case 'touchmove':
|
||||
{ if (self.isMoving)
|
||||
{ if (self.get('orientation') === "vertical")
|
||||
{ var pageX = e.pageX
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageX)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageX);
|
||||
if (!pageX) break;
|
||||
pageX -= $(self.getMap().getTargetElement()).offset().left;
|
||||
|
||||
var l = self.getMap().getSize()[0];
|
||||
l = Math.min(Math.max(0, 1-(l-pageX)/l), 1);
|
||||
self.set('position', l);
|
||||
}
|
||||
else
|
||||
{ var pageY = e.pageY
|
||||
|| (e.originalEvent.touches && e.originalEvent.touches.length && e.originalEvent.touches[0].pageY)
|
||||
|| (e.originalEvent.changedTouches && e.originalEvent.changedTouches.length && e.originalEvent.changedTouches[0].pageY);
|
||||
if (!pageY) break;
|
||||
pageY -= $(self.getMap().getTargetElement()).offset().top;
|
||||
|
||||
var l = self.getMap().getSize()[1];
|
||||
l = Math.min(Math.max(0, 1-(l-pageY)/l), 1);
|
||||
self.set('position', l);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
};
|
||||
|
||||
/** @private
|
||||
*/
|
||||
ol_control_Swipe.prototype.precomposeLeft = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
if (this.get('orientation') === "vertical") ctx.rect (0,0, canvas.width*this.get('position'), canvas.height);
|
||||
else ctx.rect (0,0, canvas.width, canvas.height*this.get('position'));
|
||||
ctx.clip();
|
||||
};
|
||||
|
||||
/** @private
|
||||
*/
|
||||
ol_control_Swipe.prototype.precomposeRight = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
if (this.get('orientation') === "vertical") ctx.rect (canvas.width*this.get('position'), 0, canvas.width, canvas.height);
|
||||
else ctx.rect (0,canvas.height*this.get('position'), canvas.width, canvas.height);
|
||||
ctx.clip();
|
||||
};
|
||||
|
||||
/** @private
|
||||
*/
|
||||
ol_control_Swipe.prototype.postcompose = function(e)
|
||||
{ e.context.restore();
|
||||
};
|
||||
|
||||
export default ol_control_Swipe
|
||||
153
build/control/Target.js
Normal file
153
build/control/Target.js
Normal file
@ -0,0 +1,153 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
import ol_style_RegularShape from 'ol/style/regularshape'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
import ol_Map from 'ol/map'
|
||||
|
||||
/** ol_control_Target draw a target at the center of the map.
|
||||
* @constructor
|
||||
* @param {Object} options
|
||||
* - style {ol.style.Style|Array<ol.style.Style>} ol.style.Stroke: draw a cross on the map, ol.style.Image: draw the image on the map
|
||||
* - composite {string} composite operation : difference|multiply|xor|screen|overlay|darken|lighter|lighten|...
|
||||
*/
|
||||
var ol_control_Target = function(options)
|
||||
{ options = options || {};
|
||||
|
||||
this.style = options.style ||
|
||||
[ new ol.style.Style({ image: new ol_style_RegularShape ({ points: 4, radius: 11, radius1: 0, radius2: 0, snapToPixel:true, stroke: new ol.style.Stroke({ color: "#fff", width:3 }) }) }),
|
||||
new ol.style.Style({ image: new ol_style_RegularShape ({ points: 4, radius: 11, radius1: 0, radius2: 0, snapToPixel:true, stroke: new ol.style.Stroke({ color: "#000", width:1 }) }) })
|
||||
];
|
||||
if (!(this.style instanceof Array)) this.style = [this.style];
|
||||
this.composite = options.composite || '';
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.className = "ol-target ol-unselectable ol-control";
|
||||
ol_control_Control.call(this,
|
||||
{ element: div,
|
||||
target: options.target
|
||||
});
|
||||
|
||||
this.setVisible(options.visible!==false);
|
||||
};
|
||||
ol.inherits(ol_control_Target, ol_control_Control);
|
||||
|
||||
/**
|
||||
* Remove the control from its current map and attach it to the new map.
|
||||
* Subclasses may set up event handlers to get notified about changes to
|
||||
* the map here.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Target.prototype.setMap = function (map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().un('postcompose', this.drawTarget_, this);
|
||||
if (this.getVisible()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ map.on('postcompose', this.drawTarget_, this);
|
||||
}
|
||||
};
|
||||
|
||||
/** Set the control visibility
|
||||
* @paraam {boolean} b
|
||||
*/
|
||||
ol_control_Target.prototype.setVisible = function (b)
|
||||
{ this.set("visible",b);
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
};
|
||||
|
||||
/** Get the control visibility
|
||||
* @return {boolean} b
|
||||
*/
|
||||
ol_control_Target.prototype.getVisible = function ()
|
||||
{ return this.get("visible");
|
||||
};
|
||||
|
||||
/** Draw the target
|
||||
* @private
|
||||
*/
|
||||
ol_control_Target.prototype.drawTarget_ = function (e)
|
||||
{ if (!this.getMap() || !this.getVisible()) return;
|
||||
var ctx = e.context;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
|
||||
ctx.save();
|
||||
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
var cx = ctx.canvas.width/(2*ratio);
|
||||
var cy = ctx.canvas.height/(2*ratio);
|
||||
var geom = new ol_geom_Point (this.getMap().getCoordinateFromPixel([cx,cy]));
|
||||
|
||||
if (this.composite) ctx.globalCompositeOperation = this.composite;
|
||||
|
||||
for (var i=0; i<this.style.length; i++)
|
||||
{ var style = this.style[i];
|
||||
|
||||
if (style instanceof ol.style.Style)
|
||||
{ var sc=0;
|
||||
// OL < v4.3 : setImageStyle don't check retina
|
||||
var imgs = ol_Map.prototype.getFeaturesAtPixel ? false : style.getImage();
|
||||
if (imgs)
|
||||
{ sc = imgs.getScale();
|
||||
imgs.setScale(ratio*sc);
|
||||
}
|
||||
e.vectorContext.setStyle(style);
|
||||
e.vectorContext.drawGeometry(geom);
|
||||
if (imgs) imgs.setScale(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for (var i=0; i<this.style.length; i++)
|
||||
{ var style = this.style[i];
|
||||
if (style.stroke instanceof ol.style.Stroke)
|
||||
{ ctx.lineWidth = style.stroke.getWidth();
|
||||
ctx.strokeStyle = ol.color.asString(style.stroke.getColor());
|
||||
var m = style.radius || 10;
|
||||
|
||||
var dx = cx + ctx.lineWidth/2;
|
||||
var dy = cy + ctx.lineWidth/2;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo (dx-m, dy);
|
||||
ctx.lineTo (dx+m, dy);
|
||||
ctx.moveTo (dx, dy-m);
|
||||
ctx.lineTo( dx, dy+m);
|
||||
ctx.stroke();
|
||||
}
|
||||
else if (style instanceof ol.style.Image)
|
||||
{ var img = style.getImage();
|
||||
ctx.drawImage(img, cx-img.width/2, cy-img.height/2);
|
||||
}
|
||||
else if (style instanceof ol.style.Text)
|
||||
{ ctx.font = style.getFont();
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.textAlign = "center";
|
||||
var fill = style.getFill();
|
||||
if (fill)
|
||||
{ ctx.fillStyle = ol.color.asString(fill.getColor());
|
||||
ctx.fillText(style.getText(), cx, cy);
|
||||
}
|
||||
var stroke = style.getStroke();
|
||||
if (stroke)
|
||||
{ ctx.lineWidth = stroke.getWidth();
|
||||
ctx.strokeStyle = ol.color.asString(stroke.getColor());
|
||||
ctx.strokeText(style.getText(), cx, cy);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_control_Target
|
||||
26
build/control/TextButton.js
Normal file
26
build/control/TextButton.js
Normal file
@ -0,0 +1,26 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Button from "./Button";
|
||||
|
||||
/** A simple push button control drawn as text
|
||||
* @constructor
|
||||
* @extends {ol_control_Button}
|
||||
* @param {Object=} options Control options.
|
||||
* @param {String} options.className class of the control
|
||||
* @param {String} options.title title of the control
|
||||
* @param {String} options.html html to insert in the control
|
||||
* @param {function} options.handleClick callback when control is clicked (or use change:active event)
|
||||
*/
|
||||
|
||||
var ol_control_TextButton = function(options)
|
||||
{ options = options || {};
|
||||
options.className = (options.className||"") + " ol-text-button";
|
||||
ol_control_Button.call(this, options);
|
||||
};
|
||||
ol.inherits(ol_control_TextButton, ol_control_Button);
|
||||
|
||||
export default ol_control_TextButton
|
||||
151
build/control/Toggle.js
Normal file
151
build/control/Toggle.js
Normal file
@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_control_Button from './Button'
|
||||
import ol_control_Control from 'ol/control/control'
|
||||
|
||||
/** A simple toggle control
|
||||
* The control can be created with an interaction to control its activation.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_control_Control}
|
||||
* @fires change:active, change:disable
|
||||
* @param {Object=} options Control options.
|
||||
* className {String} class of the control
|
||||
* title {String} title of the control
|
||||
* html {String} html to insert in the control
|
||||
* interaction {ol.interaction} interaction associated with the control
|
||||
* active {bool} the control is created active, default false
|
||||
* disable {bool} the control is created disabled, default false
|
||||
* bar {ol.control.Bar} a subbar associated with the control (drawn when active if control is nested in a ol.control.Bar)
|
||||
* autoActive {bool} the control will activate when shown in an ol.control.Bar, default false
|
||||
* onToggle {function} callback when control is clicked (or use change:active event)
|
||||
*/
|
||||
var ol_control_Toggle = function(options)
|
||||
{ options = options || {};
|
||||
var self = this;
|
||||
|
||||
this.interaction_ = options.interaction;
|
||||
if (this.interaction_)
|
||||
{ this.interaction_.on("change:active", function(e)
|
||||
{ self.setActive(!e.oldValue);
|
||||
});
|
||||
}
|
||||
|
||||
if (options.toggleFn) options.onToggle = options.toggleFn; // compat old version
|
||||
options.handleClick = function()
|
||||
{ self.toggle();
|
||||
if (options.onToggle) options.onToggle.call(self, self.getActive());
|
||||
};
|
||||
options.className = (options.className||"") + " ol-toggle";
|
||||
ol_control_Button.call(this, options);
|
||||
|
||||
this.set("title", options.title);
|
||||
|
||||
this.set ("autoActivate", options.autoActivate);
|
||||
if (options.bar)
|
||||
{ this.subbar_ = options.bar;
|
||||
this.subbar_.setTarget(this.element);
|
||||
$(this.subbar_.element).addClass("ol-option-bar");
|
||||
}
|
||||
|
||||
this.setActive (options.active);
|
||||
this.setDisable (options.disable);
|
||||
};
|
||||
ol.inherits(ol_control_Toggle, ol_control_Button);
|
||||
|
||||
/**
|
||||
* Set the map instance the control is associated with
|
||||
* and add interaction attached to it to this map.
|
||||
* @param {_ol_Map_} map The map instance.
|
||||
*/
|
||||
ol_control_Toggle.prototype.setMap = function(map)
|
||||
{ if (!map && this.getMap())
|
||||
{ if (this.interaction_)
|
||||
{ this.getMap().removeInteraction (this.interaction_);
|
||||
}
|
||||
if (this.subbar_) this.getMap().removeControl (this.subbar_);
|
||||
}
|
||||
|
||||
ol_control_Control.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ if (this.interaction_) map.addInteraction (this.interaction_);
|
||||
if (this.subbar_) map.addControl (this.subbar_);
|
||||
}
|
||||
};
|
||||
|
||||
/** Get the subbar associated with a control
|
||||
* @return {ol_control_Bar}
|
||||
*/
|
||||
ol_control_Toggle.prototype.getSubBar = function ()
|
||||
{ return this.subbar_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the control is disabled.
|
||||
* @return {bool}.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Toggle.prototype.getDisable = function()
|
||||
{ return $("button", this.element).prop("disabled");
|
||||
};
|
||||
|
||||
/** Disable the control. If disable, the control will be deactivated too.
|
||||
* @param {bool} b disable (or enable) the control, default false (enable)
|
||||
*/
|
||||
ol_control_Toggle.prototype.setDisable = function(b)
|
||||
{ if (this.getDisable()==b) return;
|
||||
$("button", this.element).prop("disabled", b);
|
||||
if (b && this.getActive()) this.setActive(false);
|
||||
|
||||
this.dispatchEvent({ type:'change:disable', key:'disable', oldValue:!b, disable:b });
|
||||
};
|
||||
|
||||
/**
|
||||
* Test if the control is active.
|
||||
* @return {bool}.
|
||||
* @api stable
|
||||
*/
|
||||
ol_control_Toggle.prototype.getActive = function()
|
||||
{ return $(this.element).hasClass("ol-active");
|
||||
};
|
||||
|
||||
/** Toggle control state active/deactive
|
||||
*/
|
||||
ol_control_Toggle.prototype.toggle = function()
|
||||
{ if (this.getActive()) this.setActive(false);
|
||||
else this.setActive(true);
|
||||
};
|
||||
|
||||
/** Change control state
|
||||
* @param {bool} b activate or deactivate the control, default false
|
||||
*/
|
||||
ol_control_Toggle.prototype.setActive = function(b)
|
||||
{ if (this.getActive()==b) return;
|
||||
if (b) $(this.element).addClass("ol-active");
|
||||
else $(this.element).removeClass("ol-active");
|
||||
if (this.interaction_) this.interaction_.setActive (b);
|
||||
if (this.subbar_) this.subbar_.setActive(b);
|
||||
|
||||
this.dispatchEvent({ type:'change:active', key:'active', oldValue:!b, active:b });
|
||||
};
|
||||
|
||||
/** Set the control interaction
|
||||
* @param {_ol_interaction_} i interaction to associate with the control
|
||||
*/
|
||||
ol_control_Toggle.prototype.setInteraction = function(i)
|
||||
{ this.interaction_ = i;
|
||||
};
|
||||
|
||||
/** Get the control interaction
|
||||
* @return {_ol_interaction_} interaction associated with the control
|
||||
*/
|
||||
ol_control_Toggle.prototype.getInteraction = function()
|
||||
{ return this.interaction_;
|
||||
};
|
||||
|
||||
export default ol_control_Toggle
|
||||
BIN
build/control/piratecontrol.jpg
Normal file
BIN
build/control/piratecontrol.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
BIN
build/control/piratecontrol.png
Normal file
BIN
build/control/piratecontrol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
528
build/control/piratecontrol.svg
Normal file
528
build/control/piratecontrol.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 46 KiB |
45
build/featureanimation/Bounce.js
Normal file
45
build/featureanimation/Bounce.js
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Bounce animation:
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationBounceOptions} options
|
||||
* @param {Integer} options.bounce number of bounce, default 3
|
||||
* @param {Integer} options.amplitude bounce amplitude,default 40
|
||||
* @param {ol.easing} options.easing easing used for decaying amplitude, use function(){return 0} for no decay, default ol.easing.linear
|
||||
* @param {Integer} options.duration duration in ms, default 1000
|
||||
*/
|
||||
var ol_featureAnimation_Bounce = function(options)
|
||||
{ options = options || {};
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.amplitude_ = options.amplitude || 40;
|
||||
this.bounce_ = -Math.PI*(options.bounce || 3);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Bounce, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Bounce.prototype.animate = function (e)
|
||||
{ // Animate
|
||||
var flashGeom = e.geom.clone();
|
||||
|
||||
/*
|
||||
var t = this.easing_(e.elapsed)
|
||||
t = Math.abs(Math.sin(this.bounce_*t)) * this.amplitude_ * (1-t) * e.frameState.viewState.resolution;
|
||||
*/
|
||||
var t = Math.abs(Math.sin(this.bounce_*e.elapsed)) * this.amplitude_ * (1-this.easing_(e.elapsed)) * e.frameState.viewState.resolution;
|
||||
flashGeom.translate(0, t);
|
||||
this.drawGeom_(e, flashGeom, e.geom);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Bounce
|
||||
51
build/featureanimation/Drop.js
Normal file
51
build/featureanimation/Drop.js
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Drop animation: drop a feature on the map
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationDropOptions} options
|
||||
* @param {Number} options.speed speed of the feature if 0 the duration parameter will be used instead, default 0
|
||||
* @param {Number} options.side top or bottom, default top
|
||||
*/
|
||||
var ol_featureAnimation_Drop = function(options)
|
||||
{ options = options || {};
|
||||
this.speed_ = options.speed || 0;
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.side_ = options.side || 'top';
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Drop, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Drop.prototype.animate = function (e)
|
||||
{ // First time > calculate duration / speed
|
||||
if (!e.time)
|
||||
{ var angle = e.frameState.viewState.rotation;
|
||||
var s = e.frameState.size[1] * e.frameState.viewState.resolution;
|
||||
if (this.side_!='top') s *= -1;
|
||||
this.dx = -Math.sin(angle)*s;
|
||||
this.dy = Math.cos(angle)*s;
|
||||
if (this.speed_)
|
||||
{ this.duration_ = s/this.speed_/e.frameState.viewState.resolution;
|
||||
}
|
||||
}
|
||||
// Animate
|
||||
var flashGeom = e.geom.clone();
|
||||
flashGeom.translate(
|
||||
this.dx*(1-this.easing_(e.elapsed)),
|
||||
this.dy*(1-this.easing_(e.elapsed))
|
||||
);
|
||||
this.drawGeom_(e, flashGeom, e.geom);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Drop
|
||||
32
build/featureanimation/Fade.js
Normal file
32
build/featureanimation/Fade.js
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Fade animation: feature fade in
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationOptions} options
|
||||
*/
|
||||
var ol_featureAnimation_Fade = function(options)
|
||||
{ options = options || {};
|
||||
this.speed_ = options.speed || 0;
|
||||
ol_featureAnimation.call(this, options);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Fade, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Fade.prototype.animate = function (e)
|
||||
{ e.context.globalAlpha = this.easing_(e.elapsed);
|
||||
this.drawGeom_(e, e.geom);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Fade
|
||||
231
build/featureanimation/FeatureAnimation.js
Normal file
231
build/featureanimation/FeatureAnimation.js
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_Object from 'ol/object'
|
||||
import ol_easing from 'ol/easing'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_extent from 'ol/extent'
|
||||
import ol_Observable from 'ol/observable'
|
||||
|
||||
/** Feature animation base class
|
||||
* Use the {@link _ol_Map_#animateFeature} or {@link _ol_layer_Vector_#animateFeature} to animate a feature
|
||||
* on postcompose in a map or a layer
|
||||
* @constructor
|
||||
* @fires animationstart|animationend
|
||||
* @param {ol_featureAnimationOptions} options
|
||||
* @param {Number} options.duration duration of the animation in ms, default 1000
|
||||
* @param {bool} options.revers revers the animation direction
|
||||
* @param {Number} options.repeat number of time to repeat the animation, default 0
|
||||
* @param {oo.style.Style} options.hiddenStyle a style to display the feature when playing the animation
|
||||
* to be used to make the feature selectable when playing animation
|
||||
* (@see {@link ../examples/map.featureanimation.select.html}), default the feature
|
||||
* will be hidden when playing (and niot selectable)
|
||||
* @param {ol_easing_Function} options.fade an easing function used to fade in the feature, default none
|
||||
* @param {ol_easing_Function} options.easing an easing function for the animation, default ol_easing.linear
|
||||
*/
|
||||
var ol_featureAnimation = function(options)
|
||||
{ options = options || {};
|
||||
|
||||
this.duration_ = typeof (options.duration)=='number' ? (options.duration>=0 ? options.duration : 0) : 1000;
|
||||
this.fade_ = typeof(options.fade) == 'function' ? options.fade : null;
|
||||
this.repeat_ = Number(options.repeat);
|
||||
|
||||
var easing = typeof(options.easing) =='function' ? options.easing : ol_easing.linear;
|
||||
if (options.revers) this.easing_ = function(t) { return (1 - easing(t)); };
|
||||
else this.easing_ = easing;
|
||||
|
||||
this.hiddenStyle = options.hiddenStyle;
|
||||
|
||||
ol_Object.call(this);
|
||||
};
|
||||
ol.inherits(ol_featureAnimation, ol_Object);
|
||||
|
||||
/** Draw a geometry
|
||||
* @param {olx.animateFeatureEvent} e
|
||||
* @param {ol.geom} geom geometry for shadow
|
||||
* @param {ol.geom} shadow geometry for shadow (ie. style with zIndex = -1)
|
||||
* @private
|
||||
*/
|
||||
ol_featureAnimation.prototype.drawGeom_ = function (e, geom, shadow)
|
||||
{ if (this.fade_)
|
||||
{ e.context.globalAlpha = this.fade_(1-e.elapsed);
|
||||
}
|
||||
var style = e.style;
|
||||
for (var i=0; i<style.length; i++)
|
||||
{ var sc=0;
|
||||
// OL < v4.3 : setImageStyle doesn't check retina
|
||||
var imgs = ol_Map.prototype.getFeaturesAtPixel ? false : style[i].getImage();
|
||||
if (imgs)
|
||||
{ sc = imgs.getScale();
|
||||
imgs.setScale(e.frameState.pixelRatio*sc);
|
||||
}
|
||||
// Prevent crach if the style is not ready (image not loaded)
|
||||
try{
|
||||
e.vectorContext.setStyle(style[i]);
|
||||
if (style[i].getZIndex()<0) e.vectorContext.drawGeometry(shadow||geom);
|
||||
else e.vectorContext.drawGeometry(geom);
|
||||
} catch(e) {};
|
||||
if (imgs) imgs.setScale(sc);
|
||||
}
|
||||
};
|
||||
|
||||
/** Function to perform manipulations onpostcompose.
|
||||
* This function is called with an ol_featureAnimationEvent argument.
|
||||
* The function will be overridden by the child implementation.
|
||||
* Return true to keep this function for the next frame, false to remove it.
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
* @return {bool} true to continue animation.
|
||||
* @api
|
||||
*/
|
||||
ol_featureAnimation.prototype.animate = function (e)
|
||||
{ return false;
|
||||
};
|
||||
|
||||
/** An animation controler object an object to control animation with start, stop and isPlaying function.
|
||||
* To be used with {@link olx.Map#animateFeature} or {@link ol.layer.Vector#animateFeature}
|
||||
* @typedef {Object} ol.animationControler
|
||||
* @property {function} start - start animation.
|
||||
* @property {function} stop - stop animation option arguments can be passed in animationend event.
|
||||
* @property {function} isPlaying - return true if animation is playing.
|
||||
*/
|
||||
|
||||
/** Animate feature on a map
|
||||
* @function
|
||||
* @fires animationstart, animationend
|
||||
* @param {ol.Feature} feature Feature to animate
|
||||
* @param {ol_featureAnimation|Array<ol_featureAnimation>} fanim the animation to play
|
||||
* @return {olx.animationControler} an object to control animation with start, stop and isPlaying function
|
||||
*/
|
||||
ol_Map.prototype.animateFeature =
|
||||
|
||||
/** Animate feature on a vector layer
|
||||
* @fires animationstart, animationend
|
||||
* @param {ol.Feature} feature Feature to animate
|
||||
* @param {ol_featureAnimation|Array<ol_featureAnimation>} fanim the animation to play
|
||||
* @return {olx.animationControler} an object to control animation with start, stop and isPlaying function
|
||||
*/
|
||||
ol_layer_Vector.prototype.animateFeature = function(feature, fanim)
|
||||
{ var self = this;
|
||||
var listenerKey;
|
||||
|
||||
// Save style
|
||||
var style = feature.getStyle();
|
||||
var flashStyle = style || (this.getStyleFunction ? this.getStyleFunction()(feature) : null);
|
||||
if (!flashStyle) flashStyle=[];
|
||||
if (!(flashStyle instanceof Array)) flashStyle = [flashStyle];
|
||||
|
||||
// Hide feature while animating
|
||||
feature.setStyle(fanim.hiddenStyle || []);
|
||||
|
||||
// Structure pass for animating
|
||||
var event =
|
||||
{ // Frame context
|
||||
vectorContext: null,
|
||||
frameState: null,
|
||||
start: 0,
|
||||
time: 0,
|
||||
elapsed: 0,
|
||||
extent: false,
|
||||
// Feature information
|
||||
feature: feature,
|
||||
geom: feature.getGeometry(),
|
||||
typeGeom: feature.getGeometry().getType(),
|
||||
bbox: feature.getGeometry().getExtent(),
|
||||
coord: ol_extent.getCenter(feature.getGeometry().getExtent()),
|
||||
style: flashStyle
|
||||
};
|
||||
|
||||
if (!(fanim instanceof Array)) fanim = [fanim];
|
||||
// Remove null animations
|
||||
for (var i=fanim.length-1; i>=0; i--)
|
||||
{ if (fanim[i].duration_===0) fanim.splice(i,1);
|
||||
}
|
||||
|
||||
var nb=0, step = 0;
|
||||
|
||||
function animate(e)
|
||||
{ event.vectorContext = e.vectorContext;
|
||||
event.frameState = e.frameState;
|
||||
if (!event.extent)
|
||||
{ event.extent = e.frameState.extent;
|
||||
event.start = e.frameState.time;
|
||||
event.context = e.context;
|
||||
}
|
||||
event.time = e.frameState.time - event.start;
|
||||
event.elapsed = event.time / fanim[step].duration_;
|
||||
if (event.elapsed > 1) event.elapsed = 1;
|
||||
|
||||
// Stop animation?
|
||||
if (!fanim[step].animate(event))
|
||||
{ nb++;
|
||||
// Repeat animation
|
||||
if (nb < fanim[step].repeat_)
|
||||
{ event.extent = false;
|
||||
}
|
||||
// newt step
|
||||
else if (step < fanim.length-1)
|
||||
{ fanim[step].dispatchEvent({ type:'animationend', feature: feature });
|
||||
step++;
|
||||
nb=0;
|
||||
event.extent = false;
|
||||
}
|
||||
// the end
|
||||
else
|
||||
{ stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tell OL3 to continue postcompose animation
|
||||
e.frameState.animate = true;
|
||||
}
|
||||
|
||||
// Stop animation
|
||||
function stop(options)
|
||||
{ ol_Observable.unByKey(listenerKey);
|
||||
listenerKey = null;
|
||||
feature.setStyle(style);
|
||||
// Send event
|
||||
var event = { type:'animationend', feature: feature };
|
||||
if (options)
|
||||
{ for (var i in options) if (options.hasOwnProperty(i))
|
||||
{ event[i] = options[i];
|
||||
}
|
||||
}
|
||||
fanim[step].dispatchEvent(event);
|
||||
self.dispatchEvent(event);
|
||||
}
|
||||
|
||||
// Launch animation
|
||||
function start(options)
|
||||
{ if (fanim.length && !listenerKey)
|
||||
{ listenerKey = self.on('postcompose', animate, self);
|
||||
// map or layer?
|
||||
if (self.renderSync) self.renderSync();
|
||||
else self.changed();
|
||||
// Send event
|
||||
var event = { type:'animationstart', feature: feature };
|
||||
if (options)
|
||||
{ for (var i in options) if (options.hasOwnProperty(i))
|
||||
{ event[i] = options[i];
|
||||
}
|
||||
}
|
||||
fanim[step].dispatchEvent(event);
|
||||
self.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
start();
|
||||
|
||||
// Return animation controler
|
||||
return {
|
||||
start: start,
|
||||
stop: stop,
|
||||
isPlaying: function() { return (!!listenerKey); }
|
||||
};
|
||||
};
|
||||
|
||||
export default ol_featureAnimation
|
||||
29
build/featureanimation/None.js
Normal file
29
build/featureanimation/None.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Do nothing for a given duration
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationShowOptions} options
|
||||
*
|
||||
*/
|
||||
var ol_featureAnimation_None = function(options)
|
||||
{ ol_featureAnimation.call(this, options);
|
||||
};
|
||||
ol.inherits(ol_featureAnimation_None, ol_featureAnimation);
|
||||
|
||||
/** Animate: do nothing during the laps time
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_None.prototype.animate = function (e)
|
||||
{
|
||||
return (e.time <= this.duration_);
|
||||
};
|
||||
|
||||
export default ol_featureAnimation_None
|
||||
18
build/featureanimation/Null.js
Normal file
18
build/featureanimation/Null.js
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Do nothing
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationShowOptions} options
|
||||
*/
|
||||
var ol_featureAnimation_Null = function(options)
|
||||
{ ol_featureAnimation.call(this, { duration:0 });
|
||||
};
|
||||
ol.inherits(ol_featureAnimation_Null, ol_featureAnimation);
|
||||
65
build/featureanimation/Path.js
Normal file
65
build/featureanimation/Path.js
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Path animation: feature follow a path
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationPathOptions} options
|
||||
* @param {Number} options.speed speed of the feature, if 0 the duration parameter will be used instead, default 0
|
||||
* @param {ol.geom.LineString|ol.Feature} options.path the path to follow
|
||||
*/
|
||||
var ol_featureAnimation_Path = function(options)
|
||||
{ options = options || {};
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.speed_ = options.speed || 0;
|
||||
this.path_ = options.path;
|
||||
if (this.path_ && this.path_.getGeometry) this.path_ = this.path_.getGeometry();
|
||||
if (this.path_ && this.path_.getLineString) this.path_ = this.path_.getLineString();
|
||||
if (this.path_.getLength)
|
||||
{ this.dist_ = this.path_.getLength()
|
||||
if (this.path_ && this.path_.getCoordinates) this.path_ = this.path_.getCoordinates();
|
||||
}
|
||||
else this.dist_ = 0;
|
||||
if (this.speed_>0) this.duration_ = this.dist_/this.speed_;
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Path, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Path.prototype.animate = function (e)
|
||||
{ // First time
|
||||
if (!e.time)
|
||||
{ if (!this.dist_) return false;
|
||||
}
|
||||
var dmax = this.dist_*this.easing_(e.elapsed);
|
||||
var p0, p, dx,dy, dl, d = 0;
|
||||
p = this.path_[0];
|
||||
// Linear interpol
|
||||
for (var i = 1; i<this.path_.length; i++)
|
||||
{ p0 = p;
|
||||
p = this.path_[i];
|
||||
dx = p[0]-p0[0];
|
||||
dy = p[1]-p0[1];
|
||||
dl = Math.sqrt(dx*dx+dy*dy);
|
||||
if (dl && d+dl>=dmax)
|
||||
{ var s = (dmax-d)/dl;
|
||||
p = [ p0[0] + (p[0]-p0[0])*s, p0[1] + (p[1]-p0[1])*s];
|
||||
break;
|
||||
}
|
||||
d += dl;
|
||||
}
|
||||
e.geom.setCoordinates(p);
|
||||
// Animate
|
||||
this.drawGeom_(e, e.geom);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Path
|
||||
48
build/featureanimation/Shake.js
Normal file
48
build/featureanimation/Shake.js
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Shakee animation:
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationShakeOptions} options
|
||||
* @param {Integer} options.bounce number o bounds, default 6
|
||||
* @param {Integer} options.amplitude amplitude of the animation, default 40
|
||||
* @param {bool} options.horizontal shake horizontally default false (vertical)
|
||||
*/
|
||||
var ol_featureAnimation_Shake = function(options)
|
||||
{ options = options || {};
|
||||
ol_featureAnimation.call(this, options);
|
||||
// this.easing_ = options.easing_ || function(t){return (0.5+t)*t -0.5*t ;};
|
||||
this.amplitude_ = options.amplitude || 40;
|
||||
this.bounce_ = -Math.PI*(options.bounce || 6);
|
||||
this.horizontal_ = options.horizontal;
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Shake, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Shake.prototype.animate = function (e)
|
||||
{ // Animate
|
||||
var flashGeom = e.geom.clone();
|
||||
var shadow = e.geom.clone();
|
||||
|
||||
var t = this.easing_(e.elapsed)
|
||||
t = Math.sin(this.bounce_*t) * this.amplitude_ * (1-t) * e.frameState.viewState.resolution;
|
||||
if (this.horizontal_)
|
||||
{ flashGeom.translate(t, 0);
|
||||
shadow.translate(t, 0);
|
||||
}
|
||||
else flashGeom.translate(0, t);
|
||||
this.drawGeom_(e, flashGeom, shadow);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Shake
|
||||
29
build/featureanimation/Show.js
Normal file
29
build/featureanimation/Show.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Show an object for a given duration
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationOptions} options
|
||||
*/
|
||||
var ol_featureAnimation_Show = function(options)
|
||||
{ ol_featureAnimation.call(this, options);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Show, ol_featureAnimation);
|
||||
|
||||
/** Animate: just show the object during the laps time
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Show.prototype.animate = function (e)
|
||||
{
|
||||
this.drawGeom_(e, e.geom);
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Show
|
||||
42
build/featureanimation/Slide.js
Normal file
42
build/featureanimation/Slide.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Slice animation: feature enter from left
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationSlideOptions} options
|
||||
* @param {Number} options.speed speed of the animation, if 0 the duration parameter will be used instead, default 0
|
||||
*/
|
||||
var ol_featureAnimation_Slide = function(options)
|
||||
{ options = options || {};
|
||||
this.speed_ = options.speed || 0;
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.side_ = options.side || 'left';
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Slide, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Slide.prototype.animate = function (e)
|
||||
{ // First time > calculate duration / speed
|
||||
if (!e.time)
|
||||
{ if (this.side_=='left') this.dx = (e.extent[0]-e.bbox[2])
|
||||
else this.dx = (e.extent[2]-e.bbox[0])
|
||||
if (this.speed_) this.duration_ = Math.abs(this.dx)/this.speed_/e.frameState.viewState.resolution;
|
||||
}
|
||||
// Animate
|
||||
var flashGeom = e.geom.clone();
|
||||
flashGeom.translate(this.dx*(1-this.easing_(e.elapsed)), 0);
|
||||
this.drawGeom_(e, flashGeom);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Slide
|
||||
41
build/featureanimation/Teleport.js
Normal file
41
build/featureanimation/Teleport.js
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Teleport a feature at a given place
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationOptions} options
|
||||
*/
|
||||
var ol_featureAnimation_Teleport = function(options)
|
||||
{ ol_featureAnimation.call(this, options);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Teleport, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Teleport.prototype.animate = function (e)
|
||||
{ var sc = this.easing_(e.elapsed);
|
||||
if (sc)
|
||||
{ e.context.save()
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
e.context.globalAlpha = sc;
|
||||
e.context.scale(sc,1/sc);
|
||||
var m = e.frameState.coordinateToPixelTransform;
|
||||
var dx = (1/sc-1) * ratio * (m[0]*e.coord[0] + m[1]*e.coord[1] +m[4]);
|
||||
var dy = (sc-1) * ratio * (m[2]*e.coord[0] + m[3]*e.coord[1] +m[5]);
|
||||
e.context.translate(dx,dy);
|
||||
this.drawGeom_(e, e.geom);
|
||||
e.context.restore()
|
||||
}
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Teleport
|
||||
53
build/featureanimation/Throw.js
Normal file
53
build/featureanimation/Throw.js
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Slice animation: feature enter from left
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationThrowOptions} options
|
||||
* @param {left|right} options.side side of the animation, default left
|
||||
*/
|
||||
var ol_featureAnimation_Throw = function(options)
|
||||
{ options = options || {};
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.speed_ = options.speed || 0;
|
||||
this.side_ = options.side || 'left';
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Throw, ol_featureAnimation);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Throw.prototype.animate = function (e)
|
||||
{ // First time > calculate duration / speed
|
||||
if (!e.time && this.speed_)
|
||||
{ var dx, dy;
|
||||
if (this.side_=='left')
|
||||
{ dx = this.dx = e.extent[0]-e.bbox[2];
|
||||
dy = this.dy = e.extent[3]-e.bbox[1];
|
||||
}
|
||||
else
|
||||
{ dx = this.dx = e.extent[2]-e.bbox[0];
|
||||
dy = this.dy = e.extent[3]-e.bbox[1];
|
||||
}
|
||||
this.duration_ = Math.sqrt(dx*dx+dy*dy)/this.speed_/e.frameState.viewState.resolution;
|
||||
}
|
||||
// Animate
|
||||
var flashGeom = e.geom.clone();
|
||||
var shadow = e.geom.clone();
|
||||
|
||||
flashGeom.translate(this.dx*(1-this.easing_(e.elapsed)),
|
||||
this.dy*Math.cos(Math.PI/2*this.easing_(e.elapsed)));
|
||||
shadow.translate(this.dx*(1-this.easing_(e.elapsed)), 0);
|
||||
this.drawGeom_(e, flashGeom, shadow);
|
||||
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export default ol_featureAnimation_Throw
|
||||
86
build/featureanimation/Zoom.js
Normal file
86
build/featureanimation/Zoom.js
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL license (http://www.cecill.info/).
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_featureAnimation from './FeatureAnimation'
|
||||
|
||||
/** Zoom animation: feature zoom in (for points)
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationZoomOptions} options
|
||||
* @param {bool} options.zoomOut to zoom out
|
||||
*/
|
||||
var ol_featureAnimation_Zoom = function(options)
|
||||
{ options = options || {};
|
||||
ol_featureAnimation.call(this, options);
|
||||
this.set('zoomout', options.zoomOut);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_Zoom, ol_featureAnimation);
|
||||
|
||||
|
||||
/** Zoom animation: feature zoom out (for points)
|
||||
* @constructor
|
||||
* @extends {ol_featureAnimation}
|
||||
* @param {ol_featureAnimationZoomOptions} options
|
||||
*/
|
||||
var ol_featureAnimation_ZoomOut = function(options)
|
||||
{ options = options || {};
|
||||
options.zoomOut = true;
|
||||
ol_featureAnimation_Zoom.call(this, options);
|
||||
}
|
||||
ol.inherits(ol_featureAnimation_ZoomOut, ol_featureAnimation_Zoom);
|
||||
|
||||
/** Animate
|
||||
* @param {ol_featureAnimationEvent} e
|
||||
*/
|
||||
ol_featureAnimation_Zoom.prototype.animate = function (e)
|
||||
{ var fac = this.easing_(e.elapsed);
|
||||
if (fac)
|
||||
{ if (this.get('zoomout')) fac = 1/fac;
|
||||
var style = e.style;
|
||||
var imgs, sc=[]
|
||||
for (var i=0; i<style.length; i++)
|
||||
{ imgs = style[i].getImage();
|
||||
if (imgs)
|
||||
{ sc[i] = imgs.getScale();
|
||||
imgs.setScale(sc[i]*fac);
|
||||
}
|
||||
}
|
||||
|
||||
e.context.save()
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
var m = e.frameState.coordinateToPixelTransform;
|
||||
var dx = (1/fac-1)* ratio * (m[0]*e.coord[0] + m[1]*e.coord[1] +m[4]);
|
||||
var dy = (1/fac-1)* ratio * (m[2]*e.coord[0] + m[3]*e.coord[1] +m[5]);
|
||||
e.context.scale(fac,fac);
|
||||
e.context.translate(dx,dy);
|
||||
this.drawGeom_(e, e.geom);
|
||||
e.context.restore()
|
||||
|
||||
for (var i=0; i<style.length; i++)
|
||||
{ imgs = style[i].getImage();
|
||||
if (imgs) imgs.setScale(sc[i]);
|
||||
}
|
||||
}
|
||||
/*
|
||||
var sc = this.easing_(e.elapsed);
|
||||
if (sc)
|
||||
{ e.context.save()
|
||||
console.log(e)
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
var m = e.frameState.coordinateToPixelTransform;
|
||||
var dx = (1/(sc)-1)* ratio * (m[0]*e.coord[0] + m[1]*e.coord[1] +m[4]);
|
||||
var dy = (1/(sc)-1)*ratio * (m[2]*e.coord[0] + m[3]*e.coord[1] +m[5]);
|
||||
e.context.scale(sc,sc);
|
||||
e.context.translate(dx,dy);
|
||||
this.drawGeom_(e, e.geom);
|
||||
e.context.restore()
|
||||
}
|
||||
*/
|
||||
return (e.time <= this.duration_);
|
||||
}
|
||||
|
||||
export {ol_featureAnimation_Zoom, ol_featureAnimation_ZoomOut}
|
||||
140
build/filter/Base.js
Normal file
140
build/filter/Base.js
Normal file
@ -0,0 +1,140 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_layer_Base from 'ol/layer/base'
|
||||
import ol_Object from 'ol/object'
|
||||
import ol_Map from 'ol/map'
|
||||
|
||||
var ol_filter = {};
|
||||
/**
|
||||
* @classdesc
|
||||
* Abstract base class; normally only used for creating subclasses and not instantiated in apps.
|
||||
* Used to create filters
|
||||
* Use {@link _ol_Map_#addFilter}, {@link _ol_Map_#removeFilter} or {@link _ol_Map_#getFilters} to handle filters on a map.
|
||||
* Use {@link ol_layer_Base#addFilter}, {@link ol_layer_Base#removeFilter} or {@link ol_layer_Base#getFilters}
|
||||
* to handle filters on layers.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.Object}
|
||||
* @param {} options Extend {@link _ol_control_Control_} options.
|
||||
* @param {bool} options.active
|
||||
*/
|
||||
var ol_filter_Base = function(options)
|
||||
{ ol_Object.call(this);
|
||||
if (options && options.active===false) this.set('active', false);
|
||||
else this.set('active', true);
|
||||
};
|
||||
ol.inherits(ol_filter_Base, ol_Object);
|
||||
|
||||
/** Activate / deactivate filter
|
||||
* @param {bool} b
|
||||
*/
|
||||
ol_filter_Base.prototype.setActive = function (b)
|
||||
{ this.set('active', b===true);
|
||||
};
|
||||
|
||||
/** Get filter active
|
||||
* @return {bool}
|
||||
*/
|
||||
ol_filter_Base.prototype.getActive = function (b)
|
||||
{ return this.get('active');
|
||||
};
|
||||
|
||||
(function(){
|
||||
|
||||
/** Internal function
|
||||
* @scoop {ol.filter} this the filter
|
||||
* @private
|
||||
*/
|
||||
function precompose_(e)
|
||||
{ if (this.get('active')) this.precompose(e);
|
||||
}
|
||||
/** Internal function
|
||||
* @scoop {ol.filter} this the filter
|
||||
* @private
|
||||
*/
|
||||
function postcompose_(e)
|
||||
{ if (this.get('active')) this.postcompose(e);
|
||||
}
|
||||
/** Force filter redraw / Internal function
|
||||
* @scoop {ol.map||ol.layer} this: the map or layer the filter is added to
|
||||
* @private
|
||||
*/
|
||||
function filterRedraw_(e)
|
||||
{ if (this.renderSync) this.renderSync();
|
||||
else this.changed();
|
||||
}
|
||||
|
||||
/** Add a filter to an ol object
|
||||
* @scoop {ol.map||ol.layer} this: the map or layer the filter is added to
|
||||
* @private
|
||||
*/
|
||||
function addFilter_(filter)
|
||||
{ if (!this.filters_) this.filters_ = [];
|
||||
this.filters_.push(filter);
|
||||
if (filter.precompose) this.on('precompose', precompose_, filter);
|
||||
if (filter.postcompose) this.on('postcompose', postcompose_, filter);
|
||||
filter.on('propertychange', filterRedraw_, this);
|
||||
filterRedraw_.call (this);
|
||||
};
|
||||
|
||||
/** Remove a filter to an ol object
|
||||
* @scoop {ol.map||ol.layer} this: the map or layer the filter is added to
|
||||
* @private
|
||||
*/
|
||||
function removeFilter_(filter)
|
||||
{ if (!this.filters_) this.filters_ = [];
|
||||
for (var i=this.filters_.length-1; i>=0; i--)
|
||||
{ if (this.filters_[i]===filter) this.filters_.splice(i,1);
|
||||
}
|
||||
if (filter.precompose) this.un('precompose', precompose_, filter);
|
||||
if (filter.postcompose) this.un('postcompose', postcompose_, filter);
|
||||
filter.un('propertychange', filterRedraw_, this);
|
||||
filterRedraw_.call (this);
|
||||
};
|
||||
|
||||
/** Add a filter to an ol.Map
|
||||
* @param {ol.filter}
|
||||
*/
|
||||
ol_Map.prototype.addFilter = function (filter)
|
||||
{ addFilter_.call (this, filter);
|
||||
};
|
||||
/** Remove a filter to an ol.Map
|
||||
* @param {ol.filter}
|
||||
*/
|
||||
ol_Map.prototype.removeFilter = function (filter)
|
||||
{ removeFilter_.call (this, filter);
|
||||
};
|
||||
/** Get filters associated with an ol.Map
|
||||
* @return {Array<ol.filter>}
|
||||
*/
|
||||
ol_Map.prototype.getFilters = function ()
|
||||
{ return this.filters_;
|
||||
};
|
||||
|
||||
/** Add a filter to an ol.Layer
|
||||
* @param {ol.filter}
|
||||
*/
|
||||
ol_layer_Base.prototype.addFilter = function (filter)
|
||||
{ addFilter_.call (this, filter);
|
||||
};
|
||||
/** Remove a filter to an ol.Layer
|
||||
* @param {ol.filter}
|
||||
*/
|
||||
ol_layer_Base.prototype.removeFilter = function (filter)
|
||||
{ removeFilter_.call (this, filter);
|
||||
};
|
||||
|
||||
/** Get filters associated with an ol.Map
|
||||
* @return {Array<ol.filter>}
|
||||
*/
|
||||
ol_layer_Base.prototype.getFilters = function ()
|
||||
{ return this.filters_;
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
export default ol_filter_Base
|
||||
118
build/filter/Clip.js
Normal file
118
build/filter/Clip.js
Normal file
@ -0,0 +1,118 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
|
||||
/** Clip layer or map
|
||||
* @constructor
|
||||
* @requires ol.filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_ClipOptions} options
|
||||
* - coords {Array<ol.Coordinate>}
|
||||
* - extent {ol.Extent}
|
||||
* - units {%|px} coords units percent or pixel
|
||||
* - keepAspectRatio {boolean} keep aspect ratio
|
||||
* - color {string} backgroundcolor
|
||||
*/
|
||||
var ol_filter_Clip = function(options)
|
||||
{ options = options || {};
|
||||
ol_filter_Base.call(this, options);
|
||||
|
||||
this.set("coords", options.coords);
|
||||
this.set("units", options.units);
|
||||
this.set("keepAspectRatio", options.keepAspectRatio);
|
||||
this.set("extent", options.extent || [0,0,1,1]);
|
||||
this.set("color", options.color);
|
||||
if (!options.extent && options.units!="%" && options.coords)
|
||||
{ var xmin = Infinity;
|
||||
var ymin = Infinity;
|
||||
var xmax = -Infinity;
|
||||
var ymax = -Infinity;
|
||||
for (var i=0, p; p=options.coords[i]; i++)
|
||||
{ if (xmin > p[0]) xmin = p[0];
|
||||
if (xmax < p[0]) xmax = p[0];
|
||||
if (ymin > p[1]) ymin = p[1];
|
||||
if (ymax < p[1]) ymax = p[1];
|
||||
}
|
||||
options.extent = [xmin,ymin,xmax,ymax];
|
||||
}
|
||||
}
|
||||
ol.inherits(ol_filter_Clip, ol_filter_Base);
|
||||
|
||||
ol_filter_Clip.prototype.clipPath_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var coords = this.get("coords");
|
||||
if (!coords) return;
|
||||
var ex = this.get('extent');
|
||||
var scx = 1, scy = 1;
|
||||
if (this.get("units")=="%")
|
||||
{ scx = canvas.width/(ex[2]-ex[0]);
|
||||
scy = canvas.height/(ex[3]-ex[1]);
|
||||
}
|
||||
if (this.get("keepAspectRatio"))
|
||||
{ scx = scy = Math.min (scx, scy);
|
||||
}
|
||||
var pos = this.get('position');
|
||||
var dx=0, dy=0;
|
||||
if (/left/.test(pos))
|
||||
{ dx = -ex[0]*scx;
|
||||
}
|
||||
else if (/center/.test(pos))
|
||||
{ dx = canvas.width/2 - (ex[2]-ex[0])*scx/2;
|
||||
}
|
||||
else if (/right/.test(pos))
|
||||
{ dx = canvas.width - (ex[2]-ex[0])*scx;
|
||||
}
|
||||
var fx = function(x) { return x*scx + dx };
|
||||
if (/top/.test(pos))
|
||||
{ dy = -ex[1]*scy;
|
||||
}
|
||||
else if (/middle/.test(pos))
|
||||
{ dy = canvas.height/2 - (ex[3]-ex[1])*scy/2;
|
||||
}
|
||||
else if (/bottom/.test(pos))
|
||||
{ dy = canvas.height - (ex[3]-ex[1])*scy;
|
||||
}
|
||||
var fy = function(y) { return y*scy + dy; };
|
||||
|
||||
ctx.moveTo ( fx(coords[0][0]), fy(coords[0][1]) );
|
||||
for (var i=1; p=coords[i]; i++)
|
||||
{ ctx.lineTo ( fx(p[0]), fy(p[1]) );
|
||||
}
|
||||
ctx.lineTo ( fx(coords[0][0]), fy(coords[0][1]) );
|
||||
};
|
||||
|
||||
ol_filter_Clip.prototype.precompose = function(e)
|
||||
{ if (!this.get("color"))
|
||||
{ e.context.save();
|
||||
e.context.beginPath();
|
||||
this.clipPath_(e);
|
||||
e.context.clip();
|
||||
}
|
||||
}
|
||||
|
||||
ol_filter_Clip.prototype.postcompose = function(e)
|
||||
{ if (this.get("color"))
|
||||
{ var ctx = e.context;
|
||||
var canvas = e.context.canvas;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,0);
|
||||
ctx.lineTo(0,canvas.height);
|
||||
ctx.lineTo(canvas.width, canvas.height);
|
||||
ctx.lineTo(canvas.width, canvas.height);
|
||||
ctx.lineTo(canvas.width, 0);
|
||||
ctx.lineTo(0, 0);
|
||||
this.clipPath_(e);
|
||||
ctx.fillStyle = this.get("color");
|
||||
ctx.fill("evenodd");
|
||||
};
|
||||
|
||||
e.context.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Clip
|
||||
113
build/filter/Colorize.js
Normal file
113
build/filter/Colorize.js
Normal file
@ -0,0 +1,113 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/** Colorize map or layer
|
||||
* @constructor
|
||||
* @requires ol.filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @author Thomas Tilak https://github.com/thhomas
|
||||
* @author Jean-Marc Viglino https://github.com/viglino
|
||||
* @param {ol_filter_ColorizeOptions} options
|
||||
* - feature {ol.Feature} feature to mask with
|
||||
* - color {Array<integer>} style to fill with
|
||||
* - inner {bool} mask inner, default false
|
||||
*/
|
||||
var ol_filter_Colorize = function(options)
|
||||
{ ol_filter_Base.call(this, options);
|
||||
|
||||
this.setFilter(options);
|
||||
}
|
||||
ol.inherits(ol_filter_Colorize, ol_filter_Base);
|
||||
|
||||
ol_filter_Colorize.prototype.setFilter = function(options)
|
||||
{ options = options || {};
|
||||
switch (options)
|
||||
{ case "grayscale": options = { operation:'hue', red:0, green:0, blue:0, value:1 }; break;
|
||||
case "invert": options = { operation:'difference', red:255, green:255, blue:255, value:1 }; break;
|
||||
case "sepia": options = { operation:'color', red:153, green:102, blue:51, value:0.6 }; break;
|
||||
default: break;
|
||||
}
|
||||
var color = options.color ? ol_color.asArray(options.color) : [ options.red, options.green, options.blue, options.value];
|
||||
this.set('color', ol_color.asString(color))
|
||||
this.set ('value', color[3]||1);
|
||||
switch (options.operation)
|
||||
{ case 'color':
|
||||
case 'hue':
|
||||
case 'difference':
|
||||
case 'color-dodge':
|
||||
case 'enhance':
|
||||
this.set ('operation', options.operation);
|
||||
break;
|
||||
case 'saturation':
|
||||
var v = 255*(options.value || 0);
|
||||
this.set('color', ol_color.asString([0,0,v,v||1]));
|
||||
this.set ('operation', options.operation);
|
||||
break;
|
||||
case 'luminosity':
|
||||
var v = 255*(options.value || 0);
|
||||
this.set('color', ol_color.asString([v,v,v,255]));
|
||||
//this.set ('operation', 'luminosity')
|
||||
this.set ('operation', 'hard-light');
|
||||
break;
|
||||
case 'contrast':
|
||||
var v = 255*(options.value || 0);
|
||||
this.set('color', ol_color.asString([v,v,v,255]));
|
||||
this.set('operation', 'soft-light');
|
||||
break;
|
||||
default:
|
||||
this.set ('operation', 'color');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ol_filter_Colorize.prototype.setValue = function(v)
|
||||
{ this.set ('value', v);
|
||||
var c = ol_color.asArray(this.get("color"));
|
||||
c[3] = v;
|
||||
this.set("color", ol_color.asString(c));
|
||||
}
|
||||
|
||||
ol_filter_Colorize.prototype.setColor = function(c)
|
||||
{ c = ol_color.asArray(c);
|
||||
if (c)
|
||||
{ c[3] = this.get("value");
|
||||
this.set("color", ol_color.asString(c));
|
||||
}
|
||||
}
|
||||
|
||||
ol_filter_Colorize.prototype.precompose = function(e)
|
||||
{}
|
||||
|
||||
ol_filter_Colorize.prototype.postcompose = function(e)
|
||||
{ // Set back color hue
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
ctx.save();
|
||||
if (this.get('operation')=='enhance')
|
||||
{ var v = this.get('value');
|
||||
if (v)
|
||||
{ var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
ctx.globalCompositeOperation = 'color-burn'
|
||||
ctx.globalAlpha = v;
|
||||
ctx.drawImage (canvas, 0, 0, w, h);
|
||||
ctx.drawImage (canvas, 0, 0, w, h);
|
||||
ctx.drawImage (canvas, 0, 0, w, h);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ ctx.globalCompositeOperation = this.get('operation');
|
||||
ctx.fillStyle = this.get('color');
|
||||
ctx.fillRect(0,0,canvas.width,canvas.height);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Colorize
|
||||
40
build/filter/Composite.js
Normal file
40
build/filter/Composite.js
Normal file
@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
|
||||
/** Colorize map or layer
|
||||
* @constructor
|
||||
* @requires ol.filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_CompositeOptions} options
|
||||
* - operation {string} composite operation
|
||||
*/
|
||||
var ol_filter_Composite = function(options)
|
||||
{ ol_filter_Base.call(this, options);
|
||||
|
||||
this.set("operation", options.operation || "source-over");
|
||||
}
|
||||
ol.inherits(ol_filter_Composite, ol_filter_Base);
|
||||
|
||||
/** Change the current operation
|
||||
* @param {string} operation composite function
|
||||
*/
|
||||
ol_filter_Composite.prototype.setOperation = function(operation)
|
||||
{ this.set('operation', operation || "source-over");
|
||||
}
|
||||
|
||||
ol_filter_Composite.prototype.precompose = function(e)
|
||||
{ var ctx = e.context;
|
||||
ctx.save();
|
||||
ctx.globalCompositeOperation = this.get('operation');
|
||||
}
|
||||
|
||||
ol_filter_Composite.prototype.postcompose = function(e)
|
||||
{ e.context.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Composite
|
||||
37
build/filter/Crop.js
Normal file
37
build/filter/Crop.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Mask from './Mask'
|
||||
|
||||
/** Crop drawing using an ol.Feature
|
||||
* @constructor
|
||||
* @requires ol.filter
|
||||
* @requires ol_filter_Mask
|
||||
* @extends {ol_filter_Mask}
|
||||
* @param {ol_filter_CropOptions}
|
||||
* - feature {_ol_Feature_} feature to crop with
|
||||
* - inner {bool} crop inner, default false
|
||||
*/
|
||||
var ol_filter_Crop = function(options)
|
||||
{ options = options || {};
|
||||
ol_filter_Mask.call(this, options);
|
||||
}
|
||||
ol.inherits(ol_filter_Crop, ol_filter_Mask);
|
||||
|
||||
ol_filter_Crop.prototype.precompose = function(e)
|
||||
{ if (!this.feature_) return;
|
||||
|
||||
var ctx = e.context;
|
||||
ctx.save();
|
||||
this.drawFeaturePath_(e, this.get("inner"));
|
||||
ctx.clip("evenodd");
|
||||
}
|
||||
|
||||
ol_filter_Crop.prototype.postcompose = function(e)
|
||||
{ if (this.feature_) e.context.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Crop
|
||||
115
build/filter/Fold.js
Normal file
115
build/filter/Fold.js
Normal file
@ -0,0 +1,115 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
|
||||
/** Fold filer map
|
||||
* @constructor
|
||||
* @requires ol_filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_FoldOptions}
|
||||
* - fold {Array<int>} number of fold (horizontal and vertical)
|
||||
* - margin {Number} margin in px, default 8
|
||||
* - padding {Number} padding in px, default 8
|
||||
* - fsize {integer|Array<integer>} fold size in px, default 8,10
|
||||
*/
|
||||
var ol_filter_Fold = function(options)
|
||||
{ options = options || {};
|
||||
ol_filter_Base.call(this, options);
|
||||
|
||||
this.set("fold", options.fold || [8,4]);
|
||||
this.set("margin", options.margin || 8);
|
||||
this.set("padding", options.padding || 8);
|
||||
if (typeof options.fsize == "number") options.fsize = [options.fsize,options.fsize];
|
||||
this.set("fsize", options.fsize || [8,10]);
|
||||
}
|
||||
ol.inherits(ol_filter_Fold, ol_filter_Base);
|
||||
|
||||
ol_filter_Fold.prototype.drawLine_ = function(ctx, d, m)
|
||||
{ var canvas = ctx.canvas;
|
||||
var fold = this.get("fold");
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo ( m, m );
|
||||
for (var i=1; i<=fold[0]; i++)
|
||||
{ x = i*w/fold[0] - (i==fold[0] ? m : 0);
|
||||
y = d[1]*(i%2) +m;
|
||||
ctx.lineTo ( x, y );
|
||||
}
|
||||
for (var i=1; i<=fold[1]; i++)
|
||||
{ x = w - d[0]*(i%2) - m;
|
||||
y = i*h/fold[1] - (i==fold[1] ? d[0]*(fold[0]%2) + m : 0);
|
||||
ctx.lineTo ( x, y );
|
||||
}
|
||||
for (var i=fold[0]; i>0; i--)
|
||||
{ x = i*w/fold[0] - (i==fold[0] ? d[0]*(fold[1]%2) + m : 0);
|
||||
y = h - d[1]*(i%2) -m;
|
||||
ctx.lineTo ( x, y );
|
||||
}
|
||||
for (var i=fold[1]; i>0; i--)
|
||||
{ x = d[0]*(i%2) + m;
|
||||
y = i*h/fold[1] - (i==fold[1] ? m : 0);
|
||||
ctx.lineTo ( x, y );
|
||||
}
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
ol_filter_Fold.prototype.precompose = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
var fold = this.get("fold");
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
|
||||
ctx.save();
|
||||
ctx.shadowColor = "rgba(0,0,0,0.3)";
|
||||
ctx.shadowBlur = 8;
|
||||
ctx.shadowOffsetX = 2;
|
||||
ctx.shadowOffsetY = 3;
|
||||
this.drawLine_(ctx, this.get("fsize"), this.get("margin"));
|
||||
ctx.fillStyle="#fff";
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = "rgba(0,0,0,0.1)";
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
|
||||
ctx.save();
|
||||
this.drawLine_(ctx, this.get("fsize"), this.get("margin") + this.get("padding"));
|
||||
ctx.clip();
|
||||
|
||||
}
|
||||
|
||||
ol_filter_Fold.prototype.postcompose = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
ctx.restore();
|
||||
ctx.save();
|
||||
this.drawLine_(ctx, this.get("fsize"), this.get("margin"));
|
||||
ctx.clip();
|
||||
|
||||
var fold = this.get("fold");
|
||||
var w = canvas.width/fold[0];
|
||||
var h = canvas.height/fold[1];
|
||||
|
||||
var grd = ctx.createRadialGradient(5*w/8,5*w/8,w/4,w/2,w/2,w);
|
||||
grd.addColorStop(0,"transparent");
|
||||
grd.addColorStop(1,"rgba(0,0,0,0.2)");
|
||||
ctx.fillStyle = grd;
|
||||
ctx.scale (1,h/w);
|
||||
for (var i=0; i<fold[0]; i++) for (var j=0; j<fold[1]; j++)
|
||||
{ ctx.save()
|
||||
ctx.translate(i*w, j*w);
|
||||
ctx.fillRect(0,0,w,w);
|
||||
ctx.restore()
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Fold
|
||||
159
build/filter/Lego.js
Normal file
159
build/filter/Lego.js
Normal file
@ -0,0 +1,159 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
|
||||
/** Make a map or layer look like made of a set of Lego bricks.
|
||||
* @constructor
|
||||
* @requires ol_filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_LegoOptions}
|
||||
* - brickSize {Number} size of te brick, default 30
|
||||
* - crossOrigin {null | string | undefined} crossOrigin attribute for loaded images.
|
||||
*/
|
||||
var ol_filter_Lego = function(options)
|
||||
{ if (!options) options = {};
|
||||
ol_filter_Base.call(this, options);
|
||||
|
||||
var img = new Image();
|
||||
// Default image
|
||||
img.src = this.img[options.img] || this.img.ol3;
|
||||
img.crossOrigin = options.crossOrigin || null;
|
||||
|
||||
// and pattern
|
||||
this.pattern =
|
||||
{ canvas: document.createElement('canvas')
|
||||
};
|
||||
this.setBrick (options.brickSize, img);
|
||||
this.internal_ = document.createElement('canvas');
|
||||
}
|
||||
ol.inherits(ol_filter_Lego, ol_filter_Base);
|
||||
|
||||
/** Image definition
|
||||
*/
|
||||
ol_filter_Lego.prototype.img =
|
||||
{ brick: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAD10AAA9dAah0GUAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAGAElEQVRo3sWZy4tkVx3HP+fcc29Vd1dP17TdTcbJPDKPMGR0kVEZkuBCF0EE9Z8QXLhxMUsRF4oLwYWQTSCgSxUXroQhoiEuskgEUUQh+BhHOpkZO11dr3vvefxc3FPlNHNvPbrD1Dl016XoqvM539/znFbcZo3VjbFmxcMA3Mg2fSoAiQJDov7/B1o9+aEgkycv4PBSPU9eHeDEixNwOAFXPYvFia0+rcnQEeBr218cfLIwCqW1UWillEYphUKpCmCCIQAiCEhAJIggTiSISBAfggTvJZTifQghWO+89cOQexuOXN8Pwz/9ff9X/xF0uEA7AmTsjLp/2xZQCgXHlj0OEBEAeRwGkep3qN6pfibDB3DBixMnvdCXt8J3FZowNYFSjgv71RtPaehjD0alalVOqCtHU3qlAGrVAGbidCtUYLUAiV6dCUx8XV4BhUKjY0AJgUB4LE8sA7CkCRSalFYnE72WiBrLSCKCp6TALZNRDEDCwgAKQ/vyRidN9c32K1sbqlCP/C+P9kXJI597PA7HkGJRCLNUGCY767udF9e+9dz1S5ueoRzIEZa1OxcK9td+/fAHvYH0LY6MkgHFIuYwS0ifXe1+qXvn1vk99QfzCwokToUylPrre1/de/vMnf9+5MsSg2HMELegAsl86duvnP3e8y/f1r83v8Li1RO7k/9c2t/avHnt27xpyhRDguEIuxDA3OXXX93+8a0rz6ZvcKgadqUEL73wx+9sb5//WWKTGCOHsxEWM0H71e2ffmF3lPyEkZppVyVYefCw/9a5f3epSvsWh7MMsUgeaL20/dpLu4fJXZUvFCgi46/8i5RNFCCc4bA5JuZ7f/Kp7g9fuLSdvLnY8lEHxz8ItOPcaN7gPAB1tvPl7udupT9nvGSmLLlHSosWLdbJTgpgLna+eVv9hiO1ZIpFOGBEFmejBnrO/tc/0znXTf+sHMuPwD0MrSnETID6/SXPrH/junp3Xiw3atCjxJCRktKu10DHzrZ+pOvpc5cP/6T8CWtt4BATZ4tkBoCvTz8tbTb8TnHiYi/0pgCmPufMUkB1ss9vtU7Trgt9EgyGhIS0zgjRB6RukaSdfHpLPly2xTg2chQJmgRN2qiAa3DBtu5kYXgqAIFYEzTJDAVCnQIqaA+O0wyFjj8q1oY6AB/qd5nLw9JvcpqOOcFMT5dqlg/UAoy5exS2TgGg6DxhkHofqHVCGYf3ho/S904DcHZ6jpZ6lWMY1iogCDxsn8oDduP3BEI9QvSBWgU8YRDeGezsyEk1SNlD8HF51wjQoEAgHNkffXBw+XfJiZbXXCTBT2fZaAJfn4iEEt+z73bTk92jZTxPwOFxVCeGRif0tt4HCtxB+f0P7l//rTlBAN6gjcNicThcfU2NCnjf0NU43L59vf2XZf1A8wzX8JRTgLw+Ckx17SahIZGOyMri7dHalXf6DJdYfovPAgVlRLAzAXwI0gCQU5La8m6SXeH9pi+pWf5lUooIUFKSN6V0A1AE39RyeAYYEpvYNjf4OwP8XNuf50UycnKKKURjSTMALkjzzgpyEhI0LW7ygHvYRh00G7zARQL5dBYU9JtLWvQB52e0VX0MOl5anmOP+3yIjZldpteZijZXuIbBxZ1PAEbkc05GVspZtnX04hlHEDKucpUePYbklCgyNjjDLp9AERhjKSNAQc6IwSzPMQClt37OIeOQ7vQWxJPSZSf2OZMyK1h8jHsbNSgY0Z/tNRWA2HmuVXLIZsxnliw2mROAyR2Rjwmn8vyC0XynrUwQ3PzGs6QX06rDRgD9GIDEjF9pUFLSXyRsowLFIp2/44icDpZ02umq6S3ZxDwupp3hYs1cVMAu1noLBZaMNbJoAD3tl6prOodnTF5feBoBRmGweO8fyClISMlIowkkApRYyqbeZ5YJQrHc4UNieeGYArL8NeUkFcvgJKc/AU56ajxejod+/DT/W/IkQC4P3GoBwoGsFKAf9v2qAGIxej9MU8rTGdNjWtVsJv315aL3YwDYqG5MTDxAPMvTNkJS3ReY6AmtlTrhKsf/AHgAA6ezGE+FAAAAAElFTkSuQmCC",
|
||||
ol3: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAAD10AAA9dAah0GUAAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAHtUlEQVRo3sWZTWxcVxXHf/d9zIztcTz+pE6cOHXiyLJJadKgKE2oCBLlQwIWSCxYI0WiGxZZIYRAArFAYoEEi0hIsGBBURd0g4iK2lJAaWlaojZVKkU0H26cxB8Zz/f7uPeweHdebDLPnqlQ5l2N5/mN7tz/+Z//OffcM4rPUKCPl0eBAqqfAEAt5Ia1LwCuAg93CyCnAzgj7TstEKMluW+/x0AsWmKBmFggTu4lIpYome2Qw0kA8I2xL9T2Bp5COY6ncJRSDkopFEolANowBEAEATGIGBEkFjEiYkQbI0ZrMaFobYwxkY51pOumpSNTiau6bm7oZX1NP4Ai+ylYADkmGqUPxwSUQsG2ZbcDsBAA2QoGkeSvSZ4kr/alDcRGSyyxbJqqvG5+pHAwbRegVMz+leTBY7qcbTee8vsmQycRmnL6CkD1G4DXFl0fGegvANfpnws8+947AwqFg2MDSjAYzJY80QuAHl2gcPDJF3PiDLiimtIQC0ETEhD3klE8AJeuASg8CgeHir7vLBVOjwypQK3plyoromRNtzSamJg6QbcgvJ7C0J0YnCweG/jek/Ozw5q6bEiFiIHz+wNWBv68+rPNmlQjYnKE1Ai6cYfXA/W5Q6Uvl84f3zel3vH+SIDYoVAeofOdqa9PvbHn/PoDHYZ4eDSpE3fJgLs79YXToz858uxJ5+/en4jQ6hHr5OPZlZHhpcM/4BUv9PFw8agQdQVg1+UHnx/75fG5Gf83lFWGVUrQsmmu/HBsbN8f3Mi1MVLeGUJ3Lig8P/a7s5MN97c01I5+VUIk91err0/fLqFwgBHKOzmimzyQPzX2q1OTZfeianUVKCLNr93EZxiFIOyhnB0Tu6vf/XTp54uzY+4r3S1veYj5CEPBjqFsA3cDoEaLXy199rj/Is0eM2XILXzy5MkzSO6TAvAOFF84qf5KRfWYYhE2aJCzI5MDbxf7B58pTpf89x8qX1yWGKXKFaUBZIF1tWo/KzJPiYi3VAgYbrFEnpiYiBzBTgx0ts99YvDcvHr7YSBJka/Q4k1u3jz5eQ/EYebkXvL241NUeZN/31gkDwibhHjk8PGzTh+OrWw7X/6g/+TB8nuJrQCc4Z/KU08rb+1f/1gCSqy9NUNoP72txtXRb40dfJ+nkgMEZTw78riZLhDRndNP3vGG9GBKnRzhrppmilfhmcWoRYkxyuxv86euUaT24h4W2WN53WQmheB1ygc7MaCKuc+N5LeW6wfOXeUorwFQZIV5RlnbNqcGjBMyaAFUcfHwcHHxOznBakA6JQq34B4dkXtt+8QjvnCQa/Z/jxpFCmdbpPSJI7NyhMVzK/j2UQuFi4OLkz57FECcIcGCU8yZeirQvdxjjuvpTKGAem2EcjpjkjnUC5cvfIm/bRG3Y4e7AwOmEwPKOJotfhvlPj61dGaBEChtAdD88Yeq9et1LqWOUTj2lYzOItSmcxi2ZDXUw+k0n0bqDoXDJBsMM8rHKeIKFbxgIV9nL3cSFlPpZQBoa6AjgCYXK2YkndbckkxmWWfu2D00ozzYNinOlagwbRct/k92zNJARxFK01yur/mX2wDWGE0jfuHyNfa+Y6hQYNsmJQ45hqwwFaPpOVo6s2zDsCMDgsBq2sBR9xj8ZvX70+LJc9w+scA1Sjz49rjMy7zMywE5IY64PMcNDlkHKCbt9xhMZwhOooGODGhMzVyqTUxIm4Pll9797ixnWFZ3WORdSqz//hI+Pv7LT5dXOcNZltUa49y3qplC0Hb5uBMAbwcGDKYS/eLu6YMfrSZCUhWY+QCfGZ7iZYRbarSdYMfd0bvXazh8ii/yF2vcAVwitB1hZirWnROREFLYjN4uLQ5QTZ/WmeA2VwDUHbBks351HRxK3OaqtTTHEQwxmpjkxJApQh111kBAvBH+9O7y/KveFsfcYyNj82qywqZdxmWBAjEREbHdkrNEqNE6o6qJiVeiC4UPHuqg20PvExxGE6YAWp2jwEvabmIyqpoGuTB4ozEwd6lKvYflRzgBBIQWQrQjAG2MZABoEeJH4UU3N8f1rC/psPyz+AQWQEhIK6s09wACk+EC0NTwcCM3KrDAf6ihd6ui2ccxcrRoEaQg6lnQPYDYSLZlAS1cXBzyLHGfW0SZPDgMscgBDK10BARUs48mVgNxtl2GKh6ObVpOM8Uy94hsZpe0nakoMMdhPGJreRtAg9YuJ6NIwp18G7OJsilVyHGIQ2yySZ0WIYocQ+xhknEUhiYRoQUQ0KJBbSfleAChjvQuh4wypbQLovEpMWHrnPY2K0RoG/eR5SCgQXVn1SQAJNpNWiFlhm0+i8jZIrMNoN0j0jbhJMoPaOwu2sQFJt69oRKyadNqTGQBOFsAiM34CQchIdVuwtYyEOgu4jumQosiEX5a6aq0S9Z2T2zTThfdkS0MRN21lISAiBwD5KwDnLReStp0MZomrc4bTyaAhql131gztAhw8cnhWxeIBRASEWbVPju5wAS9/VYgdnthGwPSe5uynYqlpun9EuCTzHt0O67r5uP8teRRAC25H/cXgNmQvgKomhXdLwB2M7pu0pTyeK70mJYUm251sLfo/T8AGEoKes8eIGZ43E5wk36BBwhO2mbqgwZa9C0CAP4LFLGzNDDzmrAAAAAASUVORK5CYII=",
|
||||
lego: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD8AAAA/CAQAAAD9VthUAAAAAnNCSVQICFXsRgQAAAAJcEhZcwAADzoAAA86AZc528IAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwaAAAHvElEQVRYw8WZWWxcVxnHf+fec2fGu+M4qbPH2EmTLk4FApqQNrgiVYyKeClIwBsvPCAQkZAQPND2gRekCoGQEItYHhBLurCksoTKA6QNJW0CBZLWCc3qEBvHy3hsz93O+XiYMxM7nhmPGxGf++Dre2fO7/v+5/u+s4zigzSxVq3osaZNAwzkuq1nPeUrAE9p99JTAKWn5WYEwErpv9TdGbECRlKMgBEjRlIgsqlAKBBaSKUokAjgkcFz+Ce6BvM9sVbKU55WKKWUh1IeoJQCFhsgIIIgIohYEWwq1ooVK9ZasdbG1hhrjUmMsYlZsJEJzYIpmLwZs/8xZ9JpaGYHOYfPyvrChrdbpAxbjFRltCqhnQ2yxBTKf0WQUgNrwYqIFStGUkkllqIU5E/2aQBbEV8pz/ZM3Or8/95UmeUB+J63RiHoAWi1ZHTvNl6pNfXe99Taeq/W1HvuYOzvKG5c4q1afIWHj4eHBwgWwWCQ1aWvBvC8VXngE5DbmO3UxrOeqEhmTFEcPiIiadwEfVttWxmd623tyu7Mfnrjru5cM0Th+Nyp2Z/MztvJNDLkSImZJ27MhNWIr8j1tn+g9at7+/ubivaSHYkmjPF1f+sj7Uc3Xc29VPjm1JSJEzJkCZkjaVT8hvzubDvQ8cz9AwPeG/rHFD3BZkoeTqLwCuqzrQf7nw9+UJhOidEEFAhX0sCJr1fyXm/uPLr5849n/u1/j3mMWtqtYEFm5v/2pXUHdhzNjgaxzunQQzNX3wDdWIT0dT3bP3Qo8wIXSVWNDpWQys2xmW/3fbn1WpAWXUrWNaARvN+/7lu7jzysf8q4siuEh5A8fX5/+8XepLyEs8zfCd7raP/K9scf1T9iQjUUzU+JynOR3TQBgpAS1a16dVtusONTH8kc42ZjcFFKEApcJyBHjizt+O8Wr3e2P7Uv+3curyT7InhJ8nFCMmTJkqWlVlnzVsj0psc69vbrV1SyKnjJgCsEZMiQoanWINcfe39v6xfv808Suu6f5EVlQA7QAcC/1DXp42GmuazOiaJbjjDFSTUNCLOEZMiQEJAjrZYB9b0PmoPe7fpNZQAkYFb1A9CphtWwGlbNkmX/R59TpzhPAAwdf37XKWac1JZJAnc1VSfp0ufSqtK3NT/Y3DJVKZ5tYbHiwfvJAjc5dO7Pw4cZOb4vc51ccvZjh7ZfubaTC8y4evgeAjQaTYCpgZfq06TXpD++Rd6hHHTdZ8JKDs8yAsAD92/gjxSfGNvYzp7Wt3nj6sS2D5NxtXAeHNwnIFpOqSe+bg+2d6ejFXzXS8WlJUSyhBiKoAqj1yFuYQLQZCvFOMLDx8evPFuOF7HV0sqzXmsuP1mJ5tbfVirYc++VITnItvyN8rhJjqIrL7qS50KCX1mWeLXFr5Z02nqiJ2+lXOasIQHJkD75C6DjtQ8dH6Eg99FHyD+LBRclaomnqgL3lo++w4utWsBVbNYtr1htYZFBZgm2299Z5rmXl4+ZtwaPjDlt9CJ0gIeqXNXFN7WKDtMLnW1y+9e6Txc5z2le25Te0BTVic89ovf3yIXE1QeP4FbJbmCla21V723evjklncued/0mZA6AcEABfH/6rXzb2IM5fJD1zLvIB02zm3ak+iK0hK8mvmBnzA/Hoy3LJoyW4XIITn5daAbaX0w3XBnIIsCBL7zDpFNvPWoRvBY+larBZ5Gb6eX20xXxf/2QDMkgmc+sl8MyJH2cf/Seka3yGFv+kR7Ok/1riwxhvruJUYffhGCxWKS0IqqReFXFN5g583qaNokC0aSf/JUaVn95ufNrJ9SwGlapMkkUXuPMAy/E24CJbQVeVWeIXDAFbEYwWCymes3XAMZW9d5gC8k3Rn++79hJjErvvcBB0P53/sBBAOa5knmdnWwlywlQZ7mHfQivOsd6yVDEkGIwxDVrfo2yY4nJ5tMTLe9rkYKSkUtcEqXk9/DKok9d5nLlfpzxyn0Tu7Gk7jLVNx8eQFw98oUi6Vz07NiZ3c/4y+bz+i1gHxliEhJnQFKn6MbVu01ISRaSX2b8vk/4q4D77GErCTGxM2EBW1P8pLr4YJkjiKORhZ91hR1qpsG9m89O9pASOXxMXF6wrCb0ACIidBJe8ZNdjHID24DsA/RhCImInAnztQqr897UeI1lDp3ToU8TO2jiat39q0cLD7GJlNBdERFhLd8dPjamtldx98K8dhNGD91cZ6zKPl6hyNJPP5rYIcsGFGprVva+Nl4GF455lVzI0UcvU0ySX7R5aKabHnrwMRSJlhiQr7fT1QCprYPnmKHgzjQtliwZNrIZHyHBkHHLSMG4KI+JK6Lna+9wFuETUzecLAUHN6QkBARofHwCFImr6Mbld+Lw0Upwhy/acKWUMswS07YI77tllHJTqsW4t4lLtcLKBwyl0JN05YQSiqS0knW+a7eGu4W3rrgmJMwRNpCkLvRsaBoqKAkzZGgi66S/HV+Sf4GQxvor4xPbYDkVIuLS2RZ6CV4wRMQkNNpXGb9go1V8BSElJXRrWIXCupM9We2hvMPPG1bbaqxf3sWhamTzhjVpHsCc/a9dQ3xo82uJL9jRNRLfTTnnBO+u/pTkLT5c8fPNd9nt5tLmRbsVynbsXR704Bbeq775v0uht3btfyZT7OA5knjdAAAAAElFTkSuQmCC"
|
||||
};
|
||||
|
||||
/** Overwrite to handle brickSize
|
||||
* @param {string} key
|
||||
* @param {} val
|
||||
*/
|
||||
ol_filter_Lego.prototype.set = function (key, val)
|
||||
{ ol_filter_Base.prototype.set.call(this, key, val);
|
||||
if (key=="brickSize" && this.pattern.canvas.width!=val)
|
||||
{ this.setBrick(val);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the current brick
|
||||
* @param {Number} width the pattern width, default 30
|
||||
* @param {brick|ol3|lego|undefined} img the pattern, default ol3
|
||||
* @param {string} crossOrigin
|
||||
*/
|
||||
ol_filter_Lego.prototype.setBrick = function (width, img, crossOrigin)
|
||||
{ width = Number(width) || 30;
|
||||
if (typeof(img) === 'string')
|
||||
{ var i = new Image;
|
||||
i.src = this.img[img] || this.img.ol3;
|
||||
i.crossOrigin = crossOrigin || null;
|
||||
img = i;
|
||||
}
|
||||
if (img) this.pattern.img = img;
|
||||
if (!this.pattern.img.width)
|
||||
{ var self = this;
|
||||
this.pattern.img.onload = function()
|
||||
{ self.setBrick(width,img);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.pattern.canvas.width = this.pattern.canvas.height = width;
|
||||
this.pattern.ctx = this.pattern.canvas.getContext("2d");
|
||||
this.pattern.ctx.fillStyle = this.pattern.ctx.createPattern (this.pattern.img, 'repeat');
|
||||
this.set("brickSize", width);
|
||||
this.set("img", img.src);
|
||||
};
|
||||
|
||||
/** Get translated pattern
|
||||
* @param {number} offsetX x offset
|
||||
* @param {number} offsetY y offset
|
||||
*/
|
||||
ol_filter_Lego.prototype.getPattern = function (offsetX, offsetY)
|
||||
{
|
||||
if (!this.pattern.ctx) return "transparent";
|
||||
//return this.pattern.ctx.fillStyle
|
||||
|
||||
var c = this.pattern.canvas;
|
||||
var ctx = this.pattern.ctx;
|
||||
var sc = c.width / this.pattern.img.width;
|
||||
|
||||
ctx.save();
|
||||
ctx.clearRect(0,0,c.width,c.height);
|
||||
|
||||
ctx.scale(sc,sc);
|
||||
offsetX /= sc;
|
||||
offsetY /= sc;
|
||||
|
||||
ctx.translate(offsetX, offsetY);
|
||||
ctx.beginPath();
|
||||
ctx.clearRect(-2*c.width, -2*c.height, 4*c.width, 4*c.height);
|
||||
ctx.rect(-offsetX, -offsetY, 2*c.width/sc, 2*c.height/sc);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
return ctx.createPattern(c, 'repeat');
|
||||
};
|
||||
|
||||
/** Postcompose operation
|
||||
*/
|
||||
ol_filter_Lego.prototype.postcompose = function(e)
|
||||
{ // Set back color hue
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
|
||||
ctx.save();
|
||||
|
||||
// resize
|
||||
var step = this.pattern.canvas.width*ratio, step2 = step/2;
|
||||
var p = e.frameState.extent;
|
||||
var res = e.frameState.viewState.resolution/ratio;
|
||||
var offset = [ -Math.round((p[0]/res)%step), Math.round((p[1]/res)%step) ];
|
||||
var ctx2 = this.internal_.getContext("2d");
|
||||
var w = this.internal_.width = canvas.width;
|
||||
var h = this.internal_.height = canvas.height;
|
||||
|
||||
// No smoothing please
|
||||
ctx2.webkitImageSmoothingEnabled = false;
|
||||
ctx2.mozImageSmoothingEnabled = false;
|
||||
ctx2.imageSmoothingEnabled = false;
|
||||
/**/
|
||||
var w2 = Math.floor((w-offset[0])/step);
|
||||
var h2 = Math.floor((h-offset[1])/step);
|
||||
ctx2.drawImage (canvas, offset[0], offset[1], w2*step, h2*step, 0, 0, w2, h2);
|
||||
ctx.webkitImageSmoothingEnabled = false;
|
||||
ctx.mozImageSmoothingEnabled = false;
|
||||
ctx.imageSmoothingEnabled = false; //future
|
||||
ctx.clearRect (0, 0, w,h);
|
||||
ctx.drawImage (this.internal_, 0,0, w2,h2, offset[0],offset[1], w2*step, h2*step);
|
||||
/* /
|
||||
for (var x=offset[0]; x<w; x+=step) for (var y=offset[1]; y<h; y+=step)
|
||||
{ if (x>=0 && y<h) ctx2.drawImage (canvas, x, y, 1, 1, x, y, step, step);
|
||||
}
|
||||
ctx.clearRect (0, 0, w,h);
|
||||
ctx.drawImage (c, 0, 0);
|
||||
/**/
|
||||
// Draw brick stud
|
||||
ctx.scale(ratio,ratio);
|
||||
ctx.fillStyle = this.getPattern (offset[0]/ratio, offset[1]/ratio);
|
||||
ctx.rect(0,0, w, h);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_filter_Lego
|
||||
94
build/filter/Mask.js
Normal file
94
build/filter/Mask.js
Normal file
@ -0,0 +1,94 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/** Mask drawing using an ol.Feature
|
||||
* @constructor
|
||||
* @requires ol_filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_CropOptions} options
|
||||
* - feature {ol.Feature} feature to mask with
|
||||
* - fill {ol.style.Fill} style to fill with
|
||||
* - inner {bool} mask inner, default false
|
||||
*/
|
||||
var ol_filter_Mask = function(options)
|
||||
{ options = options || {};
|
||||
ol_filter_Base.call(this, options);
|
||||
if (options.feature)
|
||||
{ switch (options.feature.getGeometry().getType())
|
||||
{ case "Polygon":
|
||||
case "MultiPolygon":
|
||||
this.feature_ = options.feature;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
this.set("inner", options.inner);
|
||||
this.fillColor_ = options.fill ? ol_color.asString(options.fill.getColor()) || "rgba(0,0,0,0.2)" : "rgba(0,0,0,0.2)";
|
||||
}
|
||||
ol.inherits(ol_filter_Mask, ol_filter_Base);
|
||||
|
||||
/** Draw the feature into canvas
|
||||
*/
|
||||
ol_filter_Mask.prototype.drawFeaturePath_ = function(e, out)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
// Transform
|
||||
var m = e.frameState.coordinateToPixelTransform;
|
||||
function tr(pt)
|
||||
{ return [
|
||||
(pt[0]*m[0]+pt[1]*m[1]+m[4])*ratio,
|
||||
(pt[0]*m[2]+pt[1]*m[3]+m[5])*ratio
|
||||
];
|
||||
}
|
||||
// Old version
|
||||
if (!m)
|
||||
{ m = e.frameState.coordinateToPixelMatrix;
|
||||
tr = function(pt)
|
||||
{ return [
|
||||
(pt[0]*m[0]+pt[1]*m[1]+m[12])*ratio,
|
||||
(pt[0]*m[4]+pt[1]*m[5]+m[13])*ratio
|
||||
];
|
||||
}
|
||||
}
|
||||
// Geometry
|
||||
var ll = this.feature_.getGeometry().getCoordinates();
|
||||
if (this.feature_.getGeometry().getType()=="Polygon") ll = [ll];
|
||||
ctx.beginPath();
|
||||
if (out)
|
||||
{ ctx.moveTo (0,0);
|
||||
ctx.lineTo (canvas.width, 0);
|
||||
ctx.lineTo (canvas.width, canvas.height);
|
||||
ctx.lineTo (0, canvas.height);
|
||||
ctx.lineTo (0, 0);
|
||||
}
|
||||
for (var l=0; l<ll.length; l++)
|
||||
{ var c = ll[l];
|
||||
for (var i=0; i<c.length; i++)
|
||||
{ var pt = tr(c[i][0]);
|
||||
ctx.moveTo (pt[0], pt[1]);
|
||||
for (var j=1; j<c[i].length; j++)
|
||||
{ pt = tr(c[i][j]);
|
||||
ctx.lineTo (pt[0], pt[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ol_filter_Mask.prototype.postcompose = function(e)
|
||||
{ if (!this.feature_) return;
|
||||
var ctx = e.context;
|
||||
ctx.save();
|
||||
this.drawFeaturePath_(e, !this.get("inner"));
|
||||
ctx.fillStyle = this.fillColor_;
|
||||
ctx.fill("evenodd");
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Mask
|
||||
179
build/filter/Texture.js
Normal file
179
build/filter/Texture.js
Normal file
@ -0,0 +1,179 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_filter_Base from './Base'
|
||||
import ol_filter_Texture_Image from './TextureImage'
|
||||
|
||||
/** Add texture effects on maps or layers
|
||||
* @constructor
|
||||
* @requires ol.filter
|
||||
* @extends {ol_filter_Base}
|
||||
* @param {ol_filter_TextureOptions} options
|
||||
* - feature {_ol_Feature_} feature to mask with
|
||||
* - fill {_ol_style_Fill_} style to fill with
|
||||
* - inner {bool} mask inner, default false
|
||||
*/
|
||||
var ol_filter_Texture = function(options)
|
||||
{ ol_filter_Base.call(this, options);
|
||||
|
||||
this.setFilter(options);
|
||||
}
|
||||
ol.inherits(ol_filter_Texture, ol_filter_Base);
|
||||
|
||||
/** Set texture
|
||||
* @option {ol_filter_TextureOptions}
|
||||
* - img {Image | undefined} Image object for the texture
|
||||
* - src {string} Image source URI
|
||||
* - scale {number} scale to draw the image. Default 1.
|
||||
* - rotateWithView {bool} Whether to rotate the texture with the view (may cause animation lags on mobile or slow devices). Default is true.
|
||||
* - crossOrigin {null | string | undefined} The crossOrigin attribute for loaded images.
|
||||
*/
|
||||
ol_filter_Texture.prototype.setFilter = function(options)
|
||||
{ var img;
|
||||
options = options || {};
|
||||
if (options.img) img = option.img;
|
||||
else
|
||||
{ img = new Image();
|
||||
if (options.src) {
|
||||
// Look for a texture stored in ol_filter_Texture_Image
|
||||
if (ol_filter_Texture_Image && ol_filter_Texture_Image[options.src]) {
|
||||
img.src = ol_filter_Texture_Image[options.src];
|
||||
}
|
||||
// default source
|
||||
else {
|
||||
if (!img.src) img.src = options.src;
|
||||
}
|
||||
}
|
||||
img.crossOrigin = options.crossOrigin || null;
|
||||
}
|
||||
|
||||
this.set('rotateWithView', options.rotateWithView !== false);
|
||||
this.set('opacity', typeof(options.opacity)=='number' ? options.opacity : 1);
|
||||
|
||||
this.set('ready', false);
|
||||
var self = this;
|
||||
function setPattern(img)
|
||||
{ self.pattern = {};
|
||||
self.pattern.scale = options.scale || 1;
|
||||
self.pattern.canvas = document.createElement('canvas');
|
||||
self.pattern.canvas.width = img.width * self.pattern.scale;
|
||||
self.pattern.canvas.height = img.height * self.pattern.scale;
|
||||
self.pattern.canvas.width = img.width;// * self.pattern.scale;
|
||||
self.pattern.canvas.height = img.height;// * self.pattern.scale;
|
||||
self.pattern.ctx = self.pattern.canvas.getContext("2d");
|
||||
self.pattern.ctx.fillStyle = self.pattern.ctx.createPattern(img, 'repeat');
|
||||
// Force refresh
|
||||
self.set('ready', true);
|
||||
};
|
||||
|
||||
if (img.width)
|
||||
{ setPattern(img);
|
||||
}
|
||||
else
|
||||
{ img.onload = function()
|
||||
{ setPattern(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get translated pattern
|
||||
* @param {number} x offset
|
||||
* @param {number} y offset
|
||||
*/
|
||||
ol_filter_Texture.prototype.getPattern = function (offsetX, offsetY)
|
||||
{ var c = this.pattern.canvas;
|
||||
var ctx = this.pattern.ctx;
|
||||
ctx.save();
|
||||
/*
|
||||
offsetX /= this.pattern.scale;
|
||||
offsetY /= this.pattern.scale;
|
||||
ctx.scale(this.pattern.scale,this.pattern.scale);
|
||||
*/
|
||||
ctx.translate(-offsetX, offsetY);
|
||||
ctx.beginPath();
|
||||
ctx.rect(offsetX, -offsetY, c.width, c.height);
|
||||
ctx.fill();
|
||||
ctx.restore();
|
||||
return ctx.createPattern(c, 'repeat');
|
||||
}
|
||||
|
||||
/** Draw pattern over the map on postcompose
|
||||
*/
|
||||
ol_filter_Texture.prototype.postcompose = function(e)
|
||||
{ // not ready
|
||||
if (!this.pattern) return;
|
||||
|
||||
// Set back color hue
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
var m = 1.5 * Math.max(canvas.width, canvas.height);
|
||||
var mt = e.frameState.pixelToCoordinateTransform;
|
||||
// Old version (matrix)
|
||||
if (!mt)
|
||||
{ mt = e.frameState.pixelToCoordinateMatrix,
|
||||
mt[2] = mt[4];
|
||||
mt[3] = mt[5];
|
||||
mt[4] = mt[12];
|
||||
mt[5] = mt[13];
|
||||
}
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
var res = e.frameState.viewState.resolution;
|
||||
var w = canvas.width/2,
|
||||
h = canvas.height/2;
|
||||
|
||||
ctx.save();
|
||||
|
||||
ctx.globalCompositeOperation = "multiply";
|
||||
//ctx.globalCompositeOperation = "overlay";
|
||||
//ctx.globalCompositeOperation = "color";
|
||||
ctx.globalAlpha = this.get('opacity');
|
||||
ctx.scale(ratio*this.pattern.scale,ratio*this.pattern.scale);
|
||||
|
||||
if (this.get('rotateWithView'))
|
||||
{ // Translate pattern
|
||||
res *= this.pattern.scale
|
||||
ctx.fillStyle = this.getPattern ((w*mt[0] + h*mt[1] + mt[4])/res, (w*mt[2] + h*mt[3] + mt[5])/res);
|
||||
|
||||
// Rotate on canvas center and fill
|
||||
ctx.translate(w/this.pattern.scale, h/this.pattern.scale);
|
||||
ctx.rotate(e.frameState.viewState.rotation);
|
||||
ctx.beginPath();
|
||||
ctx.rect(-w-m, -h-m, 2*m, 2*m);
|
||||
ctx.fill();
|
||||
}
|
||||
else
|
||||
{
|
||||
/**/
|
||||
var dx = -(w*mt[0] + h*mt[1] + mt[4])/res;
|
||||
var dy = (w*mt[2] + h*mt[3] + mt[5])/res;
|
||||
|
||||
var cos = Math.cos(e.frameState.viewState.rotation);
|
||||
var sin = Math.sin(e.frameState.viewState.rotation);
|
||||
var offsetX = (dx*cos - dy*sin) / this.pattern.scale;
|
||||
var offsetY = (dx*sin + dy*cos) / this.pattern.scale;
|
||||
|
||||
ctx.translate(offsetX, offsetY);
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = this.pattern.ctx.fillStyle;
|
||||
ctx.rect(-offsetX -m , -offsetY -m, 2*m, 2*m);
|
||||
ctx.fill();
|
||||
/* //old version without centered rotation
|
||||
var offsetX = -(e.frameState.extent[0]/res) % this.pattern.canvas.width;
|
||||
var offsetY = (e.frameState.extent[1]/res) % this.pattern.canvas.height;
|
||||
ctx.rotate(e.frameState.viewState.rotation);
|
||||
ctx.translate(offsetX, offsetY);
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = this.pattern.ctx.fillStyle
|
||||
ctx.rect(-offsetX -m , -offsetY -m, 2*m, 2*m);
|
||||
ctx.fill();
|
||||
*/
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export default ol_filter_Texture
|
||||
23
build/filter/TextureImage.js
Normal file
23
build/filter/TextureImage.js
Normal file
File diff suppressed because one or more lines are too long
996
build/filter/legostud.svg
Normal file
996
build/filter/legostud.svg
Normal file
@ -0,0 +1,996 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="79.111137mm"
|
||||
height="69.723396mm"
|
||||
viewBox="0 0 280.31505 247.0514"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="legostud.svg">
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4479">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4481" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4483" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4264"
|
||||
osb:paint="gradient">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4266" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4268" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4165">
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4167" />
|
||||
<stop
|
||||
style="stop-color:#000000;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4169" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4165"
|
||||
id="radialGradient4171"
|
||||
cx="247.58907"
|
||||
cy="806.17749"
|
||||
fx="247.58907"
|
||||
fy="806.17749"
|
||||
r="16.712261"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1673248,0,0,1.1673248,-43.580899,-140.69401)" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4209"
|
||||
x="-0.023999365"
|
||||
width="1.0479987"
|
||||
y="-0.024000635"
|
||||
height="1.0480013">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.36829105"
|
||||
id="feGaussianBlur4211" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4260"
|
||||
x="-0.035885267"
|
||||
width="1.0717705"
|
||||
y="-0.036115468"
|
||||
height="1.0722309">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.3757032"
|
||||
id="feGaussianBlur4262" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4406"
|
||||
x="-0.023999998"
|
||||
width="1.048"
|
||||
y="-0.024000002"
|
||||
height="1.048">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.55023435"
|
||||
id="feGaussianBlur4408" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4479"
|
||||
id="radialGradient4485"
|
||||
cx="243.34979"
|
||||
cy="799.60266"
|
||||
fx="243.34979"
|
||||
fy="799.60266"
|
||||
r="26.382999"
|
||||
gradientTransform="matrix(0.94262735,-0.96925492,1.4109273,1.372166,-1114.2197,-61.71694)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4507"
|
||||
x="-0.011999792"
|
||||
width="1.0239996"
|
||||
y="-0.012000208"
|
||||
height="1.0240004">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.26382543"
|
||||
id="feGaussianBlur4509" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
y2="0"
|
||||
x2="1"
|
||||
y1="0"
|
||||
x1="0"
|
||||
id="grad">
|
||||
<stop
|
||||
id="stop4520"
|
||||
stop-opacity="0.25"
|
||||
stop-color="#000000"
|
||||
offset="20%" />
|
||||
<stop
|
||||
id="stop4522"
|
||||
stop-opacity="0.5"
|
||||
stop-color="#000000"
|
||||
offset="80%" />
|
||||
</linearGradient>
|
||||
<path
|
||||
d="M 0,0 5,10 Q 0,0 -5,10 Z"
|
||||
id="arrow"
|
||||
inkscape:connector-curvature="0"
|
||||
style="stroke:none" />
|
||||
<text
|
||||
font-style="italic"
|
||||
font-size="16"
|
||||
text-align="middle"
|
||||
dy="8.2103413e-035"
|
||||
y="0"
|
||||
x="0"
|
||||
transform="matrix(0.69282032,-0.4,0.5,0.8660254,0,0)"
|
||||
id="stud_text"
|
||||
style="font-style:italic;font-size:16px;stroke:none">LEGO</text>
|
||||
<g
|
||||
id="stud">
|
||||
<ellipse
|
||||
id="ellipse4527"
|
||||
ry="17.6777"
|
||||
rx="30.618601"
|
||||
cy="3"
|
||||
cx="6"
|
||||
style="fill:#000000;fill-opacity:0.25;stroke:none" />
|
||||
<path
|
||||
id="path4529"
|
||||
d="m -30.6186,-17 a 30.6186,17.6777 0 0 1 61.2372,0 l 0,17 a 30.6186,17.6777 0 0 1 -61.2372,0 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4531"
|
||||
d="m -30.6186,-17 a 30.6186,17.6777 0 0 0 61.2372,0 l 0,17 a 30.6186,17.6777 0 0 1 -61.2372,0 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#grad)" />
|
||||
<use
|
||||
id="use4533"
|
||||
xlink:href="#stud_text"
|
||||
transform="translate(1,-16)"
|
||||
style="fill:#000000"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4535"
|
||||
xlink:href="#stud_text"
|
||||
transform="translate(0,-17)"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<g
|
||||
id="brick">
|
||||
<path
|
||||
id="path4538"
|
||||
d="m 0,40 69.282,-40 0,-96 L 0,-136 l -69.282,40 0,96 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4540"
|
||||
d="m 0,40 0,-96 69.282,-40 0,96 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:0.5" />
|
||||
<path
|
||||
id="path4542"
|
||||
d="m 0,40 0,-96 -69.282,-40 0,96 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:0.25" />
|
||||
<use
|
||||
id="use4544"
|
||||
xlink:href="#stud"
|
||||
transform="translate(0,-96)"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<g
|
||||
id="plate">
|
||||
<path
|
||||
id="path4547"
|
||||
d="m 0,40 69.282,-40 0,-32 -138.564,-80 -69.282,40 0,32 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path4549"
|
||||
d="m 0,40 0,-32 69.282,-40 0,32 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:0.5" />
|
||||
<path
|
||||
id="path4551"
|
||||
d="m 0,40 0,-32 -138.564,-80 0,32 z"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#000000;fill-opacity:0.25" />
|
||||
<use
|
||||
id="use4553"
|
||||
xlink:href="#stud"
|
||||
transform="translate(-69.282,-72)"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4555"
|
||||
xlink:href="#stud"
|
||||
transform="translate(0,-32)"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
</g>
|
||||
<g
|
||||
font-size="16"
|
||||
id="main"
|
||||
style="font-size:16px;font-family:sans-serif;text-anchor:middle;fill:#000000;stroke:#000000;stroke-linecap:round;stroke-linejoin:round">
|
||||
<g
|
||||
id="g4558"
|
||||
transform="translate(10,-5)">
|
||||
<use
|
||||
id="use4560"
|
||||
xlink:href="#brick"
|
||||
transform="translate(69.282,-40)"
|
||||
style="fill:#ffcc00"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<text
|
||||
id="text4562"
|
||||
y="-186"
|
||||
x="69"
|
||||
style="text-anchor:middle;stroke:none">4.8 mm</text>
|
||||
<line
|
||||
id="line4564"
|
||||
y2="-180"
|
||||
x2="100"
|
||||
y1="-180"
|
||||
x1="39" />
|
||||
<use
|
||||
id="use4566"
|
||||
transform="matrix(0,-1,1,0,39,-180)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4568"
|
||||
transform="matrix(0,1,-1,0,100,-180)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4570"
|
||||
y2="-185"
|
||||
x2="39"
|
||||
y1="-161"
|
||||
x1="39" />
|
||||
<line
|
||||
id="line4572"
|
||||
y2="-185"
|
||||
x2="100"
|
||||
y1="-161"
|
||||
x1="100" />
|
||||
<text
|
||||
id="text4574"
|
||||
y="-170"
|
||||
x="160"
|
||||
style="text-anchor:start;stroke:none">1.7 mm</text>
|
||||
<line
|
||||
id="line4576"
|
||||
y2="-159"
|
||||
x2="147"
|
||||
y1="-176"
|
||||
x1="147" />
|
||||
<use
|
||||
id="use4578"
|
||||
transform="translate(147,-176)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4580"
|
||||
transform="matrix(-1,0,0,-1,147,-159)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4582"
|
||||
y2="-181"
|
||||
x2="156"
|
||||
y1="-150"
|
||||
x1="102" />
|
||||
<line
|
||||
id="line4584"
|
||||
y2="-164"
|
||||
x2="156"
|
||||
y1="-133"
|
||||
x1="102" />
|
||||
<text
|
||||
id="text4586"
|
||||
y="-80"
|
||||
x="150"
|
||||
style="text-anchor:start;stroke:none">
|
||||
<tspan
|
||||
id="tspan4588">H = 9.6 mm</tspan>
|
||||
<tspan
|
||||
id="tspan4590"
|
||||
dy="1.8479102e-034"
|
||||
x="165">= 3 × h</tspan>
|
||||
<tspan
|
||||
id="tspan4592"
|
||||
dy="1.7902963e-034"
|
||||
x="165">= 1.2 × P</tspan>
|
||||
</text>
|
||||
<line
|
||||
id="line4594"
|
||||
y2="-35"
|
||||
x2="147"
|
||||
y1="-131"
|
||||
x1="147" />
|
||||
<use
|
||||
id="use4596"
|
||||
transform="translate(147,-131)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4598"
|
||||
transform="matrix(-1,0,0,-1,147,-35)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<text
|
||||
id="text4600"
|
||||
y="0"
|
||||
x="130"
|
||||
style="text-anchor:start;stroke:none">
|
||||
<tspan
|
||||
id="tspan4602">P − 0.2 mm</tspan>
|
||||
<tspan
|
||||
id="tspan4604"
|
||||
dy="1.8528684e-034"
|
||||
x="130">= 7.8 mm</tspan>
|
||||
</text>
|
||||
<line
|
||||
id="line4606"
|
||||
y2="-35"
|
||||
x2="147"
|
||||
y1="5"
|
||||
x1="78" />
|
||||
<use
|
||||
id="use4608"
|
||||
transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,78,5)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4610"
|
||||
transform="matrix(0.5,0.8660254,-0.8660254,0.5,147,-35)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4612"
|
||||
y2="-126"
|
||||
x2="156"
|
||||
y1="-134"
|
||||
x1="142" />
|
||||
<line
|
||||
id="line4614"
|
||||
y2="-30"
|
||||
x2="156"
|
||||
y1="-38"
|
||||
x1="142" />
|
||||
<line
|
||||
id="line4616"
|
||||
y2="10"
|
||||
x2="87"
|
||||
y1="2"
|
||||
x1="73" />
|
||||
</g>
|
||||
<g
|
||||
id="g4618">
|
||||
<use
|
||||
id="use4620"
|
||||
xlink:href="#plate"
|
||||
style="fill:#ff0000"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<text
|
||||
id="text4622"
|
||||
y="-190"
|
||||
x="-170"
|
||||
style="text-anchor:start;stroke:none">
|
||||
<tspan
|
||||
id="tspan4624">P = 8.0 mm</tspan>
|
||||
<tspan
|
||||
id="tspan4626"
|
||||
dy="1.8722218e-034"
|
||||
x="-155">= 5/6 × H</tspan>
|
||||
<tspan
|
||||
id="tspan4628"
|
||||
dy="1.8727315e-034"
|
||||
x="-155">= 2.5 × h</tspan>
|
||||
</text>
|
||||
<line
|
||||
id="line4630"
|
||||
y2="-190"
|
||||
x2="-69"
|
||||
y1="-150"
|
||||
x1="0" />
|
||||
<use
|
||||
id="use4632"
|
||||
transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,0,-150)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4634"
|
||||
transform="matrix(0.5,-0.8660254,0.8660254,0.5,-69,-190)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4636"
|
||||
y2="-160"
|
||||
x2="0"
|
||||
y1="-50"
|
||||
x1="0" />
|
||||
<line
|
||||
id="line4638"
|
||||
y2="-200"
|
||||
x2="-69"
|
||||
y1="-90"
|
||||
x1="-69" />
|
||||
<text
|
||||
id="text4640"
|
||||
y="-130"
|
||||
x="-32"
|
||||
style="text-anchor:middle;stroke:none">3.2 mm</text>
|
||||
<line
|
||||
id="line4642"
|
||||
y2="-120"
|
||||
x2="-48"
|
||||
y1="-105"
|
||||
x1="-24" />
|
||||
<use
|
||||
id="use4644"
|
||||
transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,-24,-105)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4646"
|
||||
transform="matrix(0.5,-0.8660254,0.8660254,0.5,-48,-120)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4648"
|
||||
y2="-110"
|
||||
x2="-24"
|
||||
y1="-62"
|
||||
x1="-24" />
|
||||
<line
|
||||
id="line4650"
|
||||
y2="-125"
|
||||
x2="-48"
|
||||
y1="-78"
|
||||
x1="-48" />
|
||||
<text
|
||||
id="text4652"
|
||||
y="20"
|
||||
x="-90"
|
||||
style="text-anchor:end;stroke:none">
|
||||
<tspan
|
||||
id="tspan4654">2 × P − 0.2 mm</tspan>
|
||||
<tspan
|
||||
id="tspan4656"
|
||||
dy="1.8926102e-034"
|
||||
x="-90">= 15.8 mm</tspan>
|
||||
</text>
|
||||
<line
|
||||
id="line4658"
|
||||
y2="-35"
|
||||
x2="-147"
|
||||
y1="45"
|
||||
x1="-9" />
|
||||
<use
|
||||
id="use4660"
|
||||
transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,-9,45)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4662"
|
||||
transform="matrix(0.5,-0.8660254,0.8660254,0.5,-147,-35)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<text
|
||||
id="text4664"
|
||||
y="-60"
|
||||
x="-247"
|
||||
style="text-anchor:start;stroke:none">
|
||||
<tspan
|
||||
id="tspan4666">h = 3.2 mm</tspan>
|
||||
<tspan
|
||||
id="tspan4668"
|
||||
dy="1.8926892e-034"
|
||||
x="-235">= 1/3 × H</tspan>
|
||||
<tspan
|
||||
id="tspan4670"
|
||||
dy="1.8927287e-034"
|
||||
x="-235">= 0.4 × P</tspan>
|
||||
</text>
|
||||
<line
|
||||
id="line4672"
|
||||
y2="-35"
|
||||
x2="-147"
|
||||
y1="-67"
|
||||
x1="-147" />
|
||||
<use
|
||||
id="use4674"
|
||||
transform="translate(-147,-67)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<use
|
||||
id="use4676"
|
||||
transform="matrix(-1,0,0,-1,-147,-35)"
|
||||
xlink:href="#arrow"
|
||||
x="0"
|
||||
y="0"
|
||||
width="100%"
|
||||
height="100%" />
|
||||
<line
|
||||
id="line4678"
|
||||
y2="-62"
|
||||
x2="-156"
|
||||
y1="-70"
|
||||
x1="-142" />
|
||||
<line
|
||||
id="line4680"
|
||||
y2="-30"
|
||||
x2="-156"
|
||||
y1="-38"
|
||||
x1="-142" />
|
||||
<line
|
||||
id="line4682"
|
||||
y2="50"
|
||||
x2="-17"
|
||||
y1="42"
|
||||
x1="-3" />
|
||||
</g>
|
||||
</g>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter5268"
|
||||
x="-0.0091189481"
|
||||
width="1.0182379"
|
||||
y="-0.017542355"
|
||||
height="1.0350847">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.06438475"
|
||||
id="feGaussianBlur5270" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter5328"
|
||||
x="-0.018060395"
|
||||
width="1.0361208"
|
||||
y="-0.035760824"
|
||||
height="1.0715218">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.1314258"
|
||||
id="feGaussianBlur5330" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter5602"
|
||||
x="-0.019410826"
|
||||
width="1.0388217"
|
||||
y="-0.03143103"
|
||||
height="1.0628622">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.15183545"
|
||||
id="feGaussianBlur5604" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter5676"
|
||||
x="-0.019262506"
|
||||
width="1.038525"
|
||||
y="-0.031827867"
|
||||
height="1.0636557">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.1528711"
|
||||
id="feGaussianBlur5678" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4406-3"
|
||||
x="-0.023999998"
|
||||
width="1.048"
|
||||
y="-0.024000002"
|
||||
height="1.048">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.55023435"
|
||||
id="feGaussianBlur4408-6" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4165"
|
||||
id="radialGradient4171-0"
|
||||
cx="247.58907"
|
||||
cy="806.17749"
|
||||
fx="247.58907"
|
||||
fy="806.17749"
|
||||
r="16.712261"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1673248,0,0,1.1673248,-43.580899,-140.69401)" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4209-7"
|
||||
x="-0.023999365"
|
||||
width="1.0479987"
|
||||
y="-0.024000635"
|
||||
height="1.0480013">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.36829105"
|
||||
id="feGaussianBlur4211-6" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4260-5"
|
||||
x="-0.035885267"
|
||||
width="1.0717705"
|
||||
y="-0.036115468"
|
||||
height="1.0722309">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.3757032"
|
||||
id="feGaussianBlur4262-7" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4479"
|
||||
id="radialGradient4485-6"
|
||||
cx="243.34979"
|
||||
cy="799.60266"
|
||||
fx="243.34979"
|
||||
fy="799.60266"
|
||||
r="26.382999"
|
||||
gradientTransform="matrix(0.94262735,-0.96925492,1.4109273,1.372166,-1114.2197,-61.71694)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4507-13"
|
||||
x="-0.011999792"
|
||||
width="1.0239996"
|
||||
y="-0.012000208"
|
||||
height="1.0240004">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.26382543"
|
||||
id="feGaussianBlur4509-2" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4406-3-61"
|
||||
x="-0.023999998"
|
||||
width="1.048"
|
||||
y="-0.024000002"
|
||||
height="1.048">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.55023435"
|
||||
id="feGaussianBlur4408-6-3" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4165"
|
||||
id="radialGradient4171-0-4"
|
||||
cx="247.58907"
|
||||
cy="806.17749"
|
||||
fx="247.58907"
|
||||
fy="806.17749"
|
||||
r="16.712261"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.1673248,0,0,1.1673248,-43.580899,-140.69401)" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4209-7-7"
|
||||
x="-0.023999365"
|
||||
width="1.0479987"
|
||||
y="-0.024000635"
|
||||
height="1.0480013">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.36829105"
|
||||
id="feGaussianBlur4211-6-4" />
|
||||
</filter>
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4260-5-2"
|
||||
x="-0.035885267"
|
||||
width="1.0717705"
|
||||
y="-0.036115468"
|
||||
height="1.0722309">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.3757032"
|
||||
id="feGaussianBlur4262-7-25" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4479"
|
||||
id="radialGradient4485-6-5"
|
||||
cx="243.34979"
|
||||
cy="799.60266"
|
||||
fx="243.34979"
|
||||
fy="799.60266"
|
||||
r="26.382999"
|
||||
gradientTransform="matrix(0.94262735,-0.96925492,1.4109273,1.372166,-1114.2197,-61.71694)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter4507-13-6"
|
||||
x="-0.011999792"
|
||||
width="1.0239996"
|
||||
y="-0.012000208"
|
||||
height="1.0240004">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="0.26382543"
|
||||
id="feGaussianBlur4509-2-7" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.2311604"
|
||||
inkscape:cx="130.15593"
|
||||
inkscape:cy="112.1381"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="972"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
showguides="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-26.160786,-625.08677)">
|
||||
<rect
|
||||
y="665.62579"
|
||||
x="57.765621"
|
||||
height="81.142677"
|
||||
width="217.85828"
|
||||
id="rect5502"
|
||||
style="font-style:normal;font-weight:normal;font-size:medium;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;opacity:1;fill:#ff0000;fill-opacity:1;stroke:#ffffff;stroke-width:0.83908439;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||
<g
|
||||
transform="translate(-148.38464,-2.1702488)"
|
||||
id="g5868-1-0"
|
||||
inkscape:export-xdpi="99.888031"
|
||||
inkscape:export-ydpi="99.888031">
|
||||
<path
|
||||
inkscape:export-ydpi="99.888062"
|
||||
inkscape:export-xdpi="99.888062"
|
||||
id="path4296-5-6"
|
||||
d="m 216.28711,772.07227 0,55.02343 55.02344,0 0,-55.02343 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.25;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4406-3-61);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-9-7-6"
|
||||
d="m 245.4367,781.96308 a 18.414436,18.414436 0 0 0 -18.41601,18.41406 18.414436,18.414436 0 0 0 18.41601,18.41407 18.414436,18.414436 0 0 0 18.41407,-18.41407 18.414436,18.414436 0 0 0 -18.41407,-18.41406 z m -1.70312,2 a 14.545857,14.545857 0 0 1 14.54687,14.54492 14.545857,14.545857 0 0 1 -14.54687,14.54688 14.545857,14.545857 0 0 1 -14.54492,-14.54688 14.545857,14.545857 0 0 1 14.54492,-14.54492 z"
|
||||
style="opacity:1;fill:url(#radialGradient4171-0-4);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4209-7-7)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-6-4-7"
|
||||
d="m 243.65555,784.04016 a 14.545857,14.545857 0 0 0 -14.54493,14.54493 14.545857,14.545857 0 0 0 4.41993,10.42187 14.545857,14.545857 0 0 1 -3.95508,-9.95703 14.545857,14.545857 0 0 1 14.54492,-14.54492 14.545857,14.545857 0 0 1 10.11719,4.11328 14.545857,14.545857 0 0 0 -10.58203,-4.57813 z"
|
||||
style="opacity:0.7;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4260-5-2)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4296-1-2-1"
|
||||
d="m 216.96679,773.22058 0,0.74972 0,52.01445 52.766,-52.76417 z m 1.50126,1.49943 49.76348,0 -49.76348,49.76531 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.7;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#radialGradient4485-6-5);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60997915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4507-13-6);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g5868"
|
||||
inkscape:export-xdpi="99.888031"
|
||||
inkscape:export-ydpi="99.888031">
|
||||
<path
|
||||
inkscape:export-ydpi="99.888062"
|
||||
inkscape:export-xdpi="99.888062"
|
||||
id="path4296"
|
||||
d="m 216.28711,772.07227 0,55.02343 55.02344,0 0,-55.02343 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.25;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4406);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-9"
|
||||
d="m 245.4367,781.96308 a 18.414436,18.414436 0 0 0 -18.41601,18.41406 18.414436,18.414436 0 0 0 18.41601,18.41407 18.414436,18.414436 0 0 0 18.41407,-18.41407 18.414436,18.414436 0 0 0 -18.41407,-18.41406 z m -1.70312,2 a 14.545857,14.545857 0 0 1 14.54687,14.54492 14.545857,14.545857 0 0 1 -14.54687,14.54688 14.545857,14.545857 0 0 1 -14.54492,-14.54688 14.545857,14.545857 0 0 1 14.54492,-14.54492 z"
|
||||
style="opacity:1;fill:url(#radialGradient4171);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4209)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-6"
|
||||
d="m 243.65555,784.04016 a 14.545857,14.545857 0 0 0 -14.54493,14.54493 14.545857,14.545857 0 0 0 4.41993,10.42187 14.545857,14.545857 0 0 1 -3.95508,-9.95703 14.545857,14.545857 0 0 1 14.54492,-14.54492 14.545857,14.545857 0 0 1 10.11719,4.11328 14.545857,14.545857 0 0 0 -10.58203,-4.57813 z"
|
||||
style="opacity:0.7;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4260)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4296-1"
|
||||
d="m 216.96679,773.22058 0,0.74972 0,52.01445 52.766,-52.76417 z m 1.50126,1.49943 49.76348,0 -49.76348,49.76531 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.7;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#radialGradient4485);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60997915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4507);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
<g
|
||||
id="g5332"
|
||||
transform="matrix(1.1226559,0,0,1.3295087,-29.131334,-264.53007)">
|
||||
<path
|
||||
id="path4898-7"
|
||||
d="m 245.24023,795.35547 c -0.32818,0 -0.62759,0.0839 -0.89648,0.25 -0.26889,0.16226 -0.51759,0.40997 -0.74414,0.74609 -0.35993,0.53702 -0.64229,1.21012 -0.84766,2.01758 -0.20326,0.80359 -0.30468,1.65051 -0.30468,2.54297 0,1.07404 0.16742,1.91293 0.50195,2.51562 0.17136,0.3068 0.37667,0.53291 0.61523,0.6836 -0.16749,-0.1426 -0.32194,-0.31551 -0.45117,-0.54688 -0.33453,-0.60269 -0.50195,-1.44158 -0.50195,-2.51562 0,-0.89246 0.10143,-1.73938 0.30469,-2.54297 0.20537,-0.80746 0.48772,-1.48056 0.84765,-2.01758 0.22655,-0.33612 0.47525,-0.58383 0.74414,-0.74609 0.26889,-0.1661 0.56831,-0.25 0.89649,-0.25 0.29641,0 0.5786,0.0699 0.84961,0.20898 0.11658,0.0577 0.22984,0.13395 0.34179,0.2168 -0.16403,-0.14275 -0.33146,-0.26718 -0.50586,-0.35352 -0.27101,-0.13908 -0.5532,-0.20898 -0.84961,-0.20898 z m 4.94336,0 c -0.39805,0 -0.7615,0.14783 -1.09179,0.44531 -0.33029,0.29363 -0.62955,0.74101 -0.89844,1.33984 -0.22866,0.50999 -0.40976,1.09123 -0.54102,1.74415 -0.12916,0.65293 -0.19336,1.29209 -0.19336,1.91796 0,1.09336 0.16565,1.95425 0.49805,2.58399 0.17479,0.32903 0.38458,0.56731 0.62695,0.72461 -0.17215,-0.15097 -0.32987,-0.33749 -0.46289,-0.58789 -0.3324,-0.62974 -0.49804,-1.49063 -0.49804,-2.58399 0,-0.62587 0.0642,-1.26504 0.19336,-1.91797 0.13126,-0.65292 0.31235,-1.23416 0.54101,-1.74414 0.26889,-0.59883 0.56815,-1.04621 0.89844,-1.33984 0.33029,-0.29748 0.69375,-0.44531 1.0918,-0.44531 0.27698,0 0.52484,0.0759 0.74609,0.21875 -0.26064,-0.22728 -0.56071,-0.35547 -0.91016,-0.35547 z m -14.67187,0.15625 -0.91797,8.65234 0.17773,0 0.9043,-8.51562 0.4668,0 0.0137,-0.13672 -0.64453,0 z m 3.62695,0 -0.92383,8.65234 0.17774,0 0.91015,-8.51562 2.81836,0 0.0156,-0.13672 -2.99805,0 z m 11.64453,1.0664 c 0.1016,0.10262 0.19504,0.22559 0.27344,0.38868 0.21172,0.43657 0.31836,1.05378 0.31836,1.85351 0,0.45589 -0.0338,0.91525 -0.10156,1.375 -0.0677,0.45589 -0.16577,0.89136 -0.29492,1.3086 -0.19267,0.62203 -0.4261,1.09139 -0.69922,1.4082 -0.27101,0.31293 -0.58051,0.46875 -0.92774,0.46875 -0.17133,0 -0.32221,-0.0505 -0.45898,-0.13672 0.17429,0.17561 0.37854,0.27344 0.62304,0.27344 0.34723,0 0.65673,-0.15582 0.92774,-0.46875 0.27312,-0.31681 0.50655,-0.78618 0.69922,-1.40821 0.12915,-0.41723 0.22722,-0.8527 0.29492,-1.30859 0.0678,-0.45975 0.10156,-0.91911 0.10156,-1.375 0,-0.79973 -0.10664,-1.41694 -0.31836,-1.85351 -0.11844,-0.24641 -0.26587,-0.41698 -0.4375,-0.5254 z m -4.60156,0.125 c 0.20848,0.18276 0.39913,0.41306 0.56055,0.72071 l 0.01,-0.0996 c -0.15558,-0.24079 -0.32281,-0.44931 -0.51562,-0.5918 -0.0176,-0.0133 -0.0369,-0.017 -0.0547,-0.0293 z m -6.60547,2.35547 -0.0137,0.13672 2.08594,0 0.0156,-0.13672 -2.08789,0 z m 5.42188,0.58594 -0.0977,0.96094 0.17773,0 0.084,-0.82422 1.50391,0 0.0156,-0.13672 -1.68359,0 z m 0.93945,1.09766 -0.23047,2.1289 c -0.17573,0.1661 -0.36852,0.29395 -0.57812,0.38282 -0.20961,0.085 -0.42791,0.12695 -0.65235,0.12695 -0.25615,0 -0.47288,-0.0733 -0.65625,-0.20508 0.21121,0.22788 0.48368,0.3418 0.82031,0.3418 0.22444,0 0.44274,-0.0419 0.65235,-0.12696 0.2096,-0.0889 0.40239,-0.21671 0.57812,-0.38281 l 0.2461,-2.26562 -0.17969,0 z m -6.79688,2.4375 -0.0137,0.13672 2.23633,0 0.0137,-0.13672 -2.23633,0 z m -3.61914,0.0117 -0.0137,0.13671 2.12891,0 0.0156,-0.13671 -2.13086,0 z"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';letter-spacing:0px;word-spacing:0px;opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5268)"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
id="path5096"
|
||||
d="m 236.28711,795.95312 -0.7793,7.375 0.24805,0 0.7793,-7.375 -0.24805,0 z m 5.98047,0 -0.0723,0.67969 -2.35937,0 -0.27344,2.5625 0.24805,0 0.24023,-2.25781 2.35938,0 0.10546,-0.98438 -0.24804,0 z m 9.36523,0.34571 c 0.0286,0.0465 0.0609,0.0823 0.0879,0.13281 0.33453,0.62201 0.50196,1.47093 0.50196,2.54883 0,0.66452 -0.0644,1.31765 -0.19141,1.95898 -0.12704,0.64133 -0.30974,1.22258 -0.54687,1.74414 -0.27101,0.6027 -0.57027,1.05208 -0.89844,1.34571 -0.32606,0.29361 -0.68969,0.43945 -1.08985,0.43945 -0.42003,0 -0.77338,-0.17011 -1.06445,-0.49805 0.32517,0.52581 0.74732,0.80274 1.2793,0.80274 0.40016,0 0.76378,-0.14585 1.08984,-0.43946 0.32817,-0.29363 0.62743,-0.743 0.89844,-1.3457 0.23713,-0.52156 0.41983,-1.10281 0.54687,-1.74414 0.12703,-0.64133 0.19141,-1.29446 0.19141,-1.95898 0,-1.0779 -0.16742,-1.92682 -0.50195,-2.54883 -0.0914,-0.17092 -0.19296,-0.31319 -0.30274,-0.4375 z m -4.60742,0.10937 -0.11719,1.12891 c 0.073,0.10398 0.14757,0.20362 0.21289,0.32812 l 0.12891,-1.24609 c -0.0731,-0.0809 -0.14933,-0.14225 -0.22461,-0.21094 z m -1.60937,0.0352 c -0.33665,0 -0.63249,0.11783 -0.88868,0.35352 -0.25618,0.2318 -0.48636,0.59137 -0.6875,1.08203 -0.17149,0.41725 -0.30675,0.91059 -0.40625,1.47851 -0.0974,0.56406 -0.14453,1.13932 -0.14453,1.72656 0,0.80747 0.1133,1.41666 0.33985,1.82618 0.059,0.10566 0.12721,0.1954 0.20117,0.27343 -0.21635,-0.40908 -0.32617,-1.00584 -0.32617,-1.79492 0,-0.58724 0.0471,-1.1625 0.14453,-1.72656 0.0995,-0.56792 0.23476,-1.06127 0.40625,-1.47852 0.20114,-0.49066 0.43132,-0.85023 0.6875,-1.08203 0.25619,-0.23568 0.55202,-0.35351 0.88867,-0.35351 0.29006,0 0.56412,0.0959 0.82031,0.28906 0.11151,0.0824 0.21347,0.18948 0.3125,0.30469 -0.15847,-0.24921 -0.32978,-0.46339 -0.52734,-0.60938 -0.25619,-0.19316 -0.53025,-0.28906 -0.82031,-0.28906 z m 4.91406,0 c -0.35147,0 -0.66275,0.15581 -0.93164,0.46875 -0.26889,0.30907 -0.50216,0.78245 -0.70117,1.41992 -0.12704,0.40566 -0.22527,0.83708 -0.29297,1.29297 -0.0657,0.45589 -0.0977,0.91529 -0.0977,1.37891 0,0.8036 0.10485,1.42281 0.31445,1.85937 0.0711,0.14656 0.15561,0.26015 0.2461,0.35742 -0.01,-0.019 -0.0216,-0.0329 -0.0312,-0.0527 -0.2096,-0.43656 -0.31446,-1.05578 -0.31446,-1.85938 0,-0.46362 0.032,-0.92301 0.0977,-1.3789 0.0677,-0.45589 0.16593,-0.88731 0.29297,-1.29297 0.19901,-0.63747 0.43228,-1.11085 0.70117,-1.41992 0.26889,-0.31294 0.58017,-0.46875 0.93164,-0.46875 0.25109,0 0.46174,0.10403 0.63867,0.29297 -0.20888,-0.39422 -0.49094,-0.59766 -0.85351,-0.59766 z m -8.53516,3.05664 -0.0723,0.67969 -2.26368,0 -0.33203,3.13672 0.24805,0 0.29883,-2.83203 2.26367,0 0.10547,-0.98438 -0.24805,0 z m 5.01758,0.58594 -0.37695,3.50195 c -0.2816,0.28204 -0.58947,0.49976 -0.92188,0.6543 -0.33241,0.15066 -0.66531,0.22656 -1.00195,0.22656 -0.4443,0 -0.81665,-0.16771 -1.11719,-0.50391 0.3311,0.53237 0.77289,0.8086 1.33203,0.8086 0.33664,0 0.66955,-0.0759 1.00196,-0.22656 0.33241,-0.15454 0.64027,-0.37226 0.92187,-0.6543 l 0.41016,-3.80664 -0.24805,0 z m -1.50195,0.65625 -0.0312,0.30469 0.80468,0 0.0332,-0.30469 -0.80664,0 z m -3.80078,2.8789 -0.0723,0.67969 -2.81055,0 -0.0332,0.30469 3.05859,0 0.10352,-0.98438 -0.24609,0 z m -3.72657,0.0117 -0.0723,0.66797 -2.70508,0 -0.0332,0.30469 2.95312,0 0.10547,-0.97266 -0.24805,0 z"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';letter-spacing:0px;word-spacing:0px;opacity:0.5;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5328)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<path
|
||||
sodipodi:nodetypes="cssccsscccsccccscccssccsccccccccccscccscscccscccccccscccccccscccscccscccccscsccccccccccccccc"
|
||||
id="path5423"
|
||||
d="m 104.89822,791.46407 c 0.0801,0.0663 0.16145,0.13186 0.23242,0.21289 0.38967,0.4449 0.58594,1.04084 0.58594,1.78906 0,0.73309 -0.15579,1.36289 -0.46484,1.88867 -0.30571,0.5258 -0.72869,0.88602 -1.26954,1.07813 0.42327,0.18202 0.73344,0.46538 0.93164,0.84961 0.19821,0.38424 0.29883,0.89147 0.29883,1.52344 0,0.60668 -0.0981,1.17619 -0.29297,1.70703 -0.19147,0.53084 -0.46922,0.98685 -0.83203,1.37109 -0.27547,0.29324 -0.60336,0.51079 -0.98633,0.65234 -0.38296,0.14661 -0.82564,0.22071 -1.32617,0.22071 -0.31577,0 -0.63453,-0.0485 -0.95703,-0.14453 -0.15662,-0.0442 -0.31565,-0.0994 -0.47461,-0.16602 l -0.006,0.0508 c 0.33257,0.18706 0.65992,0.32502 0.98243,0.41602 0.32249,0.0961 0.64125,0.14453 0.95703,0.14453 0.50053,0 0.94321,-0.0741 1.32617,-0.2207 0.38296,-0.14156 0.71086,-0.35911 0.98633,-0.65235 0.3628,-0.38423 0.64055,-0.84025 0.83203,-1.37109 0.19483,-0.53085 0.29297,-1.10035 0.29297,-1.70703 0,-0.63197 -0.10063,-1.13921 -0.29883,-1.52344 -0.1982,-0.38424 -0.50837,-0.6676 -0.93164,-0.84961 0.54084,-0.19212 0.96383,-0.55233 1.26953,-1.07812 0.30905,-0.52579 0.46484,-1.15559 0.46484,-1.88868 0,-0.74823 -0.19626,-1.34415 -0.58593,-1.78906 -0.20565,-0.23478 -0.45209,-0.40262 -0.73438,-0.51367 z m -8.10938,0.0508 -1.25195,9.46082 0.54102,0 1.25195,-9.46082 z m -4.58984,0.0137 c 0.24292,0.18913 0.47005,0.41261 0.66211,0.70899 0.53077,0.81397 0.79688,1.92735 0.79688,3.33789 0,0.86958 -0.10118,1.72326 -0.30274,2.5625 -0.20155,0.83925 -0.49095,1.60068 -0.86719,2.2832 -0.42999,0.7887 -0.90509,1.37553 -1.42578,1.75977 -0.51734,0.38424 -1.09361,0.57617 -1.72851,0.57617 -0.37359,0 -0.70636,-0.0859 -1.01563,-0.22071 0.42915,0.33503 0.92861,0.52149 1.51758,0.52149 0.63491,0 1.21118,-0.19194 1.72852,-0.57617 0.52069,-0.38424 0.99579,-0.97108 1.42578,-1.75977 0.37624,-0.68252 0.66563,-1.44395 0.86718,-2.2832 0.20156,-0.83924 0.30274,-1.69292 0.30274,-2.5625 0,-1.41055 -0.26611,-2.52392 -0.79688,-3.33789 -0.31626,-0.48804 -0.70972,-0.81255 -1.16406,-1.00977 z m 11.13281,0.70899 c -0.32249,0 -0.6529,0.054 -0.99218,0.16015 -0.15641,0.0471 -0.31657,0.10758 -0.47852,0.17774 l -0.0664,0.58593 c 0.36281,-0.20727 0.71095,-0.36177 1.04688,-0.46289 0.33929,-0.10617 0.6697,-0.16015 0.99219,-0.16015 0.17244,0 0.32535,0.0273 0.46679,0.0703 -0.23358,-0.24575 -0.55628,-0.37109 -0.96875,-0.37109 z m -12.67773,0.0156 c -0.55764,0 -1.04993,0.20572 -1.47656,0.61524 -0.42663,0.40447 -0.79752,1.02323 -1.11328,1.85742 -0.20156,0.53085 -0.35541,1.09483 -0.4629,1.6914 -0.10416,0.59658 -0.15624,1.19801 -0.15624,1.80469 0,1.05159 0.16547,1.8623 0.49804,2.4336 0.22791,0.38759 0.52393,0.63304 0.87891,0.75781 -0.13888,-0.12558 -0.26747,-0.27084 -0.37695,-0.45703 -0.33258,-0.5713 -0.49805,-1.38201 -0.49805,-2.4336 0,-0.60668 0.0521,-1.20811 0.15625,-1.80468 0.10749,-0.59657 0.26133,-1.16056 0.46289,-1.69141 0.31577,-0.83419 0.68665,-1.45296 1.11328,-1.85742 0.42663,-0.40951 0.91892,-0.61524 1.47656,-0.61524 0.19185,0 0.36453,0.0402 0.5293,0.0977 -0.28484,-0.25761 -0.62491,-0.39844 -1.03125,-0.39844 z m 11.68164,4.86133 -0.0371,0.30078 0.875,0 c 0.21444,0 0.40312,0.0322 0.57422,0.0879 -0.25937,-0.25663 -0.61645,-0.38867 -1.07617,-0.38867 l -0.33594,0 z m -1.8125,3.93359 -0.008,0.0547 c 0.0942,0.0577 0.18876,0.10037 0.2832,0.14649 -0.0921,-0.0653 -0.18369,-0.12483 -0.27539,-0.20118 z m -1.36133,0.51563 -0.12695,0.97265 -4.14649,0 -0.0391,0.30079 4.6875,0 0.16602,-1.27344 -0.54102,0 z"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';letter-spacing:0px;word-spacing:0px;opacity:0.5;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5602)"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:nodetypes="scccsccscccsccsscccccccsccccccccccccccscsccccscsccccscccsccscccsccccscsccccccscsccccccccc"
|
||||
id="path5423-3-3"
|
||||
d="m 90.46658,790.68087 c -0.63154,0 -1.21032,0.19469 -1.73438,0.58398 -0.52404,0.38423 -0.99914,0.96831 -1.42578,1.75195 -0.3628,0.66735 -0.6472,1.42879 -0.85547,2.28321 -0.20491,0.85441 -0.30859,1.69074 -0.30859,2.50976 0,1.43077 0.26361,2.55874 0.79102,3.38282 0.0431,0.0669 0.095,0.11431 0.14062,0.17578 -0.46959,-0.80995 -0.71289,-1.88038 -0.71289,-3.23047 0,-0.81903 0.10368,-1.65535 0.30859,-2.50977 0.20827,-0.85441 0.49267,-1.61586 0.85547,-2.2832 0.42664,-0.78364 0.90174,-1.36773 1.42578,-1.75195 0.52406,-0.3893 1.10284,-0.58399 1.73438,-0.58399 0.85021,0 1.52538,0.36567 2.04297,1.06445 -0.0307,-0.0524 -0.0532,-0.11389 -0.0859,-0.16406 -0.53075,-0.81902 -1.25533,-1.22851 -2.17578,-1.22851 z m 12.86328,0 c -0.33593,0 -0.67798,0.0422 -1.02734,0.12304 -0.34601,0.0809 -0.70469,0.20151 -1.07422,0.36328 l -0.1543,1.36524 c 0.0924,-0.0528 0.18092,-0.0927 0.27149,-0.13867 l 0.10156,-0.89844 c 0.36952,-0.16178 0.72821,-0.28244 1.07422,-0.36328 0.34936,-0.0808 0.69141,-0.12305 1.02734,-0.12305 0.66514,0 1.19234,0.22307 1.58203,0.66797 0.0225,0.0257 0.0374,0.0572 0.0586,0.084 -0.0787,-0.14832 -0.16821,-0.2875 -0.27735,-0.41211 -0.38969,-0.4449 -0.91689,-0.66796 -1.58203,-0.66796 z m -7.74414,0.20507 -1.45703,11.32227 0.26172,0 1.41406,-10.99414 0.76172,0 0.043,-0.32813 -1.02344,0 z m 8.7168,1.72461 c 0.10148,0.2186 0.15625,0.48024 0.15625,0.79297 0,0.65724 -0.15993,1.17826 -0.48243,1.5625 -0.31912,0.38423 -0.75876,0.57617 -1.3164,0.57617 l -0.92774,0 -0.15429,1.24414 0.25976,0 0.11328,-0.91601 0.92774,0 c 0.55764,0 0.99728,-0.19194 1.31641,-0.57617 0.32249,-0.38424 0.48242,-0.90527 0.48242,-1.5625 0,-0.47523 -0.11643,-0.84177 -0.35157,-1.09961 -0.007,-0.008 -0.0161,-0.0137 -0.0234,-0.0215 z m -12.41407,0.25977 c 0.30812,0.5663 0.4668,1.34344 0.4668,2.3457 0,0.59657 -0.0527,1.1972 -0.16015,1.79883 -0.1075,0.59657 -0.26384,1.16688 -0.46876,1.71289 -0.3057,0.81397 -0.67602,1.4292 -1.10937,1.84375 -0.42998,0.40951 -0.91977,0.61328 -1.4707,0.61328 -0.51257,0 -0.92303,-0.2136 -1.24219,-0.61523 0.0144,0.0269 0.024,0.0601 0.0391,0.0859 0.33593,0.57128 0.81048,0.85742 1.42188,0.85742 0.55093,0 1.04072,-0.20377 1.4707,-0.61328 0.43335,-0.41456 0.80367,-1.02978 1.10938,-1.84375 0.20491,-0.54602 0.36125,-1.11632 0.46874,-1.71289 0.1075,-0.60163 0.16016,-1.20226 0.16016,-1.79883 0,-1.04653 -0.16798,-1.8545 -0.5039,-2.42578 -0.055,-0.0943 -0.11937,-0.16912 -0.18165,-0.24805 z m 11.89844,4.66797 c 0.11882,0.24454 0.1836,0.54026 0.1836,0.89453 0,0.81901 -0.20595,1.48627 -0.61915,2.00195 -0.40983,0.51063 -0.94564,0.76563 -1.60742,0.76563 -0.33592,0 -0.66578,-0.0631 -0.98828,-0.18946 -0.31913,-0.13143 -0.63735,-0.32888 -0.95312,-0.59179 l -0.18555,1.44922 c 0.0828,0.0465 0.16399,0.0806 0.24609,0.12109 l 0.15821,-1.24219 c 0.31577,0.2629 0.63399,0.46036 0.95312,0.5918 0.3225,0.12639 0.65235,0.18945 0.98828,0.18945 0.66178,0 1.19759,-0.255 1.60743,-0.76562 0.41319,-0.51568 0.61914,-1.18294 0.61914,-2.00196 0,-0.52579 -0.13055,-0.93171 -0.39258,-1.21484 -0.003,-0.003 -0.007,-0.005 -0.01,-0.008 z m -8.20703,3.39648 -0.043,0.32813 3.40235,0 0.043,-0.32813 -3.40234,0 z"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.6600647px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif Italic';letter-spacing:0px;word-spacing:0px;opacity:0.4;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter5676)"
|
||||
inkscape:connector-curvature="0" />
|
||||
<g
|
||||
transform="translate(-71.352998,-1.0760495)"
|
||||
id="g5868-1"
|
||||
inkscape:export-xdpi="99.888031"
|
||||
inkscape:export-ydpi="99.888031">
|
||||
<path
|
||||
inkscape:export-ydpi="99.888062"
|
||||
inkscape:export-xdpi="99.888062"
|
||||
id="path4296-5"
|
||||
d="m 216.28711,772.07227 0,55.02343 55.02344,0 0,-55.02343 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.25;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4406-3);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-9-7"
|
||||
d="m 245.4367,781.96308 a 18.414436,18.414436 0 0 0 -18.41601,18.41406 18.414436,18.414436 0 0 0 18.41601,18.41407 18.414436,18.414436 0 0 0 18.41407,-18.41407 18.414436,18.414436 0 0 0 -18.41407,-18.41406 z m -1.70312,2 a 14.545857,14.545857 0 0 1 14.54687,14.54492 14.545857,14.545857 0 0 1 -14.54687,14.54688 14.545857,14.545857 0 0 1 -14.54492,-14.54688 14.545857,14.545857 0 0 1 14.54492,-14.54492 z"
|
||||
style="opacity:1;fill:url(#radialGradient4171-0);fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4209-7)" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4148-6-4"
|
||||
d="m 243.65555,784.04016 a 14.545857,14.545857 0 0 0 -14.54493,14.54493 14.545857,14.545857 0 0 0 4.41993,10.42187 14.545857,14.545857 0 0 1 -3.95508,-9.95703 14.545857,14.545857 0 0 1 14.54492,-14.54492 14.545857,14.545857 0 0 1 10.11719,4.11328 14.545857,14.545857 0 0 0 -10.58203,-4.57813 z"
|
||||
style="opacity:0.7;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4260-5)" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4296-1-2"
|
||||
d="m 216.96679,773.22058 0,0.74972 0,52.01445 52.766,-52.76417 z m 1.50126,1.49943 49.76348,0 -49.76348,49.76531 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.7;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:url(#radialGradient4485-6);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.60997915;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter4507-13);color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 50 KiB |
97
build/geom/ConvexHull.js
Normal file
97
build/geom/ConvexHull.js
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (http://www.cecill.info/).
|
||||
|
||||
ol.coordinate.convexHull compute a convex hull using Andrew's Monotone Chain Algorithm.
|
||||
|
||||
@see https://en.wikipedia.org/wiki/Convex_hull_algorithms
|
||||
*/
|
||||
|
||||
import ol_geom_Geometry from 'ol/geom/geometry'
|
||||
|
||||
(function(){
|
||||
|
||||
/* Tests if a point is left or right of line (a,b).
|
||||
* @param {ol.coordinate} a point on the line
|
||||
* @param {ol.coordinate} b point on the line
|
||||
* @param {ol.coordinate} 0
|
||||
* @return {bool} true if (a,b,o) turns clockwise
|
||||
*/
|
||||
function clockwise (a, b, o)
|
||||
{ return ( (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]) <= 0 )
|
||||
}
|
||||
|
||||
/** Compute a convex hull using Andrew's Monotone Chain Algorithm
|
||||
* @param {Array<ol.geom.Point>} points an array of 2D points
|
||||
* @return {Array<ol.geom.Point>} the convex hull vertices
|
||||
*/
|
||||
var ol_coordinate_convexHull = function (points)
|
||||
{ // Sort by increasing x and then y coordinate
|
||||
points.sort(function(a, b)
|
||||
{ return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
|
||||
});
|
||||
|
||||
// Compute the lower hull
|
||||
var lower = [];
|
||||
for (var i = 0; i < points.length; i++)
|
||||
{ while (lower.length >= 2 && clockwise (lower[lower.length - 2], lower[lower.length - 1], points[i]) )
|
||||
{ lower.pop();
|
||||
}
|
||||
lower.push(points[i]);
|
||||
}
|
||||
|
||||
// Compute the upper hull
|
||||
var upper = [];
|
||||
for (var i = points.length - 1; i >= 0; i--)
|
||||
{ while (upper.length >= 2 && clockwise (upper[upper.length - 2], upper[upper.length - 1], points[i]) )
|
||||
{ upper.pop();
|
||||
}
|
||||
upper.push(points[i]);
|
||||
}
|
||||
|
||||
upper.pop();
|
||||
lower.pop();
|
||||
return lower.concat(upper);
|
||||
}
|
||||
|
||||
/* Get coordinates of a geometry */
|
||||
function getCoordinates(geom)
|
||||
{ var h = [];
|
||||
switch (geom.getType())
|
||||
{ case "Point":
|
||||
h.push(geom.getCoordinates());
|
||||
break;
|
||||
case "LineString":
|
||||
case "LinearRing":
|
||||
case "MultiPoint":
|
||||
h = geom.getCoordinates();
|
||||
break;
|
||||
case "MultiLineString":
|
||||
var p = geom.getLineStrings();
|
||||
for (var i=0; i<p.length; i++) h.concat(getCoordinates(p[i]));
|
||||
break;
|
||||
case "Polygon":
|
||||
h = getCoordinates(geom.getLinearRing(0));
|
||||
break;
|
||||
case "MultiPolygon":
|
||||
var p = geom.getPolygons();
|
||||
for (var i=0; i<p.length; i++) h.concat(getCoordinates(p[i]));
|
||||
break;
|
||||
case "GeometryCollection":
|
||||
var p = geom.getGeometries();
|
||||
for (var i=0; i<p.length; i++) h.concat(getCoordinates(p[i]));
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/** Compute a convex hull on a geometry using Andrew's Monotone Chain Algorithm
|
||||
* @return {Array<ol.geom.Point>} the convex hull vertices
|
||||
*/
|
||||
ol_geom_Geometry.prototype.convexHull = function()
|
||||
{ return ol_coordinate_convexHull( getCoordinates(this) );
|
||||
};
|
||||
|
||||
|
||||
})();
|
||||
122
build/geom/GeomUtils.js
Normal file
122
build/geom/GeomUtils.js
Normal file
@ -0,0 +1,122 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
|
||||
Usefull function to handle geometric operations
|
||||
*/
|
||||
|
||||
import ol_geom_LineString from 'ol/geom/linestring'
|
||||
import ol_coordinate from 'ol/coordinate'
|
||||
import ol_extent from 'ol/extent'
|
||||
|
||||
/** Distance beetween 2 points
|
||||
* Usefull geometric functions
|
||||
* @param {ol.coordinate} p1 first point
|
||||
* @param {ol.coordinate} p2 second point
|
||||
* @return {number} distance
|
||||
*/
|
||||
var ol_coordinate_dist2d = function(p1, p2)
|
||||
{ var dx = p1[0]-p2[0];
|
||||
var dy = p1[1]-p2[1];
|
||||
return Math.sqrt(dx*dx+dy*dy);
|
||||
}
|
||||
/** 2 points are equal
|
||||
* Usefull geometric functions
|
||||
* @param {ol.coordinate} p1 first point
|
||||
* @param {ol.coordinate} p2 second point
|
||||
* @return {boolean}
|
||||
*/
|
||||
var ol_coordinate_equal = function(p1, p2)
|
||||
{ return (p1[0]==p2[0] && p1[1]==p2[1]);
|
||||
}
|
||||
|
||||
/** Get center coordinate of a feature
|
||||
* @param {ol.Feature} f
|
||||
* @return {ol.coordinate} the center
|
||||
*/
|
||||
var ol_coordinate_getFeatureCenter = function(f)
|
||||
{ return ol_coordinate.getGeomCenter (f.getGeometry());
|
||||
};
|
||||
|
||||
/** Get center coordinate of a geometry
|
||||
* @param {ol.Feature} geom
|
||||
* @return {ol.coordinate} the center
|
||||
*/
|
||||
var ol_coordinate_getGeomCenter = function(geom)
|
||||
{ switch (geom.getType())
|
||||
{ case 'Point':
|
||||
return geom.getCoordinates();
|
||||
case "MultiPolygon":
|
||||
geom = geom.getPolygon(0);
|
||||
case "Polygon":
|
||||
return geom.getInteriorPoint().getCoordinates();
|
||||
default:
|
||||
return geom.getClosestPoint(ol_extent.getCenter(geom.getExtent()));
|
||||
};
|
||||
};
|
||||
|
||||
/** Split a lineString by a point or a list of points
|
||||
* NB: points must be on the line, use getClosestPoint() to get one
|
||||
* @param {ol.Coordinate | Array<ol.Coordinate>} pt points to split the line
|
||||
* @param {Number} tol distance tolerance for 2 points to be equal
|
||||
*/
|
||||
ol_geom_LineString.prototype.splitAt = function(pt, tol)
|
||||
{ if (!pt) return [this];
|
||||
if (!tol) tol = 1e-10;
|
||||
// Test if list of points
|
||||
if (pt.length && pt[0].length)
|
||||
{ var result = [this];
|
||||
for (var i=0; i<pt.length; i++)
|
||||
{ var r = [];
|
||||
for (var k=0; k<result.length; k++)
|
||||
{ var ri = result[k].splitAt(pt[i], tol);
|
||||
r = r.concat(ri);
|
||||
}
|
||||
result = r;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Nothing to do
|
||||
if (ol_coordinate.equal(pt,this.getFirstCoordinate())
|
||||
|| ol_coordinate.equal(pt,this.getLastCoordinate()))
|
||||
{ return [this];
|
||||
}
|
||||
// Get
|
||||
var c0 = this.getCoordinates();
|
||||
var ci=[c0[0]], p0, p1;
|
||||
var c = [];
|
||||
for (var i=0; i<c0.length-1; i++)
|
||||
{ // Filter equal points
|
||||
if (ol_coordinate.equal(c0[i],c0[i+1])) continue;
|
||||
// Extremity found
|
||||
if (ol_coordinate.equal(pt,c0[i+1]))
|
||||
{ ci.push(c0[i+1]);
|
||||
c.push(new ol.geom.LineString(ci));
|
||||
ci = [];
|
||||
}
|
||||
// Test alignement
|
||||
else if (!ol_coordinate.equal(pt,c0[i]))
|
||||
{ var d1, d2;
|
||||
if (c0[i][0] == c0[i+1][0])
|
||||
{ d1 = d2 = (c0[i][1]-pt[1]) / (c0[i][1]-c0[i+1][1]);
|
||||
}
|
||||
else if (c0[i][1] == c0[i+1][1])
|
||||
{ d1 = d2 = (c0[i][0]-pt[0]) / (c0[i][0]-c0[i+1][0]);
|
||||
}
|
||||
else
|
||||
{ d1 = (c0[i][0]-pt[0]) / (c0[i][0]-c0[i+1][0]);
|
||||
d2 = (c0[i][1]-pt[1]) / (c0[i][1]-c0[i+1][1]);
|
||||
}
|
||||
if (Math.abs(d1-d2)<tol && 0<=d1 && d1<=1)
|
||||
{ ci.push(pt);
|
||||
c.push (new ol.geom.LineString(ci));
|
||||
ci = [pt];
|
||||
}
|
||||
}
|
||||
ci.push(c0[i+1]);
|
||||
}
|
||||
if (ci.length>1) c.push (new ol_geom_LineString(ci));
|
||||
if (c.length) return c;
|
||||
else return [this];
|
||||
}
|
||||
|
||||
149
build/interaction/CenterTouch.js
Normal file
149
build/interaction/CenterTouch.js
Normal file
@ -0,0 +1,149 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_style_RegularShape from 'ol/style/regularshape'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
|
||||
/** Handles coordinates on the center of the viewport.
|
||||
* It can be used as abstract base class used for creating subclasses.
|
||||
* The CenterTouch interaction modifies map browser event coordinate and pixel properties to force pointer on the viewport center to any interaction that them.
|
||||
* Only pointermove pointerup are concerned with it.
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @param {olx.interaction.InteractionOptions} options Options
|
||||
* - targetStyle {ol_style_Style|Array<ol_style_Style>} a style to draw the target point, default cross style
|
||||
* - composite {string} composite operation : difference|multiply|xor|screen|overlay|darken|lighter|lighten|...
|
||||
*/
|
||||
var ol_interaction_CenterTouch = function(options)
|
||||
{ options = options || {};
|
||||
// Filter event
|
||||
var rex = /^pointermove$|^pointerup$/;
|
||||
|
||||
// Default style = cross
|
||||
this.targetStyle = options.targetStyle ||
|
||||
[ new ol_style_Style({ image: new ol_style_RegularShape ({ points: 4, radius: 11, radius1: 0, radius2: 0, snapToPixel:true, stroke: new ol_style_Stroke({ color: "#fff", width:3 }) }) }),
|
||||
new ol_style_Style({ image: new ol_style_RegularShape ({ points: 4, radius: 11, radius1: 0, radius2: 0, snapToPixel:true, stroke: new ol_style_Stroke({ color: "#000", width:1 }) }) })
|
||||
];
|
||||
if (!(this.targetStyle instanceof Array)) this.targetStyle = [this.targetStyle];
|
||||
this.composite = options.composite || '';
|
||||
|
||||
// Interaction to defer center on top of the interaction
|
||||
// this is done to enable other coordinates manipulation inserted after the interaction (snapping)
|
||||
this.ctouch = new ol_interaction_Interaction(
|
||||
{ handleEvent: function(e)
|
||||
{ if (rex.test(e.type) && this.getMap())
|
||||
{ e.coordinate = this.getMap().getView().getCenter();
|
||||
e.pixel = this.getMap().getSize();
|
||||
e.pixel = [ e.pixel[0]/2, e.pixel[1]/2 ];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ if (rex.test(e.type)) this.pos_ = e.coordinate;
|
||||
if (options.handleEvent) return options.handleEvent.call (this,e);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
ol.inherits(ol_interaction_CenterTouch, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {_ol_Map_} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_CenterTouch.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().removeInteraction(this.ctouch);
|
||||
this.getMap().un('postcompose', this.drawTarget_, this);
|
||||
}
|
||||
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
|
||||
if (this.getMap())
|
||||
{ if (this.getActive()) this.getMap().addInteraction(this.ctouch);
|
||||
this.getMap().on('postcompose', this.drawTarget_, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate or deactivate the interaction.
|
||||
* @param {boolean} active Active.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol_interaction_CenterTouch.prototype.setActive = function(b)
|
||||
{ ol_interaction_Interaction.prototype.setActive.call (this, b);
|
||||
|
||||
this.pos_ = null;
|
||||
|
||||
if (this.getMap())
|
||||
{ if (this.getActive())
|
||||
{ this.getMap().addInteraction(this.ctouch);
|
||||
}
|
||||
else this.getMap().removeInteraction(this.ctouch);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Get the position of the target
|
||||
*/
|
||||
ol_interaction_CenterTouch.prototype.getPosition = function (e)
|
||||
{ if (!this.pos_)
|
||||
{ var px =this.getMap().getSize();
|
||||
px = [ px[0]/2, px[1]/2 ];
|
||||
this.pos_ = this.getMap().getCoordinateFromPixel(px);
|
||||
}
|
||||
return this.pos_;
|
||||
};
|
||||
|
||||
/** Draw the target
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_CenterTouch.prototype.drawTarget_ = function (e)
|
||||
{ if (!this.getMap() || !this.getActive()) return;
|
||||
|
||||
var ctx = e.context;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
|
||||
ctx.save();
|
||||
|
||||
var cx = ctx.canvas.width/(2*ratio);
|
||||
var cy = ctx.canvas.height/(2*ratio);
|
||||
|
||||
var geom = new ol_geom_Point (this.getMap().getCoordinateFromPixel([cx,cy]));
|
||||
|
||||
if (this.composite) ctx.globalCompositeOperation = this.composite;
|
||||
|
||||
for (var i=0; i<this.targetStyle.length; i++)
|
||||
{ var style = this.targetStyle[i];
|
||||
|
||||
if (style instanceof ol_style_Style)
|
||||
{ var sc=0;
|
||||
// OL < v4.3 : setImageStyle doesn't check retina
|
||||
var imgs = ol_Map.prototype.getFeaturesAtPixel ? false : style.getImage();
|
||||
if (imgs)
|
||||
{ sc = imgs.getScale();
|
||||
imgs.setScale(ratio*sc);
|
||||
}
|
||||
e.vectorContext.setStyle(style);
|
||||
e.vectorContext.drawGeometry(geom);
|
||||
if (imgs) imgs.setScale(sc);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_interaction_CenterTouch
|
||||
148
build/interaction/Clip.js
Normal file
148
build/interaction/Clip.js
Normal file
@ -0,0 +1,148 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
|
||||
/** Clip interaction to clip layers in a circle
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Pointer}
|
||||
* @param {ol_interaction_Clip.options} options flashlight param
|
||||
* - radius {number} radius of the clip, default 100
|
||||
* - layers {ol.layer|Array<ol.layer>} layers to clip
|
||||
*/
|
||||
var ol_interaction_Clip = function(options) {
|
||||
|
||||
this.layers_ = [];
|
||||
|
||||
ol_interaction_Pointer.call(this,
|
||||
{ handleDownEvent: this.setPosition,
|
||||
handleMoveEvent: this.setPosition
|
||||
});
|
||||
|
||||
// Default options
|
||||
options = options || {};
|
||||
|
||||
this.pos = false;
|
||||
this.radius = (options.radius||100);
|
||||
if (options.layers) this.addLayer(options.layers);
|
||||
};
|
||||
ol.inherits(ol_interaction_Clip, ol_interaction_Pointer);
|
||||
|
||||
/** Set the map > start postcompose
|
||||
*/
|
||||
ol_interaction_Clip.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ for (var i=0; i<this.layers_.length; i++)
|
||||
{ this.layers_[i].un('precompose', this.precompose_, this);
|
||||
this.layers_[i].un('postcompose', this.postcompose_, this);
|
||||
}
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
|
||||
ol_interaction_Pointer.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ for (var i=0; i<this.layers_.length; i++)
|
||||
{ this.layers_[i].on('precompose', this.precompose_, this);
|
||||
this.layers_[i].on('postcompose', this.postcompose_, this);
|
||||
}
|
||||
map.renderSync();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set clip radius
|
||||
* @param {integer} radius
|
||||
*/
|
||||
ol_interaction_Clip.prototype.setRadius = function(radius)
|
||||
{ this.radius = radius;
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/** Add a layer to clip
|
||||
* @param {ol.layer|Array<ol.layer>} layer to clip
|
||||
*/
|
||||
ol_interaction_Clip.prototype.addLayer = function(layers)
|
||||
{ if (!(layers instanceof Array)) layers = [layers];
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ if (this.getMap())
|
||||
{ layers[i].on('precompose', this.precompose_, this);
|
||||
layers[i].on('postcompose', this.postcompose_, this);
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
this.layers_.push(layers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove a layer to clip
|
||||
* @param {ol.layer|Array<ol.layer>} layer to clip
|
||||
*/
|
||||
ol_interaction_Clip.prototype.removeLayer = function(layers)
|
||||
{ if (!(layers instanceof Array)) layers = [layers];
|
||||
for (var i=0; i<layers.length; i++)
|
||||
{ var k;
|
||||
for (k=0; k<this.layers_.length; k++)
|
||||
{ if (this.layers_[k]===layers[i])
|
||||
{ break;
|
||||
}
|
||||
}
|
||||
if (k!=this.layers_.length && this.getMap())
|
||||
{ this.layers_.splice(k,1);
|
||||
layers[i].un('precompose', this.precompose_, this);
|
||||
layers[i].un('postcompose', this.postcompose_, this);
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Set position of the clip
|
||||
* @param {ol.Pixel|ol.MapBrowserEvent}
|
||||
*/
|
||||
ol_interaction_Clip.prototype.setPosition = function(e)
|
||||
{ if (e.pixel) this.pos = e.pixel;
|
||||
else
|
||||
{ if (e && e instanceof Array) this.pos = e;
|
||||
else e = [-10000000,-10000000];
|
||||
}
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/* @private
|
||||
*/
|
||||
ol_interaction_Clip.prototype.precompose_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.arc (this.pos[0]*ratio, this.pos[1]*ratio, this.radius*ratio, 0, 2*Math.PI);
|
||||
ctx.clip();
|
||||
}
|
||||
|
||||
/* @private
|
||||
*/
|
||||
ol_interaction_Clip.prototype.postcompose_ = function(e)
|
||||
{ e.context.restore();
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate or deactivate the interaction.
|
||||
* @param {boolean} active Active.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol_interaction_Clip.prototype.setActive = function(b)
|
||||
{ ol_interaction_Pointer.prototype.setActive.call (this, b);
|
||||
if(b) {
|
||||
for(var i=0; i<this.layers_.length; i++) {
|
||||
this.layers_[i].on('precompose', this.precompose_, this);
|
||||
this.layers_[i].on('postcompose', this.postcompose_, this);
|
||||
}
|
||||
} else {
|
||||
for(var i=0; i<this.layers_.length; i++) {
|
||||
this.layers_[i].un('precompose', this.precompose_, this);
|
||||
this.layers_[i].un('postcompose', this.postcompose_, this);
|
||||
}
|
||||
}
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
export default ol_interaction_Clip
|
||||
171
build/interaction/DrawHole.js
Normal file
171
build/interaction/DrawHole.js
Normal file
@ -0,0 +1,171 @@
|
||||
/* Copyright (c) 2017 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_geom_Polygon from 'ol/geom/polygon'
|
||||
import ol_geom_LinearRing from 'ol/geom/linearring'
|
||||
import ol_interaction_Draw from 'ol/interaction/draw'
|
||||
import ol_interaction_Select from 'ol/interaction/select'
|
||||
|
||||
/** Interaction draw hole
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires drawstart, drawend
|
||||
* @param {olx.interaction.DrawHoleOptions} options extend olx.interaction.DrawOptions
|
||||
* @param {Array<ol.layer.Vector> | undefined} options.layers A list of layers from which polygons should be selected. Alternatively, a filter function can be provided. default: all visible layers
|
||||
*/
|
||||
var ol_interaction_DrawHole = function(options)
|
||||
{ if (!options) options = {};
|
||||
var self = this;
|
||||
|
||||
// Select interaction for the current feature
|
||||
this._select = new ol_interaction_Select();
|
||||
this._select.setActive(false);
|
||||
|
||||
// Geometry function that test points inside the current
|
||||
var geometryFn, geomFn = options.geometryFunction;
|
||||
if (geomFn)
|
||||
{ geometryFn = function(c,g)
|
||||
{ g = self._geometryFn (c, g);
|
||||
return geomFn (c,g);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ geometryFn = function(c,g) { return self._geometryFn (c, g); }
|
||||
}
|
||||
|
||||
// Create draw interaction
|
||||
options.type = "Polygon";
|
||||
options.geometryFunction = geometryFn;
|
||||
ol_interaction_Draw.call(this, options);
|
||||
|
||||
// Layer filter function
|
||||
if (options.layers)
|
||||
{ if (typeof (options.layers) === 'function') this.layers_ = options.layers;
|
||||
else if (options.layers.indexOf)
|
||||
{ this.layers_ = function(l)
|
||||
{ return (options.layers.indexOf(l) >= 0);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Start drawing if inside a feature
|
||||
this.on('drawstart', this._startDrawing, this );
|
||||
// End drawing add the hole to the current Polygon
|
||||
this.on('drawend', this._finishDrawing, this);
|
||||
};
|
||||
ol.inherits(ol_interaction_DrawHole, ol_interaction_Draw);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().removeInteraction(this._select);
|
||||
if (map) map.addInteraction(this._select);
|
||||
ol_interaction_Draw.prototype.setMap.call (this, map);
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate/deactivate the interaction
|
||||
* @param {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype.setActive = function(b)
|
||||
{ this._select.getFeatures().clear();
|
||||
ol_interaction_Draw.prototype.setActive.call (this, b);
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove last point of the feature currently being drawn
|
||||
* (test if points to remove before).
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype.removeLastPoint = function()
|
||||
{ if (this._feature && this._feature.getGeometry().getCoordinates()[0].length>2)
|
||||
{ ol_interaction_Draw.prototype.removeLastPoint.call(this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the current polygon to hole
|
||||
* @return {ol.Feature}
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype.getPolygon = function()
|
||||
{ return this._select.getFeatures().item(0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get current feature to add a hole and start drawing
|
||||
* @param {ol_interaction_Draw.Event} e
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype._startDrawing = function(e)
|
||||
{ var map = this.getMap();
|
||||
var layersFilter = this.layers_;
|
||||
this._feature = e.feature;
|
||||
coord = e.feature.getGeometry().getCoordinates()[0][0];
|
||||
// Check object under the pointer
|
||||
var features = map.getFeaturesAtPixel(
|
||||
map.getPixelFromCoordinate(coord),
|
||||
{ layerFilter: layersFilter
|
||||
}
|
||||
);
|
||||
var current = null;
|
||||
if (features)
|
||||
{ if (features[0].getGeometry().getType() !== "Polygon") current = null;
|
||||
else if (features[0].getGeometry().intersectsCoordinate(coord)) current = features[0];
|
||||
else current = null;
|
||||
}
|
||||
else current = null;
|
||||
|
||||
if (!current)
|
||||
{ this.setActive(false);
|
||||
this.setActive(true);
|
||||
this._select.getFeatures().clear();
|
||||
}
|
||||
else
|
||||
{ this._select.getFeatures().push(current);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stop drawing and add the sketch feature to the target feature.
|
||||
* @param {ol_interaction_Draw.Event} e
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype._finishDrawing = function(e)
|
||||
{ var c = e.feature.getGeometry().getCoordinates()[0];
|
||||
if (c.length > 3) this.getPolygon().getGeometry().appendLinearRing(new ol_geom_LinearRing(c));
|
||||
this._feature = null;
|
||||
this._select.getFeatures().clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that is called when a geometry's coordinates are updated.
|
||||
* @param {Array<ol.coordinate>} coordinates
|
||||
* @param {ol_geom_Polygon} geometry
|
||||
* @return {ol_geom_Polygon}
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_DrawHole.prototype._geometryFn = function(coordinates, geometry)
|
||||
{ var coord = coordinates[0].pop();
|
||||
if (!this.getPolygon() || this.getPolygon().getGeometry().intersectsCoordinate(coord))
|
||||
{ this.lastOKCoord = [coord[0],coord[1]];
|
||||
}
|
||||
coordinates[0].push([this.lastOKCoord[0],this.lastOKCoord[1]]);
|
||||
|
||||
if (geometry)
|
||||
{ geometry.setCoordinates([coordinates[0].concat([coordinates[0][0]])]);
|
||||
}
|
||||
else
|
||||
{ geometry = new ol_geom_Polygon(coordinates);
|
||||
}
|
||||
return geometry;
|
||||
};
|
||||
|
||||
export default ol_interaction_DrawHole
|
||||
417
build/interaction/DrawRegular.js
Normal file
417
build/interaction/DrawRegular.js
Normal file
@ -0,0 +1,417 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_geom_Circle from 'ol/geom/circle'
|
||||
import ol_geom_Polygon from 'ol/geom/polygon'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
|
||||
/** Interaction rotate
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires drawstart, drawing, drawend, drawcancel
|
||||
* @param {olx.interaction.TransformOptions} options
|
||||
* @param {Array<ol.Layer>} source Destination source for the drawn features
|
||||
* @param {ol.Collection<ol.Feature>} features Destination collection for the drawn features
|
||||
* @param {ol.style.Style | Array.<ol.style.Style> | ol.style.StyleFunction | undefined} style style for the sketch
|
||||
* @param {integer} sides number of sides, default 0 = circle
|
||||
* @param { ol.events.ConditionType | undefined } squareCondition A function that takes an ol.MapBrowserEvent and returns a boolean to draw square features.
|
||||
* @param { ol.events.ConditionType | undefined } centerCondition A function that takes an ol.MapBrowserEvent and returns a boolean to draw centered features.
|
||||
* @param { bool } canRotate Allow rotation when centered + square, default: true
|
||||
* @param { number } clickTolerance click tolerance on touch devices, default: 6
|
||||
* @param { number } maxCircleCoordinates Maximum number of point on a circle, default: 100
|
||||
*/
|
||||
var ol_interaction_DrawRegular = function(options)
|
||||
{ if (!options) options={};
|
||||
var self = this;
|
||||
|
||||
this.squaredClickTolerance_ = options.clickTolerance ? options.clickTolerance * options.clickTolerance : 36;
|
||||
this.maxCircleCoordinates_ = options.maxCircleCoordinates || 100;
|
||||
|
||||
// Collection of feature to transform
|
||||
this.features_ = options.features;
|
||||
// List of layers to transform
|
||||
this.source_ = options.source;
|
||||
// Square condition
|
||||
this.squareFn_ = options.squareCondition;
|
||||
// Centered condition
|
||||
this.centeredFn_ = options.centerCondition;
|
||||
// Allow rotation when centered + square
|
||||
this.canRotate_ = (options.canRotate !== false);
|
||||
|
||||
// Number of sides (default=0: circle)
|
||||
this.setSides(options.sides);
|
||||
|
||||
// Style
|
||||
var white = [255, 255, 255, 1];
|
||||
var blue = [0, 153, 255, 1];
|
||||
var width = 3;
|
||||
var defaultStyle = [
|
||||
new ol_style_Style({
|
||||
stroke: new ol_style_Stroke({ color: white, width: width + 2 })
|
||||
}),
|
||||
new ol.style.Style({
|
||||
image: new ol_style_Circle({
|
||||
radius: width * 2,
|
||||
fill: new ol_style_Fill({ color: blue }),
|
||||
stroke: new ol_style_Stroke({ color: white, width: width / 2 })
|
||||
}),
|
||||
stroke: new ol_style_Stroke({ color: blue, width: width }),
|
||||
fill: new ol_style_Fill({
|
||||
color: [255, 255, 255, 0.5]
|
||||
})
|
||||
})
|
||||
];
|
||||
|
||||
// Create a new overlay layer for the sketch
|
||||
this.sketch_ = new ol_Collection();
|
||||
this.overlayLayer_ = new ol_layer_Vector(
|
||||
{ source: new ol_source_Vector({
|
||||
features: this.sketch_,
|
||||
useSpatialIndex: false
|
||||
}),
|
||||
name:'DrawRegular overlay',
|
||||
displayInLayerSwitcher: false,
|
||||
style: options.style || defaultStyle
|
||||
});
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{
|
||||
/*
|
||||
handleDownEvent: this.handleDownEvent_,
|
||||
handleMoveEvent: this.handleMoveEvent_,
|
||||
handleUpEvent: this.handleUpEvent_,
|
||||
*/
|
||||
handleEvent: this.handleEvent_
|
||||
});
|
||||
};
|
||||
ol.inherits(ol_interaction_DrawRegular, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().removeLayer(this.overlayLayer_);
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
this.overlayLayer_.setMap(map);
|
||||
};
|
||||
|
||||
/**
|
||||
* Activate/deactivate the interaction
|
||||
* @param {boolean}
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.setActive = function(b)
|
||||
{ this.reset();
|
||||
ol_interaction_Interaction.prototype.setActive.call (this, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the interaction
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.reset = function()
|
||||
{ this.overlayLayer_.getSource().clear();
|
||||
this.started_ = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of sides.
|
||||
* @param {int} number of sides.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.setSides = function (nb)
|
||||
{ nb = parseInt(nb);
|
||||
this.sides_ = nb>2 ? nb : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow rotation when centered + square
|
||||
* @param {bool}
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.canRotate = function (b)
|
||||
{ if (b===true || b===false) this.canRotate_ = b;
|
||||
return this.canRotate_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of sides.
|
||||
* @return {int} number of sides.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.getSides = function ()
|
||||
{ return this.sides_;
|
||||
}
|
||||
|
||||
/** Default start angle array for each sides
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.startAngle =
|
||||
{ 'default':Math.PI/2,
|
||||
3: -Math.PI/2,
|
||||
4: Math.PI/4
|
||||
};
|
||||
|
||||
/** Get geom of the current drawing
|
||||
* @return {ol.geom.Polygon | ol.geom.Point}
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.getGeom_ = function ()
|
||||
{ this.overlayLayer_.getSource().clear();
|
||||
if (!this.center_) return false;
|
||||
|
||||
var g;
|
||||
if (this.coord_)
|
||||
{ var center = this.center_;
|
||||
var coord = this.coord_;
|
||||
|
||||
// Special case: circle
|
||||
if (!this.sides_ && this.square_ && !this.centered_){
|
||||
center = [(coord[0] + center[0])/2, (coord[1] + center[1])/2];
|
||||
var d = [coord[0] - center[0], coord[1] - center[1]];
|
||||
var r = Math.sqrt(d[0]*d[0]+d[1]*d[1]);
|
||||
var circle = new ol.geom.Circle(center, r, 'XY');
|
||||
// Optimize points on the circle
|
||||
var centerPx = this.getMap().getPixelFromCoordinate(center);
|
||||
var dmax = Math.max (100, Math.abs(centerPx[0]-this.coordPx_[0]), Math.abs(centerPx[1]-this.coordPx_[1]));
|
||||
dmax = Math.min ( this.maxCircleCoordinates_, Math.round(dmax / 3 ));
|
||||
return ol.geom.Polygon.fromCircle (circle, dmax, 0);
|
||||
}
|
||||
else {
|
||||
var hasrotation = this.canRotate_ && this.centered_ && this.square_;
|
||||
var d = [coord[0] - center[0], coord[1] - center[1]];
|
||||
if (this.square_ && !hasrotation)
|
||||
{ //var d = [coord[0] - center[0], coord[1] - center[1]];
|
||||
var dm = Math.max (Math.abs(d[0]), Math.abs(d[1]));
|
||||
coord[0] = center[0] + (d[0]>0 ? dm:-dm);
|
||||
coord[1] = center[1] + (d[1]>0 ? dm:-dm);
|
||||
}
|
||||
var r = Math.sqrt(d[0]*d[0]+d[1]*d[1]);
|
||||
if (r>0)
|
||||
{ var circle = new ol_geom_Circle(center, r, 'XY');
|
||||
var a;
|
||||
if (hasrotation) a = Math.atan2(d[1], d[0]);
|
||||
else a = this.startAngle[this.sides_] || this.startAngle['default'];
|
||||
|
||||
if (this.sides_) g = ol_geom_Polygon.fromCircle (circle, this.sides_, a);
|
||||
else
|
||||
{ // Optimize points on the circle
|
||||
var centerPx = this.getMap().getPixelFromCoordinate(this.center_);
|
||||
var dmax = Math.max (100, Math.abs(centerPx[0]-this.coordPx_[0]), Math.abs(centerPx[1]-this.coordPx_[1]));
|
||||
dmax = Math.min ( this.maxCircleCoordinates_, Math.round(dmax / (this.centered_ ? 3:5) ));
|
||||
g = ol.geom.Polygon.fromCircle (circle, dmax, 0);
|
||||
}
|
||||
|
||||
if (hasrotation) return g;
|
||||
|
||||
// Scale polygon to fit extent
|
||||
var ext = g.getExtent();
|
||||
if (!this.centered_) center = this.center_;
|
||||
else center = [ 2*this.center_[0]-this.coord_[0], 2*this.center_[1]-this.coord_[1] ];
|
||||
var scx = (center[0] - coord[0]) / (ext[0] - ext[2]);
|
||||
var scy = (center[1] - coord[1]) / (ext[1] - ext[3]);
|
||||
if (this.square_)
|
||||
{ var sc = Math.min(Math.abs(scx),Math.abs(scy));
|
||||
scx = Math.sign(scx)*sc;
|
||||
scy = Math.sign(scy)*sc;
|
||||
}
|
||||
var t = [ center[0] - ext[0]*scx, center[1] - ext[1]*scy ];
|
||||
|
||||
g.applyTransform(function(g1, g2, dim)
|
||||
{ for (i=0; i<g1.length; i+=dim)
|
||||
{ g2[i] = g1[i]*scx + t[0];
|
||||
g2[i+1] = g1[i+1]*scy + t[1];
|
||||
}
|
||||
return g2;
|
||||
});
|
||||
return g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No geom => return a point
|
||||
return new ol_geom_Point(this.center_);
|
||||
};
|
||||
|
||||
/** Draw sketch
|
||||
* @return {ol.Feature} The feature being drawn.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.drawSketch_ = function(evt)
|
||||
{ this.overlayLayer_.getSource().clear();
|
||||
if (evt)
|
||||
{ this.square_ = this.squareFn_ ? this.squareFn_(evt) : evt.originalEvent.shiftKey;
|
||||
this.centered_ = this.centeredFn_ ? this.centeredFn_(evt) : evt.originalEvent.metaKey || evt.originalEvent.ctrlKey;
|
||||
var g = this.getGeom_();
|
||||
if (g)
|
||||
{ var f = this.feature_;
|
||||
f.setGeometry (g);
|
||||
this.overlayLayer_.getSource().addFeature(f);
|
||||
if (this.coord_ && this.square_ && ((this.canRotate_ && this.centered_ && this.coord_) || (!this.sides_ && !this.centered_)))
|
||||
{ this.overlayLayer_.getSource().addFeature(new ol.Feature(new ol.geom.LineString([this.center_,this.coord_])));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Draw sketch (Point)
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.drawPoint_ = function(pt, noclear)
|
||||
{ if (!noclear) this.overlayLayer_.getSource().clear();
|
||||
this.overlayLayer_.getSource().addFeature(new ol.Feature(new ol.geom.Point(pt)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.handleEvent_ = function(evt)
|
||||
{ switch (evt.type)
|
||||
{ case "pointerdown": {
|
||||
this.downPx_ = evt.pixel;
|
||||
this.start_(evt);
|
||||
}
|
||||
break;
|
||||
case "pointerup":
|
||||
// Started and fisrt move
|
||||
if (this.started_ && this.coord_)
|
||||
{ var dx = this.downPx_[0] - evt.pixel[0];
|
||||
var dy = this.downPx_[1] - evt.pixel[1];
|
||||
if (dx*dx + dy*dy <= this.squaredClickTolerance_)
|
||||
{ // The pointer has moved
|
||||
if ( this.lastEvent == "pointermove" )
|
||||
{ this.end_(evt);
|
||||
}
|
||||
// On touch device there is no move event : terminate = click on the same point
|
||||
else
|
||||
{ dx = this.upPx_[0] - evt.pixel[0];
|
||||
dy = this.upPx_[1] - evt.pixel[1];
|
||||
if ( dx*dx + dy*dy <= this.squaredClickTolerance_)
|
||||
{ this.end_(evt);
|
||||
}
|
||||
else
|
||||
{ this.handleMoveEvent_(evt);
|
||||
this.drawPoint_(evt.coordinate,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.upPx_ = evt.pixel;
|
||||
break;
|
||||
case "pointerdrag":
|
||||
if (this.started_)
|
||||
{ var centerPx = this.getMap().getPixelFromCoordinate(this.center_);
|
||||
var dx = centerPx[0] - evt.pixel[0];
|
||||
var dy = centerPx[1] - evt.pixel[1];
|
||||
if (dx*dx + dy*dy <= this.squaredClickTolerance_)
|
||||
{ this.reset();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "pointermove":
|
||||
if (this.started_)
|
||||
{ var dx = this.downPx_[0] - evt.pixel[0];
|
||||
var dy = this.downPx_[1] - evt.pixel[1];
|
||||
if (dx*dx + dy*dy > this.squaredClickTolerance_)
|
||||
{ this.handleMoveEvent_(evt);
|
||||
this.lastEvent = evt.type;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.lastEvent = evt.type;
|
||||
// Prevent zoom in on dblclick
|
||||
if (this.started_ && evt.type==='dblclick')
|
||||
{ //evt.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Stop drawing.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.finishDrawing = function()
|
||||
{ if (this.started_ && this.coord_)
|
||||
{ this.end_({ pixel: this.upPx_, coordinate: this.coord_});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} evt Event.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.handleMoveEvent_ = function(evt)
|
||||
{ if (this.started_)
|
||||
{ this.coord_ = evt.coordinate;
|
||||
this.coordPx_ = evt.pixel;
|
||||
var f = this.drawSketch_(evt);
|
||||
this.dispatchEvent({
|
||||
type:'drawing',
|
||||
feature: f,
|
||||
pixel: evt.pixel,
|
||||
startCoordinate: this.center_,
|
||||
coordinate: evt.coordinate,
|
||||
square: this.square_,
|
||||
centered: this.centered_
|
||||
});
|
||||
}
|
||||
else
|
||||
{ this.drawPoint_(evt.coordinate);
|
||||
}
|
||||
};
|
||||
|
||||
/** Start an new draw
|
||||
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||
* @return {boolean} `false` to stop the drag sequence.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.start_ = function(evt)
|
||||
{ if (!this.started_)
|
||||
{ this.started_ = true;
|
||||
this.center_ = evt.coordinate;
|
||||
this.coord_ = null;
|
||||
var f = this.feature_ = new ol.Feature();
|
||||
this.drawSketch_(evt);
|
||||
this.dispatchEvent({ type:'drawstart', feature: f, pixel: evt.pixel, coordinate: evt.coordinate });
|
||||
}
|
||||
else
|
||||
{ this.coord_ = evt.coordinate;
|
||||
}
|
||||
};
|
||||
|
||||
/** End drawing
|
||||
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||
* @return {boolean} `false` to stop the drag sequence.
|
||||
*/
|
||||
ol_interaction_DrawRegular.prototype.end_ = function(evt)
|
||||
{ this.coord_ = evt.coordinate;
|
||||
this.started_ = false;
|
||||
// Add new feature
|
||||
if (this.coord_ && this.center_[0]!=this.coord_[0] && this.center_[1]!=this.coord_[1])
|
||||
{ var f = this.feature_;
|
||||
f.setGeometry(this.getGeom_());
|
||||
if (this.source_) this.source_.addFeature(f);
|
||||
else if (this.features_) this.features_.push(f);
|
||||
this.dispatchEvent({ type:'drawend', feature: f, pixel: evt.pixel, coordinate: evt.coordinate, square: this.square_, centered: this.centered_ });
|
||||
}
|
||||
else
|
||||
{ this.dispatchEvent({ type:'drawcancel', feature: null, pixel: evt.pixel, coordinate: evt.coordinate, square: this.square_, centered: this.centered_ });
|
||||
}
|
||||
|
||||
this.center_ = this.coord_ = null;
|
||||
this.drawSketch_();
|
||||
};
|
||||
|
||||
export default ol_interaction_DrawRegular
|
||||
241
build/interaction/DrawTouch.js
Normal file
241
build/interaction/DrawTouch.js
Normal file
@ -0,0 +1,241 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_CenterTouch from './CenterTouch'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_Feature from 'ol/feature'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_geom_LineString from 'ol/geom/linestring'
|
||||
import ol_geom_Polygon from 'ol/geom/polygon'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
|
||||
/** Interaction DrawTouch :
|
||||
* @constructor
|
||||
* @extends {ol_interaction_CenterTouch}
|
||||
* @param {olx.interaction.DrawOptions} options
|
||||
* - source {ol_source_Vector | undefined} Destination source for the drawn features.
|
||||
* - type {ol.geom.GeometryType} Drawing type ('Point', 'LineString', 'Polygon') not ('MultiPoint', 'MultiLineString', 'MultiPolygon' or 'Circle'). Required.
|
||||
* - tap {boolean} enable on tap, default true
|
||||
* Inherited params
|
||||
* - targetStyle {ol_style_Style|Array<ol_style_Style>} a style to draw the target point, default cross style
|
||||
* - composite {string} composite operation : difference|multiply|xor|screen|overlay|darken|lighter|lighten|...
|
||||
*/
|
||||
var ol_interaction_DrawTouch = function(options)
|
||||
{ var options = options||{};
|
||||
var self = this;
|
||||
|
||||
options.handleEvent = function(e)
|
||||
{ if (this.get("tap"))
|
||||
{ switch (e.type)
|
||||
{ case "singleclick":
|
||||
this.addPoint();
|
||||
break;
|
||||
case "dblclick":
|
||||
this.addPoint();
|
||||
this.finishDrawing();
|
||||
return false;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
ol_interaction_CenterTouch.call(this, options);
|
||||
|
||||
this.typeGeom_ = options.type;
|
||||
this.source_ = options.source;
|
||||
this.set("tap", (options.tap!==false));
|
||||
|
||||
// Style
|
||||
var white = [255, 255, 255, 1];
|
||||
var blue = [0, 153, 255, 1];
|
||||
var width = 3;
|
||||
var defaultStyle = [
|
||||
new ol_style_Style({
|
||||
stroke: new ol_style_Stroke({ color: white, width: width + 2 })
|
||||
}),
|
||||
new ol_style_Style({
|
||||
image: new ol_style_Circle({
|
||||
radius: width * 2,
|
||||
fill: new ol_style_Fill({ color: blue }),
|
||||
stroke: new ol_style_Stroke({ color: white, width: width / 2 })
|
||||
}),
|
||||
stroke: new ol_style_Stroke({ color: blue, width: width }),
|
||||
fill: new ol_style_Fill({
|
||||
color: [255, 255, 255, 0.5]
|
||||
})
|
||||
})
|
||||
];
|
||||
|
||||
this.overlay_ = new ol_layer_Vector(
|
||||
{ source: new ol_source_Vector({useSpatialIndex: false }),
|
||||
style: defaultStyle
|
||||
});
|
||||
|
||||
this.geom_ = [];
|
||||
|
||||
};
|
||||
ol.inherits(ol_interaction_DrawTouch, ol_interaction_CenterTouch);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().un("postcompose", this.drawSketchLink_, this);
|
||||
}
|
||||
|
||||
ol_interaction_CenterTouch.prototype.setMap.call (this, map);
|
||||
this.overlay_.setMap(map);
|
||||
|
||||
if (this.getMap())
|
||||
{ this.getMap().on("postcompose", this.drawSketchLink_, this);
|
||||
}
|
||||
};
|
||||
|
||||
/** Start drawing and add the sketch feature to the target layer.
|
||||
* The ol.interaction.Draw.EventType.DRAWSTART event is dispatched before inserting the feature.
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.startDrawing = function()
|
||||
{ this.geom_ = [];
|
||||
this.addPoint();
|
||||
};
|
||||
|
||||
/** Get geometry type
|
||||
* @return {ol.geom.GeometryType}
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.getGeometryType = function()
|
||||
{ return this.typeGeom_;
|
||||
};
|
||||
|
||||
/** Start drawing and add the sketch feature to the target layer.
|
||||
* The ol.interaction.Draw.EventType.DRAWEND event is dispatched before inserting the feature.
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.finishDrawing = function()
|
||||
{ if (!this.getMap()) return;
|
||||
|
||||
var f;
|
||||
switch (this.typeGeom_)
|
||||
{ case "LineString":
|
||||
if (this.geom_.length > 1) f = new ol.Feature(new ol_geom_LineString(this.geom_));
|
||||
break;
|
||||
case "Polygon":
|
||||
// Close polygon
|
||||
if (this.geom_[this.geom_.length-1] != this.geom_[0])
|
||||
{ this.geom_.push(this.geom_[0]);
|
||||
}
|
||||
// Valid ?
|
||||
if (this.geom_.length > 3)
|
||||
{ f = new ol.Feature(new ol.geom.Polygon([ this.geom_ ]));
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (f) this.source_.addFeature (f);
|
||||
|
||||
// reset
|
||||
this.geom_ = [];
|
||||
this.drawSketch_();
|
||||
}
|
||||
|
||||
/** Add a new Point to the drawing
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.addPoint = function()
|
||||
{ if (!this.getMap()) return;
|
||||
|
||||
this.geom_.push(this.getPosition());
|
||||
|
||||
switch (this.typeGeom_)
|
||||
{ case "Point":
|
||||
var f = new ol_Feature( new ol_geom_Point (this.geom_.pop()));
|
||||
this.source_.addFeature(f);
|
||||
break;
|
||||
case "LineString":
|
||||
case "Polygon":
|
||||
this.drawSketch_();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove last point of the feature currently being drawn.
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.removeLastPoint = function()
|
||||
{ if (!this.getMap()) return;
|
||||
this.geom_.pop();
|
||||
this.drawSketch_();
|
||||
}
|
||||
|
||||
/** Draw sketch
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.drawSketch_ = function()
|
||||
{ this.overlay_.getSource().clear();
|
||||
if (this.geom_.length)
|
||||
{ var f;
|
||||
if (this.typeGeom_ == "Polygon")
|
||||
{ f = new ol_Feature(new ol_geom_Polygon([this.geom_]));
|
||||
this.overlay_.getSource().addFeature(f);
|
||||
}
|
||||
var geom = new ol_geom_LineString(this.geom_);
|
||||
f = new ol_Feature(geom);
|
||||
this.overlay_.getSource().addFeature(f);
|
||||
f = new ol_Feature( new ol_geom_Point (this.geom_.slice(-1).pop()) );
|
||||
this.overlay_.getSource().addFeature(f);
|
||||
}
|
||||
}
|
||||
|
||||
/** Draw contruction lines on postcompose
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.drawSketchLink_ = function(e)
|
||||
{ if (!this.getActive() || !this.getPosition()) return;
|
||||
|
||||
var ctx = e.context;
|
||||
ctx.save();
|
||||
var p, pt = this.getMap().getPixelFromCoordinate(this.getPosition());
|
||||
var ratio = e.frameState.pixelRatio || 1;
|
||||
ctx.scale(ratio,ratio);
|
||||
ctx.strokeStyle = "rgba(0, 153, 255, 1)";
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.arc (pt[0],pt[1], 5, 0, 2*Math.PI);
|
||||
ctx.stroke();
|
||||
if (this.geom_.length)
|
||||
{ p = this.getMap().getPixelFromCoordinate(this.geom_[this.geom_.length-1]);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(p[0],p[1]);
|
||||
ctx.lineTo(pt[0],pt[1]);
|
||||
if (this.typeGeom_ == "Polygon")
|
||||
{ p = this.getMap().getPixelFromCoordinate(this.geom_[0]);
|
||||
ctx.lineTo(p[0],p[1]);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate or deactivate the interaction.
|
||||
* @param {boolean} active Active.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
ol_interaction_DrawTouch.prototype.setActive = function(b)
|
||||
{ ol_interaction_CenterTouch.prototype.setActive.call (this, b);
|
||||
|
||||
if (!b) this.geom_ = [];
|
||||
this.drawSketch_();
|
||||
}
|
||||
|
||||
export default ol_interaction_DrawTouch
|
||||
110
build/interaction/DropFile.js
Normal file
110
build/interaction/DropFile.js
Normal file
@ -0,0 +1,110 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_DragAndDrop from 'ol/interaction/draganddrop'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_format_GPX from 'ol/format/gpx'
|
||||
import ol_format_GeoJSON from 'ol/format/geojson'
|
||||
import ol_format_IGC from 'ol/format/igc'
|
||||
import ol_format_KML from 'ol/format/kml'
|
||||
import ol_format_TopoJSON from 'ol/format/topojson'
|
||||
|
||||
/** Extend DragAndDrop choose drop zone + fires loadstart, loadend
|
||||
* @require jQuery
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol_interaction_DragAndDrop}
|
||||
* @fires loadstart, loadend, addfeatures
|
||||
* @param {ol.dropfile.options} flashlight options param
|
||||
* - zone {string} selector for the drop zone, default document
|
||||
* - projection {ol.projection} default projection of the map
|
||||
* - formatConstructors {Array<function(new:ol.format.Feature)>|undefined} Format constructors, default [ ol.format.GPX, ol.format.GeoJSON, ol.format.IGC, ol.format.KML, ol.format.TopoJSON ]
|
||||
* - accept {Array<string>|undefined} list of eccepted format, default ["gpx","json","geojson","igc","kml","topojson"]
|
||||
*/
|
||||
var ol_interaction_DropFile = function(options)
|
||||
{ options = options||{};
|
||||
|
||||
ol_interaction_DragAndDrop.call(this, {});
|
||||
|
||||
var zone = options.zone || document;
|
||||
$(zone).on('dragenter', this.onstop );
|
||||
$(zone).on('dragover', this.onstop );
|
||||
$(zone).on('dragleave', this.onstop );
|
||||
|
||||
// Options
|
||||
this.formatConstructors_ = options.formatConstructors || [ ol_format_GPX, ol_format_GeoJSON, ol_format_IGC, ol_format_KML, ol_format_TopoJSON ];
|
||||
this.projection_ = options.projection;
|
||||
this.accept_ = options.accept || ["gpx","json","geojson","igc","kml","topojson"];
|
||||
|
||||
var self = this;
|
||||
$(zone).on('drop', function(e){ return self.ondrop(e.originalEvent); });
|
||||
};
|
||||
ol.inherits(ol_interaction_DropFile, ol_interaction_DragAndDrop);
|
||||
|
||||
/** Set the map
|
||||
*/
|
||||
ol_interaction_DropFile.prototype.setMap = function(map)
|
||||
{ ol_interaction_Interaction.prototype.setMap.call(this, map);
|
||||
};
|
||||
|
||||
/** Do somthing when over
|
||||
*/
|
||||
ol_interaction_DropFile.prototype.onstop = function(e)
|
||||
{ e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Do somthing when over
|
||||
*/
|
||||
ol_interaction_DropFile.prototype.ondrop = function(e)
|
||||
{ if (e.dataTransfer && e.dataTransfer.files.length)
|
||||
{ var self = this;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
// fetch FileList object
|
||||
var files = e.dataTransfer.files; // e.originalEvent.target.files ?
|
||||
// process all File objects
|
||||
var file;
|
||||
var pat = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/;
|
||||
for (var i=0; file=files[i]; i++)
|
||||
{ var ex = file.name.match(pat)[0];
|
||||
self.dispatchEvent({ type:'loadstart', file: file, filesize: file.size, filetype: file.type, fileextension: ex, projection: projection, target: self });
|
||||
|
||||
// Load file
|
||||
features = [];
|
||||
var reader = new FileReader();
|
||||
var projection = this.projection_ || this.getMap().getView().getProjection();
|
||||
var formatConstructors = this.formatConstructors_
|
||||
|
||||
if (!projection) return;
|
||||
function tryReadFeatures (format, result, options)
|
||||
{ try
|
||||
{ return format.readFeatures(result, options);
|
||||
} catch (e) {}
|
||||
}
|
||||
var theFile = file;
|
||||
reader.onload = function(e)
|
||||
{ var result = e.target.result;
|
||||
|
||||
var features = [];
|
||||
var i, ii;
|
||||
for (i = 0, ii = formatConstructors.length; i < ii; ++i)
|
||||
{ var formatConstructor = formatConstructors[i];
|
||||
var format = new formatConstructor();
|
||||
features = tryReadFeatures(format, result, { featureProjection: projection });
|
||||
if (features && features.length > 0)
|
||||
{ self.dispatchEvent({ type:'addfeatures', features: features, file: theFile, projection: projection, target: self });
|
||||
self.dispatchEvent({ type:'loadend', features: features, file: theFile, projection: projection, target: self });
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.dispatchEvent({ type:'loadend', file: theFile, target: self });
|
||||
};
|
||||
reader.readAsText(file);
|
||||
};
|
||||
}
|
||||
else {}
|
||||
return false;
|
||||
};
|
||||
|
||||
export default ol_interaction_DropFile
|
||||
118
build/interaction/Flashlight.js
Normal file
118
build/interaction/Flashlight.js
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Pointer}
|
||||
* @param {ol.flashlight.options} flashlight options param
|
||||
* - color {ol.Color} light color, default transparent
|
||||
* - fill {ol.Color} fill color, default rgba(0,0,0,0.8)
|
||||
* - radius {number} radius of the flash
|
||||
*/
|
||||
var ol_interaction_Flashlight = function(options) {
|
||||
|
||||
ol_interaction_Pointer.call(this,
|
||||
{ handleDownEvent: this.setPosition,
|
||||
handleMoveEvent: this.setPosition
|
||||
});
|
||||
|
||||
// Default options
|
||||
options = options||{};
|
||||
|
||||
this.pos = false;
|
||||
|
||||
this.radius = (options.radius||100);
|
||||
|
||||
this.setColor(options);
|
||||
|
||||
};
|
||||
ol.inherits(ol_interaction_Flashlight, ol_interaction_Pointer);
|
||||
|
||||
/** Set the map > start postcompose
|
||||
*/
|
||||
ol_interaction_Flashlight.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().un('postcompose', this.postcompose_, this);
|
||||
this.getMap().render();
|
||||
}
|
||||
|
||||
ol_interaction_Pointer.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ map.on('postcompose', this.postcompose_, this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set flashlight radius
|
||||
* @param {integer} radius
|
||||
*/
|
||||
ol_interaction_Flashlight.prototype.setRadius = function(radius)
|
||||
{ this.radius = radius
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/** Set flashlight color
|
||||
* @param {ol.flashlight.options} flashlight options param
|
||||
* - color {ol.Color} light color, default transparent
|
||||
* - fill {ol.Color} fill color, default rgba(0,0,0,0.8)
|
||||
*/
|
||||
ol_interaction_Flashlight.prototype.setColor = function(options)
|
||||
{ // Backcolor
|
||||
var color = (options.fill ? options.fill : [0,0,0,0.8]);
|
||||
var c = ol_color.asArray(color);
|
||||
this.startColor = ol_color.asString(c);
|
||||
// Halo color
|
||||
var endColor;
|
||||
if (options.color)
|
||||
{ c = this.endColor = ol_color.asString(ol_color.asArray(options.color)||options.color);
|
||||
}
|
||||
else
|
||||
{ c[3] = 0
|
||||
this.endColor = ol_color.asString(c);
|
||||
}
|
||||
c[3] = 0.1;
|
||||
this.midColor = ol_color.asString(c);
|
||||
if (this.getMap()) this.getMap().renderSync();
|
||||
}
|
||||
|
||||
/** Set position of the flashlight
|
||||
* @param {ol.Pixel|ol.MapBrowserEvent}
|
||||
*/
|
||||
ol_interaction_Flashlight.prototype.setPosition = function(e)
|
||||
{ if (e.pixel) this.pos = e.pixel;
|
||||
else this.pos = e;
|
||||
if (this.getMap())
|
||||
{ this.getMap().renderSync();
|
||||
}
|
||||
}
|
||||
|
||||
/** Postcompose function
|
||||
*/
|
||||
ol_interaction_Flashlight.prototype.postcompose_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
var ratio = e.frameState.pixelRatio;
|
||||
var w = ctx.canvas.width;
|
||||
var h = ctx.canvas.height;
|
||||
ctx.save();
|
||||
ctx.scale(ratio,ratio);
|
||||
|
||||
if (!this.pos)
|
||||
{ ctx.fillStyle = this.startColor;
|
||||
ctx.fillRect( 0,0,w,h );
|
||||
}
|
||||
else
|
||||
{ var d = Math.max(w, h);
|
||||
// reveal wherever we drag
|
||||
var radGrd = ctx.createRadialGradient( this.pos[0], this.pos[1], w*this.radius/d, this.pos[0], this.pos[1], h*this.radius/d );
|
||||
radGrd.addColorStop( 0, this.startColor );
|
||||
radGrd.addColorStop( 0.8, this.midColor );
|
||||
radGrd.addColorStop( 1, this.endColor );
|
||||
ctx.fillStyle = radGrd;
|
||||
ctx.fillRect( this.pos[0] - d, this.pos[1] - d, 2*d, 2*d );
|
||||
}
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
export default ol_interaction_Flashlight
|
||||
338
build/interaction/GeolocationDraw.js
Normal file
338
build/interaction/GeolocationDraw.js
Normal file
@ -0,0 +1,338 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_Geolocation from 'ol/geolocation'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_RegularShape from 'ol/style/regularshape'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_Feature from 'ol/feature'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
import ol_extent from 'ol/extent'
|
||||
|
||||
/** Interaction to draw on the current geolocation
|
||||
* It combines a draw with a ol_Geolocation
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires drawstart, drawend, drawing, tracking, follow
|
||||
* @param {olx.interaction.GeolocationDrawOption} options
|
||||
* @param { ol.Collection.<ol.Feature> | undefined } option.features Destination collection for the drawn features.
|
||||
* @param { ol.source.Vector | undefined } options.source Destination source for the drawn features.
|
||||
* @param {ol.geom.GeometryType} options.type Drawing type ('Point', 'LineString', 'Polygon'). Required.
|
||||
* @param {Number | undefined} options.minAccuracy minimum accuracy underneath a new point will be register (if no condition), default 20
|
||||
* @param {function | undefined} options.condition a function that take a ol_Geolocation object and return a boolean to indicate whether location should be handled or not, default return true if accuraty < minAccuraty
|
||||
* @param {Object} options.attributes a list of attributes to register as Point properties: {accuracy:true,accuracyGeometry:true,heading:true,speed:true}, default none.
|
||||
* @param {Number} options.tolerance tolerance to add a new point (in projection unit), use ol.geom.LineString.simplify() method, default 5
|
||||
* @param {Number} options.zoom zoom for tracking, default 16
|
||||
* @param {boolean|auto|position|visible} options.followTrack true if you want the interaction to follow the track on the map, default true
|
||||
* @param { ol.style.Style | Array.<ol.style.Style> | ol.StyleFunction | undefined } options.style Style for sketch features.
|
||||
*/
|
||||
var ol_interaction_GeolocationDraw = function(options)
|
||||
{ if (!options) options={};
|
||||
var self = this;
|
||||
|
||||
// Geolocation
|
||||
var geoloc = this.geolocation = new ol_Geolocation(/** @type {olx.GeolocationOptions} */
|
||||
({ projection: "EPSG:4326",
|
||||
trackingOptions:
|
||||
{ maximumAge: 10000,
|
||||
enableHighAccuracy: true,
|
||||
timeout: 600000
|
||||
}
|
||||
}));
|
||||
this.geolocation.on('change', this.draw_, this);
|
||||
|
||||
// Current path
|
||||
this.path_ = [];
|
||||
this.lastPosition_ = false;
|
||||
|
||||
// Default style
|
||||
var white = [255, 255, 255, 1];
|
||||
var blue = [0, 153, 255, 1];
|
||||
var width = 3;
|
||||
var circle = new ol_style_Circle(
|
||||
{ radius: width * 2,
|
||||
fill: new ol_style_Fill({ color: blue }),
|
||||
stroke: new ol_style_Stroke({ color: white, width: width / 2 })
|
||||
});
|
||||
var style =
|
||||
[ new ol_style_Style(
|
||||
{ stroke: new ol_style_Stroke({ color: white, width: width + 2 })
|
||||
}),
|
||||
new ol_style_Style(
|
||||
{ stroke: new ol_style_Stroke({ color: blue, width: width }),
|
||||
fill: new ol_style_Fill({
|
||||
color: [255, 255, 255, 0.5]
|
||||
})
|
||||
})
|
||||
];
|
||||
var triangle = new ol_style_RegularShape(
|
||||
{ radius: width * 3.5,
|
||||
points: 3,
|
||||
rotation: 0,
|
||||
fill: new ol_style_Fill({ color: blue }),
|
||||
stroke: new ol_style_Stroke({ color: white, width: width / 2 })
|
||||
});
|
||||
// stretch the symbol
|
||||
var c = triangle.getImage();
|
||||
var ctx = c.getContext("2d");
|
||||
var c2 = document.createElement('canvas');
|
||||
c2.width = c2.height = c.width;
|
||||
c2.getContext("2d").drawImage(c, 0,0);
|
||||
ctx.clearRect(0,0,c.width,c.height);
|
||||
ctx.drawImage(c2, 0,0, c.width, c.height, width, 0, c.width-2*width, c.height);
|
||||
|
||||
var defaultStyle = function(f)
|
||||
{ if (f.get('heading')===undefined)
|
||||
{ style[1].setImage(circle);
|
||||
}
|
||||
else
|
||||
{ style[1].setImage(triangle);
|
||||
triangle.setRotation( f.get('heading') || 0);
|
||||
}
|
||||
return style;
|
||||
}
|
||||
// Style for the accuracy geometry
|
||||
this.locStyle =
|
||||
{ error: new ol_style_Style({ fill: new ol_style_Fill({ color: [255, 0, 0, 0.2] }) }),
|
||||
warn: new ol_style_Style({ fill: new ol_style_Fill({ color: [255, 192, 0, 0.2] }) }),
|
||||
ok: new ol_style_Style({ fill: new ol_style_Fill({ color: [0, 255, 0, 0.2] }) }),
|
||||
};
|
||||
|
||||
// Create a new overlay layer for the sketch
|
||||
this.overlayLayer_ = new ol_layer_Vector(
|
||||
{ source: new ol_source_Vector(),
|
||||
name:'GeolocationDraw overlay',
|
||||
style: options.style || defaultStyle
|
||||
});
|
||||
|
||||
this.sketch_ = [new ol_Feature(), new ol_Feature(), new ol_Feature()];
|
||||
this.overlayLayer_.getSource().addFeatures(this.sketch_);
|
||||
|
||||
this.features_ = options.features;
|
||||
this.source_ = options.source;
|
||||
|
||||
this.condition_ = options.condition || function(loc) { return loc.getAccuracy() < this.get("minAccuracy") };
|
||||
|
||||
// Prevent interaction when tracking
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function()
|
||||
{ return (!this.get('followTrack') || this.get('followTrack')=='auto');// || !geoloc.getTracking());
|
||||
}
|
||||
});
|
||||
|
||||
this.set("type", options.type||"LineString");
|
||||
this.set("attributes", options.attributes||{});
|
||||
this.set("minAccuracy", options.minAccuracy||20);
|
||||
this.set("tolerance", options.tolerance||5);
|
||||
this.set("zoom", options.zoom);
|
||||
this.setFollowTrack (options.followTrack===undefined ? true : options.followTrack);
|
||||
|
||||
this.setActive(false);
|
||||
};
|
||||
ol.inherits(ol_interaction_GeolocationDraw, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().removeLayer(this.overlayLayer_);
|
||||
ol_interaction_Pointer.prototype.setMap.call (this, map);
|
||||
this.overlayLayer_.setMap(map);
|
||||
if (map) this.geolocation.setProjection(map.getView().getProjection());
|
||||
};
|
||||
|
||||
/** Activate or deactivate the interaction.
|
||||
* @param {boolean} active
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.setActive = function(active)
|
||||
{ ol_interaction_Interaction.prototype.setActive.call(this, active);
|
||||
this.overlayLayer_.setVisible(active);
|
||||
if (this.getMap())
|
||||
{ this.geolocation.setTracking(active);
|
||||
this.getMap().renderSync();
|
||||
}
|
||||
this.pause(!active);
|
||||
if (active)
|
||||
{ // Start drawing
|
||||
this.reset();
|
||||
this.dispatchEvent({ type:'drawstart', feature: this.sketch_[1]});
|
||||
}
|
||||
else
|
||||
{ var f = this.sketch_[1].clone();
|
||||
if (f.getGeometry())
|
||||
{ if (this.features_) this.features_.push(f);
|
||||
if (this.source_) this.source_.addFeature(f);
|
||||
this.dispatchEvent({ type:'drawend', feature: f});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Reset drawing
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.reset = function()
|
||||
{ this.sketch_[1].setGeometry();
|
||||
this.path_ = [];
|
||||
this.lastPosition_ = false;
|
||||
};
|
||||
|
||||
/** Start tracking = setActive(true)
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.start = function()
|
||||
{ this.setActive(true);
|
||||
};
|
||||
|
||||
/** Stop tracking = setActive(false)
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.stop = function()
|
||||
{ this.setActive(false);
|
||||
};
|
||||
|
||||
/** Pause drawing
|
||||
* @param {boolean} b
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.pause = function(b)
|
||||
{ this.pause_ = b!==false;
|
||||
};
|
||||
|
||||
/** Enable following the track on the map
|
||||
* @param {boolean|auto|position|visible} follow,
|
||||
* false: don't follow,
|
||||
* true: follow (position+zoom),
|
||||
* 'position': follow only position,
|
||||
* 'auto': start following until user move the map,
|
||||
* 'visible': center when position gets out of the visible extent
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.setFollowTrack = function(follow)
|
||||
{ this.set('followTrack', follow);
|
||||
var map = this.getMap();
|
||||
// Center if wanted
|
||||
if (follow !== false && !this.lastPosition_ && map)
|
||||
{ var pos = this.path_[this.path_.length-1];
|
||||
if (pos)
|
||||
{ map.getView().animate({
|
||||
center: pos,
|
||||
zoom: (follow!="position" ? this.get("zoom") : undefined)
|
||||
})
|
||||
}
|
||||
}
|
||||
this.lastPosition_ = false;
|
||||
this.dispatchEvent({ type:'follow', following: follow!==false });
|
||||
};
|
||||
|
||||
/** Add a new point to the current path
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_GeolocationDraw.prototype.draw_ = function(active)
|
||||
{ var map = this.getMap();
|
||||
if (!map) return;
|
||||
|
||||
// Current location
|
||||
var loc = this.geolocation;
|
||||
var accu = loc.getAccuracy();
|
||||
var pos = loc.getPosition();
|
||||
pos.push (Math.round((loc.getAltitude()||0)*100)/100);
|
||||
pos.push (Math.round((new Date()).getTime()/1000));
|
||||
var p = loc.getAccuracyGeometry();
|
||||
|
||||
// Center on point
|
||||
// console.log(this.get('followTrack'))
|
||||
switch (this.get('followTrack'))
|
||||
{ // Follow center + zoom
|
||||
case true:
|
||||
// modify zoom
|
||||
if (this.get('followTrack') == true)
|
||||
{ map.getView().setZoom( this.get("zoom") || 16 );
|
||||
if (!ol_extent.containsExtent(map.getView().calculateExtent(map.getSize()), p.getExtent()))
|
||||
{ map.getView().fit(p.getExtent());
|
||||
}
|
||||
}
|
||||
// Follow position
|
||||
case 'position':
|
||||
// modify center
|
||||
map.getView().setCenter( pos );
|
||||
break;
|
||||
// Keep on following
|
||||
case 'auto':
|
||||
if (this.lastPosition_)
|
||||
{ var center = map.getView().getCenter();
|
||||
// console.log(center,this.lastPosition_)
|
||||
if (center[0]!=this.lastPosition_[0] || center[1]!=this.lastPosition_[1])
|
||||
{ //this.dispatchEvent({ type:'follow', following: false });
|
||||
this.setFollowTrack (false);
|
||||
}
|
||||
else
|
||||
{ map.getView().setCenter( pos );
|
||||
this.lastPosition_ = pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ map.getView().setCenter( pos );
|
||||
if (this.get("zoom")) map.getView().setZoom( this.get("zoom") );
|
||||
this.lastPosition_ = pos;
|
||||
}
|
||||
break;
|
||||
// Force to stay on the map
|
||||
case 'visible':
|
||||
if (!ol_extent.containsCoordinate(map.getView().calculateExtent(map.getSize()), pos))
|
||||
{ map.getView().setCenter (pos);
|
||||
}
|
||||
break;
|
||||
// Don't follow
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Draw occuracy
|
||||
var f = this.sketch_[0];
|
||||
f.setGeometry(p);
|
||||
if (accu < this.get("minAccuracy")/2) f.setStyle(this.locStyle.ok);
|
||||
else if (accu < this.get("minAccuracy")) f.setStyle(this.locStyle.warn);
|
||||
else f.setStyle(this.locStyle.error);
|
||||
|
||||
var geo;
|
||||
if (!this.pause_ && this.condition_.call(this, loc))
|
||||
{ f = this.sketch_[1];
|
||||
this.path_.push(pos);
|
||||
switch (this.get("type"))
|
||||
{ case "Point":
|
||||
this.path_ = [pos];
|
||||
f.setGeometry(new ol_geom_Point(pos, 'XYZM'));
|
||||
var attr = this.get('attributes');
|
||||
if (attr.heading) f.set("heading",loc.getHeading());
|
||||
if (attr.accuracy) f.set("accuracy",loc.getAccuracy());
|
||||
if (attr.altitudeAccuracy) f.set("altitudeAccuracy",loc.getAltitudeAccuracy());
|
||||
if (attr.speed) f.set("speed",loc.getSpeed());
|
||||
break;
|
||||
case "LineString":
|
||||
if (this.path_.length>1)
|
||||
{ geo = new ol.geom.LineString(this.path_, 'XYZM');
|
||||
geo.simplify (this.get("tolerance"));
|
||||
f.setGeometry(geo);
|
||||
}
|
||||
else f.setGeometry();
|
||||
break;
|
||||
case "Polygon":
|
||||
if (this.path_.length>2)
|
||||
{ geo = new ol.geom.Polygon([this.path_], 'XYZM');
|
||||
geo.simplify (this.get("tolerance"));
|
||||
f.setGeometry(geo);
|
||||
}
|
||||
else f.setGeometry();
|
||||
break;
|
||||
}
|
||||
this.dispatchEvent({ type:'drawing', feature: this.sketch_[1], geolocation: loc });
|
||||
}
|
||||
this.sketch_[2].setGeometry(new ol_geom_Point(pos));
|
||||
this.sketch_[2].set("heading",loc.getHeading());
|
||||
// Drawing
|
||||
this.dispatchEvent({ type:'tracking', feature: this.sketch_[1], geolocation: loc });
|
||||
};
|
||||
|
||||
export default ol_interaction_GeolocationDraw
|
||||
127
build/interaction/Hover.js
Normal file
127
build/interaction/Hover.js
Normal file
@ -0,0 +1,127 @@
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
|
||||
/** Interaction hover do to something when hovering a feature
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires hover, enter, leave
|
||||
* @param {olx.interaction.HoverOptions}
|
||||
* - cursor { string | undefined } css cursor propertie or a function that gets a feature, default: none
|
||||
* - featureFilter {function | undefined} filter a function with two arguments, the feature and the layer of the feature. Return true to select the feature
|
||||
* - layerFilter {function | undefined} filter a function with one argument, the layer to test. Return true to test the layer
|
||||
* - handleEvent { function | undefined } Method called by the map to notify the interaction that a browser event was dispatched to the map. The function may return false to prevent the propagation of the event to other interactions in the map's interactions chain.
|
||||
*/
|
||||
var ol_interaction_Hover = function(options)
|
||||
{ if (!options) options={};
|
||||
var self = this;
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ if (e.type=="pointermove") { self.handleMove_(e); };
|
||||
if (options.handleEvent) return options.handleEvent(e);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this.setFeatureFilter (options.featureFilter);
|
||||
this.setLayerFilter (options.layerFilter);
|
||||
this.setCursor (options.cursor);
|
||||
};
|
||||
ol.inherits(ol_interaction_Hover, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_Hover.prototype.setMap = function(map)
|
||||
{ if (this.previousCursor_!==undefined && this.getMap())
|
||||
{ this.getMap().getTargetElement().style.cursor = this.previousCursor_;
|
||||
this.previousCursor_ = undefined;
|
||||
}
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set cursor on hover
|
||||
* @param { string } cursor css cursor propertie or a function that gets a feature, default: none
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_Hover.prototype.setCursor = function(cursor)
|
||||
{ if (!cursor && this.previousCursor_!==undefined && this.getMap())
|
||||
{ this.getMap().getTargetElement().style.cursor = this.previousCursor_;
|
||||
this.previousCursor_ = undefined;
|
||||
}
|
||||
this.cursor_ = cursor;
|
||||
};
|
||||
|
||||
/** Feature filter to get only one feature
|
||||
* @param {function} filter a function with two arguments, the feature and the layer of the feature. Return true to select the feature
|
||||
*/
|
||||
ol_interaction_Hover.prototype.setFeatureFilter = function(filter)
|
||||
{ if (typeof (filter) == 'function') this.featureFilter_ = filter;
|
||||
else this.featureFilter_ = function(){ return true; };
|
||||
};
|
||||
|
||||
/** Feature filter to get only one feature
|
||||
* @param {function} filter a function with one argument, the layer to test. Return true to test the layer
|
||||
*/
|
||||
ol_interaction_Hover.prototype.setLayerFilter = function(filter)
|
||||
{ if (typeof (filter) == 'function') this.layerFilter_ = filter;
|
||||
else this.layerFilter_ = function(){ return true; };
|
||||
};
|
||||
|
||||
/** Get features whenmove
|
||||
* @param {ol.event} e "move" event
|
||||
*/
|
||||
ol_interaction_Hover.prototype.handleMove_ = function(e)
|
||||
{ var map = this.getMap();
|
||||
if (map)
|
||||
{ //var b = map.hasFeatureAtPixel(e.pixel);
|
||||
var feature, layer;
|
||||
var self = this;
|
||||
var b = map.forEachFeatureAtPixel(e.pixel,
|
||||
function(f, l)
|
||||
{ if (self.layerFilter_.call(null, l)
|
||||
&& self.featureFilter_.call(null,f,l))
|
||||
{ feature = f;
|
||||
layer = l;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ feature = layer = null;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (b) this.dispatchEvent({ type:"hover", feature:feature, layer:layer, coordinate:e.coordinate, pixel: e.pixel, map: e.map, dragging:e.dragging });
|
||||
|
||||
if (this.feature_===feature && this.layer_===layer)
|
||||
{
|
||||
}
|
||||
else
|
||||
{ this.feature_ = feature;
|
||||
this.layer_ = layer;
|
||||
if (feature) this.dispatchEvent({ type:"enter", feature:feature, layer:layer, coordinate:e.coordinate, pixel: e.pixel, map: e.map, dragging:e.dragging });
|
||||
else this.dispatchEvent({ type:"leave", coordinate:e.coordinate, pixel: e.pixel, map: e.map, dragging:e.dragging });
|
||||
}
|
||||
|
||||
if (this.cursor_)
|
||||
{ var style = map.getTargetElement().style;
|
||||
if (b)
|
||||
{ if (style.cursor != this.cursor_)
|
||||
{ this.previousCursor_ = style.cursor;
|
||||
style.cursor = this.cursor_;
|
||||
}
|
||||
}
|
||||
else if (this.previousCursor_ !== undefined)
|
||||
{ style.cursor = this.previousCursor_;
|
||||
this.previousCursor_ = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ol_interaction_Hover
|
||||
58
build/interaction/LongTouch.js
Normal file
58
build/interaction/LongTouch.js
Normal file
@ -0,0 +1,58 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
|
||||
/** Interaction to handle longtouch events
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @param {olx.interaction.LongTouchOptions}
|
||||
* @param {function | undefined} options.handleLongTouchEvent Function handling "longtouch" events, it will receive a mapBrowserEvent.
|
||||
* @param {interger | undefined} options.delay The delay for a long touch in ms, default is 1000
|
||||
*/
|
||||
var ol_interaction_LongTouch = function(options)
|
||||
{ if (!options) options = {};
|
||||
|
||||
this.delay_ = options.delay || 1000;
|
||||
var ltouch = options.handleLongTouchEvent || function(){};
|
||||
|
||||
var _timeout = null;
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ if (this.getActive())
|
||||
{ switch (e.type)
|
||||
{ case 'pointerdown':
|
||||
if (_timeout) clearTimeout(_timeout);
|
||||
_timeout = setTimeout (function()
|
||||
{ e.type = "longtouch";
|
||||
ltouch(e)
|
||||
}, this.delay_);
|
||||
break;
|
||||
/* case 'pointermove': */
|
||||
case 'pointerdrag':
|
||||
case 'pointerup':
|
||||
if (_timeout)
|
||||
{ clearTimeout(_timeout);
|
||||
_timeout = null;
|
||||
}
|
||||
break;
|
||||
default: break;;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ if (_timeout)
|
||||
{ clearTimeout(_timeout);
|
||||
_timeout = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
ol.inherits(ol_interaction_LongTouch, ol_interaction_Interaction);
|
||||
|
||||
export default ol_interaction_LongTouch
|
||||
197
build/interaction/Ripple.js
Normal file
197
build/interaction/Ripple.js
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
Water ripple effect.
|
||||
Original code (Java) by Neil Wallis
|
||||
@link http://www.neilwallis.com/java/water.html
|
||||
|
||||
Original code (JS) by Sergey Chikuyonok (serge.che@gmail.com)
|
||||
@link http://chikuyonok.ru
|
||||
@link http://media.chikuyonok.ru/ripple/
|
||||
|
||||
Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
@link https://github.com/Viglino
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
import ol_Observable from 'ol/observable'
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Pointer}
|
||||
* @param {ol.flashlight.options} flashlight options param
|
||||
* - color {ol.Color} light color, default transparent
|
||||
* - fill {ol.Color} fill color, default rgba(0,0,0,0.8)
|
||||
* - radius {number} radius of the flash
|
||||
*/
|
||||
var ol_interaction_Ripple = function(options)
|
||||
{
|
||||
ol_interaction_Pointer.call(this,
|
||||
{ handleDownEvent: this.rainDrop,
|
||||
handleMoveEvent: this.rainDrop
|
||||
});
|
||||
|
||||
// Default options
|
||||
options = options||{};
|
||||
|
||||
this.riprad = options.radius || 3;
|
||||
|
||||
this.ripplemap = [];
|
||||
this.last_map = [];
|
||||
|
||||
// Generate random ripples
|
||||
this.interval = options.interval;
|
||||
this.rains (this.interval);
|
||||
};
|
||||
ol.inherits(ol_interaction_Ripple, ol_interaction_Pointer);
|
||||
|
||||
/** Set the map > start postcompose
|
||||
*/
|
||||
ol_interaction_Ripple.prototype.setMap = function(map)
|
||||
{ if (this.oncompose)
|
||||
{ ol_Observable.unByKey(oncompose);
|
||||
if (this.getMap()) this.getMap().render();
|
||||
}
|
||||
|
||||
ol_interaction_Pointer.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ this.oncompose = map.on('postcompose', this.postcompose_, this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Generate random rain drop
|
||||
* @param {integer} interval
|
||||
*/
|
||||
ol_interaction_Ripple.prototype.rains = function(interval)
|
||||
{ if (this.onrain) clearTimeout (this.onrain);
|
||||
var self = this;
|
||||
vdelay = (typeof(interval)=="number" ? interval : 1000)/2;
|
||||
delay = 3*vdelay/2;
|
||||
var rnd = Math.random;
|
||||
function rain()
|
||||
{ if (self.width) self.rainDrop([rnd() * self.width, rnd() * self.height]);
|
||||
self.onrain = setTimeout (rain, rnd()*vdelay + delay);
|
||||
};
|
||||
// Start raining
|
||||
if (delay) rain();
|
||||
}
|
||||
|
||||
/** Disturb water at specified point
|
||||
* @param {ol.Pixel|ol.MapBrowserEvent}
|
||||
*/
|
||||
ol_interaction_Ripple.prototype.rainDrop = function(e)
|
||||
{ if (!this.width) return;
|
||||
var dx,dy;
|
||||
if (e.pixel)
|
||||
{ dx = e.pixel[0]*this.ratio;
|
||||
dy = e.pixel[1]*this.ratio;
|
||||
}
|
||||
else
|
||||
{ dx = e[0]*this.ratio;
|
||||
dy = e[1]*this.ratio;
|
||||
}
|
||||
dx <<= 0;
|
||||
dy <<= 0;
|
||||
|
||||
for (var j = dy - this.riprad*this.ratio; j < dy + this.riprad*this.ratio; j++)
|
||||
{ for (var k = dx - this.riprad*this.ratio; k < dx + this.riprad*this.ratio; k++)
|
||||
{ this.ripplemap[this.oldind + (j * this.width) + k] += 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Postcompose function
|
||||
*/
|
||||
ol_interaction_Ripple.prototype.postcompose_ = function(e)
|
||||
{ var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
|
||||
// Initialize when canvas is ready / modified
|
||||
if (this.width != canvas.width || this.height != canvas.height)
|
||||
{ this.width = canvas.width;
|
||||
this.height = canvas.height;
|
||||
this.ratio = e.frameState.pixelRatio;
|
||||
this.half_width = this.width >> 1;
|
||||
this.half_height = this.height >> 1;
|
||||
this.size = this.width * (this.height + 2) * 2;
|
||||
this.oldind = this.width;
|
||||
this.newind = this.width * (this.height + 3);
|
||||
for (var i = 0; i < this.size; i++) {
|
||||
this.last_map[i] = this.ripplemap[i] = 0;
|
||||
}
|
||||
}
|
||||
this.texture = ctx.getImageData(0, 0, this.width, this.height);
|
||||
this.ripple = ctx.getImageData(0, 0, this.width, this.height);
|
||||
|
||||
// Run animation
|
||||
var a, b, data, cur_pixel, new_pixel;
|
||||
|
||||
var t = this.oldind; this.oldind = this.newind; this.newind = t;
|
||||
var i = 0;
|
||||
var _rd = this.ripple.data,
|
||||
_td = this.texture.data;
|
||||
|
||||
for (var y = 0; y < this.height; y++) {
|
||||
for (var x = 0; x < this.width; x++) {
|
||||
var _newind = this.newind + i,
|
||||
_mapind = this.oldind + i;
|
||||
data = (
|
||||
this.ripplemap[_mapind - this.width] +
|
||||
this.ripplemap[_mapind + this.width] +
|
||||
this.ripplemap[_mapind - 1] +
|
||||
this.ripplemap[_mapind + 1]) >> 1;
|
||||
|
||||
data -= this.ripplemap[_newind];
|
||||
data -= data >> 5;
|
||||
|
||||
this.ripplemap[_newind] = data;
|
||||
|
||||
//where data=0 then still, where data>0 then wave
|
||||
data = 1024 - data;
|
||||
|
||||
if (this.last_map[i] != data)
|
||||
{ this.last_map[i] = data;
|
||||
|
||||
//offsets
|
||||
a = (((x - this.half_width) * data / 1024) << 0) + this.half_width;
|
||||
b = (((y - this.half_height) * data / 1024) << 0) + this.half_height;
|
||||
|
||||
//bounds check
|
||||
if (a >= this.width) a = this.width - 1;
|
||||
if (a < 0) a = 0;
|
||||
if (b >= this.height) b = this.height - 1;
|
||||
if (b < 0) b = 0;
|
||||
|
||||
new_pixel = (a + (b * this.width)) * 4;
|
||||
cur_pixel = i * 4;
|
||||
|
||||
/**/
|
||||
_rd[cur_pixel] = _td[new_pixel];
|
||||
_rd[cur_pixel + 1] = _td[new_pixel + 1];
|
||||
_rd[cur_pixel + 2] = _td[new_pixel + 2];
|
||||
|
||||
/*/
|
||||
// only in blue pixels
|
||||
if (_td[new_pixel + 2]>_td[new_pixel + 1]
|
||||
&& _td[new_pixel + 2]>_td[new_pixel])
|
||||
{
|
||||
_rd[cur_pixel] = _td[new_pixel];
|
||||
_rd[cur_pixel + 1] = _td[new_pixel + 1];
|
||||
_rd[cur_pixel + 2] = _td[new_pixel + 2];
|
||||
}
|
||||
else this.ripplemap[_newind] = 0;
|
||||
/**/
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(this.ripple, 0, 0);
|
||||
|
||||
// tell OL3 to continue postcompose animation
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
export default ol_interaction_Ripple
|
||||
291
build/interaction/SelectCluster.js
Normal file
291
build/interaction/SelectCluster.js
Normal file
@ -0,0 +1,291 @@
|
||||
/*
|
||||
Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (http://www.cecill.info/).
|
||||
|
||||
ol.interaction.SelectCluster is an interaction for selecting vector features in a cluster.
|
||||
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_interaction_Select from 'ol/interaction/select'
|
||||
import ol_Feature from 'ol/feature'
|
||||
import ol_geom_LineString from 'ol/geom/linestring'
|
||||
import ol_Observable from 'ol/observable'
|
||||
import ol_easing from 'ol/easing'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Interaction for selecting vector features in a cluster.
|
||||
* It can be used as an ol.interaction.Select.
|
||||
* When clicking on a cluster, it springs apart to reveal the features in the cluster.
|
||||
* Revealed features are selectable and you can pick the one you meant.
|
||||
* Revealed features are themselves a cluster with an attribute features that contain the original feature.
|
||||
*
|
||||
* @constructor
|
||||
* @extends {ol.interaction.Select}
|
||||
* @param {olx.interaction.SelectOptions=} options SelectOptions.
|
||||
* @param {ol.style} options.featureStyle used to style the revealed features as options.style is used by the Select interaction.
|
||||
* @param {boolean} options.selectCluster false if you don't want to get cluster selected
|
||||
* @param {Number} options.PointRadius to calculate distance between the features
|
||||
* @param {bool} options.spiral means you want the feature to be placed on a spiral (or a circle)
|
||||
* @param {Number} options.circleMaxObject number of object that can be place on a circle
|
||||
* @param {Number} options.maxObjects number of object that can be drawn, other are hidden
|
||||
* @param {bool} options.animation if the cluster will animate when features spread out, default is false
|
||||
* @param {Number} options.animationDuration animation duration in ms, default is 500ms
|
||||
* @fires ol.interaction.SelectEvent
|
||||
* @api stable
|
||||
*/
|
||||
var ol_interaction_SelectCluster = function(options)
|
||||
{ options = options || {};
|
||||
|
||||
this.pointRadius = options.pointRadius || 12;
|
||||
this.circleMaxObjects = options.circleMaxObjects || 10;
|
||||
this.maxObjects = options.maxObjects || 60;
|
||||
this.spiral = (options.spiral !== false);
|
||||
this.animate = options.animate;
|
||||
this.animationDuration = options.animationDuration || 500;
|
||||
this.selectCluster_ = (options.selectCluster !== false);
|
||||
|
||||
// Create a new overlay layer for
|
||||
var overlay = this.overlayLayer_ = new ol_layer_Vector(
|
||||
{ source: new ol_source_Vector({
|
||||
features: new ol_Collection(),
|
||||
useSpatialIndex: true
|
||||
}),
|
||||
name:'Cluster overlay',
|
||||
updateWhileAnimating: true,
|
||||
updateWhileInteracting: true,
|
||||
displayInLayerSwitcher: false,
|
||||
style: options.featureStyle
|
||||
});
|
||||
|
||||
// Add the overlay to selection
|
||||
if (options.layers)
|
||||
{ if (typeof(options.layers) == "function")
|
||||
{ var fn = options.layers;
|
||||
options.layers = function(layer)
|
||||
{ return (layer===overlay || fn(layer));
|
||||
};
|
||||
}
|
||||
else if (options.layers.push)
|
||||
{ options.layers.push(this.overlayLayer_);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't select links
|
||||
if (options.filter)
|
||||
{ var fn = options.filter;
|
||||
options.filter = function(f,l)
|
||||
{ //if (l===overlay && f.get("selectclusterlink")) return false;
|
||||
if (!l && f.get("selectclusterlink")) return false;
|
||||
else return fn(f,l);
|
||||
};
|
||||
}
|
||||
else options.filter = function(f,l)
|
||||
{ //if (l===overlay && f.get("selectclusterlink")) return false;
|
||||
if (!l && f.get("selectclusterlink")) return false;
|
||||
else return true;
|
||||
};
|
||||
this.filter_ = options.filter;
|
||||
|
||||
ol_interaction_Select.call(this, options);
|
||||
this.on("select", this.selectCluster, this);
|
||||
};
|
||||
|
||||
ol.inherits(ol_interaction_SelectCluster, ol_interaction_Select);
|
||||
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_SelectCluster.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ if (this.getMap().getView())
|
||||
{ this.getMap().getView().un('change:resolution', this.clear, this);
|
||||
}
|
||||
this.getMap().removeLayer(this.overlayLayer_);
|
||||
}
|
||||
|
||||
ol_interaction_Select.prototype.setMap.call (this, map);
|
||||
this.overlayLayer_.setMap(map);
|
||||
// map.addLayer(this.overlayLayer_);
|
||||
|
||||
if (map && map.getView())
|
||||
{ map.getView().on('change:resolution', this.clear, this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the selection, close the cluster and remove revealed features
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_SelectCluster.prototype.clear = function()
|
||||
{ this.getFeatures().clear();
|
||||
this.overlayLayer_.getSource().clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the layer for the revealed features
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_SelectCluster.prototype.getLayer = function()
|
||||
{ return this.overlayLayer_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a cluster
|
||||
* @param {ol.Feature} a cluster feature ie. a feature with a 'features' attribute.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_SelectCluster.prototype.selectCluster = function (e)
|
||||
{ // Nothing selected
|
||||
if (!e.selected.length)
|
||||
{ this.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get selection
|
||||
var feature = e.selected[0];
|
||||
// It's one of ours
|
||||
if (feature.get('selectclusterfeature')) return;
|
||||
|
||||
// Clic out of the cluster => close it
|
||||
var source = this.overlayLayer_.getSource();
|
||||
source.clear();
|
||||
|
||||
var cluster = feature.get('features');
|
||||
// Not a cluster (or just one feature)
|
||||
if (!cluster || cluster.length==1) return;
|
||||
|
||||
// Remove cluster from selection
|
||||
if (!this.selectCluster_) this.getFeatures().clear();
|
||||
|
||||
var center = feature.getGeometry().getCoordinates();
|
||||
// Pixel size in map unit
|
||||
var pix = this.getMap().getView().getResolution();
|
||||
var r = pix * this.pointRadius * (0.5 + cluster.length / 4);
|
||||
// Draw on a circle
|
||||
if (!this.spiral || cluster.length <= this.circleMaxObjects)
|
||||
{ var max = Math.min(cluster.length, this.circleMaxObjects);
|
||||
for (i=0; i<max; i++)
|
||||
{ var a = 2*Math.PI*i/max;
|
||||
if (max==2 || max == 4) a += Math.PI/4;
|
||||
var p = [ center[0]+r*Math.sin(a), center[1]+r*Math.cos(a) ];
|
||||
var cf = new ol_Feature({ 'selectclusterfeature':true, 'features':[cluster[i]], geometry: new ol_geom_Point(p) });
|
||||
cf.setStyle(cluster[i].getStyle());
|
||||
source.addFeature(cf);
|
||||
var lk = new ol_Feature({ 'selectclusterlink':true, geometry: new ol_geom_LineString([center,p]) });
|
||||
source.addFeature(lk);
|
||||
};
|
||||
}
|
||||
// Draw on a spiral
|
||||
else
|
||||
{ // Start angle
|
||||
var a = 0;
|
||||
var r;
|
||||
var d = 2*this.pointRadius;
|
||||
var features = new Array();
|
||||
var links = new Array();
|
||||
var max = Math.min (this.maxObjects, cluster.length);
|
||||
// Feature on a spiral
|
||||
for (i=0; i<max; i++)
|
||||
{ // New radius => increase d in one turn
|
||||
r = d/2 + d*a/(2*Math.PI);
|
||||
// Angle
|
||||
a = a + (d+0.1)/r;
|
||||
var dx = pix*r*Math.sin(a)
|
||||
var dy = pix*r*Math.cos(a)
|
||||
var p = [ center[0]+dx, center[1]+dy ];
|
||||
var cf = new ol_Feature({ 'selectclusterfeature':true, 'features':[cluster[i]], geometry: new ol_geom_Point(p) });
|
||||
cf.setStyle(cluster[i].getStyle());
|
||||
source.addFeature(cf);
|
||||
var lk = new ol_Feature({ 'selectclusterlink':true, geometry: new ol_geom_LineString([center,p]) });
|
||||
source.addFeature(lk);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.animate) this.animateCluster_(center);
|
||||
};
|
||||
|
||||
/**
|
||||
* Animate the cluster and spread out the features
|
||||
* @param {ol.Coordinates} the center of the cluster
|
||||
*/
|
||||
ol_interaction_SelectCluster.prototype.animateCluster_ = function(center)
|
||||
{ // Stop animation (if one is running)
|
||||
if (this.listenerKey_)
|
||||
{ this.overlayLayer_.setVisible(true);
|
||||
ol_Observable.unByKey(this.listenerKey_);
|
||||
}
|
||||
|
||||
// Features to animate
|
||||
var features = this.overlayLayer_.getSource().getFeatures();
|
||||
if (!features.length) return;
|
||||
|
||||
this.overlayLayer_.setVisible(false);
|
||||
var style = this.overlayLayer_.getStyle();
|
||||
var stylefn = (typeof(style) == 'function') ? style : style.length ? function(){ return style; } : function(){ return [style]; } ;
|
||||
var duration = this.animationDuration || 500;
|
||||
var start = new Date().getTime();
|
||||
|
||||
// Animate function
|
||||
function animate(event)
|
||||
{ var vectorContext = event.vectorContext;
|
||||
// Retina device
|
||||
var ratio = event.frameState.pixelRatio;
|
||||
var res = event.target.getView().getResolution();
|
||||
var e = ol_easing.easeOut((event.frameState.time - start) / duration);
|
||||
for (var i=0, feature; feature = features[i]; i++) if (feature.get('features'))
|
||||
{ var pt = feature.getGeometry().getCoordinates();
|
||||
pt[0] = center[0] + e * (pt[0]-center[0]);
|
||||
pt[1] = center[1] + e * (pt[1]-center[1]);
|
||||
var geo = new ol_geom_Point(pt);
|
||||
// Image style
|
||||
var st = stylefn(feature, res);
|
||||
for (var s=0; s<st.length; s++)
|
||||
{ var sc;
|
||||
// OL < v4.3 : setImageStyle doesn't check retina
|
||||
var imgs = ol_Map.prototype.getFeaturesAtPixel ? false : st[s].getImage();
|
||||
if (imgs)
|
||||
{ sc = imgs.getScale();
|
||||
imgs.setScale(ratio);
|
||||
}
|
||||
// OL3 > v3.14
|
||||
if (vectorContext.setStyle)
|
||||
{ vectorContext.setStyle(st[s]);
|
||||
vectorContext.drawGeometry(geo);
|
||||
}
|
||||
// older version
|
||||
else
|
||||
{ vectorContext.setImageStyle(imgs);
|
||||
vectorContext.drawPointGeometry(geo);
|
||||
}
|
||||
if (imgs) imgs.setScale(sc);
|
||||
}
|
||||
}
|
||||
// Stop animation and restore cluster visibility
|
||||
if (e > 1.0)
|
||||
{ ol_Observable.unByKey(this.listenerKey_);
|
||||
this.overlayLayer_.setVisible(true);
|
||||
this.overlayLayer_.changed();
|
||||
return;
|
||||
}
|
||||
// tell OL3 to continue postcompose animation
|
||||
event.frameState.animate = true;
|
||||
}
|
||||
|
||||
// Start a new postcompose animation
|
||||
this.listenerKey_ = this.getMap().on('postcompose', animate, this);
|
||||
//select.getMap().renderSync();
|
||||
};
|
||||
|
||||
|
||||
export default ol_interaction_SelectCluster
|
||||
256
build/interaction/SnapGuides.js
Normal file
256
build/interaction/SnapGuides.js
Normal file
@ -0,0 +1,256 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_extent from 'ol/extent'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_layer_Image from 'ol/layer/image'
|
||||
import ol_Feature from 'ol/feature'
|
||||
import ol_geom_LineString from 'ol/geom/linestring'
|
||||
|
||||
/** Interaction to snap to guidelines
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @param {olx.interaction.SnapGuidesOptions}
|
||||
* - pixelTolerance {number | undefined} distance (in px) to snap to a guideline, default 10 px
|
||||
* - style {ol_style_Style | Array<ol_style_Style> | undefined} Style for the sektch features.
|
||||
*/
|
||||
var ol_interaction_SnapGuides = function(options)
|
||||
{ if (!options) options = {};
|
||||
|
||||
// Intersect 2 guides
|
||||
function getIntersectionPoint (d1, d2)
|
||||
{ var d1x = d1[1][0] - d1[0][0];
|
||||
var d1y = d1[1][1] - d1[0][1];
|
||||
var d2x = d2[1][0] - d2[0][0];
|
||||
var d2y = d2[1][1] - d2[0][1];
|
||||
var det = d1x * d2y - d1y * d2x;
|
||||
|
||||
if (det != 0)
|
||||
{ var k = (d1x * d1[0][1] - d1x * d2[0][1] - d1y * d1[0][0] + d1y * d2[0][0]) / det;
|
||||
return [d2[0][0] + k*d2x, d2[0][1] + k*d2y];
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
function dist2D (p1,p2)
|
||||
{ var dx = p1[0]-p2[0];
|
||||
var dy = p1[1]-p2[1];
|
||||
return Math.sqrt(dx*dx+dy*dy);
|
||||
}
|
||||
|
||||
// Snap distance (in px)
|
||||
this.snapDistance_ = options.pixelTolerance || 10;
|
||||
|
||||
// Default style
|
||||
var sketchStyle =
|
||||
[ new ol_style_Style({
|
||||
stroke: new ol_style_Stroke(
|
||||
{ color: '#ffcc33',
|
||||
lineDash: [8,5],
|
||||
width: 1.25
|
||||
})
|
||||
})
|
||||
];
|
||||
|
||||
// Custom style
|
||||
if (options.style) sketchStyle = options.style instanceof Array ? options.style : [options.style];
|
||||
|
||||
// Create a new overlay for the sketch
|
||||
this.overlaySource_ = new ol_source_Vector(
|
||||
{ features: new ol_Collection(),
|
||||
useSpatialIndex: false
|
||||
});
|
||||
/* Speed up with a ImageVector layer (deprecated)
|
||||
this.overlayLayer_ = new ol_layer_Image(
|
||||
{ source: new ol_source_ImageVector(
|
||||
{ source: this.overlaySource_,
|
||||
style: function(f)
|
||||
{ return sketchStyle;
|
||||
}
|
||||
}),
|
||||
name:'Snap overlay',
|
||||
displayInLayerSwitcher: false
|
||||
});
|
||||
*/
|
||||
this.overlayLayer_ = new ol_layer_Vector(
|
||||
{ source: this.overlaySource_,
|
||||
style: function(f)
|
||||
{ return sketchStyle;
|
||||
},
|
||||
name:'Snap overlay',
|
||||
displayInLayerSwitcher: false
|
||||
});
|
||||
// Use snap interaction
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ if (this.getActive())
|
||||
{ var features = this.overlaySource_.getFeatures();
|
||||
var prev = null;
|
||||
var p = null;
|
||||
var res = e.frameState.viewState.resolution;
|
||||
for (var i=0, f; f = features[i]; i++)
|
||||
{ var c = f.getGeometry().getClosestPoint(e.coordinate);
|
||||
if ( dist2D(c, e.coordinate) / res < this.snapDistance_)
|
||||
{ // Intersection on 2 lines
|
||||
if (prev)
|
||||
{ var c2 = getIntersectionPoint(prev.getGeometry().getCoordinates(), f.getGeometry().getCoordinates());
|
||||
if (c2)
|
||||
{ if (dist2D(c2, e.coordinate) / res < this.snapDistance_)
|
||||
{ p = c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ p = c;
|
||||
}
|
||||
prev = f;
|
||||
}
|
||||
}
|
||||
if (p) e.coordinate = p;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
ol.inherits(ol_interaction_SnapGuides, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().removeLayer(this.overlayLayer_);
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
this.overlayLayer_.setMap(map);
|
||||
if (map) this.projExtent_ = map.getView().getProjection().getExtent();
|
||||
};
|
||||
|
||||
/** Activate or deactivate the interaction.
|
||||
* @param {boolean} active
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.setActive = function(active)
|
||||
{ this.overlayLayer_.setVisible(active);
|
||||
ol_interaction_Interaction.prototype.setActive.call (this, active);
|
||||
}
|
||||
|
||||
/** Clear previous added guidelines
|
||||
* @param {Array<ol.Feature> | undefined} features a list of feature to remove, default remove all feature
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.clearGuides = function(features)
|
||||
{ if (!features) this.overlaySource_.clear();
|
||||
else
|
||||
{ for (var i=0, f; f=features[i]; i++)
|
||||
{ this.overlaySource_.removeFeature(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Get guidelines
|
||||
* @return {ol.Collection} guidelines features
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.getGuides = function(features)
|
||||
{ return this.overlaySource_.getFeaturesCollection();
|
||||
}
|
||||
|
||||
/** Add a new guide to snap to
|
||||
* @param {Array<ol.coordinate>} v the direction vector
|
||||
* @return {ol.Feature} feature guide
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.addGuide = function(v, ortho)
|
||||
{ if (v)
|
||||
{ var map = this.getMap();
|
||||
// Limit extent
|
||||
var extent = map.getView().calculateExtent(map.getSize());
|
||||
extent = ol_extent.buffer(extent, Math.max (1e5+1, (extent[2]-extent[0])*100));
|
||||
extent = ol_extent.getIntersection(extent, this.projExtent_);
|
||||
var dx = v[0][0] - v[1][0];
|
||||
var dy = v[0][1] - v[1][1];
|
||||
var d = 1 / Math.sqrt(dx*dx+dy*dy);
|
||||
var p, g = [];
|
||||
var p0, p1;
|
||||
for (var i= 0; i<1e8; i+=1e5)
|
||||
{ if (ortho) p = [ v[0][0] + dy*d*i, v[0][1] - dx*d*i];
|
||||
else p = [ v[0][0] + dx*d*i, v[0][1] + dy*d*i];
|
||||
if (ol_extent.containsCoordinate(extent, p)) g.push(p);
|
||||
else break;
|
||||
}
|
||||
var f0 = new ol_Feature(new ol_geom_LineString(g));
|
||||
var g=[];
|
||||
for (var i= 0; i>-1e8; i-=1e5)
|
||||
{ if (ortho) p = [ v[0][0] + dy*d*i, v[0][1] - dx*d*i];
|
||||
else p = [ v[0][0] + dx*d*i, v[0][1] + dy*d*i];
|
||||
if (ol_extent.containsCoordinate(extent, p)) g.push(p);
|
||||
else break;
|
||||
}
|
||||
var f1 = new ol_Feature(new ol_geom_LineString(g));
|
||||
this.overlaySource_.addFeature(f0);
|
||||
this.overlaySource_.addFeature(f1);
|
||||
return [f0, f1];
|
||||
}
|
||||
};
|
||||
|
||||
/** Add a new orthogonal guide to snap to
|
||||
* @param {Array<ol.coordinate>} v the direction vector
|
||||
* @return {ol.Feature} feature guide
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.addOrthoGuide = function(v)
|
||||
{ return this.addGuide(v, true);
|
||||
};
|
||||
|
||||
/** Listen to draw event to add orthogonal guidelines on the first and last point.
|
||||
* @param {_ol_interaction_Draw_} drawi a draw interaction to listen to
|
||||
* @api
|
||||
*/
|
||||
ol_interaction_SnapGuides.prototype.setDrawInteraction = function(drawi)
|
||||
{ var self = this;
|
||||
// Number of points currently drawing
|
||||
var nb = 0;
|
||||
// Current guidelines
|
||||
var features = [];
|
||||
function setGuides(e)
|
||||
{ var coord = [];
|
||||
var s = 2;
|
||||
switch (e.target.getType())
|
||||
{ case 'LineString':
|
||||
coord = e.target.getCoordinates();
|
||||
s = 2;
|
||||
break;
|
||||
case 'Polygon':
|
||||
coord = e.target.getCoordinates()[0];
|
||||
s = 3;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
var l = coord.length;
|
||||
if (l != nb && l > s)
|
||||
{ self.clearGuides(features);
|
||||
features = self.addOrthoGuide([coord[l-s],coord[l-s-1]]);
|
||||
features = features.concat(self.addGuide([coord[0],coord[1]]));
|
||||
features = features.concat(self.addOrthoGuide([coord[0],coord[1]]));
|
||||
nb = l;
|
||||
}
|
||||
};
|
||||
// New drawing
|
||||
drawi.on ("drawstart", function(e)
|
||||
{ // When geom is changing add a new orthogonal direction
|
||||
e.feature.getGeometry().on("change", setGuides);
|
||||
});
|
||||
// end drawing, clear directions
|
||||
drawi.on ("drawend", function(e)
|
||||
{ self.clearGuides(features);
|
||||
e.feature.getGeometry().un("change", setGuides);
|
||||
nb = 0;
|
||||
features = [];
|
||||
});
|
||||
};
|
||||
|
||||
export default ol_interaction_SnapGuides
|
||||
260
build/interaction/Split.js
Normal file
260
build/interaction/Split.js
Normal file
@ -0,0 +1,260 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_style_Style from 'ol/style/style'
|
||||
import ol_style_Stroke from 'ol/style/stroke'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_style_Fill from 'ol/style/fill'
|
||||
import ol_style_Circle from 'ol/style/circle'
|
||||
import ol_layer_Vector from 'ol/layer/vector'
|
||||
import ol_coordinate from 'ol/coordinate'
|
||||
import ol_geom_Point from 'ol/geom/point'
|
||||
import ol_Feature from 'ol/feature'
|
||||
import ol_geom_LineString from 'ol/geom/linestring'
|
||||
|
||||
/** Interaction split interaction for splitting feature geometry
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires beforesplit, aftersplit
|
||||
* @param {olx.interaction.SplitOptions}
|
||||
* - source {ol.source.Vector|Array{ol.source.Vector}} a list of source to split (configured with useSpatialIndex set to true)
|
||||
* - features {ol.Collection.<ol.Feature>} collection of feature to split
|
||||
* - snapDistance {integer} distance (in px) to snap to an object, default 25px
|
||||
* - cursor {string|undefined} cursor name to display when hovering an objet
|
||||
* - filter {function|undefined} a filter that takes a feature and return true if it can be clipped, default always split.
|
||||
* - featureStyle {ol_style_Style | Array<ol_style_Style> | false | undefined} Style for the selected features, choose false if you don't want feature selection. By default the default edit style is used.
|
||||
* - sketchStyle {ol_style_Style | Array<ol_style_Style> | undefined} Style for the sektch features.
|
||||
* - tolerance {function|undefined} Distance between the calculated intersection and a vertex on the source geometry below which the existing vertex will be used for the split. Default is 1e-10.
|
||||
*/
|
||||
var ol_interaction_Split = function(options)
|
||||
{ if (!options) options = {};
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ switch (e.type)
|
||||
{ case "singleclick":
|
||||
return this.handleDownEvent(e);
|
||||
case "pointermove":
|
||||
return this.handleMoveEvent(e);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Snap distance (in px)
|
||||
this.snapDistance_ = options.snapDistance || 25;
|
||||
// Split tolerance between the calculated intersection and the geometry
|
||||
this.tolerance_ = options.tolerance || 1e-10;
|
||||
// Cursor
|
||||
this.cursor_ = options.cursor;
|
||||
|
||||
// List of source to split
|
||||
this.sources_ = options.sources ? (options.sources instanceof Array) ? options.sources:[options.sources] : [];
|
||||
|
||||
if (options.features)
|
||||
{ this.sources_.push (new ol_source_Vector({ features: features }));
|
||||
}
|
||||
|
||||
// Get all features candidate
|
||||
this.filterSplit_ = options.filter || function(){ return true; };
|
||||
|
||||
// Default style
|
||||
var white = [255, 255, 255, 1];
|
||||
var blue = [0, 153, 255, 1];
|
||||
var width = 3;
|
||||
var fill = new ol_style_Fill({ color: 'rgba(255,255,255,0.4)' });
|
||||
var stroke = new ol_style_Stroke({
|
||||
color: '#3399CC',
|
||||
width: 1.25
|
||||
});
|
||||
var sketchStyle =
|
||||
[ new ol_style_Style({
|
||||
image: new ol_style_Circle({
|
||||
fill: fill,
|
||||
stroke: stroke,
|
||||
radius: 5
|
||||
}),
|
||||
fill: fill,
|
||||
stroke: stroke
|
||||
})
|
||||
];
|
||||
var featureStyle =
|
||||
[ new ol_style_Style({
|
||||
stroke: new ol_style_Stroke({
|
||||
color: white,
|
||||
width: width + 2
|
||||
})
|
||||
}),
|
||||
new ol_style_Style({
|
||||
image: new ol_style_Circle({
|
||||
radius: 2*width,
|
||||
fill: new ol_style_Fill({
|
||||
color: blue
|
||||
}),
|
||||
stroke: new ol_style_Stroke({
|
||||
color: white,
|
||||
width: width/2
|
||||
})
|
||||
}),
|
||||
stroke: new ol_style_Stroke({
|
||||
color: blue,
|
||||
width: width
|
||||
})
|
||||
}),
|
||||
];
|
||||
|
||||
// Custom style
|
||||
if (options.sketchStyle) sketchStyle = options.sketchStyle instanceof Array ? options.sketchStyle : [options.sketchStyle];
|
||||
if (options.featureStyle) featureStyle = options.featureStyle instanceof Array ? options.featureStyle : [options.featureStyle];
|
||||
|
||||
// Create a new overlay for the sketch
|
||||
this.overlayLayer_ = new ol_layer_Vector(
|
||||
{ source: new ol_source_Vector({
|
||||
useSpatialIndex: false
|
||||
}),
|
||||
name:'Split overlay',
|
||||
displayInLayerSwitcher: false,
|
||||
style: function(f)
|
||||
{ if (f._sketch_) return sketchStyle;
|
||||
else return featureStyle;
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
ol.inherits(ol_interaction_Split, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol.Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_Split.prototype.setMap = function(map)
|
||||
{ if (this.getMap()) this.getMap().removeLayer(this.overlayLayer_);
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
this.overlayLayer_.setMap(map);
|
||||
};
|
||||
|
||||
/** Get closest feature at pixel
|
||||
* @param {ol.Pixel}
|
||||
* @return {ol.feature}
|
||||
* @private
|
||||
*/
|
||||
ol_interaction_Split.prototype.getClosestFeature = function(e)
|
||||
{ var f, c, g, d = this.snapDistance_+1;
|
||||
for (var i=0; i<this.sources_.length; i++)
|
||||
{ var source = this.sources_[i];
|
||||
f = source.getClosestFeatureToCoordinate(e.coordinate);
|
||||
if (f.getGeometry().splitAt, this.tolerance_)
|
||||
{ c = f.getGeometry().getClosestPoint(e.coordinate);
|
||||
g = new ol_geom_LineString([e.coordinate,c]);
|
||||
d = g.getLength() / e.frameState.viewState.resolution;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d > this.snapDistance_) return false;
|
||||
else
|
||||
{ // Snap to node
|
||||
var coord = this.getNearestCoord (c, f.getGeometry().getCoordinates());
|
||||
var p = this.getMap().getPixelFromCoordinate(coord);
|
||||
if (ol_coordinate.dist2d(e.pixel, p) < this.snapDistance_)
|
||||
{ c = coord;
|
||||
}
|
||||
//
|
||||
return { source:source, feature:f, coord: c, link: g };
|
||||
}
|
||||
}
|
||||
|
||||
/** Get nearest coordinate in a list
|
||||
* @param {ol.coordinate} pt the point to find nearest
|
||||
* @param {Array<ol.coordinate>} coords list of coordinates
|
||||
* @return {ol.coordinate} the nearest coordinate in the list
|
||||
*/
|
||||
ol_interaction_Split.prototype.getNearestCoord = function(pt, coords)
|
||||
{ var d, dm=Number.MAX_VALUE, p0;
|
||||
for (var i=0; i < coords.length; i++)
|
||||
{ d = ol_coordinate.dist2d (pt, coords[i]);
|
||||
if (d < dm)
|
||||
{ dm = d;
|
||||
p0 = coords[i];
|
||||
}
|
||||
}
|
||||
return p0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} evt Map browser event.
|
||||
* @return {boolean} `true` to start the drag sequence.
|
||||
*/
|
||||
ol_interaction_Split.prototype.handleDownEvent = function(evt)
|
||||
{ // Something to split ?
|
||||
var current = this.getClosestFeature(evt);
|
||||
|
||||
if (current)
|
||||
{ var self = this;
|
||||
self.overlayLayer_.getSource().clear();
|
||||
var split = current.feature.getGeometry().splitAt(current.coord, this.tolerance_);
|
||||
if (split.length > 1)
|
||||
{ var tosplit = [];
|
||||
for (var i=0; i<split.length; i++)
|
||||
{ var f = current.feature.clone();
|
||||
f.setGeometry(split[i]);
|
||||
tosplit.push(f);
|
||||
}
|
||||
self.dispatchEvent({ type:'beforesplit', original: current.feature, features: tosplit });
|
||||
current.source.dispatchEvent({ type:'beforesplit', original: current.feature, features: tosplit });
|
||||
current.source.removeFeature(current.feature);
|
||||
for (var i=0; i<tosplit.length; i++)
|
||||
{ current.source.addFeature(tosplit[i]);
|
||||
}
|
||||
self.dispatchEvent({ type:'aftersplit', original: current.feature, features: tosplit });
|
||||
current.source.dispatchEvent({ type:'aftersplit', original: current.feature, features: tosplit });
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {ol.MapBrowserEvent} evt Event.
|
||||
*/
|
||||
ol_interaction_Split.prototype.handleMoveEvent = function(e)
|
||||
{ var map = e.map;
|
||||
this.overlayLayer_.getSource().clear();
|
||||
var current = this.getClosestFeature(e);
|
||||
|
||||
if (current && this.filterSplit_(current.feature))
|
||||
{ var coord, p, l;
|
||||
// Draw sketch
|
||||
this.overlayLayer_.getSource().addFeature(current.feature);
|
||||
p = new ol_Feature(new ol_geom_Point(current.coord));
|
||||
p._sketch_ = true;
|
||||
this.overlayLayer_.getSource().addFeature(p);
|
||||
//
|
||||
l = new ol_Feature(new ol_geom_LineString([e.coordinate,current.coord]));
|
||||
l._sketch_ = true;
|
||||
this.overlayLayer_.getSource().addFeature(l);
|
||||
}
|
||||
|
||||
var element = map.getTargetElement();
|
||||
if (this.cursor_)
|
||||
{ if (current)
|
||||
{ if (element.style.cursor != this.cursor_)
|
||||
{ this.previousCursor_ = element.style.cursor;
|
||||
element.style.cursor = this.cursor_;
|
||||
}
|
||||
}
|
||||
else if (this.previousCursor_ !== undefined)
|
||||
{ element.style.cursor = this.previousCursor_;
|
||||
this.previousCursor_ = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ol_interaction_Split
|
||||
|
||||
254
build/interaction/Splitter.js
Normal file
254
build/interaction/Splitter.js
Normal file
@ -0,0 +1,254 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_source_Vector from 'ol/source/vector'
|
||||
import ol_Collection from 'ol/collection'
|
||||
import ol_extent from 'ol/extent'
|
||||
|
||||
/** Interaction splitter: acts as a split feature agent while editing vector features (LineString).
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @fires beforesplit, aftersplit
|
||||
* @param {olx.interaction.SplitOptions}
|
||||
* - source {ol.source.Vector|Array{ol.source.Vector}} The target source (or array of source) with features to be split (configured with useSpatialIndex set to true)
|
||||
* - triggerSource {ol.source.Vector} Any newly created or modified features from this source will be used to split features on the target source. If none is provided the target source is used instead.
|
||||
* - features {ol_Collection.<ol.Feature>} A collection of feature to be split (replace source target).
|
||||
* - triggerFeatures {ol_Collection.<ol.Feature>} Any newly created or modified features from this collection will be used to split features on the target source (replace triggerSource).
|
||||
* - filter {function|undefined} a filter that takes a feature and return true if the feature is eligible for splitting, default always split.
|
||||
* - tolerance {function|undefined} Distance between the calculated intersection and a vertex on the source geometry below which the existing vertex will be used for the split. Default is 1e-10.
|
||||
* @todo verify auto intersection on features that split.
|
||||
*/
|
||||
var ol_interaction_Splitter = function(options)
|
||||
{ if (!options) options = {};
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ // Hack to get only one changeFeature when draging with ol.interaction.Modify on.
|
||||
if (e.type != "pointermove" && e.type != "pointerdrag")
|
||||
{ if (this.lastEvent_)
|
||||
{ this.splitSource(this.lastEvent_.feature);
|
||||
this.lastEvent_ = null;
|
||||
}
|
||||
this.moving_ = false;
|
||||
}
|
||||
else this.moving_ = true;
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
||||
// Features added / remove
|
||||
this.added_ = [];
|
||||
this.removed_ = [];
|
||||
|
||||
// Source to split
|
||||
if (options.features)
|
||||
{ this.source_ = new ol_source_Vector({ features: options.features });
|
||||
}
|
||||
else
|
||||
{ this.source_ = options.source ? options.source : new ol_source_Vector({ features: new ol_Collection() });
|
||||
}
|
||||
var trigger = this.triggerSource;
|
||||
if (options.triggerFeatures)
|
||||
{ trigger = new ol_source_Vector({ features: options.triggerFeatures });
|
||||
}
|
||||
|
||||
if (trigger)
|
||||
{ trigger.on("addfeature", this.onAddFeature, this);
|
||||
trigger.on("changefeature", this.onChangeFeature, this);
|
||||
trigger.on("removefeature", this.onRemoveFeature, this);
|
||||
}
|
||||
else
|
||||
{ this.source_.on("addfeature", this.onAddFeature, this);
|
||||
this.source_.on("changefeature", this.onChangeFeature, this);
|
||||
this.source_.on("removefeature", this.onRemoveFeature, this);
|
||||
}
|
||||
|
||||
// Split tolerance between the calculated intersection and the geometry
|
||||
this.tolerance_ = options.tolerance || 1e-10;
|
||||
|
||||
// Get all features candidate
|
||||
this.filterSplit_ = options.filter || function(){ return true; };
|
||||
};
|
||||
ol.inherits(ol_interaction_Splitter, ol_interaction_Interaction);
|
||||
|
||||
/** Calculate intersection on 2 segs
|
||||
* @param {Array<_ol_coordinate_>} s1 first seg to intersect (2 points)
|
||||
* @param {Array<_ol_coordinate_>} s2 second seg to intersect (2 points)
|
||||
* @return { boolean | _ol_coordinate_ } intersection point or false no intersection
|
||||
*/
|
||||
ol_interaction_Splitter.prototype.intersectSegs = function(s1,s2)
|
||||
{ var tol = this.tolerance_;
|
||||
|
||||
// Solve
|
||||
var x12 = s1[0][0] - s1[1][0];
|
||||
var x34 = s2[0][0] - s2[1][0];
|
||||
var y12 = s1[0][1] - s1[1][1];
|
||||
var y34 = s2[0][1] - s2[1][1];
|
||||
|
||||
var det = x12 * y34 - y12 * x34;
|
||||
// No intersection
|
||||
if (Math.abs(det) < tol)
|
||||
{ return false;
|
||||
}
|
||||
else
|
||||
{ // Outside segement
|
||||
var r1 = ((s1[0][0] - s2[1][0])*y34 - (s1[0][1] - s2[1][1])*x34) / det;
|
||||
if (Math.abs(r1)<tol) return s1[0];
|
||||
if (Math.abs(1-r1)<tol) return s1[1];
|
||||
if (r1<0 || r1>1) return false;
|
||||
|
||||
var r2 = ((s1[0][1] - s2[1][1])*x12 - (s1[0][0] - s2[1][0])*y12) / det;
|
||||
if (Math.abs(r2)<tol) return s2[1];
|
||||
if (Math.abs(1-r2)<tol) return s2[0];
|
||||
if (r2<0 || r2>1) return false;
|
||||
|
||||
// Intersection
|
||||
var a = s1[0][0] * s1[1][1] - s1[0][1] * s1[1][0];
|
||||
var b = s2[0][0] * s2[1][1] - s2[0][1] * s2[1][0];
|
||||
var p = [(a * x34 - b * x12) / det, (a * y34 - b * y12) / det];
|
||||
// Test start / end
|
||||
/*
|
||||
console.log("r1: "+r1)
|
||||
console.log("r2: "+r2)
|
||||
console.log ("s10: "+(_ol_coordinate_.dist2d(p,s1[0])<tol)) ;
|
||||
console.log ("s11: "+(_ol_coordinate_.dist2d(p,s1[1])<tol)) ;
|
||||
console.log ("s20: "+(_ol_coordinate_.dist2d(p,s2[0])<tol)) ;
|
||||
console.log ("s21: "+(_ol_coordinate_.dist2d(p,s2[1])<tol)) ;
|
||||
*/
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
/** Split the source using a feature
|
||||
* @param {ol.Feature} feature The feature to use to split.
|
||||
*/
|
||||
ol_interaction_Splitter.prototype.splitSource = function(feature)
|
||||
{ // Allready perform a split
|
||||
if (this.splitting) return;
|
||||
var self = this;
|
||||
var i, k, f2;
|
||||
// Start splitting
|
||||
this.source_.dispatchEvent({ type:'beforesplit', feaure: feature, source: this.source_ });
|
||||
|
||||
this.splitting = true;
|
||||
this.added_ = [];
|
||||
this.removed_ = [];
|
||||
|
||||
var c = feature.getGeometry().getCoordinates();
|
||||
var seg, split = [];
|
||||
function intersect (f)
|
||||
{ if (f !== feature)
|
||||
{ var c2 = f.getGeometry().getCoordinates();
|
||||
for (var j=0; j<c2.length-1; j++)
|
||||
{ var p = this.intersectSegs (seg, [c2[j],c2[j+1]]);
|
||||
if (p)
|
||||
{ split.push(p);
|
||||
g = f.getGeometry().splitAt(p, this.tolerance_);
|
||||
if (g && g.length>1)
|
||||
{ found = f;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Split existing features
|
||||
for (i=0; i<c.length-1; i++)
|
||||
{ seg = [c[i],c[i+1]];
|
||||
var extent = ol_extent.buffer(ol_extent.boundingExtent(seg), this.tolerance_ /*0.01*/ );
|
||||
var g;
|
||||
while (true)
|
||||
{ var found = false;
|
||||
this.source_.forEachFeatureIntersectingExtent(extent, intersect, this);
|
||||
// Split feature
|
||||
if (found)
|
||||
{ var f = found;
|
||||
this.source_.removeFeature(f);
|
||||
for (k=0; k<g.length; k++)
|
||||
{ f2 = f.clone();
|
||||
f2.setGeometry(g[k]);
|
||||
this.source_.addFeature(f2);
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
// Auto intersect
|
||||
for (i=0; i<c.length-2; i++)
|
||||
{ for (var j=i+1; j<c.length-1; j++)
|
||||
{ var p = this.intersectSegs ([c[i],c[i+1]], [c[j],c[j+1]]);
|
||||
if (p && p!=c[i+1])
|
||||
{ split.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Split original
|
||||
var splitOriginal = false;
|
||||
if (split.length)
|
||||
{ var result = feature.getGeometry().splitAt(split, this.tolerance_);
|
||||
if (result.length>1)
|
||||
{ for (k=0; k<result.length; k++)
|
||||
{ f2 = feature.clone();
|
||||
f2.setGeometry(result[k]);
|
||||
this.source_.addFeature(f2);
|
||||
}
|
||||
splitOriginal = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the interaction is inserted after modify interaction, the objet is not consistant
|
||||
// > wait end of other interactions
|
||||
setTimeout (function()
|
||||
{ if (splitOriginal) self.source_.removeFeature(feature);
|
||||
self.source_.dispatchEvent({ type:'aftersplit', featureAdded: self.added_, featureRemoved: self.removed_, source: this.source_ });
|
||||
// Finish
|
||||
self.splitting = false;
|
||||
},0);
|
||||
|
||||
};
|
||||
|
||||
/** New feature source is added
|
||||
*/
|
||||
ol_interaction_Splitter.prototype.onAddFeature = function(e)
|
||||
{ this.splitSource(e.feature);
|
||||
if (this.splitting)
|
||||
{ this.added_.push(e.feature);
|
||||
}
|
||||
/*
|
||||
if (this.splitting) return;
|
||||
var self = this;
|
||||
setTimeout (function() { self.splitSource(e.feature); }, 0);
|
||||
*/
|
||||
};
|
||||
|
||||
/** Feature source is removed > count features added/removed
|
||||
*/
|
||||
ol_interaction_Splitter.prototype.onRemoveFeature = function(e)
|
||||
{ if (this.splitting)
|
||||
{ var n = this.added_.indexOf(e.feature);
|
||||
if (n==-1)
|
||||
{ this.removed_.push(e.feature);
|
||||
}
|
||||
else
|
||||
{ this.added_.splice(n,1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Feature source is changing
|
||||
*/
|
||||
ol_interaction_Splitter.prototype.onChangeFeature = function(e)
|
||||
{ if (this.moving_)
|
||||
{ this.lastEvent_ = e;
|
||||
}
|
||||
else this.splitSource(e.feature);
|
||||
};
|
||||
|
||||
export default ol_interaction_Splitter
|
||||
27
build/interaction/Synchronize.css
Normal file
27
build/interaction/Synchronize.css
Normal file
@ -0,0 +1,27 @@
|
||||
.ol-target-overlay .ol-target
|
||||
{ border: 1px solid transparent;
|
||||
box-shadow: 0 0 1px 1px #fff;
|
||||
display: block;
|
||||
height: 20px;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.ol-target-overlay .ol-target:after,
|
||||
.ol-target-overlay .ol-target:before
|
||||
{ content:"";
|
||||
border: 1px solid #369;
|
||||
box-shadow: 0 0 1px 1px #fff;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 0;
|
||||
position:absolute;
|
||||
top:10px;
|
||||
left:-10px;
|
||||
}
|
||||
.ol-target-overlay .ol-target:after
|
||||
{ box-shadow: none;
|
||||
height: 20px;
|
||||
width: 0;
|
||||
top:0px;
|
||||
left:0px;
|
||||
}
|
||||
151
build/interaction/Synchronize.js
Normal file
151
build/interaction/Synchronize.js
Normal file
@ -0,0 +1,151 @@
|
||||
/* Copyright (c) 2016 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Interaction from 'ol/interaction/interaction'
|
||||
import ol_Map from 'ol/map'
|
||||
import ol_events from 'ol/events'
|
||||
import ol_events_EventType from 'ol/events/eventtype'
|
||||
import ol_Overlay from 'ol/overlay'
|
||||
|
||||
/** Interaction synchronize
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Interaction}
|
||||
* @param {olx.interaction.SynchronizeOptions}
|
||||
* - maps {Array<ol.Map>} An array of maps to synchronize with the map of the interaction
|
||||
*/
|
||||
var ol_interaction_Synchronize = function(options)
|
||||
{ if (!options) options={};
|
||||
var self = this;
|
||||
|
||||
ol_interaction_Interaction.call(this,
|
||||
{ handleEvent: function(e)
|
||||
{ if (e.type=="pointermove") { self.handleMove_(e); }
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
this.maps = options.maps;
|
||||
|
||||
};
|
||||
ol.inherits(ol_interaction_Synchronize, ol_interaction_Interaction);
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
* @param {ol_Map} map Map.
|
||||
* @api stable
|
||||
*/
|
||||
ol_interaction_Synchronize.prototype.setMap = function(map)
|
||||
{
|
||||
if (this.getMap())
|
||||
{
|
||||
this.getMap().getView().un('change:center', this.syncMaps, this);
|
||||
this.getMap().getView().un('change:rotation', this.syncMaps, this);
|
||||
this.getMap().getView().un('change:resolution', this.syncMaps, this);
|
||||
ol_events.unlisten(this.getMap().getViewport(), ol_events_EventType.MOUSEOUT, this.handleMouseOut_, this);
|
||||
}
|
||||
|
||||
ol_interaction_Interaction.prototype.setMap.call (this, map);
|
||||
|
||||
if (map)
|
||||
{ this.getMap().getView().on('change:center', this.syncMaps, this);
|
||||
this.getMap().getView().on('change:rotation', this.syncMaps, this);
|
||||
this.getMap().getView().on('change:resolution', this.syncMaps, this);
|
||||
|
||||
var me = this;
|
||||
$(this.getMap().getTargetElement()).mouseout(function() {
|
||||
for (var i=0; i<me.maps.length; i++)
|
||||
{ me.maps[i].hideTarget();
|
||||
}
|
||||
me.getMap().hideTarget();
|
||||
});
|
||||
this.syncMaps();
|
||||
}
|
||||
};
|
||||
|
||||
/** Synchronize the maps
|
||||
*/
|
||||
ol_interaction_Synchronize.prototype.syncMaps = function(e)
|
||||
{ var map = this.getMap();
|
||||
if (!e) e = { type:'all' };
|
||||
if (map)
|
||||
{ for (var i=0; i<this.maps.length; i++)
|
||||
{ switch (e.type)
|
||||
{ case 'change:rotation':
|
||||
if (this.maps[i].getView().getRotation() != map.getView().getRotation())
|
||||
this.maps[i].getView().setRotation(map.getView().getRotation());
|
||||
break;
|
||||
case 'change:center':
|
||||
if (this.maps[i].getView().getCenter() != map.getView().getCenter())
|
||||
this.maps[i].getView().setCenter(map.getView().getCenter());
|
||||
break;
|
||||
case 'change:resolution':
|
||||
if (this.maps[i].getView().getResolution() != map.getView().getResolution())
|
||||
{ /* old version prior to 1.19.1
|
||||
this.maps[i].beforeRender ( ol.animation.zoom(
|
||||
{ duration: 250,
|
||||
resolution: this.maps[i].getView().getResolution()
|
||||
}));
|
||||
*/
|
||||
this.maps[i].getView().setResolution(map.getView().getResolution());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.maps[i].getView().setRotation(map.getView().getRotation());
|
||||
this.maps[i].getView().setCenter(map.getView().getCenter());
|
||||
this.maps[i].getView().setResolution(map.getView().getResolution());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** Cursor move > tells other maps to show the cursor
|
||||
* @param {ol.event} e "move" event
|
||||
*/
|
||||
ol_interaction_Synchronize.prototype.handleMove_ = function(e)
|
||||
{ for (var i=0; i<this.maps.length; i++)
|
||||
{ this.maps[i].showTarget(e.coordinate);
|
||||
}
|
||||
this.getMap().showTarget();
|
||||
};
|
||||
|
||||
|
||||
/** Cursor out of map > tells other maps to hide the cursor
|
||||
* @param {event} e "mouseOut" event
|
||||
*/
|
||||
ol_interaction_Synchronize.prototype.handleMouseOut_ = function(e, scope)
|
||||
{ for (var i=0; i<scope.maps.length; i++)
|
||||
{
|
||||
scope.maps[i].targetOverlay_.setPosition(undefined);
|
||||
}
|
||||
};
|
||||
|
||||
/** Show a target overlay at coord
|
||||
* @param {ol.coordinate} coord
|
||||
*/
|
||||
ol_Map.prototype.showTarget = function(coord)
|
||||
{ if (!this.targetOverlay_)
|
||||
{ var elt = $("<div>").addClass("ol-target");
|
||||
this.targetOverlay_ = new ol_Overlay({ element: elt.get(0) });
|
||||
this.targetOverlay_.setPositioning('center-center');
|
||||
this.addOverlay(this.targetOverlay_);
|
||||
elt.parent().addClass("ol-target-overlay");
|
||||
// hack to render targetOverlay before positioning it
|
||||
this.targetOverlay_.setPosition([0,0]);
|
||||
}
|
||||
this.targetOverlay_.setPosition(coord);
|
||||
};
|
||||
|
||||
/** Hide the target overlay
|
||||
*/
|
||||
ol_Map.prototype.hideTarget = function()
|
||||
{
|
||||
this.removeOverlay(this.targetOverlay_);
|
||||
this.targetOverlay_ = undefined;
|
||||
};
|
||||
|
||||
export default ol_interaction_Synchronize
|
||||
97
build/interaction/TinkerBell.js
Normal file
97
build/interaction/TinkerBell.js
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
Tinker Bell effect on maps.
|
||||
|
||||
Copyright (c) 2015 Jean-Marc VIGLINO,
|
||||
released under the CeCILL-B license (French BSD license)
|
||||
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
|
||||
@link https://github.com/Viglino
|
||||
*/
|
||||
|
||||
import ol from 'ol'
|
||||
import ol_interaction_Pointer from 'ol/interaction/pointer'
|
||||
import ol_color from 'ol/color'
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @extends {ol_interaction_Pointer}
|
||||
* @param {ol_interaction_TinkerBell.options} options flashlight param
|
||||
* - color {ol_color} color of the sparkles
|
||||
*/
|
||||
var ol_interaction_TinkerBell = function(options)
|
||||
{ options = options || {};
|
||||
|
||||
ol_interaction_Pointer.call(this,
|
||||
{ handleDownEvent: this.onMove,
|
||||
handleMoveEvent: this.onMove
|
||||
});
|
||||
|
||||
this.set('color', options.color ? ol_color.asString(options.color) : "#fff");
|
||||
this.sparkle = [0,0];
|
||||
this.sparkles = [];
|
||||
this.lastSparkle = this.time = new Date();
|
||||
|
||||
var self = this;
|
||||
this.out_ = function() { self.isout_=true; };
|
||||
this.isout_ = true;
|
||||
};
|
||||
ol.inherits(ol_interaction_TinkerBell, ol_interaction_Pointer);
|
||||
|
||||
/** Set the map > start postcompose
|
||||
*/
|
||||
ol_interaction_TinkerBell.prototype.setMap = function(map)
|
||||
{ if (this.getMap())
|
||||
{ this.getMap().un('postcompose', this.postcompose_, this);
|
||||
map.getViewport().removeEventListener('mouseout', this.out_, false);
|
||||
this.getMap().render();
|
||||
}
|
||||
|
||||
ol_interaction_Pointer.prototype.setMap.call(this, map);
|
||||
|
||||
if (map)
|
||||
{ map.on('postcompose', this.postcompose_, this);
|
||||
map.on('mouseout', this.onMove, this);
|
||||
map.getViewport().addEventListener('mouseout', this.out_, false);
|
||||
}
|
||||
};
|
||||
|
||||
ol_interaction_TinkerBell.prototype.onMove = function(e)
|
||||
{ this.sparkle = e.pixel;
|
||||
this.isout_ = false;
|
||||
this.getMap().render();
|
||||
};
|
||||
|
||||
/** Postcompose function
|
||||
*/
|
||||
ol_interaction_TinkerBell.prototype.postcompose_ = function(e)
|
||||
{ var delta = 15;
|
||||
var ctx = e.context;
|
||||
var canvas = ctx.canvas;
|
||||
var dt = e.frameState.time - this.time;
|
||||
this.time = e.frameState.time;
|
||||
if (e.frameState.time-this.lastSparkle > 30 && !this.isout_)
|
||||
{ this.lastSparkle = e.frameState.time;
|
||||
this.sparkles.push({ p:[this.sparkle[0]+Math.random()*delta-delta/2, this.sparkle[1]+Math.random()*delta], o:1 });
|
||||
}
|
||||
ctx.save();
|
||||
ctx.scale(e.frameState.pixelRatio,e.frameState.pixelRatio);
|
||||
ctx.fillStyle = this.get("color");
|
||||
for (var i=this.sparkles.length-1, p; p=this.sparkles[i]; i--)
|
||||
{ if (p.o < 0.2)
|
||||
{ this.sparkles.splice(0,i+1);
|
||||
break;
|
||||
}
|
||||
ctx.globalAlpha = p.o;
|
||||
ctx.beginPath();
|
||||
ctx.arc (p.p[0], p.p[1], 2.2, 0, 2 * Math.PI, false);
|
||||
ctx.fill();
|
||||
p.o *= 0.98;
|
||||
p.p[0] += (Math.random()-0.5);
|
||||
p.p[1] += dt*(1+Math.random())/30;
|
||||
};
|
||||
ctx.restore();
|
||||
|
||||
// tell OL3 to continue postcompose animation
|
||||
if (this.sparkles.length) this.getMap().render();
|
||||
};
|
||||
|
||||
export default ol_interaction_TinkerBell
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user