.. include:: /Includes.rst.txt .. _developer: ================= Developer's Guide ================= This chapter covers the technical aspects of integrating the Focal Point Editor in your TYPO3 templates and custom extensions. .. contents:: :local: :depth: 2 .. _developer-namespace: Namespace ========= The extension uses the namespace: .. code-block:: php Nng\Nnfocalpoint .. _developer-viewhelpers: ViewHelpers =========== The extension provides six ViewHelpers for easy frontend integration. .. _developer-css: CSS Styles ---------- The extension includes a frontend CSS file with basic styles. Include it via TypoScript: .. code-block:: typoscript page.includeCSS.nnfocalpoint = EXT:nnfocalpoint/Resources/Public/Css/Frontend.css Or include the static TypoScript "Focal Point Editor" in your template. **Available CSS classes:** - ``.nnfp-image`` - Automatically added to images from ``nnfp:image`` (width/height 100%, display block) - ``.nnfp-container`` - Container with overflow hidden for focal point images - ``.nnfp-container--16-9``, ``--4-3``, ``--1-1``, ``--3-2``, ``--21-9`` - Aspect ratio helpers - ``.nnfp-bg`` - Background image helper (background-size: cover, no-repeat) .. _developer-viewhelpers-namespace: Registering the Namespace ------------------------- The extension registers a global namespace ``nnfp`` automatically. You can use the ViewHelpers without any namespace declaration: .. code-block:: html
Alternatively, you can use the full namespace declaration: .. code-block:: html {namespace nnfocalpoint=Nng\Nnfocalpoint\ViewHelpers} Or use the XML namespace syntax: .. code-block:: html .. _developer-viewhelper-image: ImageViewHelper (Drop-in f:image replacement) --------------------------------------------- A drop-in replacement for ``f:image`` that automatically adds focal point styling. All standard ``f:image`` arguments are supported. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\ImageViewHelper`` **Additional Arguments:** .. list-table:: :header-rows: 1 :widths: 20 20 10 50 * - Argument - Type - Required - Description * - objectFit - string - No - CSS object-fit value (default: ``cover``) * - disableFocalPoint - bool - No - Set to true to disable focal point styling **Usage:** .. code-block:: html **Output:** .. code-block:: html .. note:: The ``nnfp-image`` CSS class is automatically added to all images rendered with this ViewHelper. This class provides basic styling (width/height 100%, display block) that works well with container-based layouts. .. _developer-viewhelper-focalcrop: FocalCropViewHelper (Server-side focal crop) -------------------------------------------- Crops images to exact dimensions while keeping the focal point centered. Unlike ``nnfp:image`` which uses CSS positioning, this ViewHelper performs actual server-side cropping - the generated image file has the exact target dimensions. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\FocalCropViewHelper`` **Arguments:** .. list-table:: :header-rows: 1 :widths: 20 20 10 50 * - Argument - Type - Required - Description * - image - object - Yes - The file reference object * - width - string - No - Width specification (append "c" for crop) * - height - string - No - Height specification (append "c" for crop) * - cropVariant - string - No - Crop variant for focal point lookup (default: ``default``) * - absolute - bool - No - Force absolute URL (default: ``false``) **Usage:** .. code-block:: html **How it works:** The "c" suffix indicates that dimension should be cropped. The ViewHelper: 1. Calculates the target aspect ratio (e.g., 400:200 = 2:1) 2. Crops the original image to match that aspect ratio, centered on the focal point 3. Scales the cropped result to the final dimensions **Example:** For a 1200x800 image with focal point at (0.7, 0.3): - ``width="400c" height="200"`` creates a 2:1 crop (800x400 from original) - The crop window is positioned to keep the focal point (at x=840, y=240) as centered as possible - Result is scaled to 400x200 **Output:** .. code-block:: html .. _developer-viewhelper-focalcrop-replacing-cropvariants: Replacing CropVariants with FocalCrop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``nnfp:focalCrop`` ViewHelper can largely replace the need for multiple crop variants. Traditional TYPO3 crop variants require editors to manually define crop areas for each aspect ratio (desktop, tablet, mobile, square, etc.). This is time-consuming and error-prone. **With focal points, you can simplify this workflow:** 1. Use only the **default crop variant** in your TCA configuration 2. Let editors set a **single focal point** on the important part of the image 3. Use ``nnfp:focalCrop`` with different dimensions - the focal point stays centered automatically **Before (traditional approach):** .. code-block:: html **After (with focal point):** .. code-block:: html **Benefits:** - **Less editor work:** One focal point instead of multiple crop definitions - **Consistent results:** The important subject stays visible in all aspect ratios - **Flexible frontend:** Developers can use any aspect ratio without backend changes - **Simpler TCA:** No need to configure multiple crop variants .. tip:: This approach works best for images where there's a clear subject (person, product, logo) that should remain visible. For images requiring precise artistic framing per aspect ratio, traditional crop variants may still be preferred. .. _developer-viewhelper-uri-focalcrop: Uri\\FocalCropViewHelper (URI only) ----------------------------------- Returns only the URI of a focal-point-cropped image. Use this when you need the image URL for custom markup, srcset, or JavaScript. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\Uri\FocalCropViewHelper`` **Arguments:** Same as ``FocalCropViewHelper`` **Usage:** .. code-block:: html {image.alternative}
{nnfp:uri.focalCrop(image: image, width: '400c', height: '200', absolute: 1)} **Output:** .. code-block:: text /fileadmin/_processed_/csm_image_abc123.jpg .. _developer-viewhelper-backgroundstyle: BackgroundStyleViewHelper ------------------------- Returns a complete style attribute value for background images with focal point. Use this for divs or other elements with background images. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\BackgroundStyleViewHelper`` **Arguments:** .. list-table:: :header-rows: 1 :widths: 20 20 10 50 * - Argument - Type - Required - Description * - image - mixed - Yes - The file reference object or array * - cropVariant - string - No - The crop variant (default: ``default``) * - width - string - No - Width for image processing (e.g., "1920" or "1920c") * - height - string - No - Height for image processing * - backgroundSize - string - No - CSS background-size value (default: ``cover``) * - includeRepeat - bool - No - Include background-repeat: no-repeat (default: ``true``) * - fallbackPosition - string - No - Fallback position if no focal point (default: ``50% 50%``) **Usage:** .. code-block:: html
Content here

Hero Title

Content
Content
**Output:** .. code-block:: html
Content here
.. _developer-viewhelper-objectposition: ObjectPositionViewHelper ------------------------ Returns a CSS ``object-position`` value based on the focal point coordinates. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\ObjectPositionViewHelper`` **Arguments:** .. list-table:: :header-rows: 1 :widths: 20 20 10 50 * - Argument - Type - Required - Description * - image - mixed - Yes - The file reference object or array * - cropVariant - string - No - The crop variant to get the focal point for (default: ``default``) * - fallback - string - No - Fallback value if no focal point is set (default: ``50% 50%``) **Usage:** .. code-block:: html **Output:** .. code-block:: html **With fallback:** .. code-block:: html .. _developer-viewhelper-focalpoint: FocalPointViewHelper -------------------- Returns the raw focal point data for a specific crop variant. **Class:** ``Nng\Nnfocalpoint\ViewHelpers\FocalPointViewHelper`` **Arguments:** .. list-table:: :header-rows: 1 :widths: 20 20 10 50 * - Argument - Type - Required - Description * - image - mixed - Yes - The file reference object or array * - cropVariant - string - No - The crop variant to get the focal point for (default: ``default``) * - as - string - No - Variable name to assign the focal point to **Usage (inline):** .. code-block:: html {nnfp:focalPoint(image: image, cropVariant: 'default')} **Usage (with variable):** .. code-block:: html

Focal point: {fp.x} / {fp.y}

**Return value:** Returns an array with ``x`` and ``y`` keys (values 0-1), or ``null`` if no focal point is set: .. code-block:: php ['x' => 0.5, 'y' => 0.3] .. _developer-data-format: Data Format =========== Focal points are stored in the ``sys_file_reference.tx_nnfocalpoint_points`` field as a JSON string: .. code-block:: json { "default": {"x": 0.5, "y": 0.3}, "landscape": {"x": 0.9, "y": 0.712}, "portrait": {"x": 0.2, "y": 0.5} } **Coordinate System:** - ``x: 0`` = left edge - ``x: 1`` = right edge - ``y: 0`` = top edge - ``y: 1`` = bottom edge - ``x: 0.5, y: 0.5`` = center of the image .. _developer-php-access: Accessing Focal Points in PHP ============================= From FileReference Object ------------------------- .. code-block:: php use TYPO3\CMS\Core\Resource\FileReference; /** @var FileReference $image */ $focalPointsJson = $image->getProperty('tx_nnfocalpoint_points'); $focalPoints = json_decode($focalPointsJson, true) ?: []; // Get focal point for a specific variant $defaultFocalPoint = $focalPoints['default'] ?? null; if ($defaultFocalPoint) { $x = $defaultFocalPoint['x']; $y = $defaultFocalPoint['y']; } From Extbase FileReference -------------------------- .. code-block:: php use TYPO3\CMS\Extbase\Domain\Model\FileReference; /** @var FileReference $image */ $originalResource = $image->getOriginalResource(); $focalPointsJson = $originalResource->getProperty('tx_nnfocalpoint_points'); $focalPoints = json_decode($focalPointsJson, true) ?: []; .. _developer-custom-integration: Custom Integration Examples =========================== The following examples show how to use the focal point data in your templates. The result ensures that the important part of the image remains visible when the container is scaled or cropped. .. figure:: /Images/03.jpeg :alt: Frontend result with focal point :class: with-shadow Using ``object-position`` with the focal point coordinates keeps the subject visible regardless of container dimensions. .. _developer-css: Required CSS ------------ For focal points to work correctly, you need CSS that allows the image to be positioned within its container. Here are the essential styles: .. code-block:: css /* Basic focal point container */ .focal-container { position: relative; overflow: hidden; } /* Image with focal point - fills container and respects focal point */ .focal-container img { width: 100%; height: 100%; object-fit: cover; /* object-position is set inline via ViewHelper */ } /* Fixed aspect ratio containers */ .focal-container--16-9 { aspect-ratio: 16 / 9; } .focal-container--4-3 { aspect-ratio: 4 / 3; } .focal-container--1-1 { aspect-ratio: 1 / 1; } /* Background image with focal point */ .focal-bg { background-size: cover; background-repeat: no-repeat; /* background-position is set inline via ViewHelper */ } .. _developer-example-img: Example 1: Simple IMG Tag ------------------------- The most basic usage with a standard ```` tag: .. code-block:: html
{image.alternative}
{image.alternative}
.. _developer-example-fimage: Example 2: Using f:image ViewHelper ----------------------------------- Combine TYPO3's ``f:image`` ViewHelper with focal point positioning: .. code-block:: html
.. note:: When using ``f:image`` with cropping (``width="600c"``), the focal point provides additional fine-tuning for how the already-cropped image is positioned in its container. .. _developer-example-background: Example 3: Background Images ---------------------------- Use focal points with CSS background images: .. code-block:: html

Hero Title

{headline}

{subheadline}

CSS for the hero section: .. code-block:: css .hero { position: relative; display: flex; align-items: center; justify-content: center; color: white; text-align: center; } .hero::before { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.4); } .hero__content { position: relative; z-index: 1; padding: 2rem; } .. _developer-example-custom: Example 4: Custom Logic with FocalPoint ViewHelper -------------------------------------------------- For advanced use cases, access the raw focal point data: .. code-block:: html

Focal point: X={fp.x}, Y={fp.y}

Text on right (focal point is on left)
Text on left (focal point is on right)
CSS for hotspot marker: .. code-block:: css .image-with-hotspot { position: relative; display: inline-block; } .hotspot { position: absolute; width: 20px; height: 20px; background: rgba(255, 0, 0, 0.7); border: 2px solid white; border-radius: 50%; transform: translate(-50%, -50%); pointer-events: none; animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); } 50% { transform: translate(-50%, -50%) scale(1.2); } } .. _developer-example-responsive: Example 5: Responsive Images with Picture Element ------------------------------------------------- Different focal points for different crop variants: .. code-block:: html {image.alternative} .. _developer-example-data-attr: Example 6: Data Attributes for JavaScript ----------------------------------------- Pass focal point data to JavaScript for dynamic effects: .. code-block:: html {image.alternative} Example JavaScript for parallax effect respecting focal point: .. code-block:: javascript document.querySelectorAll('.js-parallax-image').forEach(img => { const focalX = parseFloat(img.dataset.focalX) || 0.5; const focalY = parseFloat(img.dataset.focalY) || 0.5; window.addEventListener('scroll', () => { const rect = img.getBoundingClientRect(); const scrollProgress = 1 - (rect.bottom / (window.innerHeight + rect.height)); // Parallax offset based on focal point const offsetY = (scrollProgress - 0.5) * 50 * (1 - focalY); img.style.objectPosition = `${focalX * 100}% calc(${focalY * 100}% + ${offsetY}px)`; }); }); .. _developer-extending: Extending the Extension ======================= Custom Form Element ------------------- The focal point form element is registered in ``ext_localconf.php``: .. code-block:: php $GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][1702100000] = [ 'nodeName' => 'focalPointElement', 'priority' => 40, 'class' => \Nng\Nnfocalpoint\Form\Element\FocalPointElement::class, ]; You can create a custom form element by extending ``FocalPointElement`` and registering it with a higher priority. Custom ViewHelper ----------------- Create custom ViewHelpers by extending the existing ones: .. code-block:: php namespace YourVendor\YourExtension\ViewHelpers; use Nng\Nnfocalpoint\ViewHelpers\ObjectPositionViewHelper; class CustomObjectPositionViewHelper extends ObjectPositionViewHelper { public function render(): string { $position = parent::render(); // Add custom logic return $position; } } .. _developer-api: API Reference ============= FocalPointController -------------------- **Class:** ``Nng\Nnfocalpoint\Controller\FocalPointController`` Handles AJAX requests for the backend modal. **Methods:** ``wizardAction(ServerRequestInterface $request): ResponseInterface`` Returns JSON data for the focal point wizard modal, including image URL, dimensions, crop variants, and existing focal points. ``imageAction(ServerRequestInterface $request): ResponseInterface`` Returns image data for a specific crop variant. FocalPointElement ----------------- **Class:** ``Nng\Nnfocalpoint\Form\Element\FocalPointElement`` Custom FormEngine element that renders the focal point button and hidden input. **Extends:** ``TYPO3\CMS\Backend\Form\Element\AbstractFormElement`` ObjectPositionViewHelper ------------------------ **Class:** ``Nng\Nnfocalpoint\ViewHelpers\ObjectPositionViewHelper`` **Extends:** ``TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper`` **Methods:** ``render(): string`` Returns CSS object-position value (e.g., "50% 30%") FocalPointViewHelper -------------------- **Class:** ``Nng\Nnfocalpoint\ViewHelpers\FocalPointViewHelper`` **Extends:** ``TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper`` **Methods:** ``render(): mixed`` Returns focal point array or renders children with focal point variable FocalCropViewHelper ------------------- **Class:** ``Nng\Nnfocalpoint\ViewHelpers\FocalCropViewHelper`` **Extends:** ``TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper`` **Methods:** ``render(): string`` Returns ```` tag with server-side cropped image centered on focal point Uri\\FocalCropViewHelper ------------------------ **Class:** ``Nng\Nnfocalpoint\ViewHelpers\Uri\FocalCropViewHelper`` **Extends:** ``TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper`` **Methods:** ``render(): string`` Returns URI of focal-point-cropped processed image