显示自定义 Gutenberg 块的预览图像

Posted

技术标签:

【中文标题】显示自定义 Gutenberg 块的预览图像【英文标题】:Show preview image for custom Gutenberg blocks 【发布时间】:2021-04-29 09:16:27 【问题描述】:

我创建了一批自定义 ACF gutenberg 块,现在尝试分配预览图像。

问题:让预览图像显示

这里的下图显示了一个paragraph 组件,它是一个默认块。

您可以在右侧看到,段落块旁边有一个图像和说明。以下是我的组件当前的显示方式(完整代码将在最后)

如您所见,它显示“没有可用的预览”并且没有添加描述,即使我在代码中都定义了。

方法:

acf-blocks/blocks.php

<?php
$img_root = "../../src/components";

$hero = array(
    'name' => 'hero',
    'title' => __('Hero') ,
    'description' => __('Hero section') ,
    'render_callback' => 'block_render',
    'category' => 'formatting',
    'icon' => 'admin-comments',
    'image' => $img_root . '/hero/hero.png',
    'mode' => 'edit',
    'keywords' => array(
        'hero'
    ) ,
);

$blocks = [$hero];

return $blocks;

?>

acf-blocks/functions.php

<?php

function block_acf_init()
  $path = get_template_directory().'/inc/acf-blocks/blocks.php';
  $blocks = require($path);
  foreach($blocks as $block) 
    acf_register_block_type($block);
  


if( function_exists('acf_register_block_type') ) 
  add_action('acf/init', 'block_acf_init');



?>

我的文件夹结构如下:

theme
  inc
    acf-blocks
      blocks.php
      functions.php
  src
    components
      hero
        hero.js
        hero.scss
        hero.png

不确定为什么我的预览图片不显示?

编辑:

我已经添加了block_render 函数,但仍然没有成功。这是我当前的functions.php 文件:

<?php

$component_path = "../../src/components" . strtolower($block['title']) . strtolower($block['title']).".js";

function block_render( $block, $content = '', $is_preview = false ) 
  $context = get_context();
    $context['block'] = $block; // store block values
    $context['fields'] = get_fields(); // store field values
    $context['is_preview'] = $is_preview;
    render($component_path, $context ); // render the block


function block_acf_init()
  $path = get_template_directory().'/inc/acf-blocks/blocks.php';
  $blocks = require($path);
  foreach($blocks as $block) 
    acf_register_block_type($block);
  


if( function_exists('acf_register_block_type') ) 
  add_action('acf/init', 'block_acf_init');


?>

编辑 2:

<?php

$hero = array(
    'name' => 'hero',
    'title' => __('Hero'),
    'description' => __('Add hero section'),
    'render_callback' => 'block_render',
    'category' => 'formatting',
    'icon' => 'admin-comments',
    'mode' => 'edit',
    'category' => 'custom',
    'post_types' => array(
        'page'
    ),
    'keywords' => array(
        'hero'
    ),
    'example' => array(
        'mode' => 'preview',
        'data' => array(
            'field' => 'value' // sample data
        )
    )
);


function block_render($block, $content = '', $is_preview = false)

    if ($is_preview && !empty($block['data'])) 
        echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
        return;
     elseif ($is_preview) 
        echo 'A Hero block using ACF';
        return;
    
    
    echo 'A Hero block using ACF.';



?>

甚至尝试过:

<?php

function block_render( $block, $content = '', $is_preview = false ) 
  if($is_preview):
    echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
  else:
    echo '<img src="https://i.picsum.photos/id/1021/536/354.jpg?hmac=XeUbyCXoxX2IrSELemo2mRl4zVXzhjFyxtj3GTVZ8xo">';
  endif;



?>

在这两种情况下,当尝试显示图像(不是块预览)时,我看到的是块的 ACF 字段,而不是定义的虚拟图像:

【问题讨论】:

嗨弗雷迪。您的 block.php 正在调用一个名为“block_render”的回调函数,但我看不到该函数在哪里。通常预览不可用,因为 acf 找不到您的块的视图。 嗨@MarcelloPerri - 我没有block_render 的函数。我的块显示在后端,如上图所示,例如,当我更改其标题或描述时,它也会在后端更新,它只是图像。你认为这与block_render有关? 尝试创建一个函数'block_render'并查看Wordpress是否在创建该类型的块后调用该函数,我认为该函数是强制性的,否则,您始终可以定义哪个文件是查看该块 @MarcelloPerri - 深入了解了render_callback,从外观上看,它负责在管理员中显示内容。尽管如此,我已经添加了该功能(我已经在上面编辑了我的问题),不幸的是仍然没有预览图像 【参考方案1】:

我没有在文档 (https://www.advancedcustomfields.com/resources/acf_register_block_type/) 的 acf_register_block_type() 函数中找到有关“图像”的任何信息。

如果您使用此功能并将mode 设置为preview,如果您将鼠标悬停在块编辑器中,您将获得渲染模板的预览。

functions.php

acf_register_block_type(array(
    'name' => 'name-of-block',
    'title' => __('Your Title'),
    'description' => __('Your description'),
    'post_types' => array('page'),
    'category' => 'common',
    'render_template' => '../your/path/block_template.php', // your template file
    'enqueue_style' => get_template_directory_uri() . '/style.css', // path to css file
    'icon' => '', // svg code for icon
    'keywords' => array('Keyword', 'another'),
    'example'  => array(
        'attributes' => array(
            'mode' => 'preview' // this needs to be set to preview (!)
        )
    ),
));

如果您为块使用自定义字段,则需要确保在您的古腾堡块模板文件的预览中显示一个值。

block_template.php

$myfield = get_field( 'my_field' );

<p><?php if ($myfield)  echo $myfield;  else  echo "my fallback paragraph";  ?></p>

这样预览将成为您渲染的块模板。它不是您想要的图像,但它显示了您的块的外观。这就是预览的本意。

【讨论】:

嗨,抱歉,我应该更清楚一点,我尝试添加图像而不是生成块预览的原因是因为我正在创建反应组件。我也不能enqueue_style,因为我所有的块样式都是.scss 格式。今后寻找一种解决方案,我可以将图像分配给块 例如,在核心paragraph 块中,他们分配给该块的图像(如我上面的问题所示),它不是块的preview,而是图像。只是看不出他们是怎么做到的 @Freddy,这确实是块预览,只是它不是图像。我同意 rank 的回答,但我发布了我自己的答案以及其他信息,希望对您有所帮助。让我知道。 :)【参考方案2】:

它说“没有可用的预览”并且没有添加描述,即使我已经在代码中定义了两者

它说“没有可用的预览”,因为确实如此,而且您定义的不是 ACF 甚至 WordPress 支持的东西,即 image arg ('image' =&gt; $img_root . '/hero/hero.png') 不会做任何开箱即用的事情.

您可以在右侧看到,段落块旁边有一个图像和说明。

不,那不是图像

它是由块的渲染回调(在您的情况下是 block_render() 函数)或在 ACF 块类型的情况下的模板返回的 块输出 的预览。

还有那个(核心)段落块,它实际上定义了example property,然后启用块预览即使属性为空(即没有定义属性)。使用registerBlockType() 的工作示例:

registerBlockType( 'my-blocks/foo-bar', 
    title: 'My Foo Bar block',
    category: 'formatting',
    description: 'Sample description.',

    // Just define this property and there'll be a preview.
    example: ,

    // And the preview is the one coming from this callback.
    edit: () => <p>just testing the block previews :)</p>,

    save: () => null,
 );

这样,您将获得以下预览:

但我提供该示例只是为了让您知道如何将预览添加到 非动态 块。

那么如何通过ACF添加块预览

简单,如另一个答案以及acf_register_block_type() documentation 所示,使用example arg:

示例(数组)(可选)结构化数据数组,用于构建块插入器中显示的预览。所有值 输入“数据”属性数组将在 通过$block['data']get_field().

因此,在您的情况下,您可以将该 arg 添加到您的 $hero 数组中:

$hero = array(
    'name'            => 'hero',
    'title'           => __( 'Hero' ),
    'description'     => __( 'Hero section' ),
    'render_callback' => 'block_render',
    'category'        => 'formatting',
    'icon'            => 'admin-comments',
    'keywords'        => array( 'hero' ),
    // Just add this and you'll get the block preview:
    'example'         => array(
        'attributes' => array(
            'mode' => 'preview',
        ),
    ),
);

基本上,无论渲染回调/模板输出如何,当您通过块插入器 UI 添加块时,您在预览中看到的内容。

但是,如果您希望在预览模式下获得不同的输出——无论是通过 UI 插入块时还是在将块添加到编辑器之后,您都可以使用传递给渲染回调的 $is_preview 参数:

function block_render( $block, $content = '', $is_preview = false ) 
    // back-end preview
    if ( $is_preview ) 
        echo 'A Hero block using ACF — In preview mode.';
        return;
    

    // front-end output
    echo 'A Hero block using ACF.';

如果您想在插入器 UI 和编辑器中进行不同的预览,则在 example 参数中设置 data 参数,并在渲染回调中检查 data 是否不为空:

/* In $hero, add example.attributes.data:
$hero = array(
    'name'            => 'hero',
    ...
    'example'         => array(
        'attributes' => array(
            'mode' => 'preview',
            'data' => array(
                'my_field' => 'Sample value',
            ),
        ),
    ),
);
 */

function block_render( $block, $content = '', $is_preview = false ) 
    // back-end previews
    if ( $is_preview && ! empty( $block['data'] ) ) 
        echo 'A Hero block using ACF — In preview mode — In the block inserter UI.';
        return;
     elseif ( $is_preview ) 
        echo 'A Hero block using ACF — In preview mode — In the editor.';
        return;
    

    // front-end output
    echo 'A Hero block using ACF.';

实际上,您可以通过if 显示实际图像

if ( $is_preview && ! empty( $block['data'] ) ) 
    echo '<img src="https://example.com/path/to/image-file-name.png">';
    return;

然后为您提供如下所示的预览:

所以我希望这会有所帮助? :)

请注意,这些示例已经过使用 ACF Pro 5.9.4 和 WordPress 5.6 的尝试和测试,这两个版本都是撰写本文时的最新版本。

【讨论】:

嗨,莎莉,感谢您的回答,图像也确实有帮助:) 我尝试通过检查 data 数组是否不为空然后显示图像来采用您的方法,但是,对我来说,这样做时,ACF 字段显示为块预览,而不是 echo 中定义的虚拟图像。我已经编辑了我的问题,以向您展示我所做和尝试的内容,您认为我没有遗漏您的解释吗? D*mn,对不起,我的错!我专注于 JS 版本,因此打错了 答案已修改。让我知道。 :) 你太棒了,我现在设法让它工作了。非常感谢您的深入回答,非常感谢:) 很高兴我能提供帮助并感谢您的赏金!【参考方案3】:

在互联网上阅读了大量关于如何在自定义 ACF 块中添加图像作为预览的帖子后,我发现自己无处可去:

    您需要在注册 ACF 块时添加“示例”,将“模式”属性添加为“预览”以及您要传递的任何特定数据。
acf_register_block_type(
        array(
            'name' => 'name-of-block',
            'title' => __('Your Title'),
            'description' => __('Your description'),
            'post_types' => array('page'),
            'category' => 'common',
            'render_template' => '../your/path/block_template.php', // your template
            'icon' => '', // svg code for icon
            'keywords' => array('Keyword', 'another'),
            'example'  => array(
                'attributes' => array(
                    'mode' => 'preview',
                    'data' => array(
                        'preview_image_help' => '../your/dir/block-image-preview.jpg',
                    )
                )
            )
        )
    );

警告: “preview_image_help”字段必须是唯一的名称,并且不能在块字段中存在。

块将在 2 个位置以预览模式呈现,编辑器和块插入器预览(当您将鼠标悬停在块的名称上时)。 在编辑器中呈现时,它将具有您在块中定义的所有字段。 当插入器预览中的渲染将只有“preview_image_help”字段。

    现在渲染部分(在您的模板中),检查唯一字段,您将知道渲染发生在哪里:
<?       
        if( isset( $block['data']['preview_image_help'] )  ) :    /* rendering in inserter preview  */

            echo '<img src="'. $block['data']['preview_image_help'] .'" style="width:100%; height:auto;">';
    
        
        else : /* rendering in editor body */
            
            $text   = get_field('text');
            $author = get_field('author');
            $title  = get_field('title');
            ?>
            <div class="my-class">
                <span class="class-title"><?=$title?></span>
                <span class="class-text"><?=$text?></span>
                <span class="class-author"><?=$author?></span>
            </div>
            <?
            
        endif;

【讨论】:

【参考方案4】:

    添加回调函数

    'render_callback' => 'block_render',

    添加示例和图片

     'example' => array(
     'attributes' => array(
         'mode' => 'preview', // Important!
         'data' => array(
             'image' => '<img src="' . get_template_directory_uri() . '/gutenberg-preview/cta.png' . '" style="display: block; margin: 0 auto;">'
         ),
     ),
    

    ),

    制作回调函数

     /**
      * Callback block render,
      * return preview image
      */
     function block_render( $block, $content = '', $is_preview = false ) 
         /**
          * Back-end preview
          */
          if ( $is_preview && ! empty( $block['data'] ) ) 
               echo $block['data']['image'];
               return;
           else 
               if ( $block ) :
                    $template = $block['render_template'];
                    $template = str_replace( '.php', '', $template );
                    get_template_part( '/' . $template );
               endif;
          
     
    

来源https://www.grbav.com/acf-custom-block-shows-preview-image-in-gutenberg/

【讨论】:

当链接到您自己的网站或内容(或您附属的内容)时,您must disclose your affiliation in the answer 以免被视为垃圾邮件。根据 Stack Exchange 政策,在您的用户名中包含与 URL 相同的文本或在您的个人资料中提及它不被视为充分披露。

以上是关于显示自定义 Gutenberg 块的预览图像的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式在主题中使用 Wordpress Gutenberg 块?

为Gutenberg自定义块添加内置调色板

如何正确弃用 Gutenberg 块

在 WordPress Gutenberg Block 插件中包含图像资产

Post Gutenberg 编辑器中未显示自定义分类法

在 Gutenberg 自定义横幅块中使用页面标题