Version 1.0.2 mit node_modules Verzeichnis

This commit is contained in:
ISA
2024-10-02 07:58:24 +02:00
parent f353a06b1b
commit 62b6e55a0a
68228 changed files with 4548477 additions and 651 deletions

4
node_modules/leaflet.smooth_marker_bouncing/.babelrc generated vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"presets": [ "@babel/preset-env" ],
"plugins": [ "@babel/plugin-proposal-class-properties" ]
}

View File

@@ -0,0 +1,53 @@
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
env:
node_version: 17.6.x
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node ${{ env.node_version }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.node_version }}
- name: Install
run: npm install
- name: Compile
run: npm run compile
- name: Test
run: npm test
- name: Build
run: npm run build
coverage:
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/master'
env:
node_version: 17.6.x
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup Node ${{ env.node_version }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.node_version }}
- name: Install
run: npm install
- name: Report coverage
run: |
npm run test:ci
npm run coverage

24
node_modules/leaflet.smooth_marker_bouncing/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,24 @@
Copyright (c) 2015, Alexei KLENIN
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

148
node_modules/leaflet.smooth_marker_bouncing/README.md generated vendored Normal file
View File

@@ -0,0 +1,148 @@
# Leaflet.SmoothMarkerBouncing
[![npm](https://img.shields.io/npm/v/leaflet.smooth_marker_bouncing.svg)](http://npm.im/leaflet.smooth_marker_bouncing)
[![CI](https://github.com/hosuaby/Leaflet.SmoothMarkerBouncing/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/hosuaby/Leaflet.SmoothMarkerBouncing/actions/workflows/ci.yml)
[![Coverage Status](https://coveralls.io/repos/github/hosuaby/Leaflet.SmoothMarkerBouncing/badge.svg?branch=master)](https://coveralls.io/github/hosuaby/Leaflet.SmoothMarkerBouncing?branch=master)
Plugin for [Leaflet](http://leafletjs.com/) that will make you markers bounce!
<p align="center">
<img src="./doc/bouncing_marker.gif"/>
</p>
It provides smooth, lightweight and customizable animation of marker bouncing.
Allows the bouncing of multiple markers on the map, without loss of performance.
### Older browsers
Starting from version `v3.0.0`, plugin is based on CSS3 keyframes to make animation. If you need support older browsers,
it will be better to stick to `v2.0.x`.
## Demo
Check out the [demo](http://hosuaby.github.io/Leaflet.SmoothMarkerBouncing/).
## Install
Add Javascript file on your page:
```html
<script type="text/javascript"
src="https://cdn.jsdelivr.net/gh/hosuaby/Leaflet.SmoothMarkerBouncing@v3.0.3/dist/bundle.js"
crossorigin="anonymous"></script>
```
Or install it as `npm` module:
```shell script
npm install leaflet.smooth_marker_bouncing
```
### ES module
Since `v3.1.0` plugin provides ES module, that can be imported in your code as following:
```javascript
import L from 'leaflet';
import SmoothMarkerBouncing from 'leaflet.smooth_marker_bouncing';
SmoothMarkerBouncing(L); // <-- adds plugins code to global L variable
```
## Usage
Plugin provides additional methods to `Marker`:
```javascript
/* Methods of L.Marker class */
L.Marker.setBouncingOptions({..}); // sets options of bouncing of all markers
L.Marker.getBouncingMarkers(); // gets all bouncing markers
L.Marker.stopAllBouncingMarkers(); // asks all markers to stop bouncing
L.Marker.stopAllBouncingMarkers(true); // stops bouncing of all markers abruptly
/* Methods of marker instances */
const marker = L.marker([lat, lng]);
marker.setBouncingOptions({..}); // sets options of bouncing for this marker
marker.isBouncing(); // checks if marker is bouncing
marker.bounce(); // starts the bouncing
marker.bounce(n); // makes marker bounce "n" times
marker.stopBouncing(); // stops bouncing of the marker
marker.stopBouncing(true); // stops bouncing of the marker abruptly
marker.toggleBouncing(); // starts/stops bouncing of the marker
```
Plugin respects fluent API. All marker instance methods (except `isBouncing`) return the marker object.
Some usage examples:
```javascript
/* Create a marker and make it bounce immediately */
const marker = L.marker([lat, lng]).addTo(map).bounce();
/* Create a marker and make it bounce 2 times when clicked.
* Do something when the bouncing is stopped, like open a popup.
*/
const marker = L.marker([lat, lng])
.addTo(map)
.on('click', function() {
this.bounce(2) // bounce 2 times
.on('bounceend',function() {
console.log('bounce end');
});
});
/* Create a marker and set its bouncing options.
* Bouncing can be started/stopped by the click on the marker.
*/
const marker = L.marker([lat, lng])
.setBouncingOptions({
bounceHeight : 60, // height of the bouncing
bounceSpeed : 54, // bouncing speed coefficient
exclusive : true, // if this marker is bouncing all others must stop
})
.addTo(map)
.on('click', function() {
this.toggleBouncing();
});
/* Define options of bouncing for all markers */
L.Marker.setBouncingOptions({
bounceHeight : 60, // height of the bouncing
bounceSpeed : 54, // bouncing speed coefficient
});
/* Create 10 markers and each of them will bounce 3 times when clicked */
for (let i = 0; i < 10; i++) {
const marker = L.marker([lat, lng])
.addTo(map)
.on('click', function() {
this.bounce(3); // bounce 3 times
});
}
```
## Options of bouncing
You can easily customize bouncing animation supplying options in method `setBouncingOptions`.
This method available on the marker class `L.Marker` and on each of marker instances.
It's highly recommended define options for all markers via `L.Marker.setBouncingOptions` instead of define them on each
marker individually.
The animation performance highly increases when all markers have the same options.
Method `setBouncingOptions` accepts an object with options as parameters.
Animation can be customized with following properties:
- **bounceHeight** - how high marker will bounce (px), *default: 15*
- **contractHeight** - how much marker will contract when it touches the ground (px), *default: 12*
- **bounceSpeed** - bouncing speed coefficient, value used to calculate the speed of bounce animation,
more it becomes high, more animation becomes slow, *default: 52*
- **contractSpeed** - contracting speed coefficient, *default: 52*
- **shadowAngle** - shadow inclination angle, if set to `null` shadow animation disabled (radians), *default:* -𝜋÷4
- **elastic** - activate contract animation when marker touches the ground, *default: true*
- **exclusive** - when it's true, stops the bouncing of other markers when this one starts to bounce.
If another marker start to bounce after, this marker stops. *default: false*
- **immediateStop** - when it's true, when marker stops, it does not execute animation until its end, but instead stops
abruptly. *default: false*
## Events
|Event|Description|
|---|---|
|bounceend|Fired when the animation is done|

View File

@@ -0,0 +1,282 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _leaflet = require("leaflet");
var _BouncingOptions = _interopRequireDefault(require("./BouncingOptions"));
var _Cache = _interopRequireDefault(require("./Cache"));
var _Styles = _interopRequireDefault(require("./Styles"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var bonceEndEvent = 'bounceend';
var BouncingMotion = /*#__PURE__*/function () {
// TODO: check if this cache working right (keys don't need prefix)
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotion(marker, position, bouncingOptions) {
_classCallCheck(this, BouncingMotion);
_defineProperty(this, "marker", void 0);
_defineProperty(this, "position", void 0);
_defineProperty(this, "bouncingOptions", void 0);
_defineProperty(this, "moveSteps", void 0);
_defineProperty(this, "moveDelays", void 0);
_defineProperty(this, "resizeSteps", void 0);
_defineProperty(this, "resizeDelays", void 0);
_defineProperty(this, "isBouncing", false);
_defineProperty(this, "iconStyles", void 0);
_defineProperty(this, "shadowStyles", void 0);
_defineProperty(this, "bouncingAnimationPlaying", false);
this.marker = marker;
this.position = position;
this.updateBouncingOptions(bouncingOptions);
}
_createClass(BouncingMotion, [{
key: "updateBouncingOptions",
value: function updateBouncingOptions(options) {
this.bouncingOptions = options instanceof _BouncingOptions["default"] ? options : this.bouncingOptions.override(options);
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
bounceSpeed = _this$bouncingOptions.bounceSpeed,
elastic = _this$bouncingOptions.elastic;
this.moveSteps = BouncingMotion.cache.get("moveSteps_".concat(bounceHeight), function () {
return BouncingMotion.calculateSteps(bounceHeight);
});
this.moveDelays = BouncingMotion.cache.get("moveDelays_".concat(bounceHeight, "_").concat(bounceSpeed), function () {
return BouncingMotion.calculateDelays(bounceHeight, bounceSpeed);
});
if (elastic) {
var _this$bouncingOptions2 = this.bouncingOptions,
contractHeight = _this$bouncingOptions2.contractHeight,
contractSpeed = _this$bouncingOptions2.contractSpeed;
this.resizeSteps = BouncingMotion.cache.get("resizeSteps_".concat(contractHeight), function () {
return BouncingMotion.calculateSteps(contractHeight);
});
this.resizeDelays = BouncingMotion.cache.get("resizeDelays_".concat(contractHeight, "_").concat(contractSpeed), function () {
return BouncingMotion.calculateDelays(contractHeight, contractSpeed);
});
}
this.recalculateMotion(this.position);
}
}, {
key: "resetStyles",
value: function resetStyles(marker) {
this.iconStyles = _Styles["default"].ofMarker(marker);
if (marker._shadow) {
this.shadowStyles = _Styles["default"].parse(marker._shadow.style.cssText);
}
}
/**
* Recalculates bouncing motion for new marker position.
* @param position {Point} new marker position
*/
}, {
key: "recalculateMotion",
value: function recalculateMotion(position) {
this.position = position;
}
/**
* @param times {number|null}
*/
}, {
key: "bounce",
value: function bounce() {
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (this.bouncingAnimationPlaying) {
this.isBouncing = true;
return;
}
this.isBouncing = true;
this.bouncingAnimationPlaying = true;
this.move(times);
}
}, {
key: "stopBouncing",
value: function stopBouncing() {
this.isBouncing = false;
}
/**
* @param times {number|null}
*/
}, {
key: "move",
value: function move() {
var _this = this;
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (times !== null) {
if (! --times) {
this.isBouncing = false; // this is the last bouncing
this.bouncingAnimationPlaying = false;
}
}
/* Launch timeouts for every step of the movement animation */
var i = this.moveSteps.length;
while (i--) {
setTimeout(function (step) {
return _this.makeMoveStep(step);
}, this.moveDelays[i], this.moveSteps[i]);
}
setTimeout(function () {
return _this.afterMove(times);
}, this.moveDelays[this.moveSteps.length - 1]);
}
}, {
key: "afterMove",
value: function afterMove(times) {
var _this2 = this;
if (this.isBouncing) {
setTimeout(function () {
return _this2.move(times);
}, this.bouncingOptions.bounceSpeed);
} else {
this.bouncingAnimationPlaying = false;
this.marker.fire(bonceEndEvent);
}
}
/**
* @param step {number}
*/
}, {
key: "makeMoveStep",
value: function makeMoveStep(step) {
this.marker._icon.style.cssText = this.iconStyles.toString();
if (this.marker._shadow) {
this.marker._shadow.style.cssText = this.shadowStyles.toString();
}
}
/**
* Returns calculated array of animation steps. This function used to calculate both movement
* and resizing animations.
*
* @param height {number} height of movement or resizing (px)
*
* @return {number[]} array of animation steps
*/
}], [{
key: "calculateSteps",
value: function calculateSteps(height) {
/* Calculate the sequence of animation steps:
* steps = [1 .. height] concat [height-1 .. 0]
*/
var i = 1;
var steps = [];
while (i <= height) {
steps.push(i++);
}
i = height;
while (i--) {
steps.push(i);
}
return steps;
}
/**
* Returns calculated array of delays between animation start and the steps of animation. This
* function used to calculate both movement and resizing animations. Element with index i of
* this array contains the delay in milliseconds between animation start and the step number i.
*
* @param height {number} height of movement or resizing (px)
* @param speed {number} speed coefficient
*
* @return {number[]} array of delays before steps of animation
*/
}, {
key: "calculateDelays",
value: function calculateDelays(height, speed) {
// Calculate delta time for bouncing animation
// Delta time to movement in one direction
var deltas = []; // time between steps of animation
deltas[height] = speed;
deltas[0] = 0;
var i = height;
while (--i) {
deltas[i] = Math.round(speed / (height - i));
} // Delta time for movement in two directions
i = height;
while (i--) {
deltas.push(deltas[i]);
} // Calculate move delays (cumulated deltas)
// TODO: instead of deltas.lenght write bounceHeight * 2 - 1
var delays = []; // delays before steps from beginning of animation
var totalDelay = 0;
for (i = 0; i < deltas.length; i++) {
totalDelay += deltas[i];
delays.push(totalDelay);
}
return delays;
}
}]);
return BouncingMotion;
}();
exports["default"] = BouncingMotion;
_defineProperty(BouncingMotion, "cache", new _Cache["default"]());

View File

@@ -0,0 +1,258 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _leaflet = require("leaflet");
var _BouncingMotion2 = _interopRequireDefault(require("./BouncingMotion"));
var _Matrix3D = _interopRequireDefault(require("./Matrix3D"));
var _line = require("./line");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var moveMatrixFormat = _Matrix3D["default"].identity().toFormat('d1', 'd2');
var resizeMatrixFormat = _Matrix3D["default"].identity().toFormat('b2', 'd1', 'd2');
var BouncingMotion3D = /*#__PURE__*/function (_BouncingMotion) {
_inherits(BouncingMotion3D, _BouncingMotion);
var _super = _createSuper(BouncingMotion3D);
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotion3D(marker, position, bouncingOptions) {
var _this;
_classCallCheck(this, BouncingMotion3D);
_this = _super.call(this, marker, position, bouncingOptions);
_defineProperty(_assertThisInitialized(_this), "iconMoveTransforms", void 0);
_defineProperty(_assertThisInitialized(_this), "iconResizeTransforms", void 0);
_defineProperty(_assertThisInitialized(_this), "shadowMoveTransforms", void 0);
_defineProperty(_assertThisInitialized(_this), "shadowResizeTransforms", void 0);
_this.recalculateMotion(position);
return _this;
}
_createClass(BouncingMotion3D, [{
key: "recalculateMotion",
value: function recalculateMotion(position) {
var _this$marker$getIcon, _this$marker$getIcon$, _this$marker, _this$marker$_iconObj, _this$marker$_iconObj2;
_get(_getPrototypeOf(BouncingMotion3D.prototype), "recalculateMotion", this).call(this, position);
var iconHeight = ((_this$marker$getIcon = this.marker.getIcon()) === null || _this$marker$getIcon === void 0 ? void 0 : (_this$marker$getIcon$ = _this$marker$getIcon.options) === null || _this$marker$getIcon$ === void 0 ? void 0 : _this$marker$getIcon$.iconSize[1]) || ((_this$marker = this.marker) === null || _this$marker === void 0 ? void 0 : (_this$marker$_iconObj = _this$marker._iconObj) === null || _this$marker$_iconObj === void 0 ? void 0 : (_this$marker$_iconObj2 = _this$marker$_iconObj.options) === null || _this$marker$_iconObj2 === void 0 ? void 0 : _this$marker$_iconObj2.iconSize[1]);
var x = position.x,
y = position.y;
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
contractHeight = _this$bouncingOptions.contractHeight,
shadowAngle = _this$bouncingOptions.shadowAngle;
this.iconMoveTransforms = BouncingMotion3D.calculateIconMoveTransforms(x, y, bounceHeight);
this.iconResizeTransforms = BouncingMotion3D.calculateResizeTransforms(x, y, iconHeight, contractHeight);
if (this.marker._shadow) {
var _this$marker$getIcon2, _this$marker$getIcon3;
this.shadowMoveTransforms = BouncingMotion3D.calculateShadowMoveTransforms(x, y, bounceHeight, shadowAngle);
var shadowHeight = (_this$marker$getIcon2 = this.marker.getIcon()) === null || _this$marker$getIcon2 === void 0 ? void 0 : (_this$marker$getIcon3 = _this$marker$getIcon2.options) === null || _this$marker$getIcon3 === void 0 ? void 0 : _this$marker$getIcon3.shadowSize[1];
this.shadowResizeTransforms = BouncingMotion3D.calculateResizeTransforms(x, y, shadowHeight, contractHeight);
}
}
}, {
key: "afterMove",
value: function afterMove(times) {
if (this.bouncingOptions.elastic) {
this.resize(times);
} else {
_get(_getPrototypeOf(BouncingMotion3D.prototype), "afterMove", this).call(this, times);
}
}
}, {
key: "resize",
value: function resize(times) {
var _this2 = this;
var nbResizeSteps = this.resizeSteps.length;
var i = nbResizeSteps;
while (i--) {
setTimeout(function (step) {
return _this2.makeResizeStep(step);
}, this.resizeDelays[i], this.resizeSteps[i]);
}
setTimeout(function () {
if (!_this2.isBouncing) {
_this2.bouncingAnimationPlaying = false;
}
}, this.resizeDelays[this.resizeSteps.length]);
setTimeout(function () {
if (_this2.isBouncing) {
_this2.move(times);
} else {
_this2.marker.fire('bounceend');
}
}, this.resizeDelays[nbResizeSteps - 1]);
}
}, {
key: "makeMoveStep",
value: function makeMoveStep(step) {
this.marker._icon.style.cssText = this.iconStyles.withTransform(this.iconMoveTransforms[step]).toString();
if (this.marker._shadow) {
this.marker._shadow.style.cssText = this.shadowStyles.withTransform(this.shadowMoveTransforms[step]).toString();
}
}
/**
* @param step {number}
*/
}, {
key: "makeResizeStep",
value: function makeResizeStep(step) {
this.marker._icon.style.cssText = this.iconStyles.withTransform(this.iconResizeTransforms[step]).toString();
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
this.marker._shadow.style.cssText = this.shadowStyles.withTransform(this.shadowResizeTransforms[step]).toString();
}
}
/**
* Returns calculated array of transformation definitions for the animation of icon movement.
* Function defines one transform for every pixel of shift of the icon from it's original y
* position.
*
* @param x {number} x coordinate of original position of the marker
* @param y {number} y coordinate of original position of the marker
* @param bounceHeight {number} height of bouncing (px)
*
* @return {string[]} array of transformation definitions
*/
}], [{
key: "calculateIconMoveTransforms",
value: function calculateIconMoveTransforms(x, y, bounceHeight) {
var transforms = [];
var deltaY = bounceHeight + 1; // Use fast inverse while loop to fill the array
while (deltaY--) {
transforms[deltaY] = moveMatrixFormat(x, y - deltaY);
}
return transforms;
}
/**
* Returns calculated array of transformation definitions for the animation of icon resizing.
* Function defines one transform for every pixel of resizing of marker from it's original
* height.
*
* @param x {number} x coordinate of original position of marker
* @param y {number} y coordinate of original position of marker
* @param height {number} original marker height (px)
* @param contractHeight {number} height of marker contraction (px)
*
* @return {string[]} array of transformation definitions
*/
}, {
key: "calculateResizeTransforms",
value: function calculateResizeTransforms(x, y, height, contractHeight) {
var transforms = [];
var deltaHeight = contractHeight + 1; // Use fast inverse while loop to fill the array
while (deltaHeight--) {
transforms[deltaHeight] = resizeMatrixFormat((height - deltaHeight) / height, x, y + deltaHeight);
}
return transforms;
}
/**
* Returns calculated array of transformation definitions for the animation of shadow movement.
* Function defines one transform for every pixel of shift of the shadow from it's original
* position.
*
* @param x {number} x coordinate of original position of marker
* @param y {number} y coordinate of original position of marker
* @param bounceHeight {number} height of bouncing (px)
* @param angle {number|null} shadow inclination angle, if null shadow don't moves from it's
* initial position (radians)
*
* @return {string[]} array of transformation definitions
*/
}, {
key: "calculateShadowMoveTransforms",
value: function calculateShadowMoveTransforms(x, y, bounceHeight) {
var angle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
// TODO: check this method to know if bounceHeight + 1 is normal
var transforms = [];
var deltaY = bounceHeight + 1;
var points = [];
if (angle != null) {
// important: 0 is not null
points = (0, _line.calculateLine)(x, y, angle, bounceHeight + 1);
} else {
for (var i = 0; i <= bounceHeight; i++) {
points[i] = [x, y];
}
} // Use fast inverse while loop to fill the array
while (deltaY--) {
transforms[deltaY] = moveMatrixFormat(points[deltaY][0], points[deltaY][1]);
}
return transforms;
}
}]);
return BouncingMotion3D;
}(_BouncingMotion2["default"]);
exports["default"] = BouncingMotion3D;

View File

@@ -0,0 +1,297 @@
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _leaflet = require("leaflet");
var _line = require("./line");
require("./bouncing.css");
var _BouncingOptions = _interopRequireDefault(require("./BouncingOptions"));
var _Styles = _interopRequireDefault(require("./Styles"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
function _classPrivateFieldSet(s, a, r) { return s.set(_assertClassBrand(s, a), r), r; }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
var animationNamePrefix = 'l-smooth-marker-bouncing-';
var moveAnimationName = animationNamePrefix + 'move';
var contractAnimationName = animationNamePrefix + 'contract';
/*
* CSS3 animation runs faster than transform-based animation. We need to reduce speed in order
* to be compatible with old API.
*/
var speedCoefficient = 0.8;
/**
* Removes and then resets required classes on the HTML element.
* Used as hack to restart CSS3 animation.
*
* @param element {HTMLElement} HTML element
* @param classes {string[]} names of classes
*/
function resetClasses(element, classes) {
classes.forEach(function (className) {
return _leaflet.DomUtil.removeClass(element, className);
});
void element.offsetWidth;
classes.forEach(function (className) {
return _leaflet.DomUtil.addClass(element, className);
});
}
var _lastAnimationName = /*#__PURE__*/new WeakMap();
var _classes = /*#__PURE__*/new WeakMap();
var _eventCounter = /*#__PURE__*/new WeakMap();
var _times = /*#__PURE__*/new WeakMap();
var _listener = /*#__PURE__*/new WeakMap();
var BouncingMotionCss3 = exports["default"] = /*#__PURE__*/function () {
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotionCss3(marker, position, bouncingOptions) {
var _this = this;
_classCallCheck(this, BouncingMotionCss3);
_defineProperty(this, "marker", void 0);
_defineProperty(this, "position", void 0);
_defineProperty(this, "bouncingOptions", void 0);
_defineProperty(this, "isBouncing", false);
_defineProperty(this, "iconStyles", void 0);
_defineProperty(this, "shadowStyles", void 0);
_defineProperty(this, "bouncingAnimationPlaying", false);
_defineProperty(this, "onMotionEnd", void 0);
_classPrivateFieldInitSpec(this, _lastAnimationName, contractAnimationName);
_classPrivateFieldInitSpec(this, _classes, ['bouncing']);
_classPrivateFieldInitSpec(this, _eventCounter, void 0);
_classPrivateFieldInitSpec(this, _times, void 0);
_classPrivateFieldInitSpec(this, _listener, function (event) {
return _this.onAnimationEnd(event);
});
this.marker = marker;
this.position = position;
this.updateBouncingOptions(bouncingOptions);
}
return _createClass(BouncingMotionCss3, [{
key: "updateBouncingOptions",
value: function updateBouncingOptions(options) {
this.bouncingOptions = options instanceof _BouncingOptions["default"] ? options : this.bouncingOptions.override(options);
if (this.bouncingOptions.elastic && this.bouncingOptions.contractHeight) {
_classPrivateFieldSet(_lastAnimationName, this, contractAnimationName);
var index = _classPrivateFieldGet(_classes, this).indexOf('simple');
if (index > -1) {
_classPrivateFieldGet(_classes, this).splice(index, 1);
}
if (this.marker._icon) {
_leaflet.DomUtil.removeClass(this.marker._icon, 'simple');
}
} else {
_classPrivateFieldSet(_lastAnimationName, this, moveAnimationName);
_classPrivateFieldGet(_classes, this).push('simple');
}
if (this.marker._icon) {
this.resetStyles(this.marker);
}
}
}, {
key: "onAnimationEnd",
value: function onAnimationEnd(event) {
if (event.animationName === _classPrivateFieldGet(_lastAnimationName, this)) {
var _this$eventCounter, _this$eventCounter2;
_classPrivateFieldSet(_eventCounter, this, (_this$eventCounter = _classPrivateFieldGet(_eventCounter, this), _this$eventCounter2 = _this$eventCounter++, _this$eventCounter)), _this$eventCounter2;
_classPrivateFieldSet(_eventCounter, this, _classPrivateFieldGet(_eventCounter, this) % 2);
if (!_classPrivateFieldGet(_eventCounter, this)) {
var _this$times;
if (this.isBouncing && (_classPrivateFieldGet(_times, this) === null || _classPrivateFieldSet(_times, this, (_this$times = _classPrivateFieldGet(_times, this), --_this$times)))) {
resetClasses(this.marker._icon, _classPrivateFieldGet(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet(_classes, this));
}
} else {
this._stopBouncingAnimation();
}
}
}
}
}, {
key: "resetStyles",
value: function resetStyles(marker) {
var _this$marker$getIcon,
_this$marker,
_this2 = this;
this.marker = marker;
this.iconStyles = _Styles["default"].ofMarker(marker);
if (marker._shadow) {
this.shadowStyles = _Styles["default"].parse(marker._shadow.style.cssText);
}
var iconHeight = ((_this$marker$getIcon = this.marker.getIcon()) === null || _this$marker$getIcon === void 0 || (_this$marker$getIcon = _this$marker$getIcon.options) === null || _this$marker$getIcon === void 0 ? void 0 : _this$marker$getIcon.iconSize[1]) || ((_this$marker = this.marker) === null || _this$marker === void 0 || (_this$marker = _this$marker._iconObj) === null || _this$marker === void 0 || (_this$marker = _this$marker.options) === null || _this$marker === void 0 ? void 0 : _this$marker.iconSize[1]);
var iconAnimationParams = BouncingMotionCss3.animationParams(this.position, this.bouncingOptions, iconHeight);
this.iconStyles = this.iconStyles.withStyles(iconAnimationParams);
this.marker._icon.style.cssText = this.iconStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._icon, _classPrivateFieldGet(_classes, this));
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet(_listener, this));
}
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
contractHeight = _this$bouncingOptions.contractHeight,
shadowAngle = _this$bouncingOptions.shadowAngle;
if (this.marker._shadow) {
if (shadowAngle) {
var _this$marker$getIcon2;
var _this$position = this.position,
x = _this$position.x,
y = _this$position.y;
var points = (0, _line.calculateLine)(x, y, shadowAngle, bounceHeight + 1);
var _points$bounceHeight = _slicedToArray(points[bounceHeight], 2),
posXJump = _points$bounceHeight[0],
posYJump = _points$bounceHeight[1];
var shadowHeight = (_this$marker$getIcon2 = this.marker.getIcon()) === null || _this$marker$getIcon2 === void 0 || (_this$marker$getIcon2 = _this$marker$getIcon2.options) === null || _this$marker$getIcon2 === void 0 ? void 0 : _this$marker$getIcon2.shadowSize[1];
var shadowScaleContract = BouncingMotionCss3.contractScale(shadowHeight, contractHeight);
this.shadowStyles = this.shadowStyles.withStyles(iconAnimationParams).withStyles({
'--pos-x-jump': "".concat(posXJump, "px"),
'--pos-y-jump': "".concat(posYJump, "px"),
'--scale-contract': shadowScaleContract
});
this.marker._shadow.style.cssText = this.shadowStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._shadow, _classPrivateFieldGet(_classes, this));
}
} else {
_classPrivateFieldGet(_classes, this).forEach(function (className) {
_leaflet.DomUtil.removeClass(_this2.marker._shadow, className);
});
}
}
}
}, {
key: "bounce",
value: function bounce() {
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
_classPrivateFieldSet(_times, this, times);
this.isBouncing = true;
if (this.bouncingAnimationPlaying) {
return;
}
_classPrivateFieldSet(_eventCounter, this, 0);
this.bouncingAnimationPlaying = true;
resetClasses(this.marker._icon, _classPrivateFieldGet(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet(_classes, this));
}
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet(_listener, this));
}
}, {
key: "stopBouncing",
value: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this.isBouncing = false;
immediate || (immediate = this.bouncingOptions.immediateStop);
if (immediate) {
this._stopBouncingAnimation();
}
}
}, {
key: "_stopBouncingAnimation",
value: function _stopBouncingAnimation() {
var _this3 = this;
_classPrivateFieldGet(_classes, this).forEach(function (className) {
_leaflet.DomUtil.removeClass(_this3.marker._icon, className);
if (_this3.marker._shadow) {
_leaflet.DomUtil.removeClass(_this3.marker._shadow, className);
}
});
this.bouncingAnimationPlaying = false;
if (this.onMotionEnd) {
this.onMotionEnd();
this.onMotionEnd = null;
}
this.marker.fire('bounceend');
}
/**
* Calculates parameters of CSS3 animation of bouncing.
*
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
* @param height {number} icons height
* @return {object} CSS3 animation parameters
*/
}], [{
key: "animationParams",
value: function animationParams(position, bouncingOptions, height) {
var x = position.x,
y = position.y;
var bounceHeight = bouncingOptions.bounceHeight,
contractHeight = bouncingOptions.contractHeight,
bounceSpeed = bouncingOptions.bounceSpeed,
contractSpeed = bouncingOptions.contractSpeed;
var scaleContract = BouncingMotionCss3.contractScale(height, contractHeight);
var durationJump = BouncingMotionCss3.calculateDuration(bounceHeight, bounceSpeed);
var durationContract = BouncingMotionCss3.calculateDuration(contractHeight, contractSpeed);
var delays = [0, durationJump, durationJump * 2, durationJump * 2 + durationContract];
return {
'--pos-x': "".concat(x, "px"),
'--pos-y': "".concat(y, "px"),
'--pos-y-jump': "".concat(y - bounceHeight, "px"),
'--pos-y-contract': "".concat(y + contractHeight, "px"),
'--scale-contract': scaleContract,
'--duration-jump': "".concat(durationJump, "ms"),
'--duration-contract': "".concat(durationContract, "ms"),
'--delays': "0ms, ".concat(delays[1], "ms, ").concat(delays[2], "ms, ").concat(delays[3], "ms")
};
}
/**
* Calculates scale of contracting.
*
* @param {number} height original height
* @param {number} contractHeight how much it must contract
* @return {number} contracting scale between 0 and 1
*/
}, {
key: "contractScale",
value: function contractScale(height, contractHeight) {
return (height - contractHeight) / height;
}
/**
* Calculates duration of animation.
*
* @param height {number} height of movement or resizing (px)
* @param speed {number} speed coefficient
*
* @return {number} duration of animation (ms)
*/
}, {
key: "calculateDuration",
value: function calculateDuration(height, speed) {
if (height === 0) {
return 0;
}
var duration = Math.round(speed * speedCoefficient);
var i = height;
while (--i) {
duration += Math.round(speed / (height - i));
}
return duration;
}
}]);
}();

View File

@@ -0,0 +1,153 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _BouncingMotion2 = _interopRequireDefault(require("./BouncingMotion"));
var _line = require("./line");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var BouncingMotionSimple = /*#__PURE__*/function (_BouncingMotion) {
_inherits(BouncingMotionSimple, _BouncingMotion);
var _super = _createSuper(BouncingMotionSimple);
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotionSimple(marker, position, bouncingOptions) {
var _this;
_classCallCheck(this, BouncingMotionSimple);
_this = _super.call(this, marker, position, bouncingOptions);
_defineProperty(_assertThisInitialized(_this), "iconMovePoints", void 0);
_defineProperty(_assertThisInitialized(_this), "shadowMovePoints", void 0);
_this.recalculateMotion(position);
return _this;
}
_createClass(BouncingMotionSimple, [{
key: "recalculateMotion",
value: function recalculateMotion(position) {
_get(_getPrototypeOf(BouncingMotionSimple.prototype), "recalculateMotion", this).call(this, position);
var x = position.x,
y = position.y;
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
shadowAngle = _this$bouncingOptions.shadowAngle;
this.iconMovePoints = BouncingMotionSimple.calculateIconMovePoints(x, y, bounceHeight);
this.shadowMovePoints = BouncingMotionSimple.calculateShadowMovePoints(x, y, bounceHeight, shadowAngle);
}
}, {
key: "makeMoveStep",
value: function makeMoveStep(step) {
_get(_getPrototypeOf(BouncingMotionSimple.prototype), "makeMoveStep", this).call(this, step);
this.marker._icon.style.left = this.iconMovePoints[step][0] + 'px';
this.marker._icon.style.top = this.iconMovePoints[step][1] + 'px';
if (this.marker._shadow) {
this.marker._shadow.style.left = this.shadowMovePoints[step][0] + 'px';
this.marker._shadow.style.top = this.shadowMovePoints[step][1] + 'px';
}
}
/**
* Returns calculated array of points for icon movement. Used to animate markers in browsers
* that doesn't support 'transform' attribute.
*
* @param x {number} x coordinate of original position of the marker
* @param y {number} y coordinate of original position of the marker
* @param bounceHeight {number} height of bouncing (px)
*
* @return {[number, number][]} array of points
*/
}], [{
key: "calculateIconMovePoints",
value: function calculateIconMovePoints(x, y, bounceHeight) {
var deltaHeight = bounceHeight + 1;
var points = []; // Use fast inverse while loop to fill the array
while (deltaHeight--) {
points[deltaHeight] = [x, y - deltaHeight];
}
return points;
}
/**
* Returns calculated array of points for shadow movement. Used to animate markers in browsers
* that doesn't support 'transform' attribute.
*
* @param x {number} x coordinate of original position of the marker
* @param y {number} y coordinate of original position of the marker
* @param bounceHeight {number} height of bouncing (px)
* @param angle {number} shadow inclination angle, if null shadow don't moves from it's initial
* position (radians)
*
* @return {[number, number][]} array of points
*/
}, {
key: "calculateShadowMovePoints",
value: function calculateShadowMovePoints(x, y, bounceHeight, angle) {
if (angle != null) {
// important: 0 is not null
return (0, _line.calculateLine)(x, y, angle, bounceHeight + 1);
} else {
var points = [];
for (var i = 0; i <= bounceHeight; i++) {
points[i] = [x, y];
}
return points;
}
}
}]);
return BouncingMotionSimple;
}(_BouncingMotion2["default"]);
exports["default"] = BouncingMotionSimple;

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var BouncingOptions = exports["default"] = /*#__PURE__*/function () {
function BouncingOptions(options) {
_classCallCheck(this, BouncingOptions);
/**
* How high marker can bounce (px)
* @type {number}
*/
_defineProperty(this, "bounceHeight", 15);
/**
* How much marker can contract (px)
* @type {number}
*/
_defineProperty(this, "contractHeight", 12);
/**
* Bouncing speed coefficient
* @type {number}
*/
_defineProperty(this, "bounceSpeed", 52);
/**
* Contracting speed coefficient
* @type {number}
*/
_defineProperty(this, "contractSpeed", 52);
/**
* Shadow inclination angle(radians); null to cancel shadow movement
* @type {number}
*/
_defineProperty(this, "shadowAngle", -Math.PI / 4);
/**
* Activate contract animation
* @type {boolean}
*/
_defineProperty(this, "elastic", true);
/**
* Many markers can bounce in the same time
* @type {boolean}
*/
_defineProperty(this, "exclusive", false);
/**
* If true, when marker stops, it does not execute animation until its end, but instead stops
* abruptly.
* @type {boolean}
*/
_defineProperty(this, "immediateStop", false);
options && Object.assign(this, options);
}
return _createClass(BouncingOptions, [{
key: "override",
value: function override(options) {
return Object.assign(new BouncingOptions(this), options);
}
}]);
}();

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var Cache = /*#__PURE__*/function () {
function Cache() {
_classCallCheck(this, Cache);
_defineProperty(this, "cache", {});
}
_createClass(Cache, [{
key: "get",
/**
* If item with supplied {@code key} is present in cache, returns it, otherwise executes
* {@code supplier} function and caches the result.
*
* @param key {String} key of the cache
* @param supplier {function} item supplier
* @return {Object} item
*/
value: function get(key, supplier) {
return this.cache[key] || (this.cache[key] = supplier.apply());
}
}]);
return Cache;
}();
exports["default"] = Cache;

View File

@@ -0,0 +1,107 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = MarkerPrototypeExt;
var _BouncingOptions = _interopRequireDefault(require("./BouncingOptions"));
var _Orchestration = _interopRequireDefault(require("./Orchestration"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function MarkerPrototypeExt(Leaflet) {
var oldSetPos = Leaflet.Marker.prototype._setPos;
var oldOnAdd = Leaflet.Marker.prototype.onAdd;
var oldSetIcon = Leaflet.Marker.prototype.setIcon;
return {
/** Bouncing options shared by all markers. */
_bouncingOptions: new _BouncingOptions["default"](),
_orchestration: new _Orchestration["default"](),
_realMarker: true,
/**
* Registers options of bouncing animation for this marker. After registration of options for
* this marker, it will ignore changes of default options. Function automatically recalculates
* animation steps and delays.
*
* @param options {BouncingOptions} options object
* @return {Marker} this marker
*/
setBouncingOptions: function setBouncingOptions(options) {
this._bouncingMotion.updateBouncingOptions(options);
return this;
},
/**
* Returns true if this marker is bouncing. If this marker is not bouncing returns false.
* @return {boolean} true if marker is bouncing, false if not
*/
isBouncing: function isBouncing() {
return this._bouncingMotion.isBouncing;
},
/**
* Starts bouncing of this marker.
* @param times {number|null} number of times the marker must to bounce
* @return {Marker} this marker
*/
bounce: function bounce() {
var _this = this;
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (times) {
this._bouncingMotion.onMotionEnd = function () {
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(_this);
};
}
this._bouncingMotion.bounce(times);
var exclusive = this._bouncingMotion.bouncingOptions.exclusive;
Leaflet.Marker.prototype._orchestration.addBouncingMarker(this, exclusive);
return this;
},
/**
* Stops bouncing of this marker.
* Note: unless 'immediate' flag is set to true, by the call to this method or in marker options,
* the bouncing will not stop immediately after the call of this method. Instead, the animation
* is executed until marker returns to its original position and takes its full size.
*
* @param immediate {boolean} if true, marker stop to bounce immediately, without waiting
* animation to end
* @return {Marker} this marker
*/
stopBouncing: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this._bouncingMotion.stopBouncing(immediate);
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(this);
return this;
},
/**
* Starts/stops bouncing of this marker.
* @return {Marker} marker
*/
toggleBouncing: function toggleBouncing() {
if (this._bouncingMotion.isBouncing) {
this.stopBouncing();
} else {
this.bounce();
}
return this;
},
isRealMarker: function isRealMarker() {
return Object.hasOwn(this.__proto__, '_realMarker');
},
_setPos: function _setPos(position) {
oldSetPos.call(this, position);
if (this.isRealMarker()) {
this._bouncingMotion.position = position;
this._bouncingMotion.resetStyles(this);
}
},
onAdd: function onAdd(map) {
oldOnAdd.call(this, map);
if (this.isRealMarker()) {
this._bouncingMotion.resetStyles(this);
}
},
setIcon: function setIcon(icon) {
oldSetIcon.call(this, icon);
if (this.isRealMarker() && this._icon) {
this._bouncingMotion.resetStyles(this);
}
}
};
}

View File

@@ -0,0 +1,106 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to get private field on non-instance"); } if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = privateMap.get(receiver); if (!descriptor) { throw new TypeError("attempted to set private field on non-instance"); } if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } return value; }
var rowMap = {
'a': 0,
'b': 1,
'c': 2,
'd': 3
};
var zeros = Array(16).fill(0);
var _identity = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
/**
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d
*/
var _matrix = new WeakMap();
var Matrix3D = /*#__PURE__*/function () {
function Matrix3D() {
var matrix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : zeros;
_classCallCheck(this, Matrix3D);
_matrix.set(this, {
writable: true,
value: void 0
});
_classPrivateFieldSet(this, _matrix, _toConsumableArray(matrix));
}
_createClass(Matrix3D, [{
key: "toFormat",
value: function toFormat() {
for (var _len = arguments.length, placeholders = new Array(_len), _key = 0; _key < _len; _key++) {
placeholders[_key] = arguments[_key];
}
placeholders = placeholders.map(Matrix3D.valueNameToIndex);
var nextPlaceholderIndex = 0;
var fnBody = _classPrivateFieldGet(this, _matrix).map(function (value, index) {
return index === placeholders[nextPlaceholderIndex] ? "'+arguments[".concat(nextPlaceholderIndex++, "]+'") : value;
}).join(',');
fnBody = "return ' matrix3d(".concat(fnBody, ") ';");
function formatFn() {
return Function.apply(this, [fnBody]);
}
formatFn.prototype = Function.prototype;
return new formatFn();
}
}, {
key: "toString",
value: function toString() {
return " matrix3d(".concat(_classPrivateFieldGet(this, _matrix).join(','), ") ");
}
}], [{
key: "zeros",
value: function zeros() {
return new Matrix3D();
}
}, {
key: "identity",
value: function identity() {
return new Matrix3D(_identity);
}
}, {
key: "valueNameToIndex",
value: function valueNameToIndex(valueName) {
return rowMap[valueName[0]] * 4 + parseInt(valueName[1]) - 1;
}
}]);
return Matrix3D;
}();
exports["default"] = Matrix3D;

View File

@@ -0,0 +1,91 @@
"use strict";
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _classPrivateFieldInitSpec(e, t, a) { _checkPrivateRedeclaration(e, t), t.set(e, a); }
function _checkPrivateRedeclaration(e, t) { if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object"); }
function _classPrivateFieldGet(s, a) { return s.get(_assertClassBrand(s, a)); }
function _assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); }
var _bouncingMarkers = /*#__PURE__*/new WeakMap();
var Orchestration = exports["default"] = /*#__PURE__*/function () {
function Orchestration() {
_classCallCheck(this, Orchestration);
_classPrivateFieldInitSpec(this, _bouncingMarkers, []);
}
return _createClass(Orchestration, [{
key: "getBouncingMarkers",
value: function getBouncingMarkers() {
return _classPrivateFieldGet(_bouncingMarkers, this);
}
/**
* Adds the marker to the list of bouncing markers.
* If flag 'exclusive' is set to true, stops all bouncing markers before.
*
* @param marker {Marker} marker object
* @param exclusive {boolean} flag of exclusive bouncing. If set to true, stops the bouncing
* of all other markers.
*/
}, {
key: "addBouncingMarker",
value: function addBouncingMarker(marker, exclusive) {
if (exclusive || marker._bouncingMotion.bouncingOptions.exclusive) {
this.stopAllBouncingMarkers();
} else {
this.stopExclusiveMarkerBouncing();
}
_classPrivateFieldGet(_bouncingMarkers, this).push(marker);
}
/**
* Stops the bouncing of exclusive marker.
*/
}, {
key: "stopExclusiveMarkerBouncing",
value: function stopExclusiveMarkerBouncing() {
var exclusiveMarker = _classPrivateFieldGet(_bouncingMarkers, this).find(function (marker) {
return marker._bouncingMotion.bouncingOptions.exclusive;
});
if (exclusiveMarker) {
exclusiveMarker.stopBouncing();
}
}
/**
* Removes the marker from the list of bouncing markers.
* @param marker {Marker} marker
*/
}, {
key: "removeBouncingMarker",
value: function removeBouncingMarker(marker) {
var i = _classPrivateFieldGet(_bouncingMarkers, this).indexOf(marker);
if (~i) {
_classPrivateFieldGet(_bouncingMarkers, this).splice(i, 1);
}
}
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
}, {
key: "stopAllBouncingMarkers",
value: function stopAllBouncingMarkers() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var marker;
while (marker = _classPrivateFieldGet(_bouncingMarkers, this).shift()) {
marker.stopBouncing(immediate);
}
}
}]);
}();

View File

@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = SmoothMarkerBouncing;
var _BouncingOptions = _interopRequireDefault(require("./BouncingOptions"));
var _MarkerPrototypeExt = _interopRequireDefault(require("./MarkerPrototypeExt"));
var _BouncingMotionCss = _interopRequireDefault(require("./BouncingMotionCss3"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function SmoothMarkerBouncing(Leaflet) {
Leaflet.Marker.include((0, _MarkerPrototypeExt["default"])(Leaflet));
/**
* Registers default options of bouncing animation.
* @param options {BouncingOptions|object} object with options
*/
Leaflet.Marker.setBouncingOptions = function (options) {
Leaflet.Marker.prototype._bouncingOptions = options instanceof _BouncingOptions["default"] ? options : new _BouncingOptions["default"](options);
};
/**
* Returns array of currently bouncing markers.
* @return {Marker[]} array of bouncing markers
*/
Leaflet.Marker.getBouncingMarkers = function () {
return Leaflet.Marker.prototype._orchestration.getBouncingMarkers();
};
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
Leaflet.Marker.stopAllBouncingMarkers = function () {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
Leaflet.Marker.prototype._orchestration.stopAllBouncingMarkers(immediate);
};
Leaflet.Marker.addInitHook(function () {
if (this.isRealMarker()) {
var bouncingOptions = new _BouncingOptions["default"](Leaflet.Marker.prototype._bouncingOptions);
this._bouncingMotion = new _BouncingMotionCss["default"](this, new Leaflet.Point(0, 0), bouncingOptions);
}
});
return Leaflet;
}

View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/** Regex to parse style definitions. */
var regStyle = /([\w-]+): ([^;]+);/g;
var Styles = exports["default"] = /*#__PURE__*/function () {
function Styles(styles) {
_classCallCheck(this, Styles);
styles && Object.assign(this, styles);
}
return _createClass(Styles, [{
key: "findOpacity",
value: function findOpacity(options) {
this.opacity = (options === null || options === void 0 ? void 0 : options.opacityWhenUnclustered // used by cluster plugin
) || (options === null || options === void 0 ? void 0 : options.opacity) || 1;
}
/**
* Creates a copy of styles merged with provided 'styles'.
* @param {Object} styles object with styles to merge
* @return {Styles} copy of styles
*/
}, {
key: "withStyles",
value: function withStyles(styles) {
var copy = new Styles(this);
copy && Object.assign(copy, styles);
return copy;
}
}, {
key: "toString",
value: function toString() {
return Object.entries(this).map(function (entry) {
return "".concat(entry[0], ": ").concat(entry[1], ";");
}).join(' ');
}
/**
* Parses cssText attribute into Styles object.
* @param cssText {string} cssText string
* @return {Styles} Styles object
*/
}], [{
key: "parse",
value: function parse(cssText) {
var styles = {};
var match = regStyle.exec(cssText);
while (match) {
styles[match[1]] = match[2];
match = regStyle.exec(cssText);
}
delete styles['z-index'];
delete styles['opacity'];
styles['outline'] = 'none';
return new Styles(styles);
}
/**
* @param marker {Marker}
*/
}, {
key: "ofMarker",
value: function ofMarker(marker) {
var styles = Styles.parse(marker._icon.style.cssText);
styles.findOpacity(marker.options);
styles['z-index'] = marker._zIndex;
return styles;
}
}]);
}();

View File

@@ -0,0 +1,780 @@
(function (L) {
'use strict';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _assertClassBrand(e, t, n) {
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
throw new TypeError("Private element is not present on this object");
}
function _checkPrivateRedeclaration(e, t) {
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _classPrivateFieldGet2(s, a) {
return s.get(_assertClassBrand(s, a));
}
function _classPrivateFieldInitSpec(e, t, a) {
_checkPrivateRedeclaration(e, t), t.set(e, a);
}
function _classPrivateFieldSet2(s, a, r) {
return s.set(_assertClassBrand(s, a), r), r;
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var BouncingOptions = /*#__PURE__*/function () {
function BouncingOptions(options) {
_classCallCheck(this, BouncingOptions);
/**
* How high marker can bounce (px)
* @type {number}
*/
_defineProperty(this, "bounceHeight", 15);
/**
* How much marker can contract (px)
* @type {number}
*/
_defineProperty(this, "contractHeight", 12);
/**
* Bouncing speed coefficient
* @type {number}
*/
_defineProperty(this, "bounceSpeed", 52);
/**
* Contracting speed coefficient
* @type {number}
*/
_defineProperty(this, "contractSpeed", 52);
/**
* Shadow inclination angle(radians); null to cancel shadow movement
* @type {number}
*/
_defineProperty(this, "shadowAngle", -Math.PI / 4);
/**
* Activate contract animation
* @type {boolean}
*/
_defineProperty(this, "elastic", true);
/**
* Many markers can bounce in the same time
* @type {boolean}
*/
_defineProperty(this, "exclusive", false);
/**
* If true, when marker stops, it does not execute animation until its end, but instead stops
* abruptly.
* @type {boolean}
*/
_defineProperty(this, "immediateStop", false);
options && Object.assign(this, options);
}
return _createClass(BouncingOptions, [{
key: "override",
value: function override(options) {
return Object.assign(new BouncingOptions(this), options);
}
}]);
}();
var _bouncingMarkers = /*#__PURE__*/new WeakMap();
var Orchestration = /*#__PURE__*/function () {
function Orchestration() {
_classCallCheck(this, Orchestration);
_classPrivateFieldInitSpec(this, _bouncingMarkers, []);
}
return _createClass(Orchestration, [{
key: "getBouncingMarkers",
value: function getBouncingMarkers() {
return _classPrivateFieldGet2(_bouncingMarkers, this);
}
/**
* Adds the marker to the list of bouncing markers.
* If flag 'exclusive' is set to true, stops all bouncing markers before.
*
* @param marker {Marker} marker object
* @param exclusive {boolean} flag of exclusive bouncing. If set to true, stops the bouncing
* of all other markers.
*/
}, {
key: "addBouncingMarker",
value: function addBouncingMarker(marker, exclusive) {
if (exclusive || marker._bouncingMotion.bouncingOptions.exclusive) {
this.stopAllBouncingMarkers();
} else {
this.stopExclusiveMarkerBouncing();
}
_classPrivateFieldGet2(_bouncingMarkers, this).push(marker);
}
/**
* Stops the bouncing of exclusive marker.
*/
}, {
key: "stopExclusiveMarkerBouncing",
value: function stopExclusiveMarkerBouncing() {
var exclusiveMarker = _classPrivateFieldGet2(_bouncingMarkers, this).find(function (marker) {
return marker._bouncingMotion.bouncingOptions.exclusive;
});
if (exclusiveMarker) {
exclusiveMarker.stopBouncing();
}
}
/**
* Removes the marker from the list of bouncing markers.
* @param marker {Marker} marker
*/
}, {
key: "removeBouncingMarker",
value: function removeBouncingMarker(marker) {
var i = _classPrivateFieldGet2(_bouncingMarkers, this).indexOf(marker);
if (~i) {
_classPrivateFieldGet2(_bouncingMarkers, this).splice(i, 1);
}
}
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
}, {
key: "stopAllBouncingMarkers",
value: function stopAllBouncingMarkers() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var marker;
while (marker = _classPrivateFieldGet2(_bouncingMarkers, this).shift()) {
marker.stopBouncing(immediate);
}
}
}]);
}();
function MarkerPrototypeExt(Leaflet) {
var oldSetPos = Leaflet.Marker.prototype._setPos;
var oldOnAdd = Leaflet.Marker.prototype.onAdd;
var oldSetIcon = Leaflet.Marker.prototype.setIcon;
return {
/** Bouncing options shared by all markers. */
_bouncingOptions: new BouncingOptions(),
_orchestration: new Orchestration(),
_realMarker: true,
/**
* Registers options of bouncing animation for this marker. After registration of options for
* this marker, it will ignore changes of default options. Function automatically recalculates
* animation steps and delays.
*
* @param options {BouncingOptions} options object
* @return {Marker} this marker
*/
setBouncingOptions: function setBouncingOptions(options) {
this._bouncingMotion.updateBouncingOptions(options);
return this;
},
/**
* Returns true if this marker is bouncing. If this marker is not bouncing returns false.
* @return {boolean} true if marker is bouncing, false if not
*/
isBouncing: function isBouncing() {
return this._bouncingMotion.isBouncing;
},
/**
* Starts bouncing of this marker.
* @param times {number|null} number of times the marker must to bounce
* @return {Marker} this marker
*/
bounce: function bounce() {
var _this = this;
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (times) {
this._bouncingMotion.onMotionEnd = function () {
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(_this);
};
}
this._bouncingMotion.bounce(times);
var exclusive = this._bouncingMotion.bouncingOptions.exclusive;
Leaflet.Marker.prototype._orchestration.addBouncingMarker(this, exclusive);
return this;
},
/**
* Stops bouncing of this marker.
* Note: unless 'immediate' flag is set to true, by the call to this method or in marker options,
* the bouncing will not stop immediately after the call of this method. Instead, the animation
* is executed until marker returns to its original position and takes its full size.
*
* @param immediate {boolean} if true, marker stop to bounce immediately, without waiting
* animation to end
* @return {Marker} this marker
*/
stopBouncing: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this._bouncingMotion.stopBouncing(immediate);
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(this);
return this;
},
/**
* Starts/stops bouncing of this marker.
* @return {Marker} marker
*/
toggleBouncing: function toggleBouncing() {
if (this._bouncingMotion.isBouncing) {
this.stopBouncing();
} else {
this.bounce();
}
return this;
},
isRealMarker: function isRealMarker() {
return Object.hasOwn(this.__proto__, '_realMarker');
},
_setPos: function _setPos(position) {
oldSetPos.call(this, position);
if (this.isRealMarker()) {
this._bouncingMotion.position = position;
this._bouncingMotion.resetStyles(this);
}
},
onAdd: function onAdd(map) {
oldOnAdd.call(this, map);
if (this.isRealMarker()) {
this._bouncingMotion.resetStyles(this);
}
},
setIcon: function setIcon(icon) {
oldSetIcon.call(this, icon);
if (this.isRealMarker() && this._icon) {
this._bouncingMotion.resetStyles(this);
}
}
};
}
/**
* Calculates the points to draw the continous line on the screen. Returns the array of ordered
* point coordinates. Uses Bresenham algorithm.
*
* @param x {number} x coordinate of origin
* @param y {number} y coordinate of origin
* @param angle {number} angle (radians)
* @param length {number} length of line (px)
*
* @return {[number, number][]} array of ordered point coordinates
*
* @see http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
*/
function calculateLine(x, y, angle, length) {
// TODO: use something else than multiply length by 2 to calculate the line with defined
// length
var xD = Math.round(x + Math.cos(angle) * (length * 2)),
yD = Math.round(y + Math.sin(angle) * (length * 2)),
dx = Math.abs(xD - x),
sx = x < xD ? 1 : -1,
dy = Math.abs(yD - y),
sy = y < yD ? 1 : -1,
err = (dx > dy ? dx : -dy) / 2,
e2,
p = [],
i = 0;
while (true) {
p.push([x, y]);
i++;
if (i === length) break;
e2 = err;
if (e2 > -dx) {
err -= dy;
x += sx;
}
if (e2 < dy) {
err += dx;
y += sy;
}
}
return p;
}
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "@keyframes l-smooth-marker-bouncing-move {\n from {\n transform: translate(var(--pos-x), var(--pos-y))\n }\n to {\n transform: translate(var(--pos-x-jump, var(--pos-x)), var(--pos-y-jump))\n }\n}\n\n@keyframes l-smooth-marker-bouncing-contract {\n from {\n transform: translate(var(--pos-x), var(--pos-y))\n }\n to {\n transform: translate(var(--pos-x), var(--pos-y-contract)) scaleY(var(--scale-contract))\n }\n}\n\n.bouncing {\n animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-contract, l-smooth-marker-bouncing-contract;\n animation-direction: normal, reverse, normal, reverse;\n animation-duration: var(--duration-jump), var(--duration-jump), var(--duration-contract), var(--duration-contract);\n animation-delay: var(--delays)\n}\n\n.bouncing.simple {\n animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move;\n animation-direction: normal, reverse;\n animation-duration: var(--duration-jump), var(--duration-jump);\n animation-delay: var(--delays)\n}\n";
styleInject(css_248z);
/** Regex to parse style definitions. */
var regStyle = /([\w-]+): ([^;]+);/g;
var Styles = /*#__PURE__*/function () {
function Styles(styles) {
_classCallCheck(this, Styles);
styles && Object.assign(this, styles);
}
return _createClass(Styles, [{
key: "findOpacity",
value: function findOpacity(options) {
this.opacity = (options === null || options === void 0 ? void 0 : options.opacityWhenUnclustered // used by cluster plugin
) || (options === null || options === void 0 ? void 0 : options.opacity) || 1;
}
/**
* Creates a copy of styles merged with provided 'styles'.
* @param {Object} styles object with styles to merge
* @return {Styles} copy of styles
*/
}, {
key: "withStyles",
value: function withStyles(styles) {
var copy = new Styles(this);
copy && Object.assign(copy, styles);
return copy;
}
}, {
key: "toString",
value: function toString() {
return Object.entries(this).map(function (entry) {
return "".concat(entry[0], ": ").concat(entry[1], ";");
}).join(' ');
}
/**
* Parses cssText attribute into Styles object.
* @param cssText {string} cssText string
* @return {Styles} Styles object
*/
}], [{
key: "parse",
value: function parse(cssText) {
var styles = {};
var match = regStyle.exec(cssText);
while (match) {
styles[match[1]] = match[2];
match = regStyle.exec(cssText);
}
delete styles['z-index'];
delete styles['opacity'];
styles['outline'] = 'none';
return new Styles(styles);
}
/**
* @param marker {Marker}
*/
}, {
key: "ofMarker",
value: function ofMarker(marker) {
var styles = Styles.parse(marker._icon.style.cssText);
styles.findOpacity(marker.options);
styles['z-index'] = marker._zIndex;
return styles;
}
}]);
}();
var animationNamePrefix = 'l-smooth-marker-bouncing-';
var moveAnimationName = animationNamePrefix + 'move';
var contractAnimationName = animationNamePrefix + 'contract';
/*
* CSS3 animation runs faster than transform-based animation. We need to reduce speed in order
* to be compatible with old API.
*/
var speedCoefficient = 0.8;
/**
* Removes and then resets required classes on the HTML element.
* Used as hack to restart CSS3 animation.
*
* @param element {HTMLElement} HTML element
* @param classes {string[]} names of classes
*/
function resetClasses(element, classes) {
classes.forEach(function (className) {
return L.DomUtil.removeClass(element, className);
});
void element.offsetWidth;
classes.forEach(function (className) {
return L.DomUtil.addClass(element, className);
});
}
var _lastAnimationName = /*#__PURE__*/new WeakMap();
var _classes = /*#__PURE__*/new WeakMap();
var _eventCounter = /*#__PURE__*/new WeakMap();
var _times = /*#__PURE__*/new WeakMap();
var _listener = /*#__PURE__*/new WeakMap();
var BouncingMotionCss3 = /*#__PURE__*/function () {
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotionCss3(marker, position, bouncingOptions) {
var _this = this;
_classCallCheck(this, BouncingMotionCss3);
_defineProperty(this, "marker", void 0);
_defineProperty(this, "position", void 0);
_defineProperty(this, "bouncingOptions", void 0);
_defineProperty(this, "isBouncing", false);
_defineProperty(this, "iconStyles", void 0);
_defineProperty(this, "shadowStyles", void 0);
_defineProperty(this, "bouncingAnimationPlaying", false);
_defineProperty(this, "onMotionEnd", void 0);
_classPrivateFieldInitSpec(this, _lastAnimationName, contractAnimationName);
_classPrivateFieldInitSpec(this, _classes, ['bouncing']);
_classPrivateFieldInitSpec(this, _eventCounter, void 0);
_classPrivateFieldInitSpec(this, _times, void 0);
_classPrivateFieldInitSpec(this, _listener, function (event) {
return _this.onAnimationEnd(event);
});
this.marker = marker;
this.position = position;
this.updateBouncingOptions(bouncingOptions);
}
return _createClass(BouncingMotionCss3, [{
key: "updateBouncingOptions",
value: function updateBouncingOptions(options) {
this.bouncingOptions = options instanceof BouncingOptions ? options : this.bouncingOptions.override(options);
if (this.bouncingOptions.elastic && this.bouncingOptions.contractHeight) {
_classPrivateFieldSet2(_lastAnimationName, this, contractAnimationName);
var index = _classPrivateFieldGet2(_classes, this).indexOf('simple');
if (index > -1) {
_classPrivateFieldGet2(_classes, this).splice(index, 1);
}
if (this.marker._icon) {
L.DomUtil.removeClass(this.marker._icon, 'simple');
}
} else {
_classPrivateFieldSet2(_lastAnimationName, this, moveAnimationName);
_classPrivateFieldGet2(_classes, this).push('simple');
}
if (this.marker._icon) {
this.resetStyles(this.marker);
}
}
}, {
key: "onAnimationEnd",
value: function onAnimationEnd(event) {
if (event.animationName === _classPrivateFieldGet2(_lastAnimationName, this)) {
var _this$eventCounter;
_classPrivateFieldSet2(_eventCounter, this, (_this$eventCounter = _classPrivateFieldGet2(_eventCounter, this), _this$eventCounter++, _this$eventCounter));
_classPrivateFieldSet2(_eventCounter, this, _classPrivateFieldGet2(_eventCounter, this) % 2);
if (!_classPrivateFieldGet2(_eventCounter, this)) {
var _this$times;
if (this.isBouncing && (_classPrivateFieldGet2(_times, this) === null || _classPrivateFieldSet2(_times, this, (_this$times = _classPrivateFieldGet2(_times, this), --_this$times)))) {
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
} else {
this._stopBouncingAnimation();
}
}
}
}
}, {
key: "resetStyles",
value: function resetStyles(marker) {
var _this$marker$getIcon,
_this$marker,
_this2 = this;
this.marker = marker;
this.iconStyles = Styles.ofMarker(marker);
if (marker._shadow) {
this.shadowStyles = Styles.parse(marker._shadow.style.cssText);
}
var iconHeight = ((_this$marker$getIcon = this.marker.getIcon()) === null || _this$marker$getIcon === void 0 || (_this$marker$getIcon = _this$marker$getIcon.options) === null || _this$marker$getIcon === void 0 ? void 0 : _this$marker$getIcon.iconSize[1]) || ((_this$marker = this.marker) === null || _this$marker === void 0 || (_this$marker = _this$marker._iconObj) === null || _this$marker === void 0 || (_this$marker = _this$marker.options) === null || _this$marker === void 0 ? void 0 : _this$marker.iconSize[1]);
var iconAnimationParams = BouncingMotionCss3.animationParams(this.position, this.bouncingOptions, iconHeight);
this.iconStyles = this.iconStyles.withStyles(iconAnimationParams);
this.marker._icon.style.cssText = this.iconStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet2(_listener, this));
}
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
contractHeight = _this$bouncingOptions.contractHeight,
shadowAngle = _this$bouncingOptions.shadowAngle;
if (this.marker._shadow) {
if (shadowAngle) {
var _this$marker$getIcon2;
var _this$position = this.position,
x = _this$position.x,
y = _this$position.y;
var points = calculateLine(x, y, shadowAngle, bounceHeight + 1);
var _points$bounceHeight = _slicedToArray(points[bounceHeight], 2),
posXJump = _points$bounceHeight[0],
posYJump = _points$bounceHeight[1];
var shadowHeight = (_this$marker$getIcon2 = this.marker.getIcon()) === null || _this$marker$getIcon2 === void 0 || (_this$marker$getIcon2 = _this$marker$getIcon2.options) === null || _this$marker$getIcon2 === void 0 ? void 0 : _this$marker$getIcon2.shadowSize[1];
var shadowScaleContract = BouncingMotionCss3.contractScale(shadowHeight, contractHeight);
this.shadowStyles = this.shadowStyles.withStyles(iconAnimationParams).withStyles({
'--pos-x-jump': "".concat(posXJump, "px"),
'--pos-y-jump': "".concat(posYJump, "px"),
'--scale-contract': shadowScaleContract
});
this.marker._shadow.style.cssText = this.shadowStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
} else {
_classPrivateFieldGet2(_classes, this).forEach(function (className) {
L.DomUtil.removeClass(_this2.marker._shadow, className);
});
}
}
}
}, {
key: "bounce",
value: function bounce() {
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
_classPrivateFieldSet2(_times, this, times);
this.isBouncing = true;
if (this.bouncingAnimationPlaying) {
return;
}
_classPrivateFieldSet2(_eventCounter, this, 0);
this.bouncingAnimationPlaying = true;
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet2(_listener, this));
}
}, {
key: "stopBouncing",
value: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this.isBouncing = false;
immediate || (immediate = this.bouncingOptions.immediateStop);
if (immediate) {
this._stopBouncingAnimation();
}
}
}, {
key: "_stopBouncingAnimation",
value: function _stopBouncingAnimation() {
var _this3 = this;
_classPrivateFieldGet2(_classes, this).forEach(function (className) {
L.DomUtil.removeClass(_this3.marker._icon, className);
if (_this3.marker._shadow) {
L.DomUtil.removeClass(_this3.marker._shadow, className);
}
});
this.bouncingAnimationPlaying = false;
if (this.onMotionEnd) {
this.onMotionEnd();
this.onMotionEnd = null;
}
this.marker.fire('bounceend');
}
/**
* Calculates parameters of CSS3 animation of bouncing.
*
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
* @param height {number} icons height
* @return {object} CSS3 animation parameters
*/
}], [{
key: "animationParams",
value: function animationParams(position, bouncingOptions, height) {
var x = position.x,
y = position.y;
var bounceHeight = bouncingOptions.bounceHeight,
contractHeight = bouncingOptions.contractHeight,
bounceSpeed = bouncingOptions.bounceSpeed,
contractSpeed = bouncingOptions.contractSpeed;
var scaleContract = BouncingMotionCss3.contractScale(height, contractHeight);
var durationJump = BouncingMotionCss3.calculateDuration(bounceHeight, bounceSpeed);
var durationContract = BouncingMotionCss3.calculateDuration(contractHeight, contractSpeed);
var delays = [0, durationJump, durationJump * 2, durationJump * 2 + durationContract];
return {
'--pos-x': "".concat(x, "px"),
'--pos-y': "".concat(y, "px"),
'--pos-y-jump': "".concat(y - bounceHeight, "px"),
'--pos-y-contract': "".concat(y + contractHeight, "px"),
'--scale-contract': scaleContract,
'--duration-jump': "".concat(durationJump, "ms"),
'--duration-contract': "".concat(durationContract, "ms"),
'--delays': "0ms, ".concat(delays[1], "ms, ").concat(delays[2], "ms, ").concat(delays[3], "ms")
};
}
/**
* Calculates scale of contracting.
*
* @param {number} height original height
* @param {number} contractHeight how much it must contract
* @return {number} contracting scale between 0 and 1
*/
}, {
key: "contractScale",
value: function contractScale(height, contractHeight) {
return (height - contractHeight) / height;
}
/**
* Calculates duration of animation.
*
* @param height {number} height of movement or resizing (px)
* @param speed {number} speed coefficient
*
* @return {number} duration of animation (ms)
*/
}, {
key: "calculateDuration",
value: function calculateDuration(height, speed) {
if (height === 0) {
return 0;
}
var duration = Math.round(speed * speedCoefficient);
var i = height;
while (--i) {
duration += Math.round(speed / (height - i));
}
return duration;
}
}]);
}();
function SmoothMarkerBouncing(Leaflet) {
Leaflet.Marker.include(MarkerPrototypeExt(Leaflet));
/**
* Registers default options of bouncing animation.
* @param options {BouncingOptions|object} object with options
*/
Leaflet.Marker.setBouncingOptions = function (options) {
Leaflet.Marker.prototype._bouncingOptions = options instanceof BouncingOptions ? options : new BouncingOptions(options);
};
/**
* Returns array of currently bouncing markers.
* @return {Marker[]} array of bouncing markers
*/
Leaflet.Marker.getBouncingMarkers = function () {
return Leaflet.Marker.prototype._orchestration.getBouncingMarkers();
};
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
Leaflet.Marker.stopAllBouncingMarkers = function () {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
Leaflet.Marker.prototype._orchestration.stopAllBouncingMarkers(immediate);
};
Leaflet.Marker.addInitHook(function () {
if (this.isRealMarker()) {
var bouncingOptions = new BouncingOptions(Leaflet.Marker.prototype._bouncingOptions);
this._bouncingMotion = new BouncingMotionCss3(this, new Leaflet.Point(0, 0), bouncingOptions);
}
});
return Leaflet;
}
SmoothMarkerBouncing(L);
})(L);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,777 @@
import { DomUtil } from 'leaflet';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _assertClassBrand(e, t, n) {
if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n;
throw new TypeError("Private element is not present on this object");
}
function _checkPrivateRedeclaration(e, t) {
if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object");
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _classPrivateFieldGet2(s, a) {
return s.get(_assertClassBrand(s, a));
}
function _classPrivateFieldInitSpec(e, t, a) {
_checkPrivateRedeclaration(e, t), t.set(e, a);
}
function _classPrivateFieldSet2(s, a, r) {
return s.set(_assertClassBrand(s, a), r), r;
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var BouncingOptions = /*#__PURE__*/function () {
function BouncingOptions(options) {
_classCallCheck(this, BouncingOptions);
/**
* How high marker can bounce (px)
* @type {number}
*/
_defineProperty(this, "bounceHeight", 15);
/**
* How much marker can contract (px)
* @type {number}
*/
_defineProperty(this, "contractHeight", 12);
/**
* Bouncing speed coefficient
* @type {number}
*/
_defineProperty(this, "bounceSpeed", 52);
/**
* Contracting speed coefficient
* @type {number}
*/
_defineProperty(this, "contractSpeed", 52);
/**
* Shadow inclination angle(radians); null to cancel shadow movement
* @type {number}
*/
_defineProperty(this, "shadowAngle", -Math.PI / 4);
/**
* Activate contract animation
* @type {boolean}
*/
_defineProperty(this, "elastic", true);
/**
* Many markers can bounce in the same time
* @type {boolean}
*/
_defineProperty(this, "exclusive", false);
/**
* If true, when marker stops, it does not execute animation until its end, but instead stops
* abruptly.
* @type {boolean}
*/
_defineProperty(this, "immediateStop", false);
options && Object.assign(this, options);
}
return _createClass(BouncingOptions, [{
key: "override",
value: function override(options) {
return Object.assign(new BouncingOptions(this), options);
}
}]);
}();
var _bouncingMarkers = /*#__PURE__*/new WeakMap();
var Orchestration = /*#__PURE__*/function () {
function Orchestration() {
_classCallCheck(this, Orchestration);
_classPrivateFieldInitSpec(this, _bouncingMarkers, []);
}
return _createClass(Orchestration, [{
key: "getBouncingMarkers",
value: function getBouncingMarkers() {
return _classPrivateFieldGet2(_bouncingMarkers, this);
}
/**
* Adds the marker to the list of bouncing markers.
* If flag 'exclusive' is set to true, stops all bouncing markers before.
*
* @param marker {Marker} marker object
* @param exclusive {boolean} flag of exclusive bouncing. If set to true, stops the bouncing
* of all other markers.
*/
}, {
key: "addBouncingMarker",
value: function addBouncingMarker(marker, exclusive) {
if (exclusive || marker._bouncingMotion.bouncingOptions.exclusive) {
this.stopAllBouncingMarkers();
} else {
this.stopExclusiveMarkerBouncing();
}
_classPrivateFieldGet2(_bouncingMarkers, this).push(marker);
}
/**
* Stops the bouncing of exclusive marker.
*/
}, {
key: "stopExclusiveMarkerBouncing",
value: function stopExclusiveMarkerBouncing() {
var exclusiveMarker = _classPrivateFieldGet2(_bouncingMarkers, this).find(function (marker) {
return marker._bouncingMotion.bouncingOptions.exclusive;
});
if (exclusiveMarker) {
exclusiveMarker.stopBouncing();
}
}
/**
* Removes the marker from the list of bouncing markers.
* @param marker {Marker} marker
*/
}, {
key: "removeBouncingMarker",
value: function removeBouncingMarker(marker) {
var i = _classPrivateFieldGet2(_bouncingMarkers, this).indexOf(marker);
if (~i) {
_classPrivateFieldGet2(_bouncingMarkers, this).splice(i, 1);
}
}
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
}, {
key: "stopAllBouncingMarkers",
value: function stopAllBouncingMarkers() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var marker;
while (marker = _classPrivateFieldGet2(_bouncingMarkers, this).shift()) {
marker.stopBouncing(immediate);
}
}
}]);
}();
function MarkerPrototypeExt(Leaflet) {
var oldSetPos = Leaflet.Marker.prototype._setPos;
var oldOnAdd = Leaflet.Marker.prototype.onAdd;
var oldSetIcon = Leaflet.Marker.prototype.setIcon;
return {
/** Bouncing options shared by all markers. */
_bouncingOptions: new BouncingOptions(),
_orchestration: new Orchestration(),
_realMarker: true,
/**
* Registers options of bouncing animation for this marker. After registration of options for
* this marker, it will ignore changes of default options. Function automatically recalculates
* animation steps and delays.
*
* @param options {BouncingOptions} options object
* @return {Marker} this marker
*/
setBouncingOptions: function setBouncingOptions(options) {
this._bouncingMotion.updateBouncingOptions(options);
return this;
},
/**
* Returns true if this marker is bouncing. If this marker is not bouncing returns false.
* @return {boolean} true if marker is bouncing, false if not
*/
isBouncing: function isBouncing() {
return this._bouncingMotion.isBouncing;
},
/**
* Starts bouncing of this marker.
* @param times {number|null} number of times the marker must to bounce
* @return {Marker} this marker
*/
bounce: function bounce() {
var _this = this;
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
if (times) {
this._bouncingMotion.onMotionEnd = function () {
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(_this);
};
}
this._bouncingMotion.bounce(times);
var exclusive = this._bouncingMotion.bouncingOptions.exclusive;
Leaflet.Marker.prototype._orchestration.addBouncingMarker(this, exclusive);
return this;
},
/**
* Stops bouncing of this marker.
* Note: unless 'immediate' flag is set to true, by the call to this method or in marker options,
* the bouncing will not stop immediately after the call of this method. Instead, the animation
* is executed until marker returns to its original position and takes its full size.
*
* @param immediate {boolean} if true, marker stop to bounce immediately, without waiting
* animation to end
* @return {Marker} this marker
*/
stopBouncing: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this._bouncingMotion.stopBouncing(immediate);
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(this);
return this;
},
/**
* Starts/stops bouncing of this marker.
* @return {Marker} marker
*/
toggleBouncing: function toggleBouncing() {
if (this._bouncingMotion.isBouncing) {
this.stopBouncing();
} else {
this.bounce();
}
return this;
},
isRealMarker: function isRealMarker() {
return Object.hasOwn(this.__proto__, '_realMarker');
},
_setPos: function _setPos(position) {
oldSetPos.call(this, position);
if (this.isRealMarker()) {
this._bouncingMotion.position = position;
this._bouncingMotion.resetStyles(this);
}
},
onAdd: function onAdd(map) {
oldOnAdd.call(this, map);
if (this.isRealMarker()) {
this._bouncingMotion.resetStyles(this);
}
},
setIcon: function setIcon(icon) {
oldSetIcon.call(this, icon);
if (this.isRealMarker() && this._icon) {
this._bouncingMotion.resetStyles(this);
}
}
};
}
/**
* Calculates the points to draw the continous line on the screen. Returns the array of ordered
* point coordinates. Uses Bresenham algorithm.
*
* @param x {number} x coordinate of origin
* @param y {number} y coordinate of origin
* @param angle {number} angle (radians)
* @param length {number} length of line (px)
*
* @return {[number, number][]} array of ordered point coordinates
*
* @see http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
*/
function calculateLine(x, y, angle, length) {
// TODO: use something else than multiply length by 2 to calculate the line with defined
// length
var xD = Math.round(x + Math.cos(angle) * (length * 2)),
yD = Math.round(y + Math.sin(angle) * (length * 2)),
dx = Math.abs(xD - x),
sx = x < xD ? 1 : -1,
dy = Math.abs(yD - y),
sy = y < yD ? 1 : -1,
err = (dx > dy ? dx : -dy) / 2,
e2,
p = [],
i = 0;
while (true) {
p.push([x, y]);
i++;
if (i === length) break;
e2 = err;
if (e2 > -dx) {
err -= dy;
x += sx;
}
if (e2 < dy) {
err += dx;
y += sy;
}
}
return p;
}
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = "@keyframes l-smooth-marker-bouncing-move {\n from {\n transform: translate(var(--pos-x), var(--pos-y))\n }\n to {\n transform: translate(var(--pos-x-jump, var(--pos-x)), var(--pos-y-jump))\n }\n}\n\n@keyframes l-smooth-marker-bouncing-contract {\n from {\n transform: translate(var(--pos-x), var(--pos-y))\n }\n to {\n transform: translate(var(--pos-x), var(--pos-y-contract)) scaleY(var(--scale-contract))\n }\n}\n\n.bouncing {\n animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-contract, l-smooth-marker-bouncing-contract;\n animation-direction: normal, reverse, normal, reverse;\n animation-duration: var(--duration-jump), var(--duration-jump), var(--duration-contract), var(--duration-contract);\n animation-delay: var(--delays)\n}\n\n.bouncing.simple {\n animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move;\n animation-direction: normal, reverse;\n animation-duration: var(--duration-jump), var(--duration-jump);\n animation-delay: var(--delays)\n}\n";
styleInject(css_248z);
/** Regex to parse style definitions. */
var regStyle = /([\w-]+): ([^;]+);/g;
var Styles = /*#__PURE__*/function () {
function Styles(styles) {
_classCallCheck(this, Styles);
styles && Object.assign(this, styles);
}
return _createClass(Styles, [{
key: "findOpacity",
value: function findOpacity(options) {
this.opacity = (options === null || options === void 0 ? void 0 : options.opacityWhenUnclustered // used by cluster plugin
) || (options === null || options === void 0 ? void 0 : options.opacity) || 1;
}
/**
* Creates a copy of styles merged with provided 'styles'.
* @param {Object} styles object with styles to merge
* @return {Styles} copy of styles
*/
}, {
key: "withStyles",
value: function withStyles(styles) {
var copy = new Styles(this);
copy && Object.assign(copy, styles);
return copy;
}
}, {
key: "toString",
value: function toString() {
return Object.entries(this).map(function (entry) {
return "".concat(entry[0], ": ").concat(entry[1], ";");
}).join(' ');
}
/**
* Parses cssText attribute into Styles object.
* @param cssText {string} cssText string
* @return {Styles} Styles object
*/
}], [{
key: "parse",
value: function parse(cssText) {
var styles = {};
var match = regStyle.exec(cssText);
while (match) {
styles[match[1]] = match[2];
match = regStyle.exec(cssText);
}
delete styles['z-index'];
delete styles['opacity'];
styles['outline'] = 'none';
return new Styles(styles);
}
/**
* @param marker {Marker}
*/
}, {
key: "ofMarker",
value: function ofMarker(marker) {
var styles = Styles.parse(marker._icon.style.cssText);
styles.findOpacity(marker.options);
styles['z-index'] = marker._zIndex;
return styles;
}
}]);
}();
var animationNamePrefix = 'l-smooth-marker-bouncing-';
var moveAnimationName = animationNamePrefix + 'move';
var contractAnimationName = animationNamePrefix + 'contract';
/*
* CSS3 animation runs faster than transform-based animation. We need to reduce speed in order
* to be compatible with old API.
*/
var speedCoefficient = 0.8;
/**
* Removes and then resets required classes on the HTML element.
* Used as hack to restart CSS3 animation.
*
* @param element {HTMLElement} HTML element
* @param classes {string[]} names of classes
*/
function resetClasses(element, classes) {
classes.forEach(function (className) {
return DomUtil.removeClass(element, className);
});
void element.offsetWidth;
classes.forEach(function (className) {
return DomUtil.addClass(element, className);
});
}
var _lastAnimationName = /*#__PURE__*/new WeakMap();
var _classes = /*#__PURE__*/new WeakMap();
var _eventCounter = /*#__PURE__*/new WeakMap();
var _times = /*#__PURE__*/new WeakMap();
var _listener = /*#__PURE__*/new WeakMap();
var BouncingMotionCss3 = /*#__PURE__*/function () {
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
function BouncingMotionCss3(marker, position, bouncingOptions) {
var _this = this;
_classCallCheck(this, BouncingMotionCss3);
_defineProperty(this, "marker", void 0);
_defineProperty(this, "position", void 0);
_defineProperty(this, "bouncingOptions", void 0);
_defineProperty(this, "isBouncing", false);
_defineProperty(this, "iconStyles", void 0);
_defineProperty(this, "shadowStyles", void 0);
_defineProperty(this, "bouncingAnimationPlaying", false);
_defineProperty(this, "onMotionEnd", void 0);
_classPrivateFieldInitSpec(this, _lastAnimationName, contractAnimationName);
_classPrivateFieldInitSpec(this, _classes, ['bouncing']);
_classPrivateFieldInitSpec(this, _eventCounter, void 0);
_classPrivateFieldInitSpec(this, _times, void 0);
_classPrivateFieldInitSpec(this, _listener, function (event) {
return _this.onAnimationEnd(event);
});
this.marker = marker;
this.position = position;
this.updateBouncingOptions(bouncingOptions);
}
return _createClass(BouncingMotionCss3, [{
key: "updateBouncingOptions",
value: function updateBouncingOptions(options) {
this.bouncingOptions = options instanceof BouncingOptions ? options : this.bouncingOptions.override(options);
if (this.bouncingOptions.elastic && this.bouncingOptions.contractHeight) {
_classPrivateFieldSet2(_lastAnimationName, this, contractAnimationName);
var index = _classPrivateFieldGet2(_classes, this).indexOf('simple');
if (index > -1) {
_classPrivateFieldGet2(_classes, this).splice(index, 1);
}
if (this.marker._icon) {
DomUtil.removeClass(this.marker._icon, 'simple');
}
} else {
_classPrivateFieldSet2(_lastAnimationName, this, moveAnimationName);
_classPrivateFieldGet2(_classes, this).push('simple');
}
if (this.marker._icon) {
this.resetStyles(this.marker);
}
}
}, {
key: "onAnimationEnd",
value: function onAnimationEnd(event) {
if (event.animationName === _classPrivateFieldGet2(_lastAnimationName, this)) {
var _this$eventCounter;
_classPrivateFieldSet2(_eventCounter, this, (_this$eventCounter = _classPrivateFieldGet2(_eventCounter, this), _this$eventCounter++, _this$eventCounter));
_classPrivateFieldSet2(_eventCounter, this, _classPrivateFieldGet2(_eventCounter, this) % 2);
if (!_classPrivateFieldGet2(_eventCounter, this)) {
var _this$times;
if (this.isBouncing && (_classPrivateFieldGet2(_times, this) === null || _classPrivateFieldSet2(_times, this, (_this$times = _classPrivateFieldGet2(_times, this), --_this$times)))) {
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
} else {
this._stopBouncingAnimation();
}
}
}
}
}, {
key: "resetStyles",
value: function resetStyles(marker) {
var _this$marker$getIcon,
_this$marker,
_this2 = this;
this.marker = marker;
this.iconStyles = Styles.ofMarker(marker);
if (marker._shadow) {
this.shadowStyles = Styles.parse(marker._shadow.style.cssText);
}
var iconHeight = ((_this$marker$getIcon = this.marker.getIcon()) === null || _this$marker$getIcon === void 0 || (_this$marker$getIcon = _this$marker$getIcon.options) === null || _this$marker$getIcon === void 0 ? void 0 : _this$marker$getIcon.iconSize[1]) || ((_this$marker = this.marker) === null || _this$marker === void 0 || (_this$marker = _this$marker._iconObj) === null || _this$marker === void 0 || (_this$marker = _this$marker.options) === null || _this$marker === void 0 ? void 0 : _this$marker.iconSize[1]);
var iconAnimationParams = BouncingMotionCss3.animationParams(this.position, this.bouncingOptions, iconHeight);
this.iconStyles = this.iconStyles.withStyles(iconAnimationParams);
this.marker._icon.style.cssText = this.iconStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet2(_listener, this));
}
var _this$bouncingOptions = this.bouncingOptions,
bounceHeight = _this$bouncingOptions.bounceHeight,
contractHeight = _this$bouncingOptions.contractHeight,
shadowAngle = _this$bouncingOptions.shadowAngle;
if (this.marker._shadow) {
if (shadowAngle) {
var _this$marker$getIcon2;
var _this$position = this.position,
x = _this$position.x,
y = _this$position.y;
var points = calculateLine(x, y, shadowAngle, bounceHeight + 1);
var _points$bounceHeight = _slicedToArray(points[bounceHeight], 2),
posXJump = _points$bounceHeight[0],
posYJump = _points$bounceHeight[1];
var shadowHeight = (_this$marker$getIcon2 = this.marker.getIcon()) === null || _this$marker$getIcon2 === void 0 || (_this$marker$getIcon2 = _this$marker$getIcon2.options) === null || _this$marker$getIcon2 === void 0 ? void 0 : _this$marker$getIcon2.shadowSize[1];
var shadowScaleContract = BouncingMotionCss3.contractScale(shadowHeight, contractHeight);
this.shadowStyles = this.shadowStyles.withStyles(iconAnimationParams).withStyles({
'--pos-x-jump': "".concat(posXJump, "px"),
'--pos-y-jump': "".concat(posYJump, "px"),
'--scale-contract': shadowScaleContract
});
this.marker._shadow.style.cssText = this.shadowStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
} else {
_classPrivateFieldGet2(_classes, this).forEach(function (className) {
DomUtil.removeClass(_this2.marker._shadow, className);
});
}
}
}
}, {
key: "bounce",
value: function bounce() {
var times = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
_classPrivateFieldSet2(_times, this, times);
this.isBouncing = true;
if (this.bouncingAnimationPlaying) {
return;
}
_classPrivateFieldSet2(_eventCounter, this, 0);
this.bouncingAnimationPlaying = true;
resetClasses(this.marker._icon, _classPrivateFieldGet2(_classes, this));
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, _classPrivateFieldGet2(_classes, this));
}
this.marker._icon.addEventListener('animationend', _classPrivateFieldGet2(_listener, this));
}
}, {
key: "stopBouncing",
value: function stopBouncing() {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
this.isBouncing = false;
immediate || (immediate = this.bouncingOptions.immediateStop);
if (immediate) {
this._stopBouncingAnimation();
}
}
}, {
key: "_stopBouncingAnimation",
value: function _stopBouncingAnimation() {
var _this3 = this;
_classPrivateFieldGet2(_classes, this).forEach(function (className) {
DomUtil.removeClass(_this3.marker._icon, className);
if (_this3.marker._shadow) {
DomUtil.removeClass(_this3.marker._shadow, className);
}
});
this.bouncingAnimationPlaying = false;
if (this.onMotionEnd) {
this.onMotionEnd();
this.onMotionEnd = null;
}
this.marker.fire('bounceend');
}
/**
* Calculates parameters of CSS3 animation of bouncing.
*
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
* @param height {number} icons height
* @return {object} CSS3 animation parameters
*/
}], [{
key: "animationParams",
value: function animationParams(position, bouncingOptions, height) {
var x = position.x,
y = position.y;
var bounceHeight = bouncingOptions.bounceHeight,
contractHeight = bouncingOptions.contractHeight,
bounceSpeed = bouncingOptions.bounceSpeed,
contractSpeed = bouncingOptions.contractSpeed;
var scaleContract = BouncingMotionCss3.contractScale(height, contractHeight);
var durationJump = BouncingMotionCss3.calculateDuration(bounceHeight, bounceSpeed);
var durationContract = BouncingMotionCss3.calculateDuration(contractHeight, contractSpeed);
var delays = [0, durationJump, durationJump * 2, durationJump * 2 + durationContract];
return {
'--pos-x': "".concat(x, "px"),
'--pos-y': "".concat(y, "px"),
'--pos-y-jump': "".concat(y - bounceHeight, "px"),
'--pos-y-contract': "".concat(y + contractHeight, "px"),
'--scale-contract': scaleContract,
'--duration-jump': "".concat(durationJump, "ms"),
'--duration-contract': "".concat(durationContract, "ms"),
'--delays': "0ms, ".concat(delays[1], "ms, ").concat(delays[2], "ms, ").concat(delays[3], "ms")
};
}
/**
* Calculates scale of contracting.
*
* @param {number} height original height
* @param {number} contractHeight how much it must contract
* @return {number} contracting scale between 0 and 1
*/
}, {
key: "contractScale",
value: function contractScale(height, contractHeight) {
return (height - contractHeight) / height;
}
/**
* Calculates duration of animation.
*
* @param height {number} height of movement or resizing (px)
* @param speed {number} speed coefficient
*
* @return {number} duration of animation (ms)
*/
}, {
key: "calculateDuration",
value: function calculateDuration(height, speed) {
if (height === 0) {
return 0;
}
var duration = Math.round(speed * speedCoefficient);
var i = height;
while (--i) {
duration += Math.round(speed / (height - i));
}
return duration;
}
}]);
}();
function SmoothMarkerBouncing(Leaflet) {
Leaflet.Marker.include(MarkerPrototypeExt(Leaflet));
/**
* Registers default options of bouncing animation.
* @param options {BouncingOptions|object} object with options
*/
Leaflet.Marker.setBouncingOptions = function (options) {
Leaflet.Marker.prototype._bouncingOptions = options instanceof BouncingOptions ? options : new BouncingOptions(options);
};
/**
* Returns array of currently bouncing markers.
* @return {Marker[]} array of bouncing markers
*/
Leaflet.Marker.getBouncingMarkers = function () {
return Leaflet.Marker.prototype._orchestration.getBouncingMarkers();
};
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
Leaflet.Marker.stopAllBouncingMarkers = function () {
var immediate = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
Leaflet.Marker.prototype._orchestration.stopAllBouncingMarkers(immediate);
};
Leaflet.Marker.addInitHook(function () {
if (this.isRealMarker()) {
var bouncingOptions = new BouncingOptions(Leaflet.Marker.prototype._bouncingOptions);
this._bouncingMotion = new BouncingMotionCss3(this, new Leaflet.Point(0, 0), bouncingOptions);
}
});
return Leaflet;
}
export { SmoothMarkerBouncing as default };

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var _SmoothMarkerBouncing = require("./SmoothMarkerBouncing");
var _default = exports["default"] = _SmoothMarkerBouncing.SmoothMarkerBouncing;

View File

@@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.calculateLine = calculateLine;
/**
* Calculates the points to draw the continous line on the screen. Returns the array of ordered
* point coordinates. Uses Bresenham algorithm.
*
* @param x {number} x coordinate of origin
* @param y {number} y coordinate of origin
* @param angle {number} angle (radians)
* @param length {number} length of line (px)
*
* @return {[number, number][]} array of ordered point coordinates
*
* @see http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
*/
function calculateLine(x, y, angle, length) {
// TODO: use something else than multiply length by 2 to calculate the line with defined
// length
var xD = Math.round(x + Math.cos(angle) * (length * 2)),
yD = Math.round(y + Math.sin(angle) * (length * 2)),
dx = Math.abs(xD - x),
sx = x < xD ? 1 : -1,
dy = Math.abs(yD - y),
sy = y < yD ? 1 : -1,
err = (dx > dy ? dx : -dy) / 2,
e2,
p = [],
i = 0;
while (true) {
p.push([x, y]);
i++;
if (i === length) break;
e2 = err;
if (e2 > -dx) {
err -= dy;
x += sx;
}
if (e2 < dy) {
err += dx;
y += sy;
}
}
return p;
}

View File

@@ -0,0 +1,6 @@
"use strict";
var _leaflet = _interopRequireDefault(require("leaflet"));
var _SmoothMarkerBouncing = _interopRequireDefault(require("./SmoothMarkerBouncing"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
(0, _SmoothMarkerBouncing["default"])(_leaflet["default"]);

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

114
node_modules/leaflet.smooth_marker_bouncing/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,114 @@
import Leaflet, {Marker} from 'leaflet';
export interface BouncingOptions {
/**
* How high marker can bounce (px)
*/
bounceHeight?: number;
/**
* How much marker can contract (px)
*/
contractHeight?: number;
/**
* Bouncing speed coefficient
*/
bounceSpeed?: number;
/**
* Contracting speed coefficient
*/
contractSpeed?: number;
/**
* Shadow inclination angle(radians); null to cancel shadow movement
*/
shadowAngle?: number;
/**
* Activate contract animation
*/
elastic?: boolean;
/**
* Many markers can bounce in the same time
*/
exclusive?: boolean;
/**
* If true, when marker stops, it does not execute animation until its end, but instead stops
* abruptly.
*/
immediateStop?: boolean;
}
export class BouncingMarker extends Marker {
/**
* Registers options of bouncing animation for this marker. After registration of options for
* this marker, it will ignore changes of default options. Function automatically recalculates
* animation steps and delays.
*
* @param options {BouncingOptions} options object
* @return {Marker} this marker
*/
setBouncingOptions(options: BouncingOptions);
/**
* Returns true if this marker is bouncing. If this marker is not bouncing returns false.
* @return {boolean} true if marker is bouncing, false if not
*/
isBouncing(): boolean;
/**
* Starts bouncing of this marker.
* @param times {number|null} number of times the marker must to bounce
* @return {Marker} this marker
*/
bounce(times?: number);
/**
* Stops bouncing of this marker.
* Note: unless 'immediate' flag is set to true, by the call to this method or in marker options,
* the bouncing will not stop immediately after the call of this method. Instead, the animation
* is executed until marker returns to its original position and takes its full size.
*
* @param immediate {boolean} if true, marker stop to bounce immediately, without waiting
* animation to end
* @return {Marker} this marker
*/
stopBouncing(immediate?: boolean);
/**
* Starts/stops bouncing of this marker.
* @return {Marker} marker
*/
toggleBouncing();
}
export type MarkerExt = (typeof Marker) & {
/**
* Registers default options of bouncing animation.
* @param options {BouncingOptions|object} object with options
*/
setBouncingOptions(options: BouncingOptions);
/**
* Returns array of currently bouncing markers.
* @return {Marker[]} array of bouncing markers
*/
getBouncingMarkers(): BouncingMarker[];
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
stopAllBouncingMarkers(immediate?: boolean);
}
export default function SmoothMarkerBouncing(L: Leaflet): Leaflet;

View File

@@ -0,0 +1,79 @@
{
"name": "leaflet.smooth_marker_bouncing",
"version": "3.1.0",
"type": "module",
"description": "Smooth animation of marker bouncing for Leaflet.",
"author": "Alexei KLENIN <alexei.klenin@gmail.com> (https://github.com/hosuaby)",
"main": "dist/index.esm.js",
"license": "BSD-2-Clause",
"keywords": [
"Leaflet",
"marker",
"bouncing",
"animation",
"smooth"
],
"repository": {
"type": "git",
"url": "git+https://github.com/hosuaby/Leaflet.SmoothMarkerBouncing.git"
},
"bugs": {
"url": "https://github.com/hosuaby/Leaflet.SmoothMarkerBouncing/issues"
},
"homepage": "https://github.com/hosuaby/Leaflet.SmoothMarkerBouncing#readme",
"devDependencies": {
"@babel/cli": "7.24.8",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/preset-env": "7.24.8",
"@babel/register": "7.24.6",
"@istanbuljs/esm-loader-hook": "^0.2.0",
"@types/leaflet": "^1.9.12",
"ava": "6.1.3",
"browser-env": "^3.3.0",
"concurrently": "8.2.2",
"coveralls": "3.1.1",
"font-awesome": "^4.7.0",
"http-server": "14.1.1",
"jquery": "3.7.1",
"leaflet": "1.9.4",
"leaflet.awesome-markers": "^2.0.5",
"leaflet.markercluster": "1.5.3",
"lodash": "4.17.21",
"npm-check": "6.0.1",
"nyc": "17.0.0",
"onchange": "7.1.0",
"rollup": "4.19.0",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-postcss": "4.0.2",
"rollup-plugin-uglify": "^6.0.4",
"sidebar-v2": "^0.4.0"
},
"scripts": {
"compile": "babel src --out-dir dist",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"build": "rollup -c",
"deps:check": "npm-check || true",
"deps:upgrade": "npm-check -u -E",
"dev": "concurrently \"npm run watch\" \"npm run serve\"",
"release": "npm run test && npm run compile && npm run build",
"serve": "http-server -c-1 --cors -o /debug",
"test": "ava",
"test:ci": "nyc --reporter=html --reporter=text ava",
"watch": "onchange 'src/*' -- npm run build"
},
"ava": {
"files": [
"tests/**/*",
"!tests/helpers/*"
],
"require": [
"./tests/helpers/setup-browser-env.js"
],
"nodeArguments": [
"--es-module-specifier-resolution=node",
"--experimental-loader=./tests/helpers/cssLoader.js",
"--no-warnings"
],
"verbose": true
}
}

View File

@@ -0,0 +1,59 @@
import babel from 'rollup-plugin-babel';
import postcss from 'rollup-plugin-postcss';
import {uglify} from 'rollup-plugin-uglify';
export default [{
input: 'src/standalone.js',
external: ['leaflet'],
output: {
file: 'dist/bundle.js',
format: 'iife',
name: 'bundle',
globals: {
leaflet: 'L'
}
},
plugins: [
babel({
exclude: 'node_modules/**'
}),
postcss({
extensions: [ '.css' ]
})
]
}, {
input: 'src/standalone.js',
external: ['leaflet'],
output: {
file: 'dist/bundle.min.js',
format: 'iife',
name: 'bundle',
globals: {
leaflet: 'L'
}
},
plugins: [
babel({
exclude: 'node_modules/**'
}),
postcss({
extensions: [ '.css' ]
}),
uglify()
]
}, {
input: 'src/SmoothMarkerBouncing.js',
external: ['leaflet'],
output: {
file: 'dist/index.esm.js',
format: 'esm'
},
plugins: [
babel({
exclude: 'node_modules/**'
}),
postcss({
extensions: [ '.css' ]
})
]
}];

View File

@@ -0,0 +1,268 @@
import {DomUtil} from 'leaflet';
import {calculateLine} from './line';
import './bouncing.css';
import BouncingOptions from './BouncingOptions';
import Styles from './Styles';
const animationNamePrefix = 'l-smooth-marker-bouncing-';
const moveAnimationName = animationNamePrefix + 'move';
const contractAnimationName = animationNamePrefix + 'contract';
/*
* CSS3 animation runs faster than transform-based animation. We need to reduce speed in order
* to be compatible with old API.
*/
const speedCoefficient = 0.8;
/**
* Removes and then resets required classes on the HTML element.
* Used as hack to restart CSS3 animation.
*
* @param element {HTMLElement} HTML element
* @param classes {string[]} names of classes
*/
function resetClasses(element, classes) {
classes.forEach((className) => DomUtil.removeClass(element, className));
void element.offsetWidth;
classes.forEach((className) => DomUtil.addClass(element, className));
}
export default class BouncingMotionCss3 {
marker;
position;
bouncingOptions;
isBouncing = false;
iconStyles;
shadowStyles;
bouncingAnimationPlaying = false;
onMotionEnd;
#lastAnimationName = contractAnimationName;
#classes = ['bouncing'];
#eventCounter;
#times;
#listener = (event) => this.onAnimationEnd(event);
/**
* Constructor.
*
* @param marker {Marker} marker
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
*/
constructor(marker, position, bouncingOptions) {
this.marker = marker;
this.position = position;
this.updateBouncingOptions(bouncingOptions);
}
updateBouncingOptions(options) {
this.bouncingOptions = options instanceof BouncingOptions
? options
: this.bouncingOptions.override(options);
if (this.bouncingOptions.elastic && this.bouncingOptions.contractHeight) {
this.#lastAnimationName = contractAnimationName;
const index = this.#classes.indexOf('simple');
if (index > -1) {
this.#classes.splice(index, 1);
}
if (this.marker._icon) {
DomUtil.removeClass(this.marker._icon, 'simple');
}
} else {
this.#lastAnimationName = moveAnimationName;
this.#classes.push('simple');
}
if (this.marker._icon) {
this.resetStyles(this.marker);
}
}
onAnimationEnd(event) {
if (event.animationName === this.#lastAnimationName) {
this.#eventCounter++;
this.#eventCounter %= 2;
if (!this.#eventCounter) {
if (this.isBouncing && (this.#times === null || --this.#times)) {
resetClasses(this.marker._icon, this.#classes);
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, this.#classes);
}
} else {
this._stopBouncingAnimation();
}
}
}
}
resetStyles(marker) {
this.marker = marker;
this.iconStyles = Styles.ofMarker(marker);
if (marker._shadow) {
this.shadowStyles = Styles.parse(marker._shadow.style.cssText);
}
const iconHeight = this.marker.getIcon()?.options?.iconSize[1]
|| this.marker?._iconObj?.options?.iconSize[1];
const iconAnimationParams = BouncingMotionCss3.animationParams(
this.position, this.bouncingOptions, iconHeight);
this.iconStyles = this.iconStyles.withStyles(iconAnimationParams);
this.marker._icon.style.cssText = this.iconStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._icon, this.#classes);
this.marker._icon.addEventListener('animationend', this.#listener);
}
const {bounceHeight, contractHeight, shadowAngle} = this.bouncingOptions;
if (this.marker._shadow) {
if (shadowAngle) {
const {x, y} = this.position;
const points = calculateLine(x, y, shadowAngle, bounceHeight + 1);
const [posXJump, posYJump] = points[bounceHeight];
const shadowHeight = this.marker.getIcon()?.options?.shadowSize[1];
const shadowScaleContract = BouncingMotionCss3.contractScale(
shadowHeight, contractHeight);
this.shadowStyles = this.shadowStyles
.withStyles(iconAnimationParams)
.withStyles({
'--pos-x-jump': `${posXJump}px`,
'--pos-y-jump': `${posYJump}px`,
'--scale-contract': shadowScaleContract,
});
this.marker._shadow.style.cssText = this.shadowStyles.toString();
if (this.bouncingAnimationPlaying) {
resetClasses(this.marker._shadow, this.#classes);
}
} else {
this.#classes.forEach(className => {
DomUtil.removeClass(this.marker._shadow, className);
});
}
}
}
bounce(times = null) {
this.#times = times;
this.isBouncing = true;
if (this.bouncingAnimationPlaying) {
return;
}
this.#eventCounter = 0;
this.bouncingAnimationPlaying = true;
resetClasses(this.marker._icon, this.#classes);
if (this.marker._shadow && this.bouncingOptions.shadowAngle) {
resetClasses(this.marker._shadow, this.#classes);
}
this.marker._icon.addEventListener('animationend', this.#listener);
}
stopBouncing(immediate = false) {
this.isBouncing = false;
immediate ||= this.bouncingOptions.immediateStop;
if (immediate) {
this._stopBouncingAnimation();
}
}
_stopBouncingAnimation() {
this.#classes.forEach((className) => {
DomUtil.removeClass(this.marker._icon, className);
if (this.marker._shadow) {
DomUtil.removeClass(this.marker._shadow, className);
}
});
this.bouncingAnimationPlaying = false;
if (this.onMotionEnd) {
this.onMotionEnd();
this.onMotionEnd = null;
}
this.marker.fire('bounceend');
}
/**
* Calculates parameters of CSS3 animation of bouncing.
*
* @param position {Point} marker current position on the map canvas
* @param bouncingOptions {BouncingOptions} options of bouncing animation
* @param height {number} icons height
* @return {object} CSS3 animation parameters
*/
static animationParams(position, bouncingOptions, height) {
const {x, y} = position;
const {bounceHeight, contractHeight, bounceSpeed, contractSpeed} = bouncingOptions;
const scaleContract = BouncingMotionCss3.contractScale(height, contractHeight);
const durationJump = BouncingMotionCss3.calculateDuration(bounceHeight, bounceSpeed);
const durationContract = BouncingMotionCss3.calculateDuration(contractHeight, contractSpeed);
const delays = [
0,
durationJump,
durationJump * 2,
durationJump * 2 + durationContract
];
return {
'--pos-x': `${x}px`,
'--pos-y': `${y}px`,
'--pos-y-jump': `${y - bounceHeight}px`,
'--pos-y-contract': `${y + contractHeight}px`,
'--scale-contract': scaleContract,
'--duration-jump': `${durationJump}ms`,
'--duration-contract': `${durationContract}ms`,
'--delays': `0ms, ${delays[1]}ms, ${delays[2]}ms, ${delays[3]}ms`
};
}
/**
* Calculates scale of contracting.
*
* @param {number} height original height
* @param {number} contractHeight how much it must contract
* @return {number} contracting scale between 0 and 1
*/
static contractScale(height, contractHeight) {
return (height - contractHeight) / height;
}
/**
* Calculates duration of animation.
*
* @param height {number} height of movement or resizing (px)
* @param speed {number} speed coefficient
*
* @return {number} duration of animation (ms)
*/
static calculateDuration(height, speed) {
if (height === 0) {
return 0;
}
let duration = Math.round(speed * speedCoefficient);
let i = height;
while (--i) {
duration += Math.round(speed / (height - i));
}
return duration;
}
}

View File

@@ -0,0 +1,59 @@
export default class BouncingOptions {
/**
* How high marker can bounce (px)
* @type {number}
*/
bounceHeight = 15;
/**
* How much marker can contract (px)
* @type {number}
*/
contractHeight = 12;
/**
* Bouncing speed coefficient
* @type {number}
*/
bounceSpeed = 52;
/**
* Contracting speed coefficient
* @type {number}
*/
contractSpeed = 52;
/**
* Shadow inclination angle(radians); null to cancel shadow movement
* @type {number}
*/
shadowAngle = - Math.PI / 4;
/**
* Activate contract animation
* @type {boolean}
*/
elastic = true;
/**
* Many markers can bounce in the same time
* @type {boolean}
*/
exclusive = false;
/**
* If true, when marker stops, it does not execute animation until its end, but instead stops
* abruptly.
* @type {boolean}
*/
immediateStop = false;
constructor(options) {
options && Object.assign(this, options);
}
override(options) {
return Object.assign(new BouncingOptions(this), options);
}
}

View File

@@ -0,0 +1,112 @@
import BouncingOptions from './BouncingOptions';
import Orchestration from './Orchestration';
export default function MarkerPrototypeExt(Leaflet) {
const oldSetPos = Leaflet.Marker.prototype._setPos;
const oldOnAdd = Leaflet.Marker.prototype.onAdd;
const oldSetIcon = Leaflet.Marker.prototype.setIcon;
return {
/** Bouncing options shared by all markers. */
_bouncingOptions: new BouncingOptions(),
_orchestration: new Orchestration(),
_realMarker: true,
/**
* Registers options of bouncing animation for this marker. After registration of options for
* this marker, it will ignore changes of default options. Function automatically recalculates
* animation steps and delays.
*
* @param options {BouncingOptions} options object
* @return {Marker} this marker
*/
setBouncingOptions: function(options) {
this._bouncingMotion.updateBouncingOptions(options);
return this;
},
/**
* Returns true if this marker is bouncing. If this marker is not bouncing returns false.
* @return {boolean} true if marker is bouncing, false if not
*/
isBouncing: function() {
return this._bouncingMotion.isBouncing;
},
/**
* Starts bouncing of this marker.
* @param times {number|null} number of times the marker must to bounce
* @return {Marker} this marker
*/
bounce: function(times = null) {
if (times) {
this._bouncingMotion.onMotionEnd = () => {
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(this);
};
}
this._bouncingMotion.bounce(times);
const exclusive = this._bouncingMotion.bouncingOptions.exclusive;
Leaflet.Marker.prototype._orchestration.addBouncingMarker(this, exclusive);
return this;
},
/**
* Stops bouncing of this marker.
* Note: unless 'immediate' flag is set to true, by the call to this method or in marker options,
* the bouncing will not stop immediately after the call of this method. Instead, the animation
* is executed until marker returns to its original position and takes its full size.
*
* @param immediate {boolean} if true, marker stop to bounce immediately, without waiting
* animation to end
* @return {Marker} this marker
*/
stopBouncing: function(immediate = false) {
this._bouncingMotion.stopBouncing(immediate);
Leaflet.Marker.prototype._orchestration.removeBouncingMarker(this);
return this;
},
/**
* Starts/stops bouncing of this marker.
* @return {Marker} marker
*/
toggleBouncing: function() {
if (this._bouncingMotion.isBouncing) {
this.stopBouncing();
} else {
this.bounce();
}
return this;
},
isRealMarker: function() {
return Object.hasOwn(this.__proto__, '_realMarker');
},
_setPos: function(position) {
oldSetPos.call(this, position);
if (this.isRealMarker()) {
this._bouncingMotion.position = position;
this._bouncingMotion.resetStyles(this);
}
},
onAdd: function(map) {
oldOnAdd.call(this, map);
if (this.isRealMarker()) {
this._bouncingMotion.resetStyles(this);
}
},
setIcon: function(icon) {
oldSetIcon.call(this, icon);
if (this.isRealMarker() && this._icon) {
this._bouncingMotion.resetStyles(this);
}
},
};
}

View File

@@ -0,0 +1,60 @@
export default class Orchestration {
#bouncingMarkers = [];
getBouncingMarkers() {
return this.#bouncingMarkers;
}
/**
* Adds the marker to the list of bouncing markers.
* If flag 'exclusive' is set to true, stops all bouncing markers before.
*
* @param marker {Marker} marker object
* @param exclusive {boolean} flag of exclusive bouncing. If set to true, stops the bouncing
* of all other markers.
*/
addBouncingMarker(marker, exclusive) {
if (exclusive || marker._bouncingMotion.bouncingOptions.exclusive) {
this.stopAllBouncingMarkers();
} else {
this.stopExclusiveMarkerBouncing();
}
this.#bouncingMarkers.push(marker);
}
/**
* Stops the bouncing of exclusive marker.
*/
stopExclusiveMarkerBouncing() {
const exclusiveMarker = this.#bouncingMarkers.find(
marker => marker._bouncingMotion.bouncingOptions.exclusive);
if (exclusiveMarker) {
exclusiveMarker.stopBouncing();
}
}
/**
* Removes the marker from the list of bouncing markers.
* @param marker {Marker} marker
*/
removeBouncingMarker(marker) {
const i = this.#bouncingMarkers.indexOf(marker);
if (~i) {
this.#bouncingMarkers.splice(i, 1);
}
}
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
stopAllBouncingMarkers(immediate = false) {
let marker;
while (marker = this.#bouncingMarkers.shift()) {
marker.stopBouncing(immediate);
}
};
}

View File

@@ -0,0 +1,48 @@
import BouncingOptions from './BouncingOptions';
import MarkerPrototypeExt from './MarkerPrototypeExt';
import BouncingMotionCss3 from './BouncingMotionCss3';
export default function SmoothMarkerBouncing(Leaflet) {
Leaflet.Marker.include(MarkerPrototypeExt(Leaflet));
/**
* Registers default options of bouncing animation.
* @param options {BouncingOptions|object} object with options
*/
Leaflet.Marker.setBouncingOptions = function (options) {
Leaflet.Marker.prototype._bouncingOptions = options instanceof BouncingOptions
? options
: new BouncingOptions(options);
};
/**
* Returns array of currently bouncing markers.
* @return {Marker[]} array of bouncing markers
*/
Leaflet.Marker.getBouncingMarkers = function () {
return Leaflet.Marker.prototype._orchestration.getBouncingMarkers();
};
/**
* Stops the bouncing of all currently bouncing markers. Purge the array of bouncing markers.
*
* @param immediate {boolean} if true, markers stop to bounce immediately, without waiting
* animation to end
*/
Leaflet.Marker.stopAllBouncingMarkers = function (immediate = false) {
Leaflet.Marker.prototype._orchestration.stopAllBouncingMarkers(immediate);
};
Leaflet.Marker.addInitHook(function () {
if (this.isRealMarker()) {
const bouncingOptions = new BouncingOptions(
Leaflet.Marker.prototype._bouncingOptions);
this._bouncingMotion = new BouncingMotionCss3(
this, new Leaflet.Point(0, 0), bouncingOptions);
}
});
return Leaflet;
}

View File

@@ -0,0 +1,65 @@
/** Regex to parse style definitions. */
const regStyle = /([\w-]+): ([^;]+);/g;
export default class Styles {
constructor(styles) {
styles && Object.assign(this, styles);
}
findOpacity(options) {
this.opacity = options?.opacityWhenUnclustered // used by cluster plugin
|| options?.opacity
|| 1;
}
/**
* Creates a copy of styles merged with provided 'styles'.
* @param {Object} styles object with styles to merge
* @return {Styles} copy of styles
*/
withStyles(styles) {
const copy = new Styles(this);
copy && Object.assign(copy, styles);
return copy;
}
toString() {
return Object
.entries(this)
.map((entry) => `${entry[0]}: ${entry[1]};`)
.join(' ');
}
/**
* Parses cssText attribute into Styles object.
* @param cssText {string} cssText string
* @return {Styles} Styles object
*/
static parse(cssText) {
const styles = {};
let match = regStyle.exec(cssText);
while (match) {
styles[match[1]] = match[2];
match = regStyle.exec(cssText);
}
delete styles['z-index'];
delete styles['opacity'];
styles['outline'] = 'none';
return new Styles(styles);
}
/**
* @param marker {Marker}
*/
static ofMarker(marker) {
const styles = Styles.parse(marker._icon.style.cssText);
styles.findOpacity(marker.options);
styles['z-index'] = marker._zIndex;
return styles;
}
}

View File

@@ -0,0 +1,31 @@
@keyframes l-smooth-marker-bouncing-move {
from {
transform: translate(var(--pos-x), var(--pos-y))
}
to {
transform: translate(var(--pos-x-jump, var(--pos-x)), var(--pos-y-jump))
}
}
@keyframes l-smooth-marker-bouncing-contract {
from {
transform: translate(var(--pos-x), var(--pos-y))
}
to {
transform: translate(var(--pos-x), var(--pos-y-contract)) scaleY(var(--scale-contract))
}
}
.bouncing {
animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-contract, l-smooth-marker-bouncing-contract;
animation-direction: normal, reverse, normal, reverse;
animation-duration: var(--duration-jump), var(--duration-jump), var(--duration-contract), var(--duration-contract);
animation-delay: var(--delays)
}
.bouncing.simple {
animation-name: l-smooth-marker-bouncing-move, l-smooth-marker-bouncing-move;
animation-direction: normal, reverse;
animation-duration: var(--duration-jump), var(--duration-jump);
animation-delay: var(--delays)
}

View File

@@ -0,0 +1,49 @@
/**
* Calculates the points to draw the continous line on the screen. Returns the array of ordered
* point coordinates. Uses Bresenham algorithm.
*
* @param x {number} x coordinate of origin
* @param y {number} y coordinate of origin
* @param angle {number} angle (radians)
* @param length {number} length of line (px)
*
* @return {[number, number][]} array of ordered point coordinates
*
* @see http://rosettacode.org/wiki/Bitmap/Bresenham's_line_algorithm#JavaScript
*/
export function calculateLine(x, y, angle, length) {
// TODO: use something else than multiply length by 2 to calculate the line with defined
// length
let xD = Math.round(x + Math.cos(angle) * (length * 2)),
yD = Math.round(y + Math.sin(angle) * (length * 2)),
dx = Math.abs(xD - x),
sx = x < xD ? 1 : -1,
dy = Math.abs(yD - y),
sy = y < yD ? 1 : -1,
err = (dx > dy ? dx : -dy) / 2,
e2,
p = [],
i = 0;
while (true) {
p.push([x, y]);
i++;
if (i === length)
break;
e2 = err;
if (e2 > -dx) {
err -= dy;
x += sx;
}
if (e2 < dy) {
err += dx;
y += sy;
}
}
return p;
}

View File

@@ -0,0 +1,4 @@
import L from 'leaflet';
import SmoothMarkerBouncing from './SmoothMarkerBouncing';
SmoothMarkerBouncing(L);

View File

@@ -0,0 +1,54 @@
import test from 'ava';
import BouncingMotionCss3 from '../src/BouncingMotionCss3';
import {Point} from 'leaflet';
import BouncingOptions from '../src/BouncingOptions';
test('Test calculate contract scale', t => {
// When
const contractScale1 = BouncingMotionCss3.contractScale(41, 12);
const contractScale2 = BouncingMotionCss3.contractScale(41, 0);
// Then
t.is(contractScale1, 0.7073170731707317);
t.is(contractScale2, 1);
});
test('Test calculate duration of CSS3 animation', t => {
// When
const duration1 = BouncingMotionCss3.calculateDuration(15, 52);
const duration2 = BouncingMotionCss3.calculateDuration(12, 52);
const duration3 = BouncingMotionCss3.calculateDuration(20, 30);
const duration4 = BouncingMotionCss3.calculateDuration(0, 30);
// Then
t.is(duration1, 211);
t.is(duration2, 199);
t.is(duration3, 132);
t.is(duration4, 0);
});
test('Test calculate icon animation params', t => {
// Given
const position = new Point(100, 100);
const bouncingOptions = new BouncingOptions();
const height = 41;
// When
const animationParams = BouncingMotionCss3.animationParams(position, bouncingOptions, height);
// Then
t.deepEqual(animationParams, {
'--pos-x': '100px',
'--pos-y': '100px',
'--pos-y-jump': '85px',
'--pos-y-contract': '112px',
'--scale-contract': 0.7073170731707317,
'--duration-jump': '211ms',
'--duration-contract': '199ms',
'--delays': '0ms, 211ms, 422ms, 621ms'
});
});

View File

@@ -0,0 +1,73 @@
import test from 'ava';
import BouncingOptions from '../src/BouncingOptions';
test('Test default bouncing options', t => {
const defaultBouncingOptions = new BouncingOptions();
t.like(defaultBouncingOptions, {
bounceHeight: 15,
contractHeight: 12,
bounceSpeed: 52,
contractSpeed: 52,
shadowAngle: - Math.PI / 4,
elastic: true,
exclusive: false
});
});
test('Test customized bouncing options', t => {
const customizedBouncingOptions = new BouncingOptions({
contractHeight: 42,
exclusive: true
});
t.like(customizedBouncingOptions, {
bounceHeight: 15,
contractHeight: 42,
bounceSpeed: 52,
contractSpeed: 52,
shadowAngle: - Math.PI / 4,
elastic: true,
exclusive: true
});
});
test('Test clone bouncing options', t => {
// Given
const bouncingOptions = new BouncingOptions({
contractHeight: 42,
exclusive: true
});
// When
const clonedOptions = new BouncingOptions(bouncingOptions);
// Then
t.deepEqual(clonedOptions, bouncingOptions);
t.not(clonedOptions, bouncingOptions);
});
test('Test override', t => {
// Given
const defaultBouncingOptions = new BouncingOptions();
// When
const overriddenOptions = defaultBouncingOptions.override({
contractHeight: 42,
exclusive: true
})
// Then
t.like(overriddenOptions, {
bounceHeight: 15,
contractHeight: 42,
bounceSpeed: 52,
contractSpeed: 52,
shadowAngle: - Math.PI / 4,
elastic: true,
exclusive: true
});
t.not(overriddenOptions, defaultBouncingOptions);
});

View File

@@ -0,0 +1,21 @@
import test from 'ava';
import L from 'leaflet';
import randLatLng from './helpers/random-pos';
import SmoothMarkerBouncing from '../src/SmoothMarkerBouncing';
SmoothMarkerBouncing(L);
const MarkerCluster= L.Marker.extend({});
test('Test isRealMarker', t => {
// Given
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
const marker = L.marker(randLatLng()).addTo(map);
const cluster = new MarkerCluster({});
// Then
t.true(marker.isRealMarker());
t.false(cluster.isRealMarker());
});

View File

@@ -0,0 +1,76 @@
import test from 'ava';
import L from 'leaflet';
import randLatLng from './helpers/random-pos';
import SmoothMarkerBouncing from '../src/SmoothMarkerBouncing';
SmoothMarkerBouncing(L);
test('Test start/stop bouncing of individual markers', t => {
// Given
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
const marker1 = L.marker(randLatLng()).addTo(map);
const marker2 = L.marker(randLatLng()).addTo(map);
const marker3 = L.marker(randLatLng()).addTo(map);
// When
let bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, []);
// When
marker2.bounce();
bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, [ marker2 ]);
// When
marker2.stopBouncing();
bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, []);
});
test('Test start/stop bouncing of exclusive marker', t => {
// Given
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
const marker1 = L.marker(randLatLng()).addTo(map);
const marker2 = L.marker(randLatLng()).addTo(map);
const marker3 = L.marker(randLatLng()).setBouncingOptions({ exclusive: true }).addTo(map);
// When
let bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, []);
// When
marker1.bounce();
marker2.bounce();
bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, [ marker1, marker2 ]);
// When
marker3.bounce();
bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, [ marker3 ]);
// When
marker2.bounce();
bouncingMarkers = L.Marker.prototype._orchestration.getBouncingMarkers();
// Then
t.deepEqual(bouncingMarkers, [ marker2 ]);
});

View File

@@ -0,0 +1,68 @@
import test from 'ava';
import L from 'leaflet';
import SmoothMarkerBouncing from '../src/SmoothMarkerBouncing';
SmoothMarkerBouncing(L);
test('Test both setBouncingOptions', t => {
// Given
L.Marker.setBouncingOptions({
contractSpeed: 32
});
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
// When
const marker = L
.marker([48.847547, 2.351074])
.setBouncingOptions({
bounceHeight: 100,
exclusive: true
})
.addTo(map);
// Then
t.like(marker._bouncingMotion.bouncingOptions, {
bounceHeight: 100,
contractHeight: 12,
bounceSpeed: 52,
contractSpeed: 32,
shadowAngle: - Math.PI / 4,
elastic: true,
exclusive: true
});
});
test('Test getBouncingMarkers', t => {
// Given
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
const marker = L
.marker([48.847547, 2.351074])
.setBouncingOptions({
bounceHeight: 100,
exclusive: true
})
.addTo(map);
// When
// nothing
// Then
t.deepEqual(L.Marker.getBouncingMarkers(), []);
// When
marker.bounce();
// Then
t.deepEqual(L.Marker.getBouncingMarkers(), [ marker ]);
// When
marker.stopBouncing();
// Then
t.deepEqual(L.Marker.getBouncingMarkers(), []);
});

View File

@@ -0,0 +1,113 @@
import test from 'ava';
import Styles from '../src/Styles';
import L from 'leaflet';
test('Test parse', t => {
// Given
const cssText = 'margin-left: -12px; margin-top: -41px; width: 25px; height: 41px; z-index: 658; opacity: 0.76';
// When
const styles = Styles.parse(cssText);
// Then
t.like(styles, {
'height': '41px',
'width': '25px',
'margin-left': '-12px',
'margin-top': '-41px',
'outline': 'none'
});
});
test('Test find opacity', t => {
// Given
const styles1 = new Styles({ width: '25px', height: '41px' });
const styles2 = new Styles({ width: '25px', height: '41px' });
const styles3 = new Styles({ width: '25px', height: '41px' });
// When
styles1.findOpacity({ opacityWhenUnclustered: 0.1, opacity: 0.5 });
styles2.findOpacity({ opacity: 0.5 });
styles3.findOpacity({});
// Then
t.like(styles1, {
width: '25px',
height: '41px',
opacity: 0.1
});
t.like(styles2, {
width: '25px',
height: '41px',
opacity: 0.5
});
t.like(styles3, {
width: '25px',
height: '41px',
opacity: 1
});
});
test('Test copy with styles', t => {
// Given
const styles = new Styles({ width: '25px', height: '41px' });
// When
const copy = styles.withStyles({
'--pos-x': '50px',
'--pos-y': '100px'
})
// Then
t.like(copy, {
width: '25px',
height: '41px',
'--pos-x': '50px',
'--pos-y': '100px'
});
});
test('Test toString', t => {
// Given
const styles = new Styles({
'height': '41px',
'width': '25px',
'margin-left': '-12px',
'margin-top': '-41px'
});
// When
const cssText = styles.toString();
// Then
t.true(cssText.includes('margin-left: -12px;'));
t.true(cssText.includes('margin-top: -41px;'));
t.true(cssText.includes('width: 25px;'));
t.true(cssText.includes('height: 41px;'));
});
test('Test styles from marker', t => {
// Given
const div = document.createElement('div');
const map = L.map(div).setView([48.847547, 2.351074], 14);
const marker = L.marker([48.847547, 2.351074]).addTo(map);
// When
const styles = Styles.ofMarker(marker);
// Then
t.like(styles, {
width: '25px',
height: '41px',
opacity: 1,
'z-index': 0,
'outline': 'none'
});
});

View File

@@ -0,0 +1,12 @@
import {load as esmLoad} from '@istanbuljs/esm-loader-hook';
export function load(url, context, defaultLoad) {
if (url.endsWith('.css')) {
return {
format: 'module',
source: ''
};
}
return esmLoad(url, context, defaultLoad);
}

View File

@@ -0,0 +1,9 @@
import _ from 'lodash';
const parisArea = [[48.824384, 2.284298], [48.872054, 2.409782]];
export default function randLatLng() {
const lat = _.random(parisArea[0][0], parisArea[1][0]);
const lng = _.random(parisArea[0][1], parisArea[1][1]);
return [lat, lng];
}

View File

@@ -0,0 +1,2 @@
import browserEnv from 'browser-env';
browserEnv();

View File

@@ -0,0 +1,33 @@
import test from 'ava';
import {calculateLine} from '../src/line';
test('Test calculate line', t => {
// Given
const x = 100,
y = 100,
angle = - Math.PI / 4,
length = 15;
// When
const line = calculateLine(x, y, angle, length);
// Then
t.deepEqual(line, [
[ 100, 100 ],
[ 101, 99 ],
[ 102, 98 ],
[ 103, 97 ],
[ 104, 96 ],
[ 105, 95 ],
[ 106, 94 ],
[ 107, 93 ],
[ 108, 92 ],
[ 109, 91 ],
[ 110, 90 ],
[ 111, 89 ],
[ 112, 88 ],
[ 113, 87 ],
[ 114, 86 ]
]);
});