<?xml version="1.0" encoding="windows-1251"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="https://ktest.mybb.ru/export.php?type=rss" rel="self" type="application/rss+xml" />
		<title>Тестовый</title>
		<link>http://ktest.mybb.ru/</link>
		<description>Тестовый</description>
		<language>ru-ru</language>
		<lastBuildDate>Wed, 20 May 2026 00:34:39 +0300</lastBuildDate>
		<generator>MyBB/mybb.ru</generator>
		<item>
			<title>000&amp;#128221;</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=414#p414</link>
			<description>&lt;p&gt;000&lt;br /&gt;&amp;#128221;&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 20 May 2026 00:34:39 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=414#p414</guid>
		</item>
		<item>
			<title>6666&amp;#128221;</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=413#p413</link>
			<description>&lt;p&gt;66666&lt;br /&gt;&amp;#128221;&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 20 May 2026 00:23:19 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=413#p413</guid>
		</item>
		<item>
			<title>Это новая тема с описанием:)))&amp;#8225;очень интересное содержание&amp;</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=412#p412</link>
			<description>&lt;p&gt;555&lt;br /&gt;&amp;#128221;&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Tue, 19 May 2026 20:39:57 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=412#p412</guid>
		</item>
		<item>
			<title>тест</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=411#p411</link>
			<description>&lt;p&gt;999&lt;br /&gt;&amp;#128274;&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Tue, 19 May 2026 18:50:32 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=411#p411</guid>
		</item>
		<item>
			<title>#255fad;;г56г56г56г5г</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=398#p398</link>
			<description>&lt;p&gt;96&lt;br /&gt;&amp;#128221;&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Tue, 19 May 2026 18:19:28 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=398#p398</guid>
		</item>
		<item>
			<title>г56г56г</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=380#p380</link>
			<description>&lt;p&gt;888&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Tue, 19 May 2026 15:03:24 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=380#p380</guid>
		</item>
		<item>
			<title>333333</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=373#p373</link>
			<description>&lt;strudel-editor class=&quot;custom_tag custom_tag_strudel&quot; id=&quot;strudel-1&quot;&gt;&lt;p&gt;//$: note(&amp;quot;C#4&amp;quot;).sound(&amp;quot;piano&amp;quot;)&lt;br /&gt;//$: note(&amp;quot;E4&amp;quot;).sound(&amp;quot;piano&amp;quot;)&lt;br /&gt;//$: note(&amp;quot;A3&amp;quot;).sound(&amp;quot;piano&amp;quot;)&lt;/p&gt;&lt;/strudel-editor&gt;&lt;script&gt;jQuery(document).trigger(jQuery.Event(&quot;custom_tag&quot;,{&quot;tag&quot;:&quot;strudel&quot;,&quot;selector&quot;:&quot;.custom_tag#strudel-1&quot;,&quot;sender&quot;:$(&quot;.custom_tag#strudel-1&quot;)}));&lt;/script&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 26 Dec 2025 15:35:18 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=373#p373</guid>
		</item>
		<item>
			<title>Всем привет:)</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=372#p372</link>
			<description>&lt;p&gt;111&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Mon, 24 Nov 2025 15:02:49 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=372#p372</guid>
		</item>
		<item>
			<title>#f1c40f;;#f27d7dff;;ооооо7о77</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=365#p365</link>
			<description>&lt;p&gt;ононеоно&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 21 Nov 2025 03:53:20 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=365#p365</guid>
		</item>
		<item>
			<title>#3498db;;#e19696ff;;аааа</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=364#p364</link>
			<description>&lt;p&gt;ааааа&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 21 Nov 2025 03:33:56 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=364#p364</guid>
		</item>
		<item>
			<title>vdvdsvdv&amp;#8224;i¤</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=347#p347</link>
			<description>&lt;p&gt;00000&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Thu, 06 Nov 2025 20:52:55 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=347#p347</guid>
		</item>
		<item>
			<title>фаыфыафыа</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=324#p324</link>
			<description>&lt;div class=&quot;quote-box answer-box&quot;&gt;&lt;cite&gt;Merlin написал(а):&lt;/cite&gt;&lt;blockquote&gt;&lt;p&gt;афыафыаыфаа&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;00000000000&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 05 Nov 2025 16:05:44 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=324#p324</guid>
		</item>
		<item>
			<title>#2ecc71;;#fcd2f2ff;;uluilil</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=321#p321</link>
			<description>&lt;div class=&quot;quote-box answer-box&quot;&gt;&lt;cite&gt;308,2 написал(а):&lt;/cite&gt;&lt;blockquote&gt;&lt;p&gt;luiluiluil&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;гггг&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 05 Nov 2025 14:59:38 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=321#p321</guid>
		</item>
		<item>
			<title>12345</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=314#p314</link>
			<description>&lt;p&gt;[html]&amp;lt;div class=&amp;quot;fog-container&amp;quot;&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;fog&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;fog-bg&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;brush&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
						&lt;p&gt;&amp;lt;style&amp;gt;&lt;br /&gt;.fog-container {&lt;br /&gt;&amp;#160; &amp;#160; aspect-ratio: 16 / 9;&lt;br /&gt;&amp;#160; &amp;#160; position: relative;&lt;br /&gt;&amp;#160; &amp;#160; overflow: hidden;&lt;br /&gt;&amp;#160; &amp;#160; margin: 20px 0;&lt;br /&gt;&amp;#160; &amp;#160; border-radius: 6px;&lt;br /&gt;&amp;#160; &amp;#160; touch-action: none;&lt;br /&gt;&amp;#160; &amp;#160; width: 100%;&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;/* Уменьшаем размер только на десктопе */&lt;br /&gt;@media (min-width: 768px) {&lt;br /&gt;&amp;#160; &amp;#160; .fog-container {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; max-width: 60rem; /* &amp;#8776;960px при 16px базовом шрифте */&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; margin-left: auto;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; margin-right: auto;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;.fog-container canvas {&lt;br /&gt;&amp;#160; &amp;#160; display: block;&lt;br /&gt;&amp;#160; &amp;#160; width: 100%;&lt;br /&gt;&amp;#160; &amp;#160; height: 100%;&lt;br /&gt;&amp;#160; &amp;#160; position: absolute;&lt;br /&gt;&amp;#160; &amp;#160; left: 50%;&lt;br /&gt;&amp;#160; &amp;#160; top: 0;&lt;br /&gt;&amp;#160; &amp;#160; transform: translateX(-50%);&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;#brush {&lt;br /&gt;&amp;#160; &amp;#160; opacity: 0;&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;/p&gt;
						&lt;p&gt;&amp;lt;script&amp;gt;&lt;br /&gt;class FogParticle {&lt;br /&gt;&amp;#160; &amp;#160; constructor(ctx, canvasWidth, canvasHeight) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx = ctx;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = canvasWidth;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = canvasHeight;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = 0;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setPosition(x, y) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = x;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = y;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setVelocity(x, y) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = x;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = y;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setImage(image) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.image = image;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; render() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.image) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.drawImage(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.image,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x - this.image.width / 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y - this.image.height / 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; 400,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; 400&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x += this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y += this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.x &amp;gt;= this.canvasWidth) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = -this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = this.canvasWidth;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else if (this.x &amp;lt;= 0) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = -this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.y &amp;gt;= this.canvasHeight) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = -this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = this.canvasHeight;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else if (this.y &amp;lt;= 0) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = -this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;class Fog {&lt;br /&gt;&amp;#160; &amp;#160; constructor({ selector, density = 50, velocity = 2, particle, bgi } = {}) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const canvas = document.querySelector(selector);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = canvas.parentElement.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx = canvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = canvas.width = bcr.width;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = canvas.height = bcr.height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particleCount = density;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.maxVelocity = velocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particle = particle;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = bgi;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._createParticles();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._setImage();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.bgi) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const img = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.onload = () =&amp;gt; {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const size = coverImg(img, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = { img, w: size.w, h: size.h };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this._render();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.src = this.bgi;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _createParticles() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles = [];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const random = (min, max) =&amp;gt; Math.random() * (max - min) + min;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; for (let i = 0; i &amp;lt; this.particleCount; i++) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const particle = new FogParticle(this.ctx, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; particle.setPosition(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(0, this.canvasWidth),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(0, this.canvasHeight)&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; particle.setVelocity(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(-this.maxVelocity, this.maxVelocity),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(-this.maxVelocity, this.maxVelocity)&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles.push(particle);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _setImage() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.particle) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const img = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.onload = () =&amp;gt; this.particles.forEach(p =&amp;gt; p.setImage(img));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.src = this.particle;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _render() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.bgi) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.drawImage(this.bgi.img, 0, 0, this.bgi.w, this.bgi.h);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.fillStyle = &amp;quot;rgba(0, 0, 0, 1)&amp;quot;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles.forEach(p =&amp;gt; p.render());&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; requestAnimationFrame(this._render.bind(this));&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;class Eraser {&lt;br /&gt;&amp;#160; &amp;#160; constructor({ bgCanvas, brushCanvas, bgi, radius = 120 } = {}) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCanvas = document.querySelector(bgCanvas);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCanvas = document.querySelector(brushCanvas);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx = this.bgCanvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx = this.brushCanvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.parentElement = this.bgCanvas.parentElement;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = this.parentElement.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = this.bgCanvas.width = this.brushCanvas.width = bcr.width;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = this.bgCanvas.height = this.brushCanvas.height = bcr.height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius = radius;&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi.src = bgi;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi.onload = this._attachEvents.bind(this);&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bgCanvasEl = this.bgCanvas;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.utils = {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; distanceBetween(point1, point2) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; angleBetween(point1, point2) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return Math.atan2(point2.x - point1.x, point2.y - point1.y);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; getMousePos(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = bgCanvasEl.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return { x: e.clientX - bcr.left, y: e.clientY - bcr.top };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; getTouchPos(touch) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = bgCanvasEl.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return { x: touch.clientX - bcr.left, y: touch.clientY - bcr.top };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; };&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _attachEvents() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const parent = this.parentElement;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;mousemove&#039;, this._onMouseMove.bind(this));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;mouseleave&#039;, this._onMouseLeave.bind(this));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchstart&#039;, this._onTouchStart.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchmove&#039;, this._onTouchMove.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchend&#039;, this._onTouchEnd.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onMouseMove(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const currentPoint = this.utils.getMousePos(e);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._drawStroke(currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onMouseLeave() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = null;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchStart(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const touch = e.touches[0];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const pos = this.utils.getTouchPos(touch);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = pos;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchMove(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const touch = e.touches[0];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const currentPoint = this.utils.getTouchPos(touch);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._drawStroke(currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchEnd(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = null;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _drawStroke(currentPoint) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = this.lastPoint || currentPoint;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const dist = this.utils.distanceBetween(this.lastPoint, currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const angle = this.utils.angleBetween(this.lastPoint, currentPoint);&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; for (let ii = 0; ii &amp;lt; dist; ii += 5) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const x = this.lastPoint.x + (Math.sin(angle) * ii);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const y = this.lastPoint.y + (Math.cos(angle) * ii);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const brush = this.brushCtx.createRadialGradient(x, y, 0, x, y, this.brushRadius);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(0, &#039;rgba(0, 0, 0, 1)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(0.3, &#039;rgba(0, 0, 0, 0.1)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(1, &#039;rgba(0, 0, 0, 0)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx.fillStyle = brush;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx.fillRect(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; x - this.brushRadius,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; y - this.brushRadius,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius * 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius * 2&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = currentPoint;&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.globalCompositeOperation = &#039;source-over&#039;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const size = coverImg(this.bgi, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.drawImage(this.bgi, 0, 0, size.w, size.h);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.globalCompositeOperation = &#039;destination-in&#039;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.drawImage(this.brushCanvas, 0, 0);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;const coverImg = (img, width, height) =&amp;gt; {&lt;br /&gt;&amp;#160; &amp;#160; const ratio = img.width / img.height;&lt;br /&gt;&amp;#160; &amp;#160; let w = width;&lt;br /&gt;&amp;#160; &amp;#160; let h = w / ratio;&lt;br /&gt;&amp;#160; &amp;#160; if (h &amp;lt; height) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; h = height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; w = h * ratio;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; return { w, h };&lt;br /&gt;};&lt;/p&gt;
						&lt;p&gt;// Изображения (без лишних пробелов!)&lt;br /&gt;const bgi = &#039;https://atuin.ru/demo/i/fog-bg.webp&#039;;&lt;/p&gt;
						&lt;p&gt;// Адаптивные параметры&lt;br /&gt;function getFogDensity() {&lt;br /&gt;&amp;#160; &amp;#160; if (window.innerWidth &amp;lt; 480) return 25;&amp;#160; &amp;#160;// очень маленькие экраны&lt;br /&gt;&amp;#160; &amp;#160; if (window.innerWidth &amp;lt; 768) return 35;&amp;#160; &amp;#160;// мобильные&lt;br /&gt;&amp;#160; &amp;#160; return 60;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; // десктоп&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;function getEraserRadius() {&lt;br /&gt;&amp;#160; &amp;#160; if (window.innerWidth &amp;lt; 480) return 40;&lt;br /&gt;&amp;#160; &amp;#160; if (window.innerWidth &amp;lt; 768) return 55;&lt;br /&gt;&amp;#160; &amp;#160; return 80;&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;function resize() {&lt;br /&gt;&amp;#160; &amp;#160; // Создаём новые эффекты с адаптивными настройками&lt;br /&gt;&amp;#160; &amp;#160; new Fog({&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; selector: &#039;#fog&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; particle: &#039;https://atuin.ru/demo/i/fog-particle.png&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; density: getFogDensity(),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgi,&lt;br /&gt;&amp;#160; &amp;#160; });&lt;br /&gt;&amp;#160; &amp;#160; new Eraser({&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgCanvas: &#039;#fog-bg&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; brushCanvas: &#039;#brush&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; radius: getEraserRadius(),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgi,&lt;br /&gt;&amp;#160; &amp;#160; });&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;// Инициализация&lt;br /&gt;resize();&lt;br /&gt;window.addEventListener(&amp;quot;resize&amp;quot;, resize);&lt;br /&gt;&amp;lt;/script&amp;gt;[/html]&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 29 Oct 2025 20:41:49 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=314#p314</guid>
		</item>
		<item>
			<title>Ля-ля-ля Новое</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=313#p313</link>
			<description>&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;display: block; text-align: center&quot;&gt;Туман на фотографии, который убирается курсором мыши&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
						&lt;p&gt;[html]&amp;lt;div class=&amp;quot;fog-container&amp;quot;&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;fog&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;fog-bg&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;#160; &amp;#160; &amp;lt;canvas id=&amp;quot;brush&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
						&lt;p&gt;&amp;lt;style&amp;gt;&lt;br /&gt;.fog-container {&lt;br /&gt;&amp;#160; &amp;#160; aspect-ratio: 16 / 9;&lt;br /&gt;&amp;#160; &amp;#160; position: relative;&lt;br /&gt;&amp;#160; &amp;#160; overflow: hidden;&lt;br /&gt;&amp;#160; &amp;#160; margin: 20px 0;&lt;br /&gt;&amp;#160; &amp;#160; border-radius: 6px;&lt;br /&gt;&amp;#160; &amp;#160; touch-action: none; /* &amp;#8592; блокирует стандартные жесты (важно для мобильных) */&lt;br /&gt;}&lt;br /&gt;.fog-container canvas {&lt;br /&gt;&amp;#160; &amp;#160; display: block;&lt;br /&gt;&amp;#160; &amp;#160; width: 100%;&lt;br /&gt;&amp;#160; &amp;#160; height: 100%;&lt;br /&gt;&amp;#160; &amp;#160; position: absolute;&lt;br /&gt;&amp;#160; &amp;#160; left: 50%;&lt;br /&gt;&amp;#160; &amp;#160; top: 0;&lt;br /&gt;&amp;#160; &amp;#160; transform: translateX(-50%);&lt;br /&gt;}&lt;br /&gt;#brush {&lt;br /&gt;&amp;#160; &amp;#160; opacity: 0;&lt;br /&gt;}&lt;br /&gt;/* Мобильные устройства: оставляем на всю ширину */&lt;br /&gt;.fog-container {&lt;br /&gt;&amp;#160; &amp;#160; aspect-ratio: 16 / 9;&lt;br /&gt;&amp;#160; &amp;#160; position: relative;&lt;br /&gt;&amp;#160; &amp;#160; overflow: hidden;&lt;br /&gt;&amp;#160; &amp;#160; margin: 20px 0;&lt;br /&gt;&amp;#160; &amp;#160; border-radius: 6px;&lt;br /&gt;&amp;#160; &amp;#160; touch-action: none;&lt;br /&gt;&amp;#160; &amp;#160; width: 100%;&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;/* Десктоп: ограничиваем максимальную ширину */&lt;br /&gt;@media (min-width: 768px) {&lt;br /&gt;&amp;#160; &amp;#160; .fog-container {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; max-width: 60rem; /* &amp;#8776;960px при базовом шрифте 16px */&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; /* Или, например: max-width: 80vw; — 80% ширины окна */&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; margin-left: auto;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; margin-right: auto;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;br /&gt;&amp;lt;/style&amp;gt;&lt;/p&gt;
						&lt;p&gt;&amp;lt;script&amp;gt;&lt;br /&gt;class FogParticle {&lt;br /&gt;&amp;#160; &amp;#160; constructor(ctx, canvasWidth, canvasHeight) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx = ctx;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = canvasWidth;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = canvasHeight;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = 0;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setPosition(x, y) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = x;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = y;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setVelocity(x, y) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = x;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = y;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; setImage(image) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.image = image;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; render() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.image) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.drawImage(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.image,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x - this.image.width / 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y - this.image.height / 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; 400,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; 400&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x += this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y += this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.x &amp;gt;= this.canvasWidth) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = -this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = this.canvasWidth;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else if (this.x &amp;lt;= 0) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.xVelocity = -this.xVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.x = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.y &amp;gt;= this.canvasHeight) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = -this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = this.canvasHeight;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else if (this.y &amp;lt;= 0) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.yVelocity = -this.yVelocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.y = 0;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;class Fog {&lt;br /&gt;&amp;#160; &amp;#160; constructor({ selector, density = 50, velocity = 2, particle, bgi } = {}) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const canvas = document.querySelector(selector);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = canvas.parentElement.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx = canvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = canvas.width = bcr.width;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = canvas.height = bcr.height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particleCount = density;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.maxVelocity = velocity;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particle = particle;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = bgi;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._createParticles();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._setImage();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.bgi) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const img = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.onload = () =&amp;gt; {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const size = coverImg(img, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = { img, w: size.w, h: size.h };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this._render();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.src = this.bgi;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _createParticles() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles = [];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const random = (min, max) =&amp;gt; Math.random() * (max - min) + min;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; for (let i = 0; i &amp;lt; this.particleCount; i++) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const particle = new FogParticle(this.ctx, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; particle.setPosition(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(0, this.canvasWidth),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(0, this.canvasHeight)&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; particle.setVelocity(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(-this.maxVelocity, this.maxVelocity),&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; random(-this.maxVelocity, this.maxVelocity)&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles.push(particle);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _setImage() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (!this.particle) return;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const img = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.onload = () =&amp;gt; this.particles.forEach(p =&amp;gt; p.setImage(img));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; img.src = this.particle;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; _render() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; if (this.bgi) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.drawImage(this.bgi.img, 0, 0, this.bgi.w, this.bgi.h);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; } else {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.fillStyle = &amp;quot;rgba(0, 0, 0, 1)&amp;quot;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.particles.forEach(p =&amp;gt; p.render());&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; requestAnimationFrame(this._render.bind(this));&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;class Eraser {&lt;br /&gt;&amp;#160; &amp;#160; constructor({ bgCanvas, brushCanvas, bgi, radius = 120 } = {}) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCanvas = document.querySelector(bgCanvas);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCanvas = document.querySelector(brushCanvas);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx = this.bgCanvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx = this.brushCanvas.getContext(&#039;2d&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.parentElement = this.bgCanvas.parentElement;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = this.parentElement.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasWidth = this.bgCanvas.width = this.brushCanvas.width = bcr.width;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.canvasHeight = this.bgCanvas.height = this.brushCanvas.height = bcr.height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius = radius;&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi = new Image();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi.src = bgi;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgi.onload = this._attachEvents.bind(this);&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const bgCanvasEl = this.bgCanvas;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.utils = {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; distanceBetween(point1, point2) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; angleBetween(point1, point2) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return Math.atan2(point2.x - point1.x, point2.y - point1.y);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; getMousePos(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = bgCanvasEl.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return { x: e.clientX - bcr.left, y: e.clientY - bcr.top };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; },&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; getTouchPos(touch) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const bcr = bgCanvasEl.getBoundingClientRect();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; return { x: touch.clientX - bcr.left, y: touch.clientY - bcr.top };&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; };&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _attachEvents() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const parent = this.parentElement;&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; // Мышь&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;mousemove&#039;, this._onMouseMove.bind(this));&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;mouseleave&#039;, this._onMouseLeave.bind(this));&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; // Касания&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchstart&#039;, this._onTouchStart.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchmove&#039;, this._onTouchMove.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; parent.addEventListener(&#039;touchend&#039;, this._onTouchEnd.bind(this), { passive: false });&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onMouseMove(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const currentPoint = this.utils.getMousePos(e);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._drawStroke(currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onMouseLeave() {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = null;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchStart(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const touch = e.touches[0];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const pos = this.utils.getTouchPos(touch);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = pos;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchMove(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const touch = e.touches[0];&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const currentPoint = this.utils.getTouchPos(touch);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this._drawStroke(currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _onTouchEnd(e) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; e.preventDefault();&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = null;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; _drawStroke(currentPoint) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = this.lastPoint || currentPoint;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const dist = this.utils.distanceBetween(this.lastPoint, currentPoint);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const angle = this.utils.angleBetween(this.lastPoint, currentPoint);&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; for (let ii = 0; ii &amp;lt; dist; ii += 5) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const x = this.lastPoint.x + (Math.sin(angle) * ii);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const y = this.lastPoint.y + (Math.cos(angle) * ii);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; const brush = this.brushCtx.createRadialGradient(x, y, 0, x, y, this.brushRadius);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(0, &#039;rgba(0, 0, 0, 1)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(0.3, &#039;rgba(0, 0, 0, 0.1)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; brush.addColorStop(1, &#039;rgba(0, 0, 0, 0)&#039;);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx.fillStyle = brush;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushCtx.fillRect(&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; x - this.brushRadius,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; y - this.brushRadius,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius * 2,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; this.brushRadius * 2&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; &amp;#160; );&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; }&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.lastPoint = currentPoint;&lt;/p&gt;
						&lt;p&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; // Перерисовка фона с маской&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.globalCompositeOperation = &#039;source-over&#039;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; const size = coverImg(this.bgi, this.canvasWidth, this.canvasHeight);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.drawImage(this.bgi, 0, 0, size.w, size.h);&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.globalCompositeOperation = &#039;destination-in&#039;;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; this.bgCtx.drawImage(this.brushCanvas, 0, 0);&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;const coverImg = (img, width, height) =&amp;gt; {&lt;br /&gt;&amp;#160; &amp;#160; const ratio = img.width / img.height;&lt;br /&gt;&amp;#160; &amp;#160; let w = width;&lt;br /&gt;&amp;#160; &amp;#160; let h = w / ratio;&lt;br /&gt;&amp;#160; &amp;#160; if (h &amp;lt; height) {&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; h = height;&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; w = h * ratio;&lt;br /&gt;&amp;#160; &amp;#160; }&lt;br /&gt;&amp;#160; &amp;#160; return { w, h };&lt;br /&gt;};&lt;/p&gt;
						&lt;p&gt;// &amp;#9888;&amp;#65039; Убраны лишние пробелы в URL!&lt;br /&gt;const bgi = &#039;https://atuin.ru/demo/i/fog-bg.webp&#039;;&lt;/p&gt;
						&lt;p&gt;function resize() {&lt;br /&gt;&amp;#160; &amp;#160; // Очистим старые экземпляры при resize (опционально, но полезно)&lt;br /&gt;&amp;#160; &amp;#160; new Fog({&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; selector: &#039;#fog&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; particle: &#039;https://atuin.ru/demo/i/fog-particle.png&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; density: 60,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgi,&lt;br /&gt;&amp;#160; &amp;#160; });&lt;br /&gt;&amp;#160; &amp;#160; new Eraser({&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgCanvas: &#039;#fog-bg&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; brushCanvas: &#039;#brush&#039;,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; radius: 80,&lt;br /&gt;&amp;#160; &amp;#160; &amp;#160; &amp;#160; bgi,&lt;br /&gt;&amp;#160; &amp;#160; });&lt;br /&gt;}&lt;/p&gt;
						&lt;p&gt;resize();&lt;br /&gt;window.addEventListener(&amp;quot;resize&amp;quot;, resize);&lt;br /&gt;&amp;lt;/script&amp;gt;[/html]&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Wed, 29 Oct 2025 15:59:21 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=313#p313</guid>
		</item>
		<item>
			<title>#16a085;;#8f0505;;77474</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=303#p303</link>
			<description>&lt;p&gt;7777777&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 04:56:41 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=303#p303</guid>
		</item>
		<item>
			<title>#3498db;;#b3e6ea;;Тест</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=302#p302</link>
			<description>&lt;p&gt;00000000000&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 04:15:33 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=302#p302</guid>
		</item>
		<item>
			<title>#16a085;;#e6d0d0;;6гг6г6г6г6</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=301#p301</link>
			<description>&lt;p&gt;6г6г6гг665г65г&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 04:14:37 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=301#p301</guid>
		</item>
		<item>
			<title>#16a085;;#a69191;;г6г6г6</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=300#p300</link>
			<description>&lt;p&gt;г6г6г5г5г&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 04:14:06 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=300#p300</guid>
		</item>
		<item>
			<title>#d35400;;оеоеоеоен</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=299#p299</link>
			<description>&lt;p&gt;еноеоен&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 03:21:02 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=299#p299</guid>
		</item>
		<item>
			<title>#d35400;;5н4н45н45н</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=297#p297</link>
			<description>&lt;p&gt;н5н45н45н&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 03:00:25 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=297#p297</guid>
		</item>
		<item>
			<title>#3498db;;565656г</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=296#p296</link>
			<description>&lt;p&gt;ггггггггггггггггг&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 02:54:08 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=296#p296</guid>
		</item>
		<item>
			<title>#3498db;;Всем привет!!!</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=295#p295</link>
			<description>&lt;p&gt;ййййййййй&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 02:49:12 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=295#p295</guid>
		</item>
		<item>
			<title>#c0392b;;цсцауа</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=294#p294</link>
			<description>&lt;p&gt;ауауцуау&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 02:48:40 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=294#p294</guid>
		</item>
		<item>
			<title>#00897b;;7ш76ш76ш67</title>
			<link>http://ktest.mybb.ru/viewtopic.php?pid=293#p293</link>
			<description>&lt;p&gt;ш7ш7ш67ш&lt;/p&gt;</description>
			<author>mybb@mybb.ru (Merlin)</author>
			<pubDate>Fri, 17 Oct 2025 02:38:20 +0300</pubDate>
			<guid>http://ktest.mybb.ru/viewtopic.php?pid=293#p293</guid>
		</item>
	</channel>
</rss>
