.. 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 four 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-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
.. _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
.. _developer-example-data-attr:
Example 6: Data Attributes for JavaScript
-----------------------------------------
Pass focal point data to JavaScript for dynamic effects:
.. code-block:: html
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