kmap-ui
Version:
A components of zmap base on vue2.X
181 lines (151 loc) • 5.47 kB
JavaScript
/*
Water ripple effect.
Original code (Java) by Neil Wallis
@link http://www.neilwallis.com/java/water.html
Original code (JS) by Sergey Chikuyonok (serge.che@gmail.com)
@link http://chikuyonok.ru
@link http://media.chikuyonok.ru/ripple/
Copyright (c) 2015 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
@link https://github.com/Viglino
*/
import ol_ext_inherits from '../util/ext'
import ol_interaction_Pointer from 'ol/interaction/Pointer'
/**
* @constructor
* @extends {ol_interaction_Pointer}
* @param {*} options
* @param {ol/layer/Layer} options.layer layer to animate
* @param {number} options.radius raindrop radius
* @param {number} options.interval raindrop interval (in ms), default 1000
*/
var ol_interaction_Ripple = function(options) {
ol_interaction_Pointer.call(this, {
handleDownEvent: this.rainDrop,
handleMoveEvent: this.rainDrop
});
// Default options
options = options||{};
this.riprad = options.radius || 3;
this.ripplemap = [];
this.last_map = [];
// Generate random ripples
this.rains (this.interval);
options.layer.on(['postcompose', 'postrender'], this.postcompose_.bind(this));
};
ol_ext_inherits(ol_interaction_Ripple, ol_interaction_Pointer);
/** Generate random rain drop
* @param {integer} interval
*/
ol_interaction_Ripple.prototype.rains = function(interval) {
if (this.onrain) clearTimeout (this.onrain);
var self = this;
var vdelay = (typeof(interval)=="number" ? interval : 1000)/2;
var delay = 3*vdelay/2;
var rnd = Math.random;
function rain() {
if (self.width) self.rainDrop([rnd() * self.width, rnd() * self.height]);
self.onrain = setTimeout (rain, rnd()*vdelay + delay);
}
// Start raining
if (delay) rain();
}
/** Disturb water at specified point
* @param {ol.Pixel|ol.MapBrowserEvent}
*/
ol_interaction_Ripple.prototype.rainDrop = function(e) {
if (!this.width) return;
var dx,dy;
if (e.pixel) {
dx = e.pixel[0]*this.ratio;
dy = e.pixel[1]*this.ratio;
} else {
dx = e[0]*this.ratio;
dy = e[1]*this.ratio;
}
dx <<= 0;
dy <<= 0;
for (var j = dy - this.riprad*this.ratio; j < dy + this.riprad*this.ratio; j++) {
for (var k = dx - this.riprad*this.ratio; k < dx + this.riprad*this.ratio; k++) {
this.ripplemap[this.oldind + (j * this.width) + k] += 128;
}
}
}
/** Postcompose function
*/
ol_interaction_Ripple.prototype.postcompose_ = function(e) {
var ctx = e.context;
var canvas = ctx.canvas;
// Initialize when canvas is ready / modified
if (this.width != canvas.width || this.height != canvas.height) {
this.width = canvas.width;
this.height = canvas.height;
this.ratio = e.frameState.pixelRatio;
this.half_width = this.width >> 1;
this.half_height = this.height >> 1;
this.size = this.width * (this.height + 2) * 2;
this.oldind = this.width;
this.newind = this.width * (this.height + 3);
for (var i = 0; i < this.size; i++) {
this.last_map[i] = this.ripplemap[i] = 0;
}
}
this.texture = ctx.getImageData(0, 0, this.width, this.height);
this.ripple = ctx.getImageData(0, 0, this.width, this.height);
// Run animation
var a, b, data, cur_pixel, new_pixel;
var t = this.oldind; this.oldind = this.newind; this.newind = t;
i = 0;
var _rd = this.ripple.data,
_td = this.texture.data;
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
var _newind = this.newind + i,
_mapind = this.oldind + i;
data = (
this.ripplemap[_mapind - this.width] +
this.ripplemap[_mapind + this.width] +
this.ripplemap[_mapind - 1] +
this.ripplemap[_mapind + 1]) >> 1;
data -= this.ripplemap[_newind];
data -= data >> 5;
this.ripplemap[_newind] = data;
//where data=0 then still, where data>0 then wave
data = 1024 - data;
if (this.last_map[i] != data) {
this.last_map[i] = data;
//offsets
a = (((x - this.half_width) * data / 1024) << 0) + this.half_width;
b = (((y - this.half_height) * data / 1024) << 0) + this.half_height;
//bounds check
if (a >= this.width) a = this.width - 1;
if (a < 0) a = 0;
if (b >= this.height) b = this.height - 1;
if (b < 0) b = 0;
new_pixel = (a + (b * this.width)) * 4;
cur_pixel = i * 4;
/**/
_rd[cur_pixel] = _td[new_pixel];
_rd[cur_pixel + 1] = _td[new_pixel + 1];
_rd[cur_pixel + 2] = _td[new_pixel + 2];
/*/
// only in blue pixels
if (_td[new_pixel + 2]>_td[new_pixel + 1]
&& _td[new_pixel + 2]>_td[new_pixel])
{
_rd[cur_pixel] = _td[new_pixel];
_rd[cur_pixel + 1] = _td[new_pixel + 1];
_rd[cur_pixel + 2] = _td[new_pixel + 2];
}
else this.ripplemap[_newind] = 0;
/**/
}
++i;
}
}
ctx.putImageData(this.ripple, 0, 0);
// tell OL3 to continue postcompose animation
this.getMap().render();
};
export default ol_interaction_Ripple