用 <picture> 和 js 改变图像

Posted

技术标签:

【中文标题】用 <picture> 和 js 改变图像【英文标题】:Change image with <picture> and js 【发布时间】:2021-12-31 12:21:48 【问题描述】:

我有一个小滑块,可以将preview 图像切换到main 图像。现在可以正常使用了

blade.php

<div class="custom-carousel-section">
  <div class="custom-container">
    <div class="custom-carousel">
      @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
      <div class="custom-carousel__title">
        @if($loop->first)
          <span> $article_block_image->title </span>
        @endif
      </div>
      @endforeach @endif
      @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
      <div class="main-image">
      @if($loop->first)
          <img src=" $article_block_image->main_image "  title=" $article_block_image->image_title " data-title=" $article_block_image->title ">
      @endif
      </div>
      @endforeach @endif
      <div class="img-to-select">
        @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image)
        <div @if($loop->first) class="img-to-select__item  selected" @else class="img-to-select__item" @endif>
          <img src=" $article_block_image->preview_image "  title=" $article_block_image->image_title " data-title=" $article_block_image->title " data-main-src=" $article_block_image->main_image ">
        </div>
        @endforeach @endif
      </div>
    </div>
  </div>
</div>

js

$('.img-to-select__item').click(function () 
$('.img-to-select__item').removeClass('selected');
$(this).addClass('selected');
$('.main-image > img').attr('src', $(this).children('img').data('main-src'));
$('.custom-carousel__title > span').html($(this).children('img').attr('data-title'));
);

但我还有一张图片mobile_image,我希望mobile_image 更改而不是main_image,最大尺寸为576px,为此我使用&lt;picture&gt;

我把我的代码改成这样

<div class="main-image">
@if($loop->first)
<picture>
  <source srcset=" $article_block_image->mobile_image " media="(max-width: 576px)"  title=" $article_block_image->image_title " data-title=" $article_block_image->title ">
  <source srcset=" $article_block_image->main_image "  title=" $article_block_image->image_title " data-title=" $article_block_image->title ">
  <img src=" $article_block_image->main_image "  title=" $article_block_image->image_title " data-title=" $article_block_image->title ">
</picture>
@endif
</div>

但我的滑块停止工作

主图最终变为移动,但滑块本身不切换

在这种情况下,预览图像也会回显,但主图像本身不会改变

我的滑块基本上是这样工作的

https://jsfiddle.net/a9yvdu75/

我只需要将 main-image 类中的内容放入 &lt;picture&gt; 并根据屏幕大小更改图像

【问题讨论】:

切换到&lt;picture&gt;后是否尝试过再次初始化滑块? @VladSolomon 我这里没有初始化,这是滑块工作的所有代码 所以当你到达 576px 断点并且图像被移动图像替换时,滑块就停止工作了? @VladSolomon 它根本不起作用,更准确地说,它单击预览图像,但主图像没有改变,但同时&lt;picture&gt; 起作用,并且在所需的大小它替换了图像 【参考方案1】:

这行有问题:

$('.main-image > img').attr('src', $(this).children('img').data('main-src'));

符号&gt; 表示img 必须是.main-image 的直接子代。所以你必须选择$('.main-image img')$('.main-image &gt; picture &gt; img') 之一。但这仍然行不通,因为...

第二个问题是您不完全了解&lt;picture&gt; 的工作原理。浏览器根据media 中的规则选择&lt;source&gt; 显示自己。而同样的&lt;img&gt; 仅适用于不支持&lt;picture&gt; 的浏览器。 所以设置.attr('src'只有在你删除所有&lt;source&gt;时才有效。

在很多地方你也使用.children('img')

因此,如果您想进行此类替换,则必须删除响应式图像选择。

我相信对您来说最快的解决方案是use an alternative syntax。 (您仍然需要以编程方式删除 srcset, sizes

<img srcset="elva-fairy-480w.jpg 480w,
             elva-fairy-800w.jpg 800w"
     sizes="(max-width: 600px) 480px,
            800px"
     src="elva-fairy-800w.jpg"
     >

另一种选择是交换整个.main-image 部分。例如:

<div class="main-image">
  <picture>
    <!-- placeholder, insert the correct HTML yourself  -->
  </picture>
</div>

并像使用 JS 一样:

$('.main-image > picture').html(`
  <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg">
  <source media="(min-width: 800px)" srcset="elva-800w.jpg">
  <img src="elva-800w.jpg" >
`)

您必须在缩略图中存储“桌面”和移动资源。

<div @if($loop->first) class="img-to-select__item  selected" @else class="img-to-select__item" @endif>
  <img src=" $article_block_image->preview_image " 
    ... 
    data-main-src=" $article_block_image->main_image " 
    data-mobile-src=" $article_block_image->mobile_image "
  >
</div>

其余的只是繁琐的字符串粘合。

//编辑:可能的解决方案之一。

$('.img-to-select__item').click(function () 
  $('.img-to-select__item').removeClass('selected');
  $(this).addClass('selected');
  let mainSrc = $(this).children('img').data('main-src')
  let mobileSrc = $(this).children('img').data('mobile-src')
  let title = $(this).children('img').attr('title')
  let alt = $(this).children('img').attr('alt')
  $('.main-image > picture').html(`
    <source srcset="$mobileSrc" media="(max-width: 576px)"  title="$title">
    <source srcset="$mainSrc"  title="$title">
    <img src="$mainSrc"  title="$title">
  `);
  $('.custom-carousel__title > span').html($(this).children('img').attr('data-title'));
);

请记住,在 JS 中,您使用的是已经生成的 HTML(提供的数据),您无法访问 PHP 变量。

【讨论】:

好的,谢谢,在第二个选项中,我将有data-main-srcdata-mobile-src,那么如何确定脚本中的哪一个? 你能用 picure 和 2 个来源制作 jsfiddle 吗? 是的,稍等片刻,如果你不介意的话,我会按照第一个选项来做,可能第二个根本派不上用场 好吧,假设我收到了几张照片,主要的、移动的和预览的,我不太明白在这种情况下脚本应该是什么jsfiddle.net/17trajhx 嘿...修复了jsfiddle.net/kwxg49qz/2(我希望我在JS模板语法中是对的)

以上是关于用 <picture> 和 js 改变图像的主要内容,如果未能解决你的问题,请参考以下文章

原生js实现淘宝图片切换

怎样用js清除file type里的内容

需要用JS静音和改变图像

work picture change

个人中心的侧边栏--用jq实现侧边栏点击一块出现一块其他几块隐藏并且同时改变前面的img图片

用css改变下拉框样式