首先要感谢 @fooleap 发给我的极为给力的 jQuery 实现显示图片 Exif 代码,解决了我十年来 的一个夙愿:显示博客图片 Exif(什么是 Exif?)信息——以后再也不需要在图片的 title 属性里人肉输入用了什么设备了!
虽然从来没学过 jQuery,但好歹有十多年前可怜的一点 js 基础,加上百度,一晚上摸索着居然也搞出来了。
注意:以下代码实现的基础是图片托管于 Aliyun OSS 或 Qiniu 等。
1、将根据自己需求修订后的 jQuery 代码 yourjscode.js 上传至主题下 js 文件夹:
/* ------------------------------------------------- * Description: New exif.js file. Just make it neat. * Edition: v1.4 * Time: 2018/11/18 23:46 * Author: https://synyan.net * ------------------------------------------------*/ window.$ = jQuery; $(document).ready(function(){ $('.post-content img[src*="synyan.cn"]').each(function(){ var _ = this; var $el = $(this); var displayinfo; if( _.src.toLowerCase().lastIndexOf('.jpg') ) var index = _.src.toLowerCase().lastIndexOf('.jpg'); else if( _.src.toLowerCase().lastIndexOf('.jpeg') ) var index = _.src.toLowerCase().lastIndexOf('.jpeg'); else return; var titleString = _.title; var titleCamera = false; if (titleString.indexOf("Camera") >= 0) titleCamera = true; if( index > -1 ){ var exifUrl = _.src.slice(0, index)+'.jpg?x-oss-process=image/info'; $.ajax({ url: exifUrl, success: function (res) { var exif = res; var parse = function(attr, label){ return !attr ? '' : ( label ? label + ' ' : '') + attr.value + ' '; } /* 情况1 */ if (!!parse(exif.Make) && !!parse(exif.Model) && !!parse(exif.DateTimeOriginal)){ /* 情况1.1 */ var imgCameraOne = parse(exif.Model).replace("Canon",""); var focalLengthInNumber = Math.round((eval(parse(exif.FocalLength,'')))*100)/100; var focalLengthIn35mmFilmOutput; var focalLengthIn35mmFilmNumber = eval(parse(exif.FocalLengthIn35mmFilm,'')); var focalLenghtOutput; if (!focalLengthInNumber) { focalLenghtOutput = ""; if (!focalLengthIn35mmFilmNumber) focalLengthIn35mmFilmOutput = ""; else focalLengthIn35mmFilmOutput = " eqv " + focalLengthIn35mmFilmNumber + "mm"; } else { focalLenghtOutput = "·" + " f=" + focalLengthInNumber + "mm"; if (focalLengthIn35mmFilmNumber) focalLengthIn35mmFilmOutput = " eqv " + focalLengthIn35mmFilmNumber + "mm"; else { focalLengthIn35mmFilmOutput = ""; } if (focalLengthInNumber == focalLengthIn35mmFilmNumber) { focalLenghtOutput = ""; focalLengthIn35mmFilmOutput = "·" + " f=" + focalLengthInNumber + "mm"; } else; } var content = '<div class="exif-caption" exif-data="' + parse(exif.Make, '') + imgCameraOne + parse(exif.LensModel,'·') + parse(exif.DateTimeOriginal, '·') + focalLenghtOutput + focalLengthIn35mmFilmOutput + '"></div>'; } /* 情况2 */ else if (!parse(exif.Make) || !parse(exif.Model) || !parse(exif.DateTimeOriginal)) { if (titleString && titleCamera) { var imgTitle = titleString; imgTitle = imgTitle.replace(/(Camera:/i, ''); imgTitle = imgTitle.replace(/)/i, ''); if (imgTitle.indexOf("+") >= 0) { var imgTitleString = imgTitle.split("+"); var imgCamera = imgTitleString[0]; var imgLens = imgTitleString[1]; var imgFilm = imgTitleString[2]; var imgScanner = imgTitleString[3]; if (!imgLens){ imgTitle = "" + imgCamera; } else if (!imgFilm) { imgTitle = "" + imgCamera +"·" + imgLens; } else if (!imgScanner) { imgTitle = "" + imgCamera +"·" + imgLens + "·" + imgFilm; } else { imgTitle = "" + imgCamera +"·" + imgLens + "·" + imgFilm + "·" + imgScanner; } } else if(imgTitle.indexOf("+") < 0 && titleString.indexOf("Camera:") >=0){ imgTitle = "" + imgTitle; } if (exif.DateTimeOriginal) { var content = '<div class="exif-caption" exif-data="' + imgTitle + parse(exif.DateTimeOriginal, '·') + '"></div>'; } /* 情况2.1 */ if (!(exif.DateTimeOriginal)) { /* 情况2.1.1 */ if ((exif.DateTime && !exif.DateTimeDigitized)) { var content = '<div class="exif-caption" exif-data="' + imgTitle + parse(exif.DateTime, '·') + '"></div>'; } else if ((exif.DateTimeDigitized)) { var content = '<div class="exif-caption" exif-data="' + imgTitle + parse(exif.DateTimeDigitized, '·') + '"></div>'; } else { var content = '<div class="exif-caption" exif-data="' + imgTitle + '"></div>'; } } } /* 情况3 */ else { var content = '<div class="exif-caption" exif-data="' + ' 无Exif信息 ' + '"></div>'; } } else; $(".post-content img").attr({title:""}); $el.after(content); } }) } }) })
2、在 Single.php 头部插入:
<script src="<?phpecho get_stylesheet_directory_uri() ?>/js/yourjscode.js"></script>
3、添加 css 代码(从 @fooleap 的博客扒下来的,同样也是修订了一番,最终符合 WordPress 的贴图规范,再次感谢 @fooleap):
/* exif css */ .post-content .wp-caption .exif-caption:before{ max-width: 100%; text-align: center; margin: 0 auto; content: attr(exif-data); display: block; position: absolute !important; top: 20px; left: 25px; right: 25px; background-color: black; color: white; font-size: 12px; line-height: 25px; height: 25px; overflow: hidden; opacity: 0; transition: opacity .5s; -webkit-transition: opacity .5s; } .wp-caption:hover .exif-caption[exif-data]:before { opacity: .7; }
4、Aliyun 开通 “跨域访问 ”。
大功告成!

鼠标移到图片上显示 Exif 信息
[2018/11/3]
昨晚做得匆忙,开会抽空之余继续优化了一下代码:
- 删掉了无用的几行代码。
- 以前人肉输入的 title 属性也没浪费,加入判断语句,如果 Exif 为空或不全,则取出 title 标签中的部分文字,嵌入显示完整信息。

无 Exif 的胶片引入 title 信息
[2018/11/4]
发现存量图片显示 Exif 存在各种 bug,原代码越改越多越糊涂,改到后来已经不知道到底在写什么了。
于是静下心来列了一张代码结构表:
情况 1: 正常 Exif(标准是 Make/Model/DateTimeOriginal/FNumber 同时存在)。 情况 1.1: 若 Make 为 Canon,Model 中去除一个重复的 Canon 字样。 情况 2: 有 Exif 但 Exif 不全(标准是 Make/Model/DateTimeOriginal/FNumber 有一个不存在),或无 Exif,以人工输入的 title="(Camera:Make & Model + [LensModel] + [Film] + [Scanner])"通过分割+号代替 Make/Model/LensModel 并添上其它属性。 情况 2.1: 若 DateTimeOriginal 不存在,则以 DateTime 显示修改时间。 情况 2.1.1: 若 DateTime 不存在,则不显示修改时间。 情况 2.1.2: 若 DateTimeDigitalized 存在,则以 DateTimeDigitalized 显示图片时间。 情况 3: 无 Exif,无 title,提示无 Exif 信息。
按照代码结构表重写一遍,清爽整洁多了。精简后的代码已更新至代码 1。
取得数据的第一个判断写错了,我本意是想判断没有 exif 信息,不是 !!exif.Mark 而是 !exif.Make。
@fooleap 我其实也很疑惑,因为我后来也试了一下发现!!exif.Mark 无效,不过太晚了再加上能用就不管了……
@老虎 看起来好折腾,不过习惯很好啊,想当年每张相片都插相机信息累坏了。
@fooleap 是啊,不过也没浪费,我改了代码了,以前留的信息都用上了,特别是胶片。其实当年如果不偷懒在修图时直接手工把 Exif 全都嵌进去就更完美了。现在是不高兴弄了……
@老虎 看你折腾了好多,其实 parse 直接提出来到外面更好。
@fooleap 这不是不会弄嘛。瞎折腾。
阿里云的 oss 没搞懂,我也是借 @fooleap 之力用七牛云实现这一功能。
@老何 七牛云现在不能用测试域名了,所以我只能放弃。OSS 跟七牛云大差不差。@fooleap 是中国好博友,给戴大红花。
@老虎 夸得我不好意思了,绵薄之力。
@fooleap 别不好意思,以后有好代码要继续共享哦~
@老虎 这扫描仪型号都出来了。
@老何 是的,不过胶片和扫描仪是从前人肉输的 title 属性,如今用函数方式取出来罢了。
没有跟 php 的交互为什么要用 ajax?
@大致 代码主干部分是 fooleap 友情赞助的,并不清楚为何用 ajax。看来回头是要自学一下了。
@大致 可是和阿里云 OSS 交互了。
我觉得使用 JS Ajax 应该是成本最低的一种实现方式。
https://www.alibabacloud.com/help/zh/doc-detail/31928.html
@fooleap 了解,阿里云。
我一直觉得他们管的事太多了。
CORS,我现在就遇到了这个问题,一直解决不了
@木瓜园 我看了一下,你应该也是用的比如七牛什么的 api 吧?图片都加了-1200×900.jpg 后缀。
我一般是自己线下处理好了尺寸再上传的,减少开销。
既然能加尺寸,exif 应该也能取得,CORS 在云存储的设置里应该有。
这功能我也喜欢,可惜我不会弄啊~~_(¦3」∠)_。。。。
@JiaYin 学啊,不会我可以代劳,只要你把阿里云 OSS 开通就行。
膜拜大佬,看到这个就想起来 QQ 空间可以读取图片信息感觉很牛掰
@typecho模板 我也是站在巨人的肩膀上。