Тепловая карта и ландшафт на JavaScript
Кто в детстве не любил делать вот такие кляксы из фломастеров или красок (поводите не спеша и маленькими кругами мышкой над канвой):
очистить
А теперь это по-модному называется "тепловые карты" и много где используется. Наверное, легче всего приспособить для heat map имеющийся код, ссылка на оригинал которого есть в листинге.
Так как здесь отслеживается только перемещение мыши, на сенсорном экране для пальцев будет не очень удобно, но можно добавить обработку mousedown / touchstart как в этой заметке. Ниже показан исходник скрипта в виде файла .html в кодировке Юникода UTF-8 без стандартных обрамляющих тегов.
<div style="text-align: center;"> <canvas id="heatCanvas" width="800" height="400" style="border: 1px dotted #333; background-color: white;"></canvas> <br> <span id="clearCanvas" style="cursor: pointer;">очистить</span> </div> <script> // Объект simpleheat: https://github.com/mourner/simpleheat (function () { 'use strict'; function simpleheat (canvas) { if (!(this instanceof simpleheat)) { return new simpleheat(canvas); } this._canvas = canvas = typeof canvas === 'string' ? document.getElementById(canvas) : canvas; this._ctx = canvas.getContext('2d'); this._width = canvas.width; this._height = canvas.height; this._max = 1; this._data = []; } simpleheat.prototype = { defaultRadius: 25, defaultGradient: { 0.2: 'magenta', 0.4: 'blue', 0.6: 'cyan', 0.7: 'lime', 0.8: 'yellow', 0.9: 'orange', 1.0: 'red' }, data: function (data) { this._data = data; return this; }, max: function (max) { this._max = max; return this; }, add: function (point) { this._data.push(point); return this; }, clear: function () { this._data = []; return this; }, radius: function (r, blur) { blur = (blur === undefined ? 15 : blur); let circle = this._circle = document.createElement ('canvas'), ctx = circle.getContext('2d'), r2 = this._r = r + blur; circle.width = circle.height = r2 * 2; ctx.shadowOffsetX = ctx.shadowOffsetY = 200; ctx.shadowBlur = blur; ctx.shadowColor = 'black'; ctx.beginPath(); ctx.arc(r2 - 200, r2 - 200, r, 0, Math.PI * 2, true); ctx.closePath(); ctx.fill(); return this; }, gradient: function (grad) { let canvas = document.createElement('canvas'), ctx = canvas.getContext('2d'), gradient = ctx.createLinearGradient(0, 0, 0, 256); canvas.width = 1; canvas.height = 256; for (var i in grad) gradient.addColorStop(i, grad[i]); ctx.fillStyle = gradient; ctx.fillRect(0, 0, 1, 256); this._grad = ctx.getImageData(0, 0, 1, 256).data; return this; }, draw: function (minOpacity) { if (!this._circle) this.radius(this.defaultRadius); if (!this._grad) this.gradient(this.defaultGradient); let ctx = this._ctx; ctx.clearRect(0, 0, this._width, this._height); for (let i = 0, len = this._data.length, p; i < len; i++) { p = this._data[i]; ctx.globalAlpha = Math.max(p[2] / this._max, minOpacity === undefined ? 0.05 : minOpacity); ctx.drawImage(this._circle, p[0] - this._r, p[1] - this._r); } let colored = ctx.getImageData(0, 0, this._width, this._height); this._colorize(colored.data, this._grad); ctx.putImageData(colored, 0, 0); return this; }, _colorize: function (pixels, gradient) { for (let i = 3, len = pixels.length, j; i < len; i += 4) { j = pixels[i] * 4; if (j) { pixels[i - 3] = gradient[j]; pixels[i - 2] = gradient[j + 1]; pixels[i - 1] = gradient[j + 2]; } } } }; window.simpleheat = simpleheat; })(); // Конец кода simpleheat window.addEventListener ('load', function (e) { window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; let data = []; //начальные данные let heat = simpleheat('heatCanvas').data(data).max(20), frame; //создание карты function draw() { heat.draw(); frame = null; } //отрисовка draw(); document.getElementById('heatCanvas').onmousemove = function (e) { heat.add([e.offsetX, e.offsetY, 1]); frame = frame || window.requestAnimationFrame (draw); } document.getElementById('clearCanvas').onclick = function (e) { heat.clear(); draw(); } }); </script> <noscript> <div style="text-align: center;"> Нужен включённый в браузере JavaScript для работы приложения </div> </noscript>
Что до ландшафтов, вот несколько ссылок, от простых как в Dwarf Fortress (ещё одна культовая программистская игра) до довольно мощных:
прямоугольники, 4 вида ландшафта
Очень навороченный генератор сказочных карт
Ещё один генератор островов с параметрами
Кстати, о дварфах:
Dr. Evil warns: Snow White and the Seven Dwarfs is a racist tale. Soot Black and the Seven Dwarfs matters!
(C)
03.07.2020, 23:29 [1436 просмотров]