عندما تحتاج إلى عرض قياسات أو تسميات أو تعليقات أو أيقونات أو رسومات مؤقتة فوق نموذج Three.js — خاصة في العمارة حيث يهم الموضع والدقة الرقمية — لديك عدة خيارات عملية. أعرض فيما يلي التقنيات الشائعة مع مقتطفات كود قصيرة ومقارنة، لتختار الأداة المناسبة لكل مهمة.
1) طبقة Canvas 2D (إسقاط ثلاثي الأبعاد إلى ثنائي والرسم على canvas)
تحتفظ بـ canvas عادي لـ WebGL من أجل Three.js وتضع فوقه <canvas> شفافًا من HTML (position: absolute). في كل إطار تُسقط النقاط ثلاثية الأبعاد بـ vector.project(camera) وترسم الأشكال والنصوص في المواضع الثنائية باستخدام Canvas 2D API.
<canvas id="webglCanvas"></canvas>
<canvas id="overlayCanvas" style="position:absolute; top:0; left:0; pointer-events:none;"></canvas>
<script type="module">
import * as THREE from "three";
const overlayCanvas = document.getElementById("overlayCanvas");
const overlayCtx = overlayCanvas.getContext("2d");
// ... scene, camera, renderer and controls ...
overlayCanvas.width = window.innerWidth;
overlayCanvas.height = window.innerHeight;
const points = [new THREE.Vector3(0, 0, 0), new THREE.Vector3(1, 1, 0)];
const tempPoint = new THREE.Vector3(1, 0.5, 0);
function projectTo2D(vec3) {
const v = vec3.clone().project(camera);
return {
x: (v.x * 0.5 + 0.5) * overlayCanvas.width,
y: (-v.y * 0.5 + 0.5) * overlayCanvas.height,
};
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
// Clear and redraw the overlay every frame
overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height);
overlayCtx.fillStyle = "red";
points.forEach(p => {
const { x, y } = projectTo2D(p);
overlayCtx.beginPath();
overlayCtx.arc(x, y, 5, 0, Math.PI * 2);
overlayCtx.fill();
});
const start = projectTo2D(points[0]);
const end = projectTo2D(tempPoint);
overlayCtx.strokeStyle = "yellow";
overlayCtx.lineWidth = 2;
overlayCtx.beginPath();
overlayCtx.moveTo(start.x, start.y);
overlayCtx.lineTo(end.x, end.y);
overlayCtx.stroke();
}
animate();
</script>متى نستخدمها: المعاينات السريعة والعناصر المؤقتة (سحب خط جديد أثناء تحريك المستخدم للفأرة)، والعناصر الكثيرة التي لا تحتاج تنسيق HTML/CSS وتكون شبكات GPU ثقيلة عليها، وعندما تحتاج أقصى مرونة في الرسم الثنائي.
المزايا: تنفيذ سريع جدًا؛ Canvas 2D API بسيطة ومرنة؛ مناسبة للعناصر المؤقتة والطبقات الديناميكية الكثيرة.
العيوب: ليست كائنًا ثلاثي الأبعاد حقيقيًا — عليك إعادة الإسقاط والرسم في كل إطار لتبقى متزامنة مع الكاميرا، وإلا انزاحت الطبقة. تنسيق النص محدود مقارنة بـ HTML/CSS، ويجب ضبط الإحداثيات بـ devicePixelRatio لخطوط حادة.
2) هندسة Three.js ثلاثية الأبعاد (Line وLineSegments وPoints وشبكات صغيرة)
أنشئ هندسة ثلاثية الأبعاد حقيقية — THREE.Line مع BufferGeometry لقطعة قياس، وTHREE.SphereGeometry أو THREE.Points للعلامات. تعيش هذه الكائنات في شجرة المشهد ويعرضها WebGL، فتلتزم طبيعيًا بتحويلات الكاميرا والإخفاء والعلاقات المكانية.
// A persistent 3D line between two Vector3s (a, b)
const geometry = new THREE.BufferGeometry().setFromPoints([a, b]);
const material = new THREE.LineBasicMaterial({ color: 0xffaa00, linewidth: 2 });
const line = new THREE.Line(geometry, material);
scene.add(line);متى نستخدمها: القياسات الدائمة التي يجب أن تلتصق بالهندسة وتبقى دقيقة مع حركة الكاميرا؛ وعندما يهم الإخفاء أو علاقات العمق مع شبكات أخرى؛ وعندما تحتاج التحرير أو التحديد أو الالتقاط على الكائن نفسه.
المزايا: الخيار الأدق والأكثر متانة — الخطوط والدبابيس كائنات ثلاثية الأبعاد حقيقية متزامنة طبيعيًا مع الكاميرا. يمكنك الاستفادة من أداء GPU (BufferGeometry) والشيدرات لتنسيق عدد كبير من الخطوط.
العيوب: أكثر تعقيدًا قليلًا (تدير الهندسات والتحديثات والذاكرة). ولآلاف الشبكات الصغيرة استخدم التجميع (Batching) أو Instancing.
3) Sprites (THREE.Sprite) والمربعات المكسوّة بالخامات
THREE.Sprite سطح يواجه الكاميرا دائمًا ومكسوّ بصورة نقطية — مناسب للأيقونات الصغيرة أو صور العلامات. تعيش في الفضاء ثلاثي الأبعاد فتتبع التحويلات والعمق، لكنها نقطية.
const labelCanvas = document.createElement("canvas");
// draw text into the canvas context...
const texture = new THREE.CanvasTexture(labelCanvas);
const spriteMaterial = new THREE.SpriteMaterial({ map: texture, depthTest: false });
const sprite = new THREE.Sprite(spriteMaterial);
sprite.position.copy(point3D);
scene.add(sprite);متى نستخدمها: أيقونات أو تسميات صغيرة يجب أن تظهر في الفضاء ثلاثي الأبعاد وتواجه الكاميرا دائمًا، أو نص يُعرض كخامة.
المزايا: بسيطة وداخل المشهد (تتبع الكاميرا والإخفاء)؛ ويمكن توليدها ديناميكيًا من canvas.
العيوب: يستهلك كل Sprite خامة على GPU، لذا يحتاج العدد الكبير إلى تجميع أو Instancing. جودة النص تعتمد على الدقة وقد تصبح ضبابية مع التكبير.
4) CSS2DRenderer (تسميات HTML مرتبطة بمواضع ثلاثية الأبعاد)
يربط CSS2DRenderer في Three.js عناصر DOM بكائنات CSS2DObject في المشهد. تُنقل العناصر في كل إطار إلى موضعها الصحيح على الشاشة، فتبدو ملتصقة بنقاط ثلاثية الأبعاد. ولأنها تبقى DOM يمكنك تنسيقها بـ CSS وإضافة أحداث وتلميحات.
import { CSS2DRenderer, CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer.js";
const label = document.createElement("div");
label.className = "label";
label.innerText = "3.24 m";
const labelObject = new CSS2DObject(label);
labelObject.position.copy(point3D);
scene.add(labelObject);
// In the render loop, alongside the WebGL renderer
labelRenderer.render(scene, camera);
renderer.render(scene, camera);متى نستخدمها: تسميات نصية منسقة، وتلميحات HTML تفاعلية، وواجهات تعليقات قابلة للنقر — كلما احتجت تنسيق CSS كاملًا.
المزايا: نص حاد وتنسيق سهل بـ HTML/CSS؛ ممتاز للتسميات والواجهات التفاعلية.
العيوب: عناصر DOM ليست WebGL، لذا يتراجع الأداء مع مئات التسميات. للاستخدام المعماري المعتاد (عشرات إلى بضع مئات) عملي جدًا.
5) CSS3DRenderer (عناصر DOM حقيقية بتحويلات ثلاثية الأبعاد)
يضع CSS3DRenderer عناصر DOM ضمن تحويلات ثلاثية الأبعاد، فيمكنك وضع HTML في فضاء ثلاثي حقيقي مع الدوران والتحجيم. مفيد للوحات التفاعلية وصفحات الويب المضمّنة وعناصر الواجهة التي يجب أن تشارك في التحويلات ثلاثية الأبعاد — مثل لوحة إعلانية دوّارة بمحتوى HTML. قوي لتجارب محددة لكنه أثقل وأكثر تعقيدًا؛ وعدد عناصر DOM وتحويلات CSS هي القيود الأساسية.
6) النهج الهجين (الموصى به لأدوات القياس المعمارية)
نمط عملي ومتين:
- استخدم الخطوط والنقاط ثلاثية الأبعاد (
THREE.LineوكراتTHREE.Meshحقيقية) للقياسات الدائمة — فهذا يضمن الدقة والتحديد والالتقاط والعمق الصحيح. - استخدم CSS2DRenderer للتسميات (الأرقام والوحدات وHTML التفاعلي) لخطوط حادة وتنسيق CSS.
- استخدم طبقة Canvas 2D للمعاينات المؤقتة فقط، مثل سحب قياس جديد — رخيصة وفورية.
- استخدم Sprites اختياريًا لعدد كبير من الأيقونات الصغيرة، بشرط تجميعها أو استخدام Instancing بعناية.
يمنحك هذا المزيج أفضل ما في الدقة ومرونة الواجهة والأداء.



