9、现代JavaScript案例研究:动态画廊

现代JavaScript案例研究:动态画廊

1. 缩略图画廊的基础知识

缩略图画廊是一种常见的网页元素,用于展示一组图片的缩小版本,用户可以通过点击缩略图查看对应的全尺寸图片。这种设计不仅提高了用户体验,还有效地减少了页面加载时间。在早期互联网时代,网络连接速度较慢,缩略图画廊通过提供较小的预览图,让用户可以选择性地加载他们感兴趣的图片,从而节省带宽和时间。

1.1 缩略图画廊的演变

随着技术的进步,缩略图画廊从静态展示逐渐演变为动态交互式的画廊。最初的静态画廊通常使用HTML表格或列表来组织缩略图,并通过链接跳转到单独的页面显示全尺寸图片。这种方式虽然简单,但在现代网页设计中显得不够灵活和美观。为了提升用户体验,开发者开始引入JavaScript和CSS来增强画廊的功能和视觉效果。

2. 什么是缩略图画廊及其功能

缩略图画廊的核心理念是通过提供较小的预览图来展示图片集。这些缩略图不仅在尺寸上较小,而且文件大小也显著减小,从而加快了加载速度。用户可以选择点击感兴趣的缩略图来查看全尺寸图片,而不必下载所有图片。

2.1 缩略图的重要性

  • 节省带宽 :用户只需下载他们感兴趣的图片,减少了不必要的数据传输。
  • 提高性能 :较小的文件大小意味着更快的加载时间,提升了整体性能。
  • 增强用户体验 :用户可以快速浏览多个图片,找到他们感兴趣的内容。

2.2 不良实践

有些开发者通过CSS或JavaScript调整图片尺寸来生成缩略图,这种方法会导致图片质量下降,并且仍然需要下载完整的图片。正确的做法是在服务器端生成真正的缩略图,确保用户下载的是优化后的图片。

提示:生成缩略图的工具

有许多工具可以帮助生成高质量的缩略图,例如:
| 工具 | 描述 | 链接 |
| — | — | — |
| Picasa | 谷歌的图片管理工具,支持批量生成缩略图 | Picasa |
| IrfanView | 强大的图片查看和编辑工具,支持批量处理 | IrfanView |

此外,使用PHP和GD库也可以在服务器端生成缩略图。相关教程和代码可以在以下链接找到:
- PHP缩略图生成
- phpThumb类

3. 静态缩略图画廊

静态缩略图画廊通常由HTML表格或列表构成,每个缩略图链接到一个包含全尺寸图片的单独页面。这种方式的优点是简单易懂,缺点是缺乏灵活性和交互性。

3.1 示例代码

以下是静态缩略图画廊的基本结构:

<ul id="thumbs">
  <li>
    <a href="galleries/animals/dog2.jpg">
      <img src="galleries/animals/tn_dog2.jpg" alt="tn_dog2.jpg"/>
    </a>
  </li>
  <li>
    <a href="galleries/animals/dog3.jpg">
      <img src="galleries/animals/tn_dog3.jpg" alt="tn_dog3.jpg"/>
    </a>
  </li>
  <li>
    <a href="galleries/animals/dog4.jpg">
      <img src="galleries/animals/tn_dog4.jpg" alt="tn_dog4.jpg"/>
    </a>
  </li>
  <!-- 更多缩略图 -->
</ul>

3.2 分页处理

对于包含大量图片的画廊,分页是必不可少的。静态画廊需要为每个分页生成单独的HTML文件,这在更新时会带来大量的工作量。因此,动态生成画廊成为更好的选择。

4. 使用JavaScript伪造动态画廊

通过JavaScript,可以将静态缩略图画廊转变为看似动态的画廊。主要思路是在用户点击缩略图时,用JavaScript动态加载并显示全尺寸图片,同时保持画廊对非JavaScript用户的可访问性。

4.1 实现步骤

  1. 初始化 :检测DOM支持并获取包含缩略图的元素。
  2. 添加事件处理器 :为每个缩略图链接添加点击事件处理器,指向 showPic() 函数。
  3. 创建容器 :在文档中添加一个用于显示全尺寸图片的容器元素。
  4. 显示图片 :点击缩略图时,动态加载并显示全尺寸图片。
  5. 导航功能 :添加前后导航按钮,允许用户在图片之间切换。

4.2 示例代码

var fakegal = {
  thumbsListID: 'thumbs',
  largeContainerID: 'photo',
  closeClass: 'close',
  nextClass: 'next',
  prevClass: 'prev',
  hideClass: 'hide',
  showClass: 'show',
  closeLabel: 'close',
  prevContent: '<img src="last.gif" alt="previous photo"/>',
  nextContent: '<img src="next.gif" alt="next photo"/>',

  init: function () {
    if (!document.getElementById || !document.getElementsByTagName) return;
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
      var parent = links[i].parentNode;
      if (!DOMhelp.cssjs('check', parent, this.badgeClass)) continue;

      var newUL = document.createElement('ul');
      newUL.className = this.badgeClass;
      var dir = links[i].getAttribute('href');
      var loc = window.location.toString().match(/(^.*\/)/g);
      dir = dir.replace(loc, '');
      this.doxhr('badge.php?cd=' + dir, newUL);
      parent.parentNode.insertBefore(newUL, parent);
      parent.parentNode.removeChild(parent);
      i--;
    }
  },

  createContainer: function () {
    this.c = document.createElement('div');
    this.c.id = this.largeContainerID;

    var p = document.createElement('p');
    var cl = DOMhelp.createLink('#', this.closeLabel);
    cl.className = this.closeClass;
    p.appendChild(cl);
    DOMhelp.addEvent(cl, 'click', this.setPic, false);
    cl.onclick = DOMhelp.safariClickFix;
    this.c.appendChild(p);

    var il = DOMhelp.createLink('#', '');
    DOMhelp.addEvent(il, 'click', this.setPic, false);
    il.onclick = DOMhelp.safariClickFix;
    this.c.appendChild(il);
  },

  showPic: function (e) {
    var t = DOMhelp.getTarget(e);
    if (t.nodeName.toLowerCase() != 'a') t = t.parentNode;
    var c = this.current;
    if (t == this.prev) c -= 1;
    else c += 1;
    this.current = c;
    var pic = this.tlist.getElementsByTagName('a')[c];
    this.setPic(pic.getAttribute('href'));
    DOMhelp.cancelClick(e);
  },

  setPic: function (pic) {
    // 设置大图的逻辑
  },

  navPic: function (e) {
    var t = DOMhelp.getTarget(e);
    if (t.nodeName.toLowerCase() != 'a') t = t.parentNode;
    var c = this.current;
    if (t == this.prev) c -= 1;
    else c += 1;
    this.current = c;
    var pic = this.tlist.getElementsByTagName('a')[c];
    this.setPic(pic.getAttribute('href'));
    DOMhelp.cancelClick(e);
  }
};

DOMhelp.addEvent(window, 'load', fakegal.init, false);

4.3 流程图

graph TD;
    A[初始化] --> B{检测DOM支持};
    B -->|是| C[获取缩略图元素];
    C --> D[添加事件处理器];
    D --> E[创建容器];
    E --> F[显示图片];
    F --> G[添加导航按钮];

通过以上步骤,我们可以将静态画廊升级为动态画廊,提供更好的用户体验。接下来,我们将讨论如何为缩略图添加标题,进一步丰富画廊的功能。

5. 显示图片标题

缩略图画廊不仅是视觉展示,还应考虑到无障碍访问和SEO优化。为每张图片添加适当的标题和替代文本,不仅可以帮助视障用户理解图片内容,还可以提高图片在搜索引擎中的可见度。

5.1 添加标题和替代文本

为了实现这一点,我们需要在静态HTML中为每张缩略图添加 title alt 属性。这些属性将作为图片的描述信息,当用户将鼠标悬停在图片上时显示标题,屏幕阅读器也会朗读这些描述。

示例代码
<ul id="thumbs">
  <li>
    <a href="galleries/animals/dog2.jpg">
      <img src="galleries/animals/tn_dog2.jpg" 
           title="This square is mine" 
           alt="Dog in a shady square"/>
    </a>
  </li>
  <li>
    <a href="galleries/animals/dog3.jpg">
      <img src="galleries/animals/tn_dog3.jpg" 
           title="Sleepy bouncer" 
           alt="Dog on the steps of a shop"/>
    </a>
  </li>
  <!-- 更多缩略图 -->
</ul>

5.2 动态显示标题

为了让用户在点击缩略图后看到标题,我们需要在显示全尺寸图片的同时,也将标题显示在大图容器中。这可以通过JavaScript动态添加一个段落元素来实现。

示例代码
var fakegal = {
  // ... 其他属性 ...
  captionClass: 'caption',

  init: function () {
    // ... 初始化代码 ...
  },

  createContainer: function () {
    // ... 创建容器代码 ...

    // 添加标题容器
    var cap = document.createElement('p');
    cap.className = this.captionClass;
    this.c.appendChild(cap);
  },

  showPic: function (e) {
    // ... 显示图片代码 ...

    // 获取并显示标题
    var img = this.tlist.getElementsByTagName('a')[this.current].getElementsByTagName('img')[0];
    var cap = this.c.getElementsByClassName(this.captionClass)[0];
    cap.innerHTML = img.title;
  }
};

5.3 效果展示

通过这种方式,用户不仅可以查看大图,还能阅读到图片的描述信息,增强了画廊的信息传递能力。

6. 创建动态缩略图画廊

为了进一步提升画廊的交互性和动态性,我们可以使用PHP和Ajax技术从服务器动态加载图片。这种方法不仅减少了初始页面加载时间,还能根据用户需求按需加载图片。

6.1 使用PHP和Ajax加载图片

通过PHP脚本,我们可以动态生成缩略图列表,并使用Ajax技术在用户点击缩略图时从服务器请求全尺寸图片。这种方式避免了在页面加载时一次性加载所有图片,从而提高了性能。

示例代码
var dyngal = {
  originalPHP: 'original.php',
  dynamicPHP: 'dynamic.php',
  contentID: 'content',

  init: function () {
    if (!document.getElementById || !document.getElementsByTagName) return;
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
      var parent = links[i].parentNode;
      if (!DOMhelp.cssjs('check', parent, this.badgeClass)) continue;

      var newUL = document.createElement('ul');
      newUL.className = this.badgeClass;
      var dir = links[i].getAttribute('href');
      var loc = window.location.toString().match(/(^.*\/)/g);
      dir = dir.replace(loc, '');
      this.doxhr('badge.php?cd=' + dir, newUL);
      parent.parentNode.insertBefore(newUL, parent);
      parent.parentNode.removeChild(parent);
      i--;
    }
  },

  load: function (e) {
    var t = DOMhelp.getTarget(e);
    if (t.nodeName.toLowerCase() != 'a') t = t.parentNode;
    var h = t.getAttribute('href');
    h = h.replace(this.originalPHP, this.dynamicPHP);
    this.doxhr(h, this.contentID);
    DOMhelp.cancelClick(e);
  },

  doxhr: function (url, container) {
    var request;
    try {
      request = new XMLHttpRequest();
    } catch (error) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (error) {
        return true;
      }
    }
    request.open('get', url, true);
    request.onreadystatechange = function () {
      if (request.readyState == 1) {
        container.innerHTML = 'Loading...';
      }
      if (request.readyState == 4) {
        if (request.status && /200\|304/.test(request.status)) {
          dyngal.retrieved(request, container);
        } else {
          dyngal.failed(request);
        }
      }
    }
    request.setRequestHeader('If-Modified-Since', 'Wed, 05 Apr 2006 00:00:00 GMT');
    request.send(null);
    return false;
  },

  retrieved: function (request, container) {
    var data = request.responseText;
    document.getElementById(container).innerHTML = data;
    dyngal.assignHandlers(container);
  },

  failed: function (request) {
    alert('The XMLHttpRequest failed. Status:' + request.status);
    return true;
  },

  assignHandlers: function (o) {
    if (!document.getElementById(o)) return;
    o = document.getElementById(o);
    var gLinks = o.getElementsByTagName('a');
    for (var i = 0; i < gLinks.length; i++) {
      DOMhelp.addEvent(gLinks[i], 'click', dyngal.load, false);
      gLinks[i].onclick = DOMhelp.safariClickFix;
    }
  }
};

DOMhelp.addEvent(window, 'load', dyngal.init, false);

6.2 流程图

graph TD;
    A[初始化] --> B{检测DOM支持};
    B -->|是| C[获取缩略图元素];
    C --> D[添加事件处理器];
    D --> E[创建容器];
    E --> F[显示图片];
    F --> G[动态加载图片];

通过PHP和Ajax技术,我们可以实现更加灵活和高效的动态画廊,提升了用户体验和性能。

7. 从文件夹创建图像徽章

为了展示更多样化的图片集,我们可以创建图像徽章,允许用户通过前后导航链接浏览缩略图,并点击缩略图查看大图。这种设计不仅美观,还能有效组织和展示图片集。

7.1 PHP脚本生成徽章

首先,我们需要一个PHP脚本来生成缩略图列表。这个脚本将读取指定文件夹中的图片,并生成相应的HTML代码。

示例代码
<?php
$cd = isset($_GET['cd']) ? $_GET['cd'] : '';
$c = isset($_GET['c']) ? intval($_GET['c']) : 5;
$s = isset($_GET['s']) ? intval($_GET['s']) : 0;

$imgs = glob($cd . '*.{jpg,jpeg,png,gif}', GLOB_BRACE);
$imgs = array_slice($imgs, $s, $c);

echo '<ul>';
if ($s > 0) {
  echo '<li class="badgeprev">';
  echo '<a href="badge.php?c=' . $c . '&s=' . ($s - $c) . '&cd=' . $cd . '">prev</a>';
  echo '</li>';
} else {
  echo '<li class="badgeprev"><span>prev</span></li>';
}

foreach ($imgs as $img) {
  echo '<li><a href="' . str_replace('tn_', '', $img) . '">';
  echo '<img src="' . $img . '" alt="' . basename($img) . '"/>';
  echo '</a></li>';
}

if (($c + $s) <= sizeof($imgs)) {
  echo '<li class="badgenext">';
  echo '<a href="badge.php?c=' . $c . '&s=' . ($s + $c) . '&cd=' . $cd . '">next</a>';
  echo '</li>';
} else {
  echo '<li class="badgenext"><span>next</span></li>';
}
echo '</ul>';
?>

7.2 JavaScript代码集成

接下来,我们需要编写JavaScript代码来调用PHP脚本,并将生成的HTML代码插入到页面中。

示例代码
var badge = {
  badgeClass: 'badge',
  containerID: 'badgecontainer',

  init: function () {
    if (!document.getElementById || !document.createTextNode) return;
    var links = document.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++) {
      var parent = links[i].parentNode;
      if (!DOMhelp.cssjs('check', parent, this.badgeClass)) continue;

      var newUL = document.createElement('ul');
      newUL.className = this.badgeClass;
      var dir = links[i].getAttribute('href');
      var loc = window.location.toString().match(/(^.*\/)/g);
      dir = dir.replace(loc, '');
      this.doxhr('badge.php?cd=' + dir, newUL);
      parent.parentNode.insertBefore(newUL, parent);
      parent.parentNode.removeChild(parent);
      i--;
    }

    this.container = document.createElement('div');
    this.container.id = this.containerID;
    document.body.appendChild(this.container);
  },

  doxhr: function (url, container) {
    var request;
    try {
      request = new XMLHttpRequest();
    } catch (error) {
      try {
        request = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (error) {
        return true;
      }
    }
    request.open('get', url, true);
    request.onreadystatechange = function () {
      if (request.readyState == 1) {
      }
      if (request.readyState == 4) {
        if (request.status && /200\|304/.test(request.status)) {
          badge.retrieved(request, container);
        } else {
          badge.failed(request);
        }
      }
    }
    request.setRequestHeader('If-Modified-Since', 'Wed, 05 Apr 2006 00:00:00 GMT');
    request.send(null);
    return false;
  },

  retrieved: function (request, container) {
    var data = request.responseText;
    container.innerHTML = data;
    badge.assignHandlers(container);
  },

  failed: function (request) {
    alert('The XMLHttpRequest failed. Status:' + request.status);
    return true;
  },

  assignHandlers: function (o) {
    if (!document.getElementById(o)) return;
    o = document.getElementById(o);
    var gLinks = o.getElementsByTagName('a');
    for (var i = 0; i < gLinks.length; i++) {
      DOMhelp.addEvent(gLinks[i], 'click', badge.load, false);
      gLinks[i].onclick = DOMhelp.safariClickFix;
    }
  },

  load: function (e) {
    var t = DOMhelp.getTarget(e);
    if (t.nodeName.toLowerCase() != 'a') t = t.parentNode;
    var h = t.getAttribute('href');
    h = h.replace('original.php', 'dynamic.php');
    this.doxhr(h, this.containerID);
    DOMhelp.cancelClick(e);
  }
};

DOMhelp.addEvent(window, 'load', badge.init, false);

7.3 效果展示

通过PHP和JavaScript的结合,我们可以创建一个动态的图像徽章,用户可以轻松地浏览和查看图片集。这种设计不仅美观,还提供了良好的用户体验。

8. 总结与展望

通过上述步骤,我们详细介绍了如何创建一个现代的动态缩略图画廊。从基础知识到高级技术的应用,我们逐步展示了如何利用JavaScript、PHP和Ajax技术来增强画廊的交互性和用户体验。无论是静态画廊的优化,还是动态画廊的实现,我们都提供了具体的代码示例和操作步骤,帮助读者理解和应用这些技术。

在未来的发展中,随着Web技术的不断进步,我们可以期待更多的创新和优化。例如,结合新的API和技术栈,进一步提升画廊的性能和功能。同时,我们也可以探索如何将这些技术应用于其他类型的Web应用程序,以满足不同的需求和场景。


通过这篇文章,我们希望读者能够掌握创建动态缩略图画廊的方法,并能够在实际项目中灵活运用这些技术。无论你是初学者还是有一定经验的开发者,本文提供的内容都将为你提供有价值的参考和指导。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值