carbon / editor-image
Image focal point and map editor for Neos CMS
Package info
github.com/CarbonPackages/Carbon.Editor.Image
Language:JavaScript
Type:neos-carbon
pkg:composer/carbon/editor-image
Requires
- neos/neos-ui: ^8.3 || ^9.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Carbon.Editor.Image provides two Neos inspector editors for image properties:
- FocalPoint lets editors choose the focal point on an image.
- Map lets editors define clickable areas on an image, including a link and alternative text for each area.
The FocalPoint editor was inspired by Neos.ImageFocalPointEditor.
Both editors use the image selected in the configured image property. By default, they look for an image property on
the current node. Dialog previews scale proportionally to fit the available width and height, including SVGs without
dimension metadata. SVG previews are also enlarged to use the available dialog space; raster previews are only scaled
down. The configured image crop is preserved; resizing the preview does not change saved coordinates.
Installation
Install the package in your Neos project with Composer:
composer require carbon/editor-image
Usage
Vendor.Site:Content.Image: properties: imageFocalPoint: # If `saveAsJsonString` is set to `true` in `editorOptions` or global configuration, set the property type to `string` type: array ui: # label: The label is optional; if omitted, it defaults to the translated text “Edit focal point”. inspector: editor: "Carbon.Editor.Image/FocalPoint" imageMap: # If `saveAsJsonString` is set to `true` in `editorOptions` or global configuration, set the property type to `string` type: array ui: # label: The label is optional; if omitted, it defaults to the translated text “Edit image map”. inspector: editor: "Carbon.Editor.Image/Map"
FocalPoint
The FocalPoint editor displays the selected image and lets editors set its focal point. The value is stored as an object
with x and y coordinates. The editor always opens in a modal dialog. Changes are saved with Apply and discarded with
Cancel.
Map
The Map editor opens an image annotation dialog where editors can create and edit clickable areas. Each area can have a link and alternative text. The editor saves the areas to the property.
Global configuration
Default options for both editors are provided in Configuration/Settings.Config.yaml under
Neos.Neos.Ui.frontendConfiguration:
Neos: Neos: Ui: frontendConfiguration: "Carbon.Editor.Image.FocalPoint": imageProperty: "image" labelIfEmpty: "Carbon.Editor.Image:Main:selectImage" saveAsJsonString: false "Carbon.Editor.Image.Map": imageProperty: "image" labelIfEmpty: "Carbon.Editor.Image:Main:selectImage" saveAsJsonString: false areaProperties: href: label: "Carbon.Editor.Image:Main:map.link" editor: "Neos.Neos/Inspector/Editors/LinkEditor" editorOptions: {} title: label: "Carbon.Editor.Image:Main:map.title" editor: "Neos.Neos/Inspector/Editors/TextFieldEditor" editorOptions: {} alt: label: "Carbon.Editor.Image:Main:map.alt" editor: "Neos.Neos/Inspector/Editors/TextFieldEditor" editorOptions: {}
These are global defaults. Set an option in a property's editorOptions to override the global value for that editor
instance.
Available options:
| Option | Description |
|---|---|
imageProperty |
Name of the image property used by the editor. Defaults to image. Use parent:propertyName to read the image from the parent node. |
labelIfEmpty |
Text or translation key displayed when no image is selected. Set it to null to hide the editor output in that case. |
saveAsJsonString |
When true, stores the value as a JSON string; the Neos property must then have type: string. When false, the value is stored as a native value, so use type: array. |
areaProperties |
Map editor only. Named fields for each area, with a label, Neos editor identifier and editorOptions. Set a field to null to omit it from the popup and saved data. |
For example, to use a different image property only for one focal point field:
editorOptions: imageProperty: "heroImage" labelIfEmpty: null
Property-level editorOptions take precedence over the corresponding global setting.
Custom area fields
The Map editor creates its popup fields from areaProperties. By default, each area has href, title and alt
fields. Add custom fields or override individual field definitions in your property's editorOptions:
editorOptions: areaProperties: alt: null description: label: "Description" editor: "Neos.Neos/Inspector/Editors/TextAreaEditor" editorOptions: placeholder: "Describe this area"
This keeps the global href and title fields, removes alt, and adds description. Each field definition replaces
the global definition with the same name. Labels support translation keys, and editorOptions are passed to the
selected Neos inspector editor. Fields are stored under their configured names alongside shape and coords; those two
names are reserved. Disabled and unconfigured fields are not saved when applying changes.
Stored data format
FocalPoint data
The focal point is stored as x and y coordinates, expressed as percentages of the image dimensions:
{
"x": 30,
"y": 28
}
Map data
The image map is stored as an array of areas. shape is either rect or poly, coords is an array of alternating
x and y floating-point percentages relative to the cropped output image (from 0 to 100). The remaining fields
come from areaProperties, such as href, title and alt. X values are relative to the cropped width, Y values to
the cropped height, independently of the preview size.
[
{
"shape": "rect",
"coords": [12.5, 15.25, 68.75, 83.5],
"href": "node://3211e0a0-4066-43f8-8f9c-6ff48a1017e4",
"title": "Visit our website",
"alt": "Website"
},
{
"shape": "poly",
"coords": [21.4, 11.6, 21.3, 25.9, 31.7, 30.2, 31.8, 15.5, 28.1, 14.9],
"href": "node://e69d08dd-d0e8-464b-8552-bf4707d4f682",
"title": "",
"alt": ""
}
]
These examples show the native values. When saveAsJsonString is true, the same data is stored as a JSON-encoded
string instead.
Creating responsive image map areas
Use createAreas whenever creating the frontend <area> elements and
whenever the displayed image changes size. Stored coordinates are percentages; HTML image maps require pixel coordinates
based on the image's current displayed width and height, not its natural dimensions.
createAreas(map, imageWidth, imageHeight, areas) converts the coordinates to rounded pixel values and replaces all
existing areas in the <map>. It also copies the remaining area properties, such as href, title and alt, to HTML
attributes.
For example, after importing createAreas into your frontend bundle:
const image = document.querySelector<HTMLImageElement>("#mapped-image")!; const map = document.querySelector<HTMLMapElement>("#image-map")!; // `areas` contains the stored percentage-based data, parsed from JSON if necessary. const updateAreas = () => createAreas(map, image.clientWidth, image.clientHeight, areas); image.addEventListener("load", updateAreas); const observer = new ResizeObserver(updateAreas); observer.observe(image); if (image.complete) { updateAreas(); } // When removing the image/component: // image.removeEventListener("load", updateAreas); // observer.disconnect();
Connect the image and map using <img id="mapped-image" usemap="#image-map" ...> and
<map id="image-map" name="image-map"></map>. The image must display the same cropped output used when defining the
areas. Resolve Neos node:// links to frontend URLs before calling createAreas, and pass only trusted,
HTML-attribute-safe property names and values because the function inserts them directly into HTML.