Sunrise
قد تكون الجسيمات صغير بحيث لا يمكن رؤيتها عند استخدام الكود في مكان بعرض أقل من عرض الشاشة، لذلك عدل الكود الذي يضيف الكود القصير في ملف functions.php إلى ما يلي:
<?php
/**
* كود قصير لعرض تأثير الجسيمات لشعار الموقع
*/
function render_logo_particle_shortcode() {
ob_start();
?>
<div class="logo-particle-container">
<canvas id="logo-particle-canvas"></canvas>
</div>
<style>
.logo-particle-container {
position: relative;
width: 100%;
/* لجعل الحاوية مربّعة حساسًا للعرض */
padding-top: 100%;
background-color: #000;
overflow: hidden;
}
.logo-particle-container canvas {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
display: block;
}
</style>
<script>
jQuery(document).ready(function($) {
// العثور على مصدر شعار الموقع
var logoElement = $(".site-logo img, .custom-logo, img[alt*='logo'], .logo img").first();
if (!logoElement.length) {
console.error("لم يتم العثور على صورة الشعار في الصفحة");
return;
}
var logoSrc = logoElement.attr("src");
var canvas = document.getElementById("logo-particle-canvas");
// تعريف Particle
class Particle {
constructor(x, y, size, baseX, baseY, ctx, color) {
this.x = x; this.y = y;
this.size = size;
this.baseX = baseX; this.baseY = baseY;
this.ctx = ctx; this.color = color;
this.density = Math.random() * 30 + 2;
}
draw() {
this.ctx.fillStyle = this.color;
this.ctx.beginPath();
this.ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
this.ctx.closePath();
this.ctx.fill();
}
update(mouse) {
if (mouse.x === null) {
// ترجع إلى الموقع الأساسي
this.x += (this.baseX - this.x) * 0.05;
this.y += (this.baseY - this.y) * 0.05;
} else {
let dx = mouse.x - this.x;
let dy = mouse.y - this.y;
let dist = Math.sqrt(dx*dx + dy*dy);
if (dist < mouse.radius) {
let force = (mouse.radius - dist) / mouse.radius;
let dirX = (dx / dist) * force * this.density;
let dirY = (dy / dist) * force * this.density;
this.x -= dirX;
this.y -= dirY;
} else {
this.x += (this.baseX - this.x) * 0.05;
this.y += (this.baseY - this.y) * 0.05;
}
}
}
}
// تطبيق App
class App {
constructor(canvas, imageSrc) {
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
this.image = new Image();
this.image.crossOrigin = "Anonymous";
this.image.src = imageSrc;
this.particles = [];
this.mouse = { x: null, y: null, radius: 150 };
this.image.onload = () => {
this.resize();
};
this.animate();
this.addEventListeners();
}
// يضبط قياس الكانڤاس ويبني الجسيمات
resize() {
this.canvas.width = this.canvas.offsetWidth;
this.canvas.height = this.canvas.offsetHeight;
this.particles = [];
this.initParticles();
}
// استخراج بيانات الصورة وإنشاء الجسيمات
initParticles() {
const w = this.canvas.width;
const h = this.canvas.height;
// حجم اللوغو كنسبة من أصغر بعد
const logoSize = Math.min(w, h) * 0.6;
const logoX = (w - logoSize) / 2;
const logoY = (h - logoSize) / 2;
// رسم الصورة لاستخراج بكسلاتها
this.ctx.clearRect(0, 0, w, h);
this.ctx.drawImage(this.image, logoX, logoY, logoSize, logoSize);
const imageData = this.ctx.getImageData(logoX, logoY, logoSize, logoSize).data;
// عدد الجسيمات يعتمد على المسافة spacing
const spacing = 4;
const cols = Math.floor(logoSize / spacing);
const rows = Math.floor(logoSize / spacing);
const particleWidth = logoSize / cols;
const particleHeight = logoSize / rows;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const posX = x * particleWidth + logoX;
const posY = y * particleHeight + logoY;
const px = Math.floor(x * particleWidth);
const py = Math.floor(y * particleHeight);
const idx = (py * logoSize + px) * 4;
const r = imageData[idx];
const g = imageData[idx+1];
const b = imageData[idx+2];
const a = imageData[idx+3];
if (a > 0) {
const color = `rgba(${r},${g},${b},${a/255})`;
const size = Math.random() * 0.7 + 0.3;
this.particles.push(new Particle(posX, posY, size, posX, posY, this.ctx, color));
}
}
}
}
// رسم الجسيمات وتحديثها
animate() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.particles.forEach(p => {
p.update(this.mouse);
p.draw();
});
requestAnimationFrame(() => this.animate());
}
// التعامل مع حركة الفأرة وخروجها
addEventListeners() {
this.canvas.addEventListener("mousemove", e => {
const rect = this.canvas.getBoundingClientRect();
this.mouse.x = e.clientX - rect.left;
this.mouse.y = e.clientY - rect.top;
});
this.canvas.addEventListener("mouseleave", () => {
this.mouse.x = null;
this.mouse.y = null;
});
}
}
// إنشاء التطبيق
var app = new App(canvas, logoSrc);
// إعادة القياس عند تغيير حجم النافذة
$(window).on('resize', () => app.resize());
// في Elementor: تأكد من إعادة القياس بعد أن يصبح العنصر ظاهرًا
if (window.elementorFrontend) {
elementorFrontend.hooks.addAction(
'frontend/element_ready/shortcode.default',
function($scope) {
if ($scope.find('#logo-particle-canvas').length) {
app.resize();
}
}
);
}
});
</script>
<?php
return ob_get_clean();
}
add_shortcode('logo_particles', 'render_logo_particle_shortcode');