Jump to content

PageimageSource


nbcommunication

Recommended Posts

Hi @Krlos,

Yes, Pageimage::render() is for rendering image markup from a PageImage: https://processwire.com/api/ref/pageimage/render/

In your example above, the correct call would be:

<section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;">

Assuming that $page->images is a single Pageimage object and not multiple images. In this case it would be:

<section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->first->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;">

This of course doesn't use srcset in any way. Going on @Stefanowitsch's example above you would need to implement Lazysizes and Lazysizes beset and then add something like

<section class="about-section pt-48 pb-48" style="background-image: url(<?= $page->images->first->url ?>); background-repeat: no-repeat; background-size: cover; background-position: center;" data-bgset="<?= $page->images->first->srcset ?>">

to your markup. I'm not familiar with Lazysizes though so doubt this is a working example. If you look through this thread you can see how I implemented srcset background images using UIkit's Image component.

Cheers,

Chris

  • Thanks 1
Link to comment
Share on other sites

On 6/22/2023 at 12:48 AM, snck said:

Hi @nbcommunication,

thanks for the quick reaction! The update fixed it for me. 👍

Cheers,
Flo

@nbcommunication  I have to correct: The update fixed it in one specific case. I still have the problem in another place:

$img->render(
	[
        'picture' => true,
        'srcset' => [
          'rules' => ['800x400', '1600x800'],
          'options' => [
            'upscaling' => true,
          ],
        ], 
        'allSets' => true,
        'sizes' => '(max-width: 900px) 100vw,
            ((min-width: 901px) and (max-width: 1200px)) 67vw,
            ((min-width: 1201px) and (min-width: 1201px)) 50vw',
        'class' => 'hero-img',
        'alt' => "...",
        'markup' => "<img src='".$img->size(800, 400)->url."' alt='{alt}' class='{class}' width='".$img->size(800, 400)->width."' height='".$img->size(800, 400)->height."'>",
	]
)

leads to this markup:

<picture>
  <source srcset="FILENAME.800x400-srcset.webp 800w, FILENAME.webp 1600w" sizes="(max-width: 900px) 100vw,
    ((min-width: 901px) and (max-width: 1200px)) 67vw,
    ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/webp">
  <source srcset="FILENAME.800x400-srcset.jpg 800w, FILENAME.jpg 1600w" sizes="(max-width: 900px) 100vw,
    ((min-width: 901px) and (max-width: 1200px)) 67vw,
    ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/jpeg">
  <img src="FILENAME.800x400.jpg" alt="..." class="hero-img" width="800" height="400" loading="lazy">
</picture>

The intrinsic dimensions of the image are 1080x721.

I am really curious why the update worked in one place and not in the other. Do you need more information to investigate?

Link to comment
Share on other sites

Hi @snck,

The approach here seems odd to me but I'm probably misunderstanding the use case. I'd do:

<?php

$img->size(800,400)->render(
	[
        'picture' => true,
        'srcset' => [
          'rules' => ['800x400', '1600x800'],
          'options' => [
            'upscaling' => true,
          ],
        ], 
        'allSets' => true,
        'sizes' => '(max-width: 900px) 100vw,
            ((min-width: 901px) and (max-width: 1200px)) 67vw,
            ((min-width: 1201px) and (min-width: 1201px)) 50vw',
        'class' => 'hero-img',
        'alt' => "...",
        'markup' => "<img src={src} alt='{alt}' class='{class}' width={width} height={height}>",
	]
);

I'd then switch off upscaling to see what that would do.

What would you expect the markup to be in this case?

Cheers,

Chris

  • Like 1
Link to comment
Share on other sites

9 hours ago, nbcommunication said:

What would you expect the markup to be in this case?

I would expect it to contain only images with the exact dimensions I specified, like this:

<picture>
  <source srcset="FILENAME.800x400-srcset.webp 800w, FILENAME.1600x800-srcset.webp 1600w" sizes="(max-width: 900px) 100vw,
    ((min-width: 901px) and (max-width: 1200px)) 67vw,
    ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/webp">
  <source srcset="FILENAME.800x400-srcset.jpg 800w, FILENAME.1600x800-srcset.jpg 1600w" sizes="(max-width: 900px) 100vw,
    ((min-width: 901px) and (max-width: 1200px)) 67vw,
    ((min-width: 1201px) and (min-width: 1201px)) 50vw" type="image/jpeg">
  <img src="FILENAME.800x400.jpg" alt="..." class="hero-img" width="800" height="400" loading="lazy">
</picture>

Instead of the 1600x800 variants I get the original image URL again. Disabling upscaling does not change it. Of course I could resize the image before rendering as in your example, but shouldn't it be possible to pass an array for the srcset and get exactly the values you specified? This is a fix of course, but feels more like a hack than a solution.

Cheers,
Flo

Link to comment
Share on other sites

Hi @snck,

Thanks - I think I found the place where this is failing to generate the 1600x800 variation where it should. I've pushed the potential fix. Can you try it out?

I would note that the example implementation I gave above (creating the variation before calling render()) is a better way to implement this as the markup is meant to be a template not a string with actual values, however if the fix I've pushed works, it should work for either implementation.

Cheers,

Chris

  • Like 1
Link to comment
Share on other sites

On 6/29/2023 at 11:04 PM, nbcommunication said:

Thanks - I think I found the place where this is failing to generate the 1600x800 variation where it should. I've pushed the potential fix. Can you try it out?

I would note that the example implementation I gave above (creating the variation before calling render()) is a better way to implement this as the markup is meant to be a template not a string with actual values, however if the fix I've pushed works, it should work for either implementation.

Hi @nbcommunication, thanks for the quick reponse! Unfortunately the update did not solve my problem. You are right regarding the markup string, but that has nothing to do with my problem (source tags output fallback to original image instead of (upscaled) version with correct aspect ratio). I will scale the image before calling render, but if you find a solution or come up with an update, I am happy to try it again.

Cheers,
Flo

Link to comment
Share on other sites

Hey there,

I'm trying to track down some PHP warnings, and one comes from this module.

image.png.543e409721d2f36c80fd930ca34e731c.png

I understand you are trying to do some error checking in the configuration in the init() function, but unless I'm totally off on this there is no page context for the init() function in modules.

I get two warnings on line 68 because template is run on null and name is run on null..

$this->wire->page in the init() method is null because as far as I understand when the init() method is run there is no page actually loaded yet.

As a result $isAdmin is never true and that entire module config test block never loads?

The hooks are outside the block - so no problems there, but I'm guessing that clearing variations from the module config doesn't work.

Link to comment
Share on other sites

Hi @snck,

Indeed, now I've tested both your and my code on an image of the width you'd specified, I can see I put the fix in the wrong place. The latest version 1.0.7 should hopefully resolve this for you.

@gornycreative,

How odd - I got this way of checking if it is the admin years ago from someone else's module / a mixture of forum post responses. I've never had a situation where it triggered these warnings. If I log $this->wire()->page in init() I get the Page object. However, I do agree that relying on this in init() isn't the correct implementation. In 1.0.7 I've changed this instead to (string) $this->wire()->process === 'ProcessModule' which works for me and should also hopefully resolve the warnings.

Cheers,

Chris

Link to comment
Share on other sites

4 hours ago, nbcommunication said:

If I log $this->wire()->page in init() I get the Page object.

If I do a bd in Tracy:

	/**
	 * Initialize the module
	 *
	 */
	public function init() {

		$input = $this->wire()->input;
//		$isAdmin = $this->wire()->page->template->name === 'admin';

		bd($this->wire()->page); //Should be the same
		bd($this->wire->page); //But Just in case

I get this:

image.png.741508a9e3807985cb2bcbf27e8847b7.png

Not even a NullPage object which would at least be something. I found a similar method in a thread from years ago where the limitations of init() were also mentioned. I can't recall if that's the first place I'd seen - it - perhaps in the core code itself?

From wire/config.php - I think this is where I first saw hints that anything done in init() doesn't know what page exists.

Quote

The statuses occur in this order:
 *
 * 1. The `boot` status occurs in the ProcessWire class constructor, after PW has initialized its
 *    class loader, loaded its config files, and initialized its hooks system. One use for this
 *    state is to add static hooks to methods that might be executed between boot and init, which
 *    would be missed by the time the init state is reached.
 *
 * 2. The `init` status occurs after ProcessWire has loaded all of its core API variables, except
 *    that the $page API variable has not yet been determined.
At this point, all of the autoload
 *    modules have had their init() methods called as well.
 * 
 *    - If you want to target the state right before modules.init() methods are called, (rather
 *      than after), you can use `initBefore`.
 *
 * 3. The `ready` status is similar to the init status except that the current Page is now known,
 *    and the $page API variable is known and available.
The ready file is included after autoload
 *    modules have had their ready() methods called. 
 

But this doesn't say explicitly that you couldn't *get* the page while in the init context, just that the API var isn't instantiated yet.

I'm wondering if bumping it to the ready() state would be an option?

The thread I linked never really came to a satisfying conclusion - but I'd also like to know if there is a definitive best practice for how to do this.

@horst @Robin S ?

Link to comment
Share on other sites

Thanks @gornycreative,

I don't use TracyDebugger (*hangs head in shame*) but I do wonder whether that is why $this->wire()->page isn't available in the init(). The test I ran was on a new install of the dev branch so it does suggest something additional altering things.

Regardless, for the purposes of this module the fix I put in place to use $this->wire()->process should work. I would normally have put this logic in ready() but didn't and can't remember why, so I'd prefer to keep it where it is for now at least.

Cheers,

Chris

  • Thanks 1
Link to comment
Share on other sites

  • 3 weeks later...
On 6/28/2023 at 11:08 AM, snck said:
$img->render(
	[
        'picture' => true,
        'srcset' => [
          'rules' => ['800x400', '1600x800'],
          'options' => [
            'upscaling' => true,
          ],
        ], 
        'allSets' => true,
        'sizes' => '(max-width: 900px) 100vw,
            ((min-width: 901px) and (max-width: 1200px)) 67vw,
            ((min-width: 1201px) and (min-width: 1201px)) 50vw',
        'class' => 'hero-img',
        'alt' => "...",
        'markup' => "<img src='".$img->size(800, 400)->url."' alt='{alt}' class='{class}' width='".$img->size(800, 400)->width."' height='".$img->size(800, 400)->height."'>",
	]
)

Hi @snck,

I'm just doing some testing on the module at the moment  and was using this code as an example. Just wanted to let you know that 'allSets' should be set in srcset options alongside 'upscaling'. In this case, you wouldn't need to set upscaling as 'allSets' enables upscaling anyway.

Cheers,

Chris 

Link to comment
Share on other sites

  • 3 months later...

Hello,

maybe I missed something somewhere, but is it possible to append the "browser cache busting query string" when rendering?

With the "normal" image this is possible via $image->URL or $image->HTTPURL, but I have not found a possibility here.

Thank you very much,
Christian

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...