├── .craftplugin ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── docs ├── Deprecated.md ├── Field.md ├── Layouts.md ├── Methods.md ├── Picture.md ├── Placeholders.md ├── README.md ├── Settings.md ├── Svg.md ├── _sidebar.md ├── index.html └── variants-field.png └── src ├── ImageToolbox.php ├── assetbundles ├── AlpineAsset.php └── alpine.min.js ├── default-placeholder.png ├── fields └── ImageVariantsField.php ├── icon.svg ├── models ├── ImageVariantsFieldModel.php └── Settings.php ├── services └── ImageToolboxService.php ├── templates ├── common-settings.twig ├── image-variants-field-input.twig └── image-variants-field-settings.twig ├── translations └── en │ └── image-toolbox.php └── variables └── ImageToolboxVariable.php /.craftplugin: -------------------------------------------------------------------------------- 1 | {"pluginName":"Image toolbox","pluginDescription":"Image toolbox","pluginVersion":"1.0.0","pluginAuthorName":"Piotr Pogorzelski","pluginVendorName":"craftsnippets","pluginAuthorUrl":"http://craftsnippets.com/","pluginAuthorGithub":"","codeComments":"","pluginComponents":["services","settings","variables"],"consolecommandName":"","controllerName":"","cpsectionName":"","elementName":"","fieldName":"","modelName":"","purchasableName":"","recordName":"","serviceName":"","taskName":"","utilityName":"","widgetName":"","apiVersion":"api_version_3_0"} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CRAFT ENVIRONMENT 2 | .env.php 3 | .env.sh 4 | .env 5 | 6 | # COMPOSER 7 | /vendor 8 | 9 | # BUILD FILES 10 | /bower_components/* 11 | /node_modules/* 12 | /build/* 13 | /yarn-error.log 14 | 15 | # MISC FILES 16 | .cache 17 | .DS_Store 18 | .idea 19 | .project 20 | .settings 21 | *.esproj 22 | *.sublime-workspace 23 | *.sublime-project 24 | *.tmproj 25 | *.tmproject 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | config.codekit3 32 | prepros-6.config 33 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Image toolbox Changelog 2 | 3 | ## 3.0.1 - 2024.06.16 4 | ### Fixed 5 | * Avif generation is now disabled by default. 6 | * svgFile() function - HTML attributes array parameter is now optional. 7 | 8 | ## 3.0.0 - 2024.04.04 9 | ### Added 10 | * Added Craft CMS 5 support. 11 | 12 | ## 2.3.0 - 2024.04.04 13 | ### Added 14 | * Added the `svgFile` method. 15 | * Added the automatic avif image variants generation. 16 | 17 | ## 2.2.2 - 2023.07.18 18 | ### Added 19 | * Added the PRO edition of the plugin. This edition adds "Image variants" field which allows admins to define picture configuration in the control panel. Field is assigned to the asset source and picture configuration can be set for the whole asset source (using the field settings), or for the specific asset (using the field values). 20 | * Added the third parameter to `pictureMultiple` function - "common settings". It allows to define transform settings that will be used in all sources of picture element. 21 | 22 | ### Fixed 23 | * Updated deprecation message for deprecated functions, so developers are aware that new functions have different syntaxt compared to deprecated ones. 24 | * Fixed the issue with adding width and height attributes to sources causing performance issues. 25 | 26 | ## 2.1.2 - 2023.05.19 27 | ### Changed 28 | * Default placeholder mode now is now **file** - compared to pre 2.1.0 **svg** mode. If you want to keep using SVG mode, set `placeholderMode` to `svg` in `image-toolbox.php` config file. 29 | * Before 2.1.0, placeholder **url** mode was enabled just by entering URL value into `placeholderUrl` plugin setting. Now it also needs to be enabled by setting `placeholderMode` to `url` in `image-toolbox.php` config file. 30 | 31 | ## 2.1.0 - 2023.05.19 32 | ### Added 33 | * Added pictureMultiple() method, allowing for generating picture element with each source using different asset. 34 | * Added file placeholder mode, which generates placeholders based on source image file. 35 | * Transform layouts can now define HTML attributes using anonymous function. This allows defining attributes using asset object attributes. 36 | * Transform layouts and pictureMultiple() methods can use control panel defined image transforms. 37 | 38 | ### Fixed 39 | * Fixed bug with placeholder not generating correctly when showing width and height is enabled. 40 | * Fixed bug with of throwing error whan trying to get width and height of svg file. 41 | 42 | ### Deprecated 43 | * `picture()`, `pictureMedia()`, `pictureMax()` and `pictureMin()` are now deprecated. 44 | 45 | ## 2.0.2 - 2023.05.15 46 | ### Fixed 47 | * Width and height attributes are now properly calculated when width or height is missing from the transform. 48 | * Width and height attributes are now added to the fallback img tag of picture element. 49 | * Fixed the bug with width being used for height attribute if no transform settings were used for generating picture element. 50 | 51 | ## 2.0.1 - 2023.04.13 52 | ### Added 53 | * Added support for displaying width and height attributes on image sources when "useWidthHeightAttributes" setting is set to true 54 | 55 | ## 2.0.0 - 2022.05.25 56 | ### Added 57 | * Added Craft CMS 4 support 58 | 59 | ### Fixed 60 | * Fixed bug with `pictureMedia()` throwing error if asset was null and one of breakpoints transform was also also null. 61 | * Fixed bug with `picture()` function throwing error if asset was null and no transform array was given. 62 | 63 | ## 1.1.0 - 2021.03.11 64 | ### Added 65 | * Added `forceWebp` config setting. 66 | * Added `forcePlaceholders` config setting. 67 | 68 | ### Fixed 69 | * Code refactoring 70 | 71 | ## 1.0.0 - 2020-10-18 72 | ### Added 73 | - Initial release 74 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © Craft Snippets 2 | 3 | Permission is hereby granted to any person obtaining a copy of this software (the “Software”) to use, copy, modify, merge, publish and/or distribute copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | Don’t plagiarize. The above copyright notice and this license shall be included in all copies or substantial portions of the Software. 6 | 7 | Don’t use the same license on more than one project. Each licensed copy of the Software shall be actively installed in no more than one production environment at a time. 8 | 9 | Don’t mess with the licensing features. Software features related to licensing shall not be altered or circumvented in any way, including (but not limited to) license validation, payment prompts, feature restrictions, and update eligibility. 10 | 11 | Pay up. Payment shall be made immediately upon receipt of any notice, prompt, reminder, or other message indicating that a payment is owed. 12 | 13 | Follow the law. All use of the Software shall not violate any applicable law or regulation, nor infringe the rights of any other person or entity. 14 | 15 | Failure to comply with the foregoing conditions will automatically and immediately result in termination of the permission granted hereby. This license does not include any right to receive updates to the Software or technical support. Licensees bear all risk related to the quality and performance of the Software and any modifications made or obtained to it, including liability for actual and consequential harm, such as loss or corruption of data, and any necessary service, repair, or correction. 16 | 17 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, INCLUDING SPECIAL, INCIDENTAL AND CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image toolbox plugin for Craft CMS 5.x 2 | 3 | Image Toolbox is Craft CMS plugin that helps with the use of image transforms in templates. 4 | 5 | ## Features 6 | 7 | * Automatic creation of **avif** and **webp** variant of the images, with fallback for browsers that don't support these formats. 8 | * Automatic creation of placeholder images. Plugin outputs either transformed image or placeholder with size based on image transform, if image is missing. 9 | * Generating responsive images with multiple variants, displayed on specific breakpoints by using `` element. 10 | * [Imager-x](https://plugins.craftcms.com/imager-x) (or old [Imager](https://plugins.craftcms.com/imager)) support - but you can use it with native Craft image transforms as well. 11 | 12 | ## Installation 13 | 14 | To install the plugin, follow these instructions. 15 | 16 | 1. Open your terminal and go to your Craft project: 17 | 18 | cd /path/to/project 19 | 20 | 2. Then tell Composer to load the plugin: 21 | 22 | composer require craftsnippets/craft-image-toolbox 23 | 24 | 3. In the Control Panel, go to Settings → Plugins and click the “Install” button for Image toolbox. 25 | 26 | ## Documentation 27 | 28 | Click here for [Image toolbox documentation](http://craftsnippets.com/docs/image-toolbox) 29 | 30 | ## Roadmap 31 | 32 | * Retina support 33 | * Applying transform on assets within HTML strings 34 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "craftsnippets/craft-image-toolbox", 3 | "description": "Image toolbox", 4 | "type": "craft-plugin", 5 | "version": "3.0.1", 6 | "keywords": [ 7 | "craft", 8 | "cms", 9 | "craftcms", 10 | "craft-plugin", 11 | "image toolbox" 12 | ], 13 | "support": { 14 | "docs": "http://craftsnippets.com/docs/image-toolbox/", 15 | "issues": "https://github.com/craft-snippets/Craft-image-toolbox/issues" 16 | }, 17 | "license": "proprietary", 18 | "authors": [ 19 | { 20 | "name": "Piotr Pogorzelski", 21 | "homepage": "http://craftsnippets.com/" 22 | } 23 | ], 24 | "require": { 25 | "craftcms/cms": "^5.0.0" 26 | }, 27 | "autoload": { 28 | "psr-4": { 29 | "craftsnippets\\imagetoolbox\\": "src/" 30 | } 31 | }, 32 | "extra": { 33 | "name": "Image toolbox", 34 | "handle": "image-toolbox", 35 | "developer": "Piotr Pogorzelski", 36 | "developerUrl": "http://craftsnippets.com/", 37 | "documentationUrl": "http://craftsnippets.com/docs/image-toolbox/", 38 | "changelogUrl": "https://github.com/craft-snippets/Craft-image-toolbox/blob/master/CHANGELOG.md", 39 | "components": { 40 | "imageToolboxService": "craftsnippets\\imagetoolbox\\services\\ImageToolboxService" 41 | }, 42 | "class": "craftsnippets\\imagetoolbox\\ImageToolbox" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/Deprecated.md: -------------------------------------------------------------------------------- 1 | # Deprecated methods 2 | 3 | This methods were used before `pictureMultiple()` was introduced. They are kept for the sake of backwards compatibility. They do not allow using separate assets on multiple breakpoints - all breakpoints share same asset. 4 | 5 | ## picture() method 6 | 7 | This method can be used for generating `` with single variant (which will be generatet as two sources - webp and one in original format). 8 | 9 | ```twig 10 | In the example below, `someAsset` is asset object containing image, and `transformSettings` is array of [image transform settings](https://craftcms.com/docs/3.x/image-transforms.html). 11 | 12 | ```twig 13 | {% set someAsset = entry.imageField.one() %} 14 | {% set transformSettings = { 15 | width: 100, 16 | height: 200, 17 | mode: 'stretch' 18 | } %} 19 | {% set htmlAttributes = { 20 | class: 'some-class', 21 | } %} 22 | {{craft.images.picture(someAsset, transformSettings, htmlAttributes)}} 23 | ``` 24 | 25 | ## pictureMedia() method 26 | 27 | Here's how it is used: 28 | 29 | ``` 30 | {% set someAsset = entry.imageField.one() %} 31 | {% set transforms = { 32 | '(max-width: 600px)': { 33 | width: 100, 34 | height: 200, 35 | mode: 'crop', 36 | }, 37 | '(max-width: 999px)': { 38 | width: 400, 39 | height: 500, 40 | mode: 'fit', 41 | }, 42 | } %} 43 | {{craft.images.pictureMedia(someAsset, transforms)}} 44 | ``` 45 | 46 | As you can see, `sources` object contains multiple image transforms. Key of a single element of object is a string containing breakpoint on which specific transform should be used. Corresponding value is an array of image transform settings. 47 | 48 | If your multiple tranform settings used for breakpoints have many identical values (for example same `mode`, `format`, `position` or `quality`), you can pass to `pictureMedia` third parameter containing these common values. For example, this... 49 | 50 | ```twig 51 | {% set transforms = { 52 | '(max-width: 600px)': { 53 | width: 100, 54 | }, 55 | '(max-width: 999px)': { 56 | width: 400, 57 | }, 58 | } %} 59 | {% set common = { 60 | mode: 'fit', 61 | quality: 80, 62 | position: 'top-center', 63 | format: 'png', 64 | } %} 65 | {{craft.images.pictureMedia(someAsset, transforms, common)}} 66 | ``` 67 | 68 | ...is same as this: 69 | 70 | ```twig 71 | {% set transforms = { 72 | '(max-width: 600px)': { 73 | width: 100, 74 | mode: 'fit', 75 | quality: 80, 76 | position: 'top-center', 77 | format: 'png', 78 | }, 79 | '(max-width: 999px)': { 80 | width: 400, 81 | mode: 'fit', 82 | quality: 80, 83 | position: 'top-center', 84 | format: 'png', 85 | }, 86 | } %} 87 | {{craft.images.pictureMedia(someAsset, transforms)}} 88 | ``` 89 | 90 | Note that if you use `null` as transform value, source for this transform will be generated as transparent pixel. This can be used if we dont want to display image at all on the specific breakpoint. 91 | 92 | ## pictureMax() and pictureMin() methods 93 | 94 | Instead of explictly setting `media` values, these methods use numbers. For example, you can use `pictureMin()` like this: 95 | 96 | ```twig 97 | {% set transforms = { 98 | 1: { 99 | width: 100, 100 | height: 200, 101 | mode: 'crop', 102 | }, 103 | 600: { 104 | width: 400, 105 | height: 500, 106 | mode: 'fit', 107 | } 108 | } %} 109 | {{craft.images.pictureMin(someAsset, transforms)}} 110 | ``` 111 | 112 | This will generate same results as using `pictureMedia()` like this: 113 | 114 | ```twig 115 | {% set transforms = { 116 | '(min-width: 1px)': { 117 | width: 100, 118 | height: 200, 119 | mode: 'crop', 120 | }, 121 | '(min-width: 600px)': { 122 | width: 400, 123 | height: 500, 124 | mode: 'fit', 125 | } 126 | } %} 127 | {{craft.images.pictureMedia(someAsset, transforms)}} 128 | ``` 129 | 130 | Note, that browser always uses first `` with media query that fits. So if you are on screen of width 1024px, and first source is one with media query `(min-width: 300px)`, it would be used - even if there is other, with breakpoint `(min-width: 600px)`. That's why sources in `pictureMin()` are automatically sorted from ones with the largest min-width, to smallest. Correspondingly, for `pictureMax()`, sources are sorted from smallest `max-width` value to one with largest. -------------------------------------------------------------------------------- /docs/Field.md: -------------------------------------------------------------------------------- 1 | # Image variants field (PRO edition) 2 | 3 | The PRO version of Image toolbox allows users to define picture sources configurations with the control panel interface. This can be done using **Image variants** field. 4 | 5 | ![An image](./variants-field.png) 6 | 7 | ## Outputting pictures defined by variants field 8 | 9 | To define settings for all images in the asset source, assign variant field to its field layout. In the **field settings**, you will be able to set: 10 | 11 | * Transform settings and breakpoints for sources. 12 | * If `` should be rendered with width and height attributes 13 | * If `` should have webp variants of sources 14 | 15 | You can also do the same for specific asset, using **field values**. Configuration set in the specific assets will **overwrite** one set in field settings. 16 | 17 | To output ` element, you can use `pictureFromAsset()` method. This method takes in asset object (or `null` which will generate placeholder), handle of variant field assigned to asset source as parameters and optional array of the HTML attributes. 18 | 19 | ```twig 20 | {% set img = entry.someAssetField.one() %} 21 | {% set htmlAttributes = { 22 | class: 'some-class', 23 | } %} 24 | {{craft.images.pictureFromAsset(img, 'variantField', htmlAttributes)}} 25 | ``` 26 | 27 | Theoretically, you can pass only the asset object to this method and skip variant field handle. Hovewer, if image is missing (and we have `null` null instead of asset object), without field handle plugin will not be able select specific variant field to take picture configuration from. This means that it will be unable to generate placeholder using specific width and height set in the field. -------------------------------------------------------------------------------- /docs/Layouts.md: -------------------------------------------------------------------------------- 1 | # Transform layouts 2 | 3 | If you use some specific image transforms in multiple template files and want to avoid code duplication, you can define them in the plugin config file, along with the breakpoint values. To do that, use `transformLayouts` setting: 4 | 5 | ```php 6 | 'transformLayouts' => [ 7 | 'someHandle' => [ 8 | 'variants' => [ 9 | [ 10 | 'media' => '(max-width: 999px)', 11 | 'transform' => [ 12 | 'width' => 300, 13 | 'mode' => 'crop', 14 | ] 15 | ], 16 | [ 17 | 'media' => '(min-width: 1000px)', 18 | 'transform' => [ 19 | 'width' => 600, 20 | 'mode' => 'stretch', 21 | ] 22 | ] 23 | ], 24 | 'attributes' => [ 25 | 'class' => 'some-class' 26 | ], 27 | ], 28 | ], 29 | ``` 30 | 31 | Our transform layout handle is `someHandle`. Here's how to use it in the template: 32 | 33 | ```twig 34 | {{craft.images.layout([assetForVariant1, assetForVariant2], 'someHandle')}} 35 | ``` 36 | 37 | As you can see, we passed array of two assets to the method (one for each variant), without defining any other settings within Twig - everything else is defined in the config file. If you want, you can also pass only one asset to the function - it will be reused for every variant defined in the `variants` file. 38 | 39 | ```twig 40 | {{craft.images.layout(someAsset, 'someHandle')}} 41 | ``` 42 | HTLM attributes of `` element can be hard-coded in the `attributes` array of the transform layout, or can be outputted dynamically, using the anonymous function. Anonymous function returns array of attributes and takes in parameter containing all assets that are passed to `layout()` method. 43 | 44 | ```php 45 | 'transformLayouts' => [ 46 | 'someHandle' => [ 47 | 'variants' => [ 48 | [ 49 | 'media' => '(max-width: 999px)', 50 | 'transform' => [ 51 | 'width' => 300, 52 | 'mode' => 'crop', 53 | ] 54 | ], 55 | [ 56 | 'media' => '(min-width: 1000px)', 57 | 'transform' => [ 58 | 'width' => 600, 59 | 'mode' => 'stretch', 60 | ] 61 | ] 62 | ], 63 | 'attributes' => function($assets){ 64 | if(!is_null($assets[0])){ 65 | if($assets[0]->getFieldValue('someField') != ''){ 66 | $title = $assets[0]->getFieldValue('someField'); 67 | }else{ 68 | $title = $assets[0]->title; 69 | } 70 | }else{ 71 | $title = null; 72 | } 73 | $attrs = [ 74 | 'title' => $title; 75 | ]; 76 | return $attrs; 77 | }, 78 | ], 79 | ], 80 | ``` 81 | 82 | In the example above, we are using first asset passed to `layout` method to determine value of title attribute used on ``. If the field with `someField` handle which is assigned to asset is not empty, this field is used for title. If it is empty, `title` attribute of asset is used instead. And if asset is missing, we just use `null` which will result in `title` attribute not being added to the `` at all. -------------------------------------------------------------------------------- /docs/Methods.md: -------------------------------------------------------------------------------- 1 | # Method list 2 | 3 | For detailed information about each method, please visit [Plugin functionality](Basic) page. 4 | 5 | * `craft.images.pictureMultiple(imageVariants, htmlAttributes)` - generates `` element with multiple variants. 6 | 7 | * `variants` param is array of objects where each object can have these properties: 8 | * `asset` - asset object for variant, can be also set to `null` to generate placeholder 9 | * `transform` - asset transform settings for variant. Can be array of transform settings or handle of control panel defined transform. 10 | * `media` - breakpoint value for variant, for example: `(min-width: 1024px)` 11 | * `max` - alternative to `media` - numeric value which will be converted to `max-width` breakpoint 12 | * `min` - alternative to `media` - numeric value which will be converted to `min-width` breakpoint 13 | 14 | * `htmlAttributes` param is array of HTML attributes that will be applied to `` tag within a ``. This array uses the same attribute definitions supported by using [renderTagAttributes](yii\helpers\BaseHtml::renderTagAttributes()). 15 | 16 | * `craft.images.pictureFromAsset(asset, fieldHandle, htmlAttributes)` - generates `` element from the asset which has Image variant field assigned. Only PRO edition. 17 | 18 | * `craft.images.layout(handle, htmlAttributes)` - generates `` element based on configuration within `transformLayouts` plugin config setting. 19 | 20 | * `craft.images.placeholder(transform)` - generates image placeholder based `width` and `height` settings. 21 | 22 | * `craft.images.svgFile(file, htmlAttributes, options)` - outputs markup of SVG image. `file` attribute can be Asset object or file path. 23 | 24 | Deprecated methods: 25 | 26 | * `craft.images.picture(image, transform, htmlAttributes)` - generates `` element. 27 | 28 | * `craft.images.pictureMedia(image, transforms, commonSettings, htmlAttributes)` - generates `` element from multiple image transforms. Breakpoints are set in format like `(max-width: 600px)`. 29 | 30 | * `craft.images.pictureMin(image, transforms, commonSettings, htmlAttributes)` - generates `` element from multiple image transforms. Breakpoints are created from number that creates `min-width`. 31 | 32 | * `craft.images.pictureMax(image, transforms, commonSettings, htmlAttributes)` - generates `` element from multiple image transforms. Breakpoints are created from number that creates `max-width`. -------------------------------------------------------------------------------- /docs/Picture.md: -------------------------------------------------------------------------------- 1 | # Generating picture element 2 | 3 | ## Picture HTML element 4 | 5 | All images outputted by the plugin are using `` HTML element instead of just regular ``. On the surface, `` works same as standard `` - but its main feature is displaying multiple variants of image, in the separate `` tags. One of these sources can then be selected by brower based on breakpoint values set im `media` attribute or specific image format support. 6 | 7 | Image Toolbox uses this feature of `` for automatic generation of [webp](https://css-tricks.com/using-webp-images/) and avif versions of the images or using different image transforms for specific breakpoints. 8 | 9 | ## pictureMultiple() method 10 | 11 | `craft.images.pictureMultiple()` method can be used to generate `` element. Here is a simple example: 12 | 13 | ```twig 14 | {% set someAsset1 = entry.imageField1.one() %} 15 | 16 | {% set settings = 17 | [ 18 | { 19 | asset: someAsset1, 20 | transform: { 21 | width: 200, 22 | height: 500, 23 | mode: 'crop', 24 | }, 25 | } 26 | ] 27 | %} 28 | 29 | {% set htmlAttributes = { 30 | class: 'some-class', 31 | } %} 32 | 33 | {{ craft.images.pictureMultiple(settings, htmlAttributes) }} 34 | ``` 35 | 36 | First parameter of function takes in array of variants of image (in this case we have only one variant). Array contains: 37 | * `asset` object (if it equals `null`, placeholder image with size based on transform settings will be used instead). 38 | * `transform` settings - either array of [image transform settings](https://craftcms.com/docs/3.x/image-transforms.html), or handle of control panel defined transform. 39 | 40 | Second parameter of function is optional array of HTML attributes. This array uses the same attribute definitions supported by using [renderTagAttributes](yii\helpers\BaseHtml::renderTagAttributes()). 41 | 42 | This is the generated HTML code. 43 | 44 | ```html 45 | 46 | 47 | 48 | 49 | 50 | 51 | ``` 52 | 53 | As you can see, `` has three sources - webp source, avif source and jpg source. Browsers will choose the proper version depending on their [webp support](https://caniuse.com/#feat=webp) and ignore other one, so you don't have to worry about downloading redundant versions of image. 54 | 55 | For the browsers that don't [support picture element](https://caniuse.com/#feat=picture) - there is also fallback `` tag inside. This tag is also important because we need to use it to apply HTMl attributes such as class to our image. We cannot do that directly on the ``. 56 | 57 | Note that you can omit `transform` settings, if you want to only use webp/avif variant generation functionality of the plugin, without transforming source image in any other way. 58 | 59 | ## Picture with multiple breakpoint variants 60 | 61 | `craft.images.pictureMultiple()` method can be used to generate `` with multiple variants, displayed in specific breakpoints. These variants can all use same asset or different ones, as shown below. 62 | 63 | ```twig 64 | {% set someAsset1 = entry.imageField1.one() %} 65 | {% set someAsset2 = entry.imageField2.one() %} 66 | 67 | {% set settings = 68 | [ 69 | { 70 | asset: someAsset1, 71 | transform: { 72 | width: 200, 73 | height: 500, 74 | mode: 'crop', 75 | }, 76 | media: '(min-width: 1024px)', 77 | }, 78 | { 79 | asset: someAsset2, 80 | transform: { 81 | width: 100, 82 | height: 100, 83 | mode: 'crop', 84 | }, 85 | media: '(max-width: 1023px)', 86 | } 87 | ] 88 | %} 89 | 90 | {% set htmlAttributes = { 91 | class: 'some-class', 92 | } %} 93 | 94 | {% set commonTransformSettings = { 95 | quality: 90, 96 | } %} 97 | 98 | {{ craft.images.pictureMultiple(settings, htmlAttributes, commonTransformSettings) }} 99 | ``` 100 | 101 | As you can see, each variant contains: 102 | 103 | * asset object - each source can have different asset or we can use one same one for all of them. 104 | * transform settings. 105 | * media query value defining when this source should be shown. We can use `media` key for explicit media query. 106 | 107 | We also added the third param to the `pictureMultiple()` method - `commonTransformSettings`. These are transform settings that will be applied to all variants. This parameter is optional and can be used to avoid repeating specific settings for each variant. They can be stored in the single array instead. 108 | 109 | Here's the generated HTML. While we defined two variants, this `` has six sources, because each variant will have avif, webp and regular format ``. 110 | 111 | ```html 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | ``` 122 | 123 | Instead of setting breakpoint explictly by using `media` and setting it to value like `(max-width: 1023px)`, you may also use `min` and `max` for each source: 124 | 125 | ```twig 126 | {% set someAsset1 = entry.imageField1.one() %} 127 | {% set someAsset2 = entry.imageField2.one() %} 128 | 129 | {% set settings = 130 | [ 131 | { 132 | asset: someAsset1, 133 | transform: { 134 | width: 200, 135 | height: 500, 136 | mode: 'crop', 137 | }, 138 | min: 1024, 139 | }, 140 | { 141 | asset: someAsset2, 142 | transform: { 143 | width: 100, 144 | height: 100, 145 | mode: 'crop', 146 | }, 147 | max: 1023, 148 | } 149 | ] 150 | %} 151 | {{ craft.images.pictureMultiple(settings) }} 152 | ``` 153 | 154 | This will generate identical HTML as with using `media` setting. 155 | 156 | If you want your image to not display anything on specific media query, omit `transform` from this variant and set `asset` to null or also omit it. This `` will be generated as the transparent pixel. 157 | 158 | ## Width and height attributes 159 | 160 | Each picture source can have `width` and `height` attribute based on dimensions of transformed image for this source. This can be useful for some lazy loading solutions, althought by default this functionality is disabled. You can enable it by settings `useWidthHeightAttributes` to `true` in plugin settings. 161 | 162 | ## Avif and webp variants of images 163 | 164 | Why do we go through the hassle of generating separate avif and webp version of the image? Webp format can save you 30% to 50% of file size compared to jpg, while avif can decrease file size even 30% more compared to webp. This can mean large increases in the page load time. 165 | 166 | 167 | Generating avif and webp version of the image by the plugin actually depends on a few things. Avif/webp variants will be outputted along with image in original format if: 168 | 169 | * Provided image is not in SVG format. It would not make much sense to transform SVG which is a vector graphic format into webp which is used for raster images. 170 | * Server supports avif/webp image transforms. Avif support can be tested by using Craft `craft.app.images.supportsAvif()` method in your Twig templates, while webp with `craft.app.images.supportsWebP()`. These are the methods that Image toolbox uses internally. If Craft somehow wrongly detects lack of avif/webp support while server actually does support it, avif/webp generation can be forced by setting `forceAvif` to `true` or `forceWebp` to `true` in the plugin config. 171 | * Our source image is not already avif/webp - no need to create duplicate avif/webp variant of image that is already avif/webp. If however we want to transform avif/webp to other format, both avif/webp and other format variants will be generated. 172 | * We didn't disable avif/webp generation for this specific picture by adding `useAvif` set to `false` or `useWebp` set to `false` in the transform setting. 173 | * We didn't disable avif/webp generation globally in the plugin settings using `useAvif` or `useWebp` setting. **Please note that Avif variant generation is disabled by default, while Webp is enabled by default**. 174 | 175 | ## Deprecated methods 176 | 177 | These methods were used before `pictureMultiple()` was introduced. They are kept for the sake of backwards compatibility. They do not allow using separate assets on multiple breakpoints - all breakpoints share the same asset. 178 | 179 | Please note that in case of the missing asset, when placeholder is generated, `` outputted by these methods will have `is-placeholder` CSS class applied. This behaviour is missing from `pictureMultuple()` method, since it can use multiple assets, some of which are missing and some of which are not. Placeholder CSS class can be modified using `placeholderClass` config setting. 180 | 181 | ### picture() method 182 | 183 | This method can be used for generating `` with single variant (which will be generated as two sources - webp and one in original format). 184 | 185 | In the example below, `someAsset` is asset object containing image, and `transformSettings` is array of [image transform settings](https://craftcms.com/docs/3.x/image-transforms.html). 186 | 187 | ```twig 188 | {% set someAsset = entry.imageField.one() %} 189 | {% set transformSettings = { 190 | width: 100, 191 | height: 200, 192 | mode: 'stretch' 193 | } %} 194 | {% set htmlAttributes = { 195 | class: 'some-class', 196 | } %} 197 | {{craft.images.picture(someAsset, transformSettings, htmlAttributes)}} 198 | ``` 199 | 200 | ### pictureMedia() method 201 | 202 | Here's how it is used: 203 | 204 | ``` 205 | {% set someAsset = entry.imageField.one() %} 206 | {% set transforms = { 207 | '(max-width: 600px)': { 208 | width: 100, 209 | height: 200, 210 | mode: 'crop', 211 | }, 212 | '(max-width: 999px)': { 213 | width: 400, 214 | height: 500, 215 | mode: 'fit', 216 | }, 217 | } %} 218 | {{craft.images.pictureMedia(someAsset, transforms)}} 219 | ``` 220 | 221 | As you can see, `sources` object contains multiple image transforms. Key of a single element of object is a string containing breakpoint on which specific transform should be used. Corresponding value is an array of image transform settings. 222 | 223 | If your transform settings used for multiple breakpoints have many identical values (for example same `mode`, `format`, `position` or `quality`), you can pass third parameter containing these common values to `pictureMedia()`. For example, this... 224 | 225 | ```twig 226 | {% set transforms = { 227 | '(max-width: 600px)': { 228 | width: 100, 229 | }, 230 | '(max-width: 999px)': { 231 | width: 400, 232 | }, 233 | } %} 234 | {% set common = { 235 | mode: 'fit', 236 | quality: 80, 237 | position: 'top-center', 238 | format: 'png', 239 | } %} 240 | {{craft.images.pictureMedia(someAsset, transforms, common)}} 241 | ``` 242 | 243 | ...is the same as this: 244 | 245 | ```twig 246 | {% set transforms = { 247 | '(max-width: 600px)': { 248 | width: 100, 249 | mode: 'fit', 250 | quality: 80, 251 | position: 'top-center', 252 | format: 'png', 253 | }, 254 | '(max-width: 999px)': { 255 | width: 400, 256 | mode: 'fit', 257 | quality: 80, 258 | position: 'top-center', 259 | format: 'png', 260 | }, 261 | } %} 262 | {{craft.images.pictureMedia(someAsset, transforms)}} 263 | ``` 264 | 265 | Note that if you use `null` as transform value, source for this transform will be generated as transparent pixel. This can be used if we don't want to display image at all on the specific breakpoint. 266 | 267 | ### pictureMax() and pictureMin() methods 268 | 269 | Instead of explictly setting `media` values, these methods use numbers. For example, you can use `pictureMin()` like this: 270 | 271 | ```twig 272 | {% set transforms = { 273 | 1: { 274 | width: 100, 275 | height: 200, 276 | mode: 'crop', 277 | }, 278 | 600: { 279 | width: 400, 280 | height: 500, 281 | mode: 'fit', 282 | } 283 | } %} 284 | {{craft.images.pictureMin(someAsset, transforms)}} 285 | ``` 286 | 287 | This will generate same results as using `pictureMedia()` like this: 288 | 289 | ```twig 290 | {% set transforms = { 291 | '(min-width: 1px)': { 292 | width: 100, 293 | height: 200, 294 | mode: 'crop', 295 | }, 296 | '(min-width: 600px)': { 297 | width: 400, 298 | height: 500, 299 | mode: 'fit', 300 | } 301 | } %} 302 | {{craft.images.pictureMedia(someAsset, transforms)}} 303 | ``` 304 | 305 | Note, that browser always uses first `` with media query that fits. So if you are on screen of width 1024px, and first source is one with media query `(min-width: 300px)`, it would be used - even if there is other, with breakpoint `(min-width: 600px)`. That's why sources in `pictureMin()` are automatically sorted from ones with the largest min-width, to smallest. Correspondingly, for `pictureMax()`, sources are sorted from smallest `max-width` value to one with largest. -------------------------------------------------------------------------------- /docs/Placeholders.md: -------------------------------------------------------------------------------- 1 | # Placeholders 2 | 3 | If the image is missing (asset object equals `null`), plugin methods will output placeholder image with size based on the provided image transform settings. This is very useful for various listing pages where layout may depend on existance of image with specific dimensions. If transform settings have only height or width set, placeholder will be generated as the square - with both width and height set to same value, taken from dimenstion that was provided. 4 | 5 | ## Placeholder modes 6 | 7 | There are three methods of placeholder generation - you can select one using `placeholderMode` plugin setting. 8 | 9 | ### File mode 10 | 11 | This is the default method. To use it, set `placeholderMode` to `file`. This method will generate image placeholders, based on source image. To make image fit transform settings, space will be added either from sides or top and bottom. 12 | 13 | Plugin provides default source image for the placeholder, but you can change it to your own. Here are the plugins settings that can be used for that: 14 | 15 | * `filePlaceholderPath` - file path to source image file, relative to root directory of your project. 16 | * `filePlaceholderBackgroundColor` - hex value of background color that will be applied to empty space in the placeholder image. 17 | * `filePlaceholderBackgroundOpacity` - opacity of background color, with value from 0 to 100. 18 | 19 | Placeholder images are outputted into `@web\placeholders` directory by default. This location can be changed with `filePlaceholderDirectory` plugin config setting. Remember that when you are changing placeholder settings, you need to remove old placeholder files so they can be generated again. 20 | 21 | ### SVG mode 22 | 23 | To use it, set `placeholderMode` to `svg`. This method will generate transparent SVG placeholders. 24 | 25 | ### URL mode 26 | 27 | To use it, set `placeholderMode` to `url`. This method will use exteral URLs for placeholders, so you also need to set `placeholderUrl` setting to address of placeholder generation service. Address needs do include image width and height, for example like this: `https://via.placeholder.com/{width}x{height}`. `{height}` and `{width}` in URL be replaced by values taken from transform settings. 28 | 29 | 30 | ## Forcing placeholders 31 | 32 | If you want to force all plugin methods use placeholder images, you can set `forcePlaceholders` setting to `true`. This might be useful if you want to create some kind of development copy of the website and transferring all uploaded assets to the other server is too much hassle. 33 | 34 | ## Placeholder method 35 | 36 | Placeholder can be also generated by `placeholder()` method: 37 | 38 | ```twig 39 | {{craft.images.placeholder({ 40 | with: 200, 41 | height: 300, 42 | }) }} 43 | ``` 44 | 45 | ## Placeholder CSS class 46 | 47 | Deprecated `picture()`, `pictureMedia()`, `pictureMax()` and `pictureMin()` methods, when outputting placeholder, apply `is-placeholder` CSS class to `` element. This behaviour is missing from `pictureMultuple()` method, since it can use multiple assets, some of which are missing and some of which are not. Placeholder CSS class can be modified using `placeholderClass` config setting. -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Image toolbox plugin for Craft CMS 5.x 2 | 3 | Image Toolbox is Craft CMS plugin that helps with the use of image transforms in the templates. 4 | 5 | ## Features 6 | 7 | * Automatic creation of **avif** and *webp* variants of the images, with fallback for browsers that don't support these formats. 8 | * Automatic creation of placeholder images. Plugin outputs either transformed image or placeholder with size based on image transform, if image is missing. 9 | * Generating responsive images with multiple variants, displayed on specific breakpoints by using `` element. 10 | * [Imager-x](https://plugins.craftcms.com/imager-x) support - but you can use it with native Craft image transforms as well. 11 | * Image variants field, allowing admins to configure image variants and breakpoints using the control panel (PRO edition). 12 | 13 | ## Installation 14 | 15 | To install the plugin, follow these instructions. 16 | 17 | 1. Open your terminal and go to your Craft project: 18 | 19 | cd /path/to/project 20 | 21 | 2. Then tell Composer to load the plugin: 22 | 23 | composer require craftsnippets/craft-image-toolbox 24 | 25 | 3. In the Control Panel, go to Settings → Plugins and click the “Install” button for Image toolbox. 26 | 27 | ## Roadmap 28 | 29 | * Retina support 30 | * Applying transform on assets within HTML strings 31 | 32 | Brought to you by [Craft Snippets](http://craftsnippets.com) -------------------------------------------------------------------------------- /docs/Settings.md: -------------------------------------------------------------------------------- 1 | # Settings 2 | 3 | Place these settings in `config/image-toolbox.php` file. 4 | 5 | * `useWebp` - if webp version of image should automatically be generated. Default: `true`. 6 | * `forceWebp` - if webp version of image should be generated even if Craft detects lack of webp support on the server. Useful if Craft somehow wrongly detects lack of webp support. Default: `false`. 7 | * `useAvif` - if avif version of image should automatically be generated. Default: `true`. 8 | * `forceAvif` - if avif version of image should be generated even if Craft detects lack of avif support on the server. Useful if Craft somehow wrongly detects lack of avif support. Default: `false`. 9 | * `useImager` - if Imager-x or Imager should be used for transforms (assuming one of these plugins is installed). Default: `true`. 10 | * `useImagerForSvg` - if imager should be used also for SVG images. Default: `false`. 11 | * `transformLayouts` - pre-defined transform settings. Read more in "Transform layouts" section of documentation. 12 | * `useWidthHeightAttributes` - if width and height attributes should be added to source (and fallback img) elements. Default: `false`. 13 | * `usePlaceholders` - if placeholder should be generated if image is missing (asset object equals `null`). Default: `true`. 14 | * `forcePlaceholders` - if placeholders should be outputted by every method instead of transformed images. 15 | * `placeholderMode` - mode used when generating placeholders. Possible values: `file`, `svg`, `url`. Default value: `file`. 16 | * `filePlaceholderPath` - location (relative to the project root) of the source file used with placeholder **file mode**. 17 | * `filePlaceholderBackgroundColor` - hex value of background color used when generating placeholder files with placeholder **file mode**. 18 | * `filePlaceholderBackgroundOpacity` - opacity of background color used when generating placeholder files with placeholder **file mode**. Possible values: `1` - `100`. 19 | * `filePlaceholderDirectory` - path where generated placeholder files will be outputted, relative to the project root. 20 | * `placeholderUrl` - URL of placeholder image, used in **url mode**. `{width}` and `{height}` in URL will be replaced with width and height of placeholder. 21 | * `svgDirectory` - file directory from where SVG images should be loaded when `svgFile` method is used with file path. 22 | * `suppressExceptions` - if errors should be thrown when passing incorrect parameters to the functions or if methods should fail siliently, not outputting anything at all. 23 | 24 | Deprecated: 25 | 26 | * `placeholderClass` - CSS class added to `` inside `` element if placeholder image is displayed. Default: `is-placeholder`. Used unly with deprecated `picture()`, `pictureMedia()`, `pictureMax()` and `pictureMin()` methods. 27 | -------------------------------------------------------------------------------- /docs/Svg.md: -------------------------------------------------------------------------------- 1 | # Svg images 2 | 3 | Image toolbox provides `svgFile()` method whic is the wrapper on the Craft [svg()](https://craftcms.com/docs/4.x/dev/functions.html#svg) function. Just like regular `svg()`, it outputs markup of SVG image and can be used with Asset object or file path string. 4 | 5 | `svgFile()` method accepts three parameters: 6 | 7 | * Asset object, path of SVG file within a project (aliases can be used) or `null` (nothing will be returned). In case of asset object, if asset is not SVG, exception will be thrown (unless `suppressExceptions` is set to `true` in the plugin settings). 8 | * Object containing HTML attributes that should be applied to the SVG element. This array uses the same attribute definitions supported by using [renderTagAttributes](yii\helpers\BaseHtml::renderTagAttributes()). 9 | * Array containing additional options. 10 | 11 | Additional options can be used to remove styles from outputted SVG, so we can style it using our own CSS. 12 | * `removeFill` - if fill attributes should be removed from SVG. Default: `false`. 13 | * `removeStroke` - if stroke attributes should be removed from SVG. Default: `false`. 14 | * `removeCss` - if ` -------------------------------------------------------------------------------- /src/templates/image-variants-field-input.twig: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{'You can overwrite default configuration defined in the field settings here.'|t('image-toolbox')}} 4 |

5 |
6 | {% include 'image-toolbox/common-settings' %} 7 |
-------------------------------------------------------------------------------- /src/templates/image-variants-field-settings.twig: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{'This configuration will be default for all the assets this field will be assigned to. It can aso be overwritten by editing field values for the specific assets.'|t('image-toolbox')}} 4 |

5 |
6 | {% include 'image-toolbox/common-settings' %} 7 |
-------------------------------------------------------------------------------- /src/translations/en/image-toolbox.php: -------------------------------------------------------------------------------- 1 | 'Image variants', 4 | 'Image toolbox variant field should be only assigned to assets.' => 'Image toolbox variant field should be only assigned to assets.', 5 | 'Breakpoint type' => 'Breakpoint type', 6 | 'No breakpoint' => 'No breakpoint', 7 | 'Breakpoint - minimum width' => 'Breakpoint - minimum width', 8 | 'Breakpoint - maximum width' => 'Breakpoint - maximum width', 9 | 'Breakpoint - media query' => 'Breakpoint - media query', 10 | 'Minimum width' => 'Minimum width', 11 | 'Maximum width' => 'Maximum width', 12 | 'Media query' => 'Media query', 13 | 'For example - "(min-width: 1024px)".' => 'For example - "(min-width: 1024px)".', 14 | 'Add variant' => 'Add variant', 15 | 'Delete variant' => 'Delete variant', 16 | 'Create the webp variants of the images' => 'Create the webp variants of the images', 17 | 'Create the avif variants of the images' => 'Create the avif variants of the images', 18 | 'Add "width" and "height" attributes to the picture' => 'Add "width" and "height" attributes to the picture', 19 | 'Use the global settings' => 'Use the global settings', 20 | 'Enabled' => 'Enabled', 21 | 'Disabled' => 'Disabled', 22 | 'This configuration will be default for all the assets this field will be assigned to. It can aso be overwritten by editing field values for the specific assets.' => 'This configuration will be default for all the assets this field will be assigned to. It can aso be overwritten by editing field values for the specific assets.', 23 | 'You can overwrite default configuration defined in the field settings here.' => 'You can overwrite default configuration defined in the field settings here.', 24 | 'Move variant up' => 'Move variant up', 25 | 'Move variant down' => 'Move variant down', 26 | ]; -------------------------------------------------------------------------------- /src/variables/ImageToolboxVariable.php: -------------------------------------------------------------------------------- 1 | getDeprecator()->log('image-toolbox.picture', 'The `picture()` method of Image toolbox plugin is deprecated. Use pictureMultiple() instead. Please note that pictureMultiple() uses new syntax of the parameters - check the documentation.'); 40 | $sources = [ 41 | [ 42 | 'transform' => $transform, 43 | ] 44 | ]; 45 | return ImageToolbox::getInstance()->imageToolbox->getPicture($image, $sources, $attributes); 46 | } 47 | 48 | /** 49 | * Generate picture element with multiple breakpoints from image. 50 | * Breakpoints are explicitly set by media query. 51 | * 52 | * @param Asset|null $image 53 | * @param array $transforms 54 | * @param array|null $common_setings 55 | * @param array|null $attributes 56 | * @return \Twig\Markup|null 57 | */ 58 | public function pictureMedia(?Asset $image, array $transforms, array $common_setings = null, array $attributes = null): ?\Twig\Markup 59 | { 60 | Craft::$app->getDeprecator()->log('image-toolbox.pictureMedia', 'The `pictureMedia()` method of Image toolbox plugin is deprecated. Use pictureMultiple() instead. Please note that pictureMultiple() uses new syntax of the parameters - check the documentation.'); 61 | $sources = []; 62 | foreach ($transforms as $media => $transform) { 63 | $sources[] = Array( 64 | 'media' => $media, 65 | 'transform' => !is_null($common_setings) ? array_merge($common_setings, $transform) : $transform, 66 | ); 67 | } 68 | return ImageToolbox::getInstance()->imageToolbox->getPicture($image, $sources, $attributes); 69 | } 70 | 71 | /** 72 | * Generate picture element with multiple breakpoints from image. 73 | * Breakpoints are set by max-width value generated from number. 74 | * 75 | * @param Asset|null $image 76 | * @param array $transforms 77 | * @param array|null $common_setings 78 | * @param array|null $attributes 79 | * @return \Twig\Markup|null 80 | */ 81 | public function pictureMax(?Asset $image, array $transforms, array $common_setings = null, array $attributes = null): ?\Twig\Markup 82 | { 83 | Craft::$app->getDeprecator()->log('image-toolbox.pictureMax', 'The `pictureMax()` method of Image toolbox plugin is deprecated. Use pictureMultiple() instead. Please note that pictureMultiple() uses new syntax of the parameters - check the documentation.'); 84 | ksort($transforms); 85 | $sources = []; 86 | foreach ($transforms as $media => $transform) { 87 | $sources[] = Array( 88 | 'media' => '(max-width: ' . $media . 'px)', 89 | 'transform' => !is_null($common_setings) ? array_merge($common_setings, $transform) : $transform, 90 | ); 91 | } 92 | return ImageToolbox::getInstance()->imageToolbox->getPicture($image, $sources, $attributes); 93 | } 94 | 95 | /** 96 | * Generate picture element with multiple breakpoints from image. 97 | * Breakpoints are set by min-width value generated from number. 98 | * 99 | * @param Asset|null $image 100 | * @param array $transforms 101 | * @param array|null $common_setings 102 | * @param array|null $attributes 103 | * @return \Twig\Markup|null 104 | */ 105 | public function pictureMin(?Asset $image, array $transforms, array $common_setings = null, array $attributes = null): ?\Twig\Markup 106 | { 107 | Craft::$app->getDeprecator()->log('image-toolbox.pictureMin', 'The `pictureMin()` method of Image toolbox plugin is deprecated. Use pictureMultiple() instead. Please note that pictureMultiple() uses new syntax of the parameters - check the documentation.'); 108 | krsort($transforms); 109 | $sources = []; 110 | foreach ($transforms as $media => $transform) { 111 | $sources[] = Array( 112 | 'media' => '(min-width: ' . $media . 'px)', 113 | 'transform' => !is_null($common_setings) ? array_merge($common_setings, $transform) : $transform, 114 | ); 115 | } 116 | return ImageToolbox::getInstance()->imageToolbox->getPicture($image, $sources, $attributes); 117 | } 118 | 119 | /** 120 | * Generate placeholder image. 121 | * 122 | * @param array|null $transform 123 | * @return \Twig\Markup 124 | */ 125 | public function placeholder(string|array|null $transform = null): \Twig\Markup 126 | { 127 | return ImageToolbox::getInstance()->imageToolbox->getPlaceholder($transform); 128 | } 129 | 130 | /** 131 | * Generate picture element with multiple breakpoints from image, using transform layout set in plugin config. 132 | * 133 | * @param Asset|null $image 134 | * @param string $layout_handle 135 | * @return \Twig\Markup|null 136 | * @throws \Twig\Error\RuntimeError 137 | */ 138 | public function layout(object|array|null $image, string $layout_handle): ?\Twig\Markup 139 | { 140 | return ImageToolbox::getInstance()->imageToolbox->getLayout($image, $layout_handle); 141 | } 142 | 143 | public function pictureMultiple(array $sources, array $htmlAttributes = [], array $commonTransformSettings = []): ?\Twig\Markup 144 | { 145 | // apply common settings to sources transforms 146 | if(!empty($commonTransformSettings)){ 147 | foreach ($sources as $index => $source) { 148 | $sources[$index]['transform'] = array_merge(($sources[$index]['transform'] ?? []), $commonTransformSettings); 149 | } 150 | } 151 | 152 | return ImageToolbox::getInstance()->imageToolbox->getPictureMultiple($sources, $htmlAttributes); 153 | } 154 | 155 | public function pictureFromAsset(?Asset $image, ?string $variantsFieldHandle = null, array $htmlAttributes = []): ?\Twig\Markup 156 | { 157 | if(!ImageToolbox::getInstance()->isProEdition()){ 158 | throw new \Exception('The functionality of defining picture element configurations in the control panel requires the PRO edition of the plugin.'); 159 | } 160 | return ImageToolbox::getInstance()->imageToolbox->getPictureFromAsset($image, $variantsFieldHandle, $htmlAttributes); 161 | } 162 | 163 | public function svgFile(string|Asset|null $file, array $attributes = [], array $options = []): ?\Twig\Markup 164 | { 165 | return ImageToolbox::getInstance()->imageToolbox->svgFile($file, $attributes, $options); 166 | } 167 | 168 | } 169 | --------------------------------------------------------------------------------