“f104b15cbb9927bd71b52ebbbfe94cf65b10a0d6”上不存在“...pytest/cluster/git@gitcode.net:qq_37101384/tdengine.git”
提交 94ef7567 编写于 作者: D dallascao

1

上级
此差异已折叠。
:exclamation: 重要提示 v5beta 现在可用于测试,[在这里阅读公告](https://github.com/dimsemenov/PhotoSwipe/issues/1749) 并报告你发现的任何问题,代码位于 `v5-beta` 分支内。
## PhotoSwipe 库
[![建立Status](https://travis-ci.org/dimsemenov/PhotoSwipe.svg)](https://travis-ci.org/dimsemenov/PhotoSwipe)
JavaScript 图像库为移动和桌面.
- [Documentation and getting started guide](http://photoswipe.com/documentation/getting-started.html).
- [演示和脚本主页](http://photoswipe.com).
- [NPM](https://www.npmjs.com/package/photoswipe) `npm install photoswipe`.
- Bower`bower install photoswipe`
## 文件的位置
- 编译的 PhotoSwipe JS 和 CSS 文件、SVG 和 PNG 精灵都在 [dist/](https://github.com/dimsemenov/PhotoSwipe/tree/master/dist) 文件夹中。
- 源文件(.)JS 和。SCSS)都在 [src/](https://github.com/dimsemenov/PhotoSwipe/tree/master/src) 文件夹中。注意, PhotoSwipe 在编译 Sass 文件时使用 Autoprefixer。
- 演示网站在 [website/](https://github.com/dimsemenov/PhotoSwipe/tree/master/website) 文件夹中。
- 文档 Markdown 文件在 [website/documentation/](https://github.com/dimsemenov/PhotoSwipe/tree/master/website/documentation) 中。
## 插件 / 扩展 / 插件
- [Ruby gem](https://rubygems.org/gems/photoswipe-rails).
- Ember.js Addons:[ember-photoswipe](https://github.com/kaermorchen/ember-photoswipe)[ember-cli-photoswipe](https://github.com/poetic/ember-cli-photoswipe)
- [Eager app](https://eager.io/app/DvuKIoU8iTOt).
- [Koken CMS 插件](https://github.com/DanielMuller/koken-plugin-photoswipe).
- [果园 CMS 模块](https://gallery.orchardproject.net/List/Modules/Orchard.Module.Cascade.PhotoSwipe).
- [黄色 CMS 插件 Name ](https://github.com/datenstrom/yellow-plugins/tree/master/gallery).
- [Kirby CMS 插件](https://github.com/SiteMarina/guggenheim).
- [Drupal CMF 模块](https://www.drupal.org/project/photoswipe).
- [ProcessWire CMS 模块](https://github.com/blynx/MarkupProcesswirePhotoswipe).
- [SPIP CMS module](https://plugins.spip.net/photoswipe.html).
- [Fork CMS MediaLibrary widget](https://github.com/forkcms/forkcms).
编码一些有用的东西?<a href='mailto:diiiimaaaa@gmail.com?subject="PhotoSwipe Plugin"'> 给我发邮件 </a>,我会在这里发布一个链接。
## Build
要自己编译 PhotoSwipe ,请确保安装了 [Node.js](http://nodejs.org/)[Grunt.js](https://github.com/cowboy/grunt)[Ruby](http://www.ruby-lang.org/)[Jekyll](https://github.com/mojombo/jekyll/),然后:
1) 克隆库
git clone https://github.com/dimsemenov/PhotoSwipe.git
2) 进入你获取的 PhotoSwipe 文件夹并安装节点依赖项
cd PhotoSwipe && npm install
3) 运行 `grunt` 以生成 `dist` 文件夹和 `_site/` 文件夹中的站点中的 JS 和 CSS 文件
grunt
可选:
- 运行 `grunt watch` 以在 `src/``website/` 中更改文件时自动重建文件(JS、CSS、演示网站和文档)。
- 运行 `grunt nosite` 只构建 JS 和 CSS 文件(输出文件夹 `dist/`)。
- 运行 `grunt pswpbuild` 只构建 JS 文件。param`--pswp-exclude` 允许排除模块,例如 `grunt pswpbuild --pswp-exclude=history` 将排除历史模块。
## 使用 PhotoSwipe ?
如果你以某种有趣的方式使用了 PhotoSwipe ,或者在某个流行品牌的网站上,如果你 <a href='mailto:diiiimaaaa@gmail.com?subject="Site that uses PhotoSwipe"'> 给我拍 </a> 一个链接,我会非常感激。
## 许可证
Script 是根据 MIT 许可证授权的,但有一个例外:不要基于它创建一个公共 WordPress 插件,因为我将开发它。如果你现在需要使用它作为一个公共的 WordPress 插件,请先通过电子邮件问我。谢谢!
归因不是必需的,但很受欢迎,尤其是当你为开发人员制作产品时。
## 关于
PhotoSwipe 4.0+ 是由 [Dmitry Semenov](http://twitter.com/dimsemenov) 开发的。但最初,Script 是由曼彻斯特的一家数字机构 [Code ComputerLove ](http://www.codecomputerlove.com/) 在 2011 年创建的,他们于 2014 年 3 月开始开发。你可以在此库的历史中查看旧 PhotoSwipe (<4.0)的 。
<svg width="264" height="88" viewBox="0 0 264 88" xmlns="http://www.w3.org/2000/svg"><title>default-skin 2</title><g fill="none" fill-rule="evenodd"><g><path d="M67.002 59.5v3.768c-6.307.84-9.184 5.75-10.002 9.732 2.22-2.83 5.564-5.098 10.002-5.098V71.5L73 65.585 67.002 59.5z" id="Shape" fill="#fff"/><g fill="#fff"><path d="M13 29v-5h2v3h3v2h-5zM13 15h5v2h-3v3h-2v-5zM31 15v5h-2v-3h-3v-2h5zM31 29h-5v-2h3v-3h2v5z" id="Shape"/></g><g fill="#fff"><path d="M62 24v5h-2v-3h-3v-2h5zM62 20h-5v-2h3v-3h2v5zM70 20v-5h2v3h3v2h-5zM70 24h5v2h-3v3h-2v-5z"/></g><path d="M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z" fill="#fff"/><path d="M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z" fill="#fff"/><path d="M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z" fill="#fff"/><g><path id="Rectangle-11" fill="#fff" d="M160.957 28.543l-3.25-3.25-1.413 1.414 3.25 3.25z"/><path d="M152.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" id="Oval-1" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M150 21h5v1h-5z"/></g><g><path d="M116.957 28.543l-1.414 1.414-3.25-3.25 1.414-1.414 3.25 3.25z" fill="#fff"/><path d="M108.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M106 21h5v1h-5z"/><path fill="#fff" d="M109.043 19.008l-.085 5-1-.017.085-5z"/></g></g></g></svg>
\ No newline at end of file
:exclamation: **Important note** v5 beta is now available for testing, [read announcement here](https://github.com/dimsemenov/PhotoSwipe/issues/1749) and report any issues that you find, code is within `v5-beta` branch.
## PhotoSwipe Repository
[![Build Status](https://travis-ci.org/dimsemenov/PhotoSwipe.svg)](https://travis-ci.org/dimsemenov/PhotoSwipe)
JavaScript image gallery for mobile and desktop.
- [Documentation and getting started guide](http://photoswipe.com/documentation/getting-started.html).
- [Demo and script home page](http://photoswipe.com).
- [NPM](https://www.npmjs.com/package/photoswipe) `npm install photoswipe`.
- Bower `bower install photoswipe`.
## Location of files
- Compiled PhotoSwipe JS and CSS files, SVG and PNG sprites are in the [dist/](https://github.com/dimsemenov/PhotoSwipe/tree/master/dist) folder.
- Source files (.JS and .SCSS) are in the [src/](https://github.com/dimsemenov/PhotoSwipe/tree/master/src) folder. Note that PhotoSwipe uses Autoprefixer when compiling SASS files.
- Demo website is in the [website/](https://github.com/dimsemenov/PhotoSwipe/tree/master/website) folder.
- Documentation markdown files are in [website/documentation/](https://github.com/dimsemenov/PhotoSwipe/tree/master/website/documentation).
## Plugins / extensions / addons
- [Ruby gem](https://rubygems.org/gems/photoswipe-rails).
- Ember.js addons: [ember-photoswipe](https://github.com/kaermorchen/ember-photoswipe), [ember-cli-photoswipe](https://github.com/poetic/ember-cli-photoswipe).
- [Eager app](https://eager.io/app/DvuKIoU8iTOt).
- [Koken CMS plugin](https://github.com/DanielMuller/koken-plugin-photoswipe).
- [Orchard CMS module](https://gallery.orchardproject.net/List/Modules/Orchard.Module.Cascade.PhotoSwipe).
- [Yellow CMS plugin](https://github.com/datenstrom/yellow-plugins/tree/master/gallery).
- [Kirby CMS plugin](https://github.com/SiteMarina/guggenheim).
- [Drupal CMF module](https://www.drupal.org/project/photoswipe).
- [ProcessWire CMS module](https://github.com/blynx/MarkupProcesswirePhotoswipe).
- [SPIP CMS module](https://plugins.spip.net/photoswipe.html).
- [Fork CMS MediaLibrary widget](https://github.com/forkcms/forkcms).
Coded something useful? <a href='mailto:diiiimaaaa@gmail.com?subject="PhotoSwipe Plugin"'>Email me</a> and I’ll post a link to it here.
## Build
To compile PhotoSwipe by yourself, make sure that you have [Node.js](http://nodejs.org/), [Grunt.js](https://github.com/cowboy/grunt), [Ruby](http://www.ruby-lang.org/) and [Jekyll](https://github.com/mojombo/jekyll/) installed, then:
1) Clone the repository
git clone https://github.com/dimsemenov/PhotoSwipe.git
2) Go inside the PhotoSwipe folder that you fetched and install Node dependencies
cd PhotoSwipe && npm install
3) Run `grunt` to generate the JS and CSS files in the `dist` folder and the site in the `_site/` folder
grunt
Optionally:
- Run `grunt watch` to automatically rebuild files (JS, CSS, demo website and documentation) when you change files in `src/` or in `website/`.
- Run `grunt nosite` to build just JS and CSS files (output is folder `dist/`).
- Run `grunt pswpbuild` to build just JS files. Param `--pswp-exclude` allows to exclude modules, for example `grunt pswpbuild --pswp-exclude=history` will exclude history module.
## Using PhotoSwipe?
If you’ve used PhotoSwipe in some interesting way, or on the site of a popular brand, I’d be very grateful if you <a href='mailto:diiiimaaaa@gmail.com?subject="Site that uses PhotoSwipe"'>shoot me</a> a link to it.
## License
Script is licensed under MIT license with one exception: Do not create a public WordPress plugin based on it, as I will develop it. If you need to use it for a public WordPress plugin right now, please ask me by email first. Thanks!
Attribution is not required, but much appreciated, especially if you’re making a product for developers.
## About
PhotoSwipe 4.0+ is developed by [Dmitry Semenov](http://twitter.com/dimsemenov). But initially script was created in 2011 by [Code Computerlove](http://www.codecomputerlove.com/), a digital agency in Manchester, they [passed](https://twitter.com/PhotoSwipe/status/444134042787930113) on development in March 2014. You can view [source and documentation](https://github.com/dimsemenov/PhotoSwipe/tree/v3.0.3) of old PhotoSwipe (<4.0) in history of this repo.
<svg width="264" height="88" viewBox="0 0 264 88" xmlns="http://www.w3.org/2000/svg"><title>default-skin 2</title><g fill="none" fill-rule="evenodd"><g><path d="M67.002 59.5v3.768c-6.307.84-9.184 5.75-10.002 9.732 2.22-2.83 5.564-5.098 10.002-5.098V71.5L73 65.585 67.002 59.5z" id="Shape" fill="#fff"/><g fill="#fff"><path d="M13 29v-5h2v3h3v2h-5zM13 15h5v2h-3v3h-2v-5zM31 15v5h-2v-3h-3v-2h5zM31 29h-5v-2h3v-3h2v5z" id="Shape"/></g><g fill="#fff"><path d="M62 24v5h-2v-3h-3v-2h5zM62 20h-5v-2h3v-3h2v5zM70 20v-5h2v3h3v2h-5zM70 24h5v2h-3v3h-2v-5z"/></g><path d="M20.586 66l-5.656-5.656 1.414-1.414L22 64.586l5.656-5.656 1.414 1.414L23.414 66l5.656 5.656-1.414 1.414L22 67.414l-5.656 5.656-1.414-1.414L20.586 66z" fill="#fff"/><path d="M111.785 65.03L110 63.5l3-3.5h-10v-2h10l-3-3.5 1.785-1.468L117 59l-5.215 6.03z" fill="#fff"/><path d="M152.215 65.03L154 63.5l-3-3.5h10v-2h-10l3-3.5-1.785-1.468L147 59l5.215 6.03z" fill="#fff"/><g><path id="Rectangle-11" fill="#fff" d="M160.957 28.543l-3.25-3.25-1.413 1.414 3.25 3.25z"/><path d="M152.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" id="Oval-1" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M150 21h5v1h-5z"/></g><g><path d="M116.957 28.543l-1.414 1.414-3.25-3.25 1.414-1.414 3.25 3.25z" fill="#fff"/><path d="M108.5 27c3.038 0 5.5-2.462 5.5-5.5s-2.462-5.5-5.5-5.5-5.5 2.462-5.5 5.5 2.462 5.5 5.5 5.5z" stroke="#fff" stroke-width="1.5"/><path fill="#fff" d="M106 21h5v1h-5z"/><path fill="#fff" d="M109.043 19.008l-.085 5-1-.017.085-5z"/></g></g></g></svg>
\ No newline at end of file
---
layout: default
title: PhotoSwipe API
h1_title: API
description: Public methods, properties and events of PhotoSwipe JavaScript image gallery.
addjs: true
canonical_url: http://photoswipe.com/documentation/api.html
buildtool: true
markdownpage: true
---
此页面上列出的所有方法和属性都是公共的。如果你想查看 API 可以做什么的示例,请在 [source of default PhotoSwipe UI](https://github.com/dimsemenov/PhotoSwipe/blob/master/src/js/ui/photoswipe-ui-default.js) 中查看。
你可以在初始化期间获得 PhotoSwipe 实例对象,例如:
```javascript
var photoswipeInstance = new PhotoSwipe( /* ... */ );
```
## 方法
```javascript
var pswp = new PhotoSwipe( /* ... */ );
// Initialize and open gallery
// (you can bind events before this method)
pswp.init();
// Go to slide by index
// @param {int} `index`
pswp.goTo(index);
// Go to the next slide
pswp.next();
// Go to the previous slide
pswp.prev();
// Update gallery size
// @param {boolean} `force` If you set it to `true`,
// size of the gallery will be updated
// even if viewport size hasn't changed.
pswp.updateSize(force);
// Close gallery
pswp.close();
// Destroy gallery,
// automatically called after close()
pswp.destroy()
// Zoom current slide to (optionally with animation)
// @param {number} `destZoomLevel` Destination scale number. 1 - original.
// pswp.currItem.fitRatio - image will fit into viewport.
// @param {object} `centerPoint` Object of x and y coordinates, relative to viewport.
// @param {int} `speed` Animation duration. Can be 0.
// @param {function} `easingFn` Easing function (optional). Set to false to use default easing.
// @param {function} `updateFn` Function will be called on each update frame. (optional)
//
// Example below will 2x zoom to center of slide:
// pswp.zoomTo(2, {x:pswp.viewportSize.x/2,y:pswp.viewportSize.y/2}, 2000, false, function(now) {
//
// });
pswp.zoomTo(destZoomLevel, centerPoint, speed, easingFn, updateFn);
// Apply zoom and pan to the current slide
//
// @param {number} `zoomLevel`
// @param {int} `panX`
// @param {int} `panY`
//
// For example: `pswp.applyZoomPan(1, 0, 0)`
// will zoom current image to the original size
// and will place it on top left corner
//
//
pswp.applyZoomPan(zoomLevel, panX, panY);
```
## 属性
```javascript
// current slide object
pswp.currItem
// items array (slides, images)
pswp.items
// size of sliding viewport
pswp.viewportSize
// object holds all functions from framework
// framework-bridge.js
pswp.framework
// UI object (e.g. PhotoSwipeUI_Default instance)
pswp.ui
// background element (pswp__bg)
pswp.bg
// container element (pswp__container)
pswp.container
// options
pswp.options
// Even though methods below aren't technically properties, we list them here:
// current item index (int)
pswp.getCurrentIndex();
// total number of items
pswp.options.getNumItemsFn()
// current zoom level (number)
pswp.getZoomLevel();
// one (or more) pointer is used
pswp.isDragging();
// two (or more) pointers are used
pswp.isZooming();
// `true` when transition between is running (after swipe)
pswp.isMainScrollAnimating();
```
## 事件
PhotoSwipe 使用非常简单的事件 / 消息传递系统。它有两个方法 `shout`(触发器事件)和 `listen`(处理事件)。目前还没有解除绑定 Listener 的方法,但是当 PhotoSwipe 关闭时,所有这些方法都将被清除。
```javascript
var pswp = new PhotoSwipe(/* ... */);
// Listen for "helloWorld" event
pswp.listen('helloWorld', function(name) {
alert('Name is: ' + name);
});
// Trigger "helloWorld" event
pswp.shout('helloWorld', 'John' /* you may pass more arguments */);
```
可用活动:
```javascript
// Before slides change
// (before the content is changed, but after navigation)
// Update UI here (like "1 of X" indicator)
pswp.listen('beforeChange', function() { });
// After slides change
// (after content changed)
pswp.listen('afterChange', function() { });
// Image loaded
pswp.listen('imageLoadComplete', function(index, item) {
// index - index of a slide that was loaded
// item - slide object
});
// Viewport size changed
pswp.listen('resize', function() { });
// Triggers when PhotoSwipe "reads" slide object data,
// which happens before content is set, or before lazy-loading is initiated.
// Use it to dynamically change properties
pswp.listen('gettingData', function(index, item) {
// index - index of a slide that was loaded
// item - slide object
// e.g. change path to the image based on `something`
if( something ) {
item.src = item.something;
} else {
item.src = item.somethingElse;
}
});
// Mouse was used (triggers only once)
pswp.listen('mouseUsed', function() { });
// Opening zoom in animation starting
pswp.listen('initialZoomIn', function() { });
// Opening zoom in animation finished
pswp.listen('initialZoomInEnd', function() { });
// Closing zoom out animation started
pswp.listen('initialZoomOut', function() { });
// Closing zoom out animation finished
pswp.listen('initialZoomOutEnd', function() { });
// Allows overriding vertical margin for individual items
pswp.listen('parseVerticalMargin', function(item) {
// For example:
var gap = item.vGap;
gap.top = 50; // There will be 50px gap from top of viewport
gap.bottom = 100; // and 100px gap from the bottom
})
// Gallery starts closing
pswp.listen('close', function() { });
// Gallery unbinds events
// (triggers before closing animation)
pswp.listen('unbindEvents', function() { });
// After gallery is closed and closing animation finished.
// Clean up your stuff here.
pswp.listen('destroy', function() { });
// Called when the page scrolls.
// The callback is passed an offset with properties {x: number, y: number}.
//
// PhotoSwipe uses the offset to determine the top-left of the template,
// which by default is the top-left of the viewport. When using modal: false,
// you should listen to this event (before calling .init()) and modify the offset
// with the template's getBoundingClientRect().
//
// Look at the "Implementing inline gallery display" FAQ section for more info.
pswp.listen('updateScrollOffset', function(_offset) {
var r = gallery.template.getBoundingClientRect();
_offset.x += r.left;
_offset.y += r.top;
});
// PhotoSwipe has a special event called pswpTap.
// It's dispatched using default JavaScript event model.
// So you can, for example, call stopPropagation on it.
// pswp.framework.bind - is a shorthand for addEventListener
pswp.framework.bind( pswp.scrollWrap /* bind on any element of gallery */, 'pswpTap', function(e) {
console.log('tap', e, e.detail);
// e.detail.origEvent // original event that finished tap (e.g. mouseup or touchend)
// e.detail.target // e.target of original event
// e.detail.releasePoint // object with x/y coordinates of tap
// e.detail.pointerType // mouse, touch, or pen
});
// Allow to call preventDefault on down and up events
pswp.listen('preventDragEvent', function(e, isDown, preventObj) {
// e - original event
// isDown - true = drag start, false = drag release
// Line below will force e.preventDefault() on:
// touchstart/mousedown/pointerdown events
// as well as on:
// touchend/mouseup/pointerup events
preventObj.prevent = true;
});
// Default UI events
// -------------------------
// Share link clicked
pswp.listen('shareLinkClick', function(e, target) {
// e - original click event
// target - link that was clicked
// If `target` has `href` attribute and
// does not have `download` attribute -
// share modal window will popup
});
```
## 动态添加幻灯片
要在 PhotoSwipe 打开后添加、编辑或删除幻灯片,只需修改 `items` 数组。例如,你可以 push 将新的对象滑动到 `items` 数组中:
```javascript
pswp.items.push({
src: "path/to/image.jpg",
w:1200,
h:500
});
```
如果你更改了当前、下一个或上一个幻灯片(你应该尽量避免)–,你需要调用将更新其内容的方法:
```javascript
// sets a flag that slides should be updated
pswp.invalidateCurrItems();
// updates the content of slides
pswp.updateSize(true);
```
否则,你不需要做任何其他事情。如果你想要更新默认 UI 的某些部分(例如,“1of X”计数器),也许可以调用 `pswp.ui.update()`。另请注意:
- 你不能重新分配整个数组,你只能修改它(例如,使用 `splice` 删除元素)。
- 如果要删除当前的幻灯片 –,请先调用 `goTo` 方法。
- 至少要有一张幻灯片。
- 此技术用于 [提供响应图像](responsive-images.html)
缺少一些方法或属性?发现了语法错误?知道如何改进这个页面吗?[请建议编辑!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/api.md)
---
layout: default
title: Custom HTML Content in PhotoSwipe Slides
h1_title: Custom HTML Content in Slides
description: How to add custom HTML in PhotoSwipe slides, like ads or list of related galleries.
addjs: true
canonical_url: http://photoswipe.com/documentation/custom-html-in-slides.html
buildtool: true
markdownpage: true
---
要使 PhotoSwipe 在幻灯片中显示 HTML 内容,你需要在幻灯片对象中定义 `html` 属性。它应该包含 HTML 字符串或 DOM 元素对象。
```javascript
var items = [
// slide 1 with HTML
{
html: '<div><h1>Any HTML <a href="http://example.com">content</a></h1></div>'
},
// slide 2 with image
{
src: 'path/to/image.jpg',
w:600,
h:200
}
];
// initialise as usual
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
// You don't necessarily need to have "html" property in slide object initially.
// You may create it dynamically in gettingData event:
/*
gallery.listen('gettingData', function(index, item) {
if(index === 3) {
item.html = '<div>Dynamically generated HTML ' + Math.random() + '</div>';
}
});
*/
// Note that init() method is called after gettingData event is bound
gallery.init();
```
其他重要注意事项:
- 为了避免与第三方模块发生冲突,具有 `html` 属性的幻灯片不应具有 `src` 属性。
- PhotoSwipe 是为图像而设计的,而不是作为文本内容的滚动轮。使用“自定义 HTML”功能作为补充,例如,对于带有相关图库的幻灯片、介绍性幻灯片或图像之间的广告。
- 强烈不建议使用这种方法添加视频或音频元素(包括 YouTube、Vimeo 等 iframes)。在许多移动浏览器中,HTML5 视频阻止了在其上的触摸事件(用户将无法滑动它)。如果你确实需要在 PhotoSwipe 中有视频,你可以将其添加为当用户点击当前幻灯片时出现的模态,你可以在 DOM 中动态地创建模态,并在 `.pswp__scroll-wrap` 元素之后追加它。
- 如果你启用了初始的放大 / 缩小转换, PhotoSwipe 将自动禁用它,如果当前幻灯片有 `html`,将使用简单的渐变转换。
- 默认情况下, PhotoSwipe 只允许单击链接(`<a>`)及其子元素上的事件。要更改此行为,请查看 `isClickableElement` 选项或 `preventDragEvent` 事件。
- 目前还不支持缩放 HTML 幻灯片。
示例:
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="MYexrm" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/MYexrm/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
</div>
提示:你可以从 CodePen 下载示例,以便在本地使用它(“在 CodePen 上编辑 `->`Share`->`Export .zip`)。
知道如何改进这个页面吗?[建议编辑一下!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/custom-html-in-slides.md)
---
layout: default
title: PhotoSwipe API
h1_title: API
description: Public methods, properties and events of PhotoSwipe JavaScript image gallery.
addjs: true
canonical_url: http://photoswipe.com/documentation/api.html
buildtool: true
markdownpage: true
---
All methods and properties listed on this page are public. If you want to take a look at example of what API can do, take a look in [source of default PhotoSwipe UI](https://github.com/dimsemenov/PhotoSwipe/blob/master/src/js/ui/photoswipe-ui-default.js).
You can get PhotoSwipe instance object during the initialization, e.g.:
```javascript
var photoswipeInstance = new PhotoSwipe( /* ... */ );
```
## Methods
```javascript
var pswp = new PhotoSwipe( /* ... */ );
// Initialize and open gallery
// (you can bind events before this method)
pswp.init();
// Go to slide by index
// @param {int} `index`
pswp.goTo(index);
// Go to the next slide
pswp.next();
// Go to the previous slide
pswp.prev();
// Update gallery size
// @param {boolean} `force` If you set it to `true`,
// size of the gallery will be updated
// even if viewport size hasn't changed.
pswp.updateSize(force);
// Close gallery
pswp.close();
// Destroy gallery,
// automatically called after close()
pswp.destroy()
// Zoom current slide to (optionally with animation)
// @param {number} `destZoomLevel` Destination scale number. 1 - original.
// pswp.currItem.fitRatio - image will fit into viewport.
// @param {object} `centerPoint` Object of x and y coordinates, relative to viewport.
// @param {int} `speed` Animation duration. Can be 0.
// @param {function} `easingFn` Easing function (optional). Set to false to use default easing.
// @param {function} `updateFn` Function will be called on each update frame. (optional)
//
// Example below will 2x zoom to center of slide:
// pswp.zoomTo(2, {x:pswp.viewportSize.x/2,y:pswp.viewportSize.y/2}, 2000, false, function(now) {
//
// });
pswp.zoomTo(destZoomLevel, centerPoint, speed, easingFn, updateFn);
// Apply zoom and pan to the current slide
//
// @param {number} `zoomLevel`
// @param {int} `panX`
// @param {int} `panY`
//
// For example: `pswp.applyZoomPan(1, 0, 0)`
// will zoom current image to the original size
// and will place it on top left corner
//
//
pswp.applyZoomPan(zoomLevel, panX, panY);
```
## Properties
```javascript
// current slide object
pswp.currItem
// items array (slides, images)
pswp.items
// size of sliding viewport
pswp.viewportSize
// object holds all functions from framework
// framework-bridge.js
pswp.framework
// UI object (e.g. PhotoSwipeUI_Default instance)
pswp.ui
// background element (pswp__bg)
pswp.bg
// container element (pswp__container)
pswp.container
// options
pswp.options
// Even though methods below aren't technically properties, we list them here:
// current item index (int)
pswp.getCurrentIndex();
// total number of items
pswp.options.getNumItemsFn()
// current zoom level (number)
pswp.getZoomLevel();
// one (or more) pointer is used
pswp.isDragging();
// two (or more) pointers are used
pswp.isZooming();
// `true` when transition between is running (after swipe)
pswp.isMainScrollAnimating();
```
## Events
PhotoSwipe uses very simple Event/Messaging system. It has two methods `shout` (triggers event) and `listen` (handles event). For now there is no method to unbind listener, but all of them are cleared when PhotoSwipe is closed.
```javascript
var pswp = new PhotoSwipe(/* ... */);
// Listen for "helloWorld" event
pswp.listen('helloWorld', function(name) {
alert('Name is: ' + name);
});
// Trigger "helloWorld" event
pswp.shout('helloWorld', 'John' /* you may pass more arguments */);
```
Available events:
```javascript
// Before slides change
// (before the content is changed, but after navigation)
// Update UI here (like "1 of X" indicator)
pswp.listen('beforeChange', function() { });
// After slides change
// (after content changed)
pswp.listen('afterChange', function() { });
// Image loaded
pswp.listen('imageLoadComplete', function(index, item) {
// index - index of a slide that was loaded
// item - slide object
});
// Viewport size changed
pswp.listen('resize', function() { });
// Triggers when PhotoSwipe "reads" slide object data,
// which happens before content is set, or before lazy-loading is initiated.
// Use it to dynamically change properties
pswp.listen('gettingData', function(index, item) {
// index - index of a slide that was loaded
// item - slide object
// e.g. change path to the image based on `something`
if( something ) {
item.src = item.something;
} else {
item.src = item.somethingElse;
}
});
// Mouse was used (triggers only once)
pswp.listen('mouseUsed', function() { });
// Opening zoom in animation starting
pswp.listen('initialZoomIn', function() { });
// Opening zoom in animation finished
pswp.listen('initialZoomInEnd', function() { });
// Closing zoom out animation started
pswp.listen('initialZoomOut', function() { });
// Closing zoom out animation finished
pswp.listen('initialZoomOutEnd', function() { });
// Allows overriding vertical margin for individual items
pswp.listen('parseVerticalMargin', function(item) {
// For example:
var gap = item.vGap;
gap.top = 50; // There will be 50px gap from top of viewport
gap.bottom = 100; // and 100px gap from the bottom
})
// Gallery starts closing
pswp.listen('close', function() { });
// Gallery unbinds events
// (triggers before closing animation)
pswp.listen('unbindEvents', function() { });
// After gallery is closed and closing animation finished.
// Clean up your stuff here.
pswp.listen('destroy', function() { });
// Called when the page scrolls.
// The callback is passed an offset with properties {x: number, y: number}.
//
// PhotoSwipe uses the offset to determine the top-left of the template,
// which by default is the top-left of the viewport. When using modal: false,
// you should listen to this event (before calling .init()) and modify the offset
// with the template's getBoundingClientRect().
//
// Look at the "Implementing inline gallery display" FAQ section for more info.
pswp.listen('updateScrollOffset', function(_offset) {
var r = gallery.template.getBoundingClientRect();
_offset.x += r.left;
_offset.y += r.top;
});
// PhotoSwipe has a special event called pswpTap.
// It's dispatched using default JavaScript event model.
// So you can, for example, call stopPropagation on it.
// pswp.framework.bind - is a shorthand for addEventListener
pswp.framework.bind( pswp.scrollWrap /* bind on any element of gallery */, 'pswpTap', function(e) {
console.log('tap', e, e.detail);
// e.detail.origEvent // original event that finished tap (e.g. mouseup or touchend)
// e.detail.target // e.target of original event
// e.detail.releasePoint // object with x/y coordinates of tap
// e.detail.pointerType // mouse, touch, or pen
});
// Allow to call preventDefault on down and up events
pswp.listen('preventDragEvent', function(e, isDown, preventObj) {
// e - original event
// isDown - true = drag start, false = drag release
// Line below will force e.preventDefault() on:
// touchstart/mousedown/pointerdown events
// as well as on:
// touchend/mouseup/pointerup events
preventObj.prevent = true;
});
// Default UI events
// -------------------------
// Share link clicked
pswp.listen('shareLinkClick', function(e, target) {
// e - original click event
// target - link that was clicked
// If `target` has `href` attribute and
// does not have `download` attribute -
// share modal window will popup
});
```
## Adding slides dynamically
To add, edit, or remove slides after PhotoSwipe is opened, you just need to modify the `items` array. For example, you can push new slide objects into the `items` array:
```javascript
pswp.items.push({
src: "path/to/image.jpg",
w:1200,
h:500
});
```
If you changed slide that is CURRENT, NEXT or PREVIOUS (which you should try to avoid) &ndash; you need to call method that will update their content:
```javascript
// sets a flag that slides should be updated
pswp.invalidateCurrItems();
// updates the content of slides
pswp.updateSize(true);
```
Otherwise, you don't need to do anything else. Except, maybe, calling `pswp.ui.update()` if you want some parts of default UI to update (e.g. "1 of X" counter). Also note:
- You can't reassign whole array, you can only modify it (e.g. use `splice` to remove elements).
- If you're going to remove current slide &ndash; call `goTo` method before.
- There must be at least one slide.
- This technique is used to [serve responsive images](responsive-images.html).
Some method or property is missing? Found a grammatical mistake? Know how this page can be improved? [Please suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/api.md)
// TODO
\ No newline at end of file
---
layout: default
title: Custom HTML Content in PhotoSwipe Slides
h1_title: Custom HTML Content in Slides
description: How to add custom HTML in PhotoSwipe slides, like ads or list of related galleries.
addjs: true
canonical_url: http://photoswipe.com/documentation/custom-html-in-slides.html
buildtool: true
markdownpage: true
---
To make PhotoSwipe display HTML content in slides you need to define `html` property in slide object. It should contain HTML string or DOM element object.
```javascript
var items = [
// slide 1 with HTML
{
html: '<div><h1>Any HTML <a href="http://example.com">content</a></h1></div>'
},
// slide 2 with image
{
src: 'path/to/image.jpg',
w:600,
h:200
}
];
// initialise as usual
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
// You don't necessarily need to have "html" property in slide object initially.
// You may create it dynamically in gettingData event:
/*
gallery.listen('gettingData', function(index, item) {
if(index === 3) {
item.html = '<div>Dynamically generated HTML ' + Math.random() + '</div>';
}
});
*/
// Note that init() method is called after gettingData event is bound
gallery.init();
```
Additional important notes:
- To avoid conflicts with third-party modules, slide that has `html` property, should not have `src` (image) property.
- PhotoSwipe is designed for images, not as a scroller of text content. Use "custom HTML" feature as an addition, for example for slide with related galleries, an introductory slide, or advertisements BETWEEN images.
- It's strongly not recommended to add video or audio elements using this method (including YouTube, Vimeo etc. iframes). As HTML5 video blocks touch events over it in many mobile browsers (user won't be able to swipe it). If you really need to have video in PhotoSwipe, you may add it as modal that appears when user taps on current slide, you can dynamically create modal in DOM and append it after `.pswp__scroll-wrap` element.
- If you have initial zoom-in/zoom-out transition enabled, PhotoSwipe will automatically disable it if current slide has `html`, simple fade transition will be used instead.
- By default PhotoSwipe will allow click event just on links (`<a>`) and their child elements. To change this behavior look into `isClickableElement` option or `preventDragEvent` event.
- Zoom of HTML slides is not supported, yet.
Example:
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="MYexrm" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/MYexrm/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
</div>
Tip: you may download the example from CodePen to play with it locally (`Edit on CodePen` -> `Share` -> `Export .zip`).
Know how this page can be improved? [Suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/custom-html-in-slides.md)
---
layout: default
title: PhotoSwipe FAQ
h1_title: FAQ
description: Frequently asked questions and known issues about PhotoSwipe image gallery.
addjs: true
canonical_url: http://photoswipe.com/documentation/faq.html
buildtool: true
markdownpage: true
---
## Implementation
### <a name="image-size"></a> I'm unable to predefine image size, what to do?
Use another gallery script ([1](http://dimsemenov.com/plugins/magnific-popup/), [2](http://dimsemenov.com/plugins/royal-slider/gallery/)), or find a way:
- You can read size of an image by downloading only small part of it ([PHP version](http://stackoverflow.com/questions/4635936/super-fast-getimagesize-in-php), [Ruby](https://github.com/sdsykes/fastimage), [Node.js](http://stackoverflow.com/a/20111234/331460)).
- You can store size of an image directly in its filename and parse it on frontend during PhotoSwipe initialization (`gettingData` event in API section).
- Most CMS store size of an image in a database and have API to retrieve it.
- Most web API (Facebook, 500px, Instagram, Flickr, Twitter, YouTube, Vimeo etc.) return a size of images.
Dimensions are used for progressive loading, stretched placeholder, initial zoom-in transition, panning, zooming, caption positioning. Discussion in GitHub [issue #741](https://github.com/dimsemenov/PhotoSwipe/issues/741).
### <a name="different-thumbnail-dimensions"></a> My thumbnails are square, but large images have different dimensions, what to do with opening/closing transition?
1. If thumbnail aspect ratio does not match large image, do not define `msrc` property for slide objects and enable opacity transition option (`showHideOpacity:true, getThumbBoundsFn:false`).
2. If aspect ratio of thumbnail image file matches large image, **but thumbnail area is cropped via CSS**, just add `showHideOpacity:true` and make sure that `getThumbBoundsFn` option returns coordinates that consider crop area.
I strongly recommend to display thumbnails that match aspect ratio of large image, or crop the visible area via CSS (2).
I'll try to explain why this is not implemented yet. There are two ways to make expanding area animation:
1. Animate `clip` property. But [it forces Paint](http://csstriggers.com/#clip) each time, which makes animations jerky.
2. Wrap an image that expands with two divs that have `overflow:hidden` and reposition them via `transform:translate` during the animation so they clip it at right parts. This method does not force Paint or Layout, but requires two additional elements in markup of each slide. Test prototype showed that it works smooth only on high-end mobile devices (like Nexus 5 with Chrome). Maybe some day I'll implement it.
### <a name="scroll-in-caption"></a> My captions are large, can I add scroll to them?
Refer to [issue #657](https://github.com/dimsemenov/PhotoSwipe/issues/657).
### <a name="inline-gallery"></a>How to implement inline gallery display
Note that this is an experimental feature, for now it doesn't allow to scroll the page vertically over the gallery on mobile (as it calls `prevetDefault()` on touch events). Please report issues if you'll find any. To implement an embedded gallery that flows with the rest of your document, follow these steps:
1. Put the `.pswp` template inside a positioned parent element.
2. Set `modal: false, closeOnScroll: false` options.
3. Modify the `getThumbBoundsFn` (if you're using it) to subtract the template parent's bounding rect.
4. Construct the PhotoSwipe.
5. Listen for the `updateScrollOffset` event and add the template's bounding rect to the offset.
6. `init()` the PhotoSwipe.
[**Live example on CodePen &rarr;**](http://codepen.io/dimsemenov/pen/JogxWM)
```html
<div style="position: relative;" class="parent">
<div id="gallery" class="pswp"> ... </div>
</div>
```
```javascript
var items = [...];
var template = document.getElementById("gallery"); // .pswp
var options = {
...,
modal: false,
closeOnScroll: false,
getThumbBoundsFn: function(index) {
// rect was the original bounds
var rect = {x: ..., y: ..., w: ...},
var templateBounds = template.parentElement.getBoundingClientRect();
rect.x -= templateBounds.left;
rect.y -= templateBounds.top;
return rect;
}
};
var photoSwipe = new PhotoSwipe(template, PhotoSwipeUI_Default, items, options);
photoSwipe.listen('updateScrollOffset', function(_offset) {
var r = template.getBoundingClientRect();
_offset.x += r.left;
_offset.y += r.top;
});
photoSwipe.init();
```
### <a name="custom-pid-in-url"></a>How to use custom identifiers instead of indexes in URL
to make URLs to a single image look like this:
```
http://example.com/#&gid=1&pid=custom-first-id
http://example.com/#&gid=1&pid=custom-second-id
```
instead of:
```
http://example.com/#&gid=1&pid=1
http://example.com/#&gid=1&pid=2
```
... enable options `history:true, galleryPIDs:true` and add `pid` (unique picture identifier) property to slide objects (`pid` can be an integer or a string), for example:
```js
var slides = [
{
src: 'path/to/1.jpg',
w:500,
h:400,
pid: 'custom-first-id'
},
{
src: 'path/to/2.jpg',
w:300,
h:700,
pid: 'custom-second-id'
},
...
];
```
- Note that PhotoSwipe does not execute any code until you initialize and open it. That's why on initial page load you need to parse the URL by yourself. Default code from the [Getting Started](http://photoswipe.com/documentation/getting-started.html#dom-to-slide-objects) section of documentation includes this functionality (check `photoswipeParseHash` function if you need some modification).
- Option `galleryPIDs` is available since PhotoSwipe v4.0.8 ([option description](options.html#galleryPIDs)).
## Bugs
### <a name="gif-freeze-ios"></a> GIF images sometimes freeze on iOS8
iOS Safari has a bug that freezes GIF images that are shifted outside of the window (or outside of element with `overflow:hidden`). My recommendation is to avoid using animated GIFs in PhotoSwipe at all, as they slow down animation performance in any mobile browser. But if you really need to use it, refer to [this hack](https://github.com/dimsemenov/PhotoSwipe/issues/662#issuecomment-66420874).
### <a name="mobile-crash"></a> Mobile browser crashes when opening gallery with huge images
Mostly, it can happen on mobile devices with low memory limit &ndash; iOS Safari, default browser in old Android (before KitKat). The most common reason of a crash is too big images (usually larger than 2000x1500px). PhotoSwipe applies hardware-acceleration on images, which consumes more memory than regular image on page, so when you run out of limit browser starts lagging or even crashes.
So [serve responsive images](responsive-images.html), or at least don't serve huge images. Ideally, for an average 900x600 phone you should serve 1200px wide image. Note that if everything works smoothly in iOS Simulator, it doesn't mean that crash won't occur on real device.
In much more rare cases crash can occur if you open PhotoSwipe during some process on your page (this can be initial page load/render, or some complex animation on page), try to delay PhotoSwipe initialization until page is rendered (18-300ms after document.ready), especially if you are displaying large images.
**UPD.:** in [v4.1.0](https://github.com/dimsemenov/PhotoSwipe/releases/tag/v4.1.0) this is partly fixed.
## Miscellaneous
### <a name="keep-updated"></a> Where is the changelog, how to do I get notified about updates?
Each time PhotoSwipe gets an update - [GitHub releases](https://github.com/dimsemenov/PhotoSwipe/releases) page is updated with details.
Releases page has an [Atom feed](https://github.com/dimsemenov/PhotoSwipe/releases.atom), you may setup email notifications when feed is updated [using IFTTT](https://ifttt.com/recipes/230902-photoswipe-update-notification).
Also, you may join my [email newsletter](http://dimsemenov.com/subscribe.html?i=pswp) (sent 3-4 times a year), follow [@PhotoSwipe on Twitter](http://twitter.com/photoswipe), and star/watch [PhotoSwipe on GitHub](https://github.com/dimsemenov/PhotoSwipe/).
### <a name="wordpress-release"></a> When WordPress plugin will be released?
Plugin is under development and will be released in 2015. To get notified [subscribe to my newsletter](http://dimsemenov.com/subscribe.html?i=pswp-wp).
### <a name="can-i-use-in-theme"></a> I want to use PhotoSwipe in WordPress/Magento/Joomla... template, can I?
Yes, you can use PhotoSwipe in a free or commercial themes without any limitations. If you can, please leave a credit (link to PhotoSwipe homepage) in theme description or/and in admin area.
<div style="margin-top:30px;"><p>Know how this page can be improved? Found a grammatical mistake? <a href="https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md">Please suggest an edit!</a></p></div>
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
<style type="text/css">
body {
overflow-y:scroll;
}
h3 {
cursor: pointer;
font-weight: normal;
-webkit-user-select:none;
-moz-user-select:none;
user-select:none;
color: #3169B3;
padding-left: 18px;
position: relative;
}
h3:hover {
color: #C00;
}
h3:before {
content:'▼';
font-size: 12px;
position: absolute;
left: 0;
top: 2px;
}
h3.tab-closed:before {
content: '►';
}
</style>
<script>
(function() {
// tabs
if(!document.addEventListener) {
return;
}
var els = document.getElementsByClassName('row--docs')[0].children,
el;
var isContentEl = function(el) {
if(!el) {
return;
}
if( (/(P|UL|OL)/i).test(el.tagName) || el.className === 'highlight' ) {
return true;
}
return;
},
toggleTab = function(el) {
var dStyle = el.classList.contains('tab-closed') ? 'block' : 'none';
el.classList.toggle('tab-closed');
var s = el.nextElementSibling;
while( isContentEl(s) ) {
s.style.display = dStyle;
s = s.nextElementSibling;
}
};
for(var i = 0; i < els.length; i++) {
el = els[i];
if(el.tagName === 'H3') {
if(window.location.hash !== '#' + el.firstElementChild.name) {
toggleTab(el);
}
el.onclick = function() {
toggleTab(this);
};
}
}
})();
</script>
---
layout: default
title: "PhotoSwipe Documentation: Getting Started"
h1_title: Getting Started
description: PhotoSwipe image gallery getting started guide.
addjs: true
canonical_url: http://photoswipe.com/documentation/getting-started.html
buildtool: true
markdownpage: true
---
First things that you should know before you start:
- PhotoSwipe is not a simple jQuery plugin, at least basic JavaScript knowledge is required to install.
- PhotoSwipe requires predefined image dimensions ([more about this](faq.html#image-size)).
- If you use PhotoSwipe on non-responsive website &ndash; controls will be scaled on mobile (as the whole page is scaled). So you'll need to implement custom controls (e.g. single large close button in top right corner).
- All code in the documentation is pure Vanilla JS and supports IE 8 and above. If your website or app uses some JavaScript framework (like jQuery or MooTools) or you don't need to support old browsers – feel free to simplify the code.
- Avoid serving big images (larger than 2000x1500px) for mobile, as they will dramatically reduce animation performance and can cause crash (especially on iOS Safari). Possible solutions: [serve responsive images](responsive-images.html), or open image on a separate page, or use libraries that support image tiling (like [Leaflet](http://leafletjs.com/)) ([more in FAQ](faq.html#mobile-crash)).
## <a name="initialization"></a> Initialization
### <a name="init-include-files"></a>Step 1: include JS and CSS files
You can find them in [dist/](https://github.com/dimsemenov/PhotoSwipe/tree/master/dist) folder of [GitHub](https://github.com/dimsemenov/PhotoSwipe) repository. Sass and uncompiled JS files are in folder [src/](https://github.com/dimsemenov/PhotoSwipe/tree/master/src). I recommend using Sass if you're planning to modify existing styles, as code there is structured and commented.
```html
<!-- Core CSS file -->
<link rel="stylesheet" href="path/to/photoswipe.css">
<!-- Skin CSS file (styling of UI - buttons, caption, etc.)
In the folder of skin CSS file there are also:
- .png and .svg icons sprite,
- preloader.gif (for browsers that do not support CSS animations) -->
<link rel="stylesheet" href="path/to/default-skin/default-skin.css">
<!-- Core JS file -->
<script src="path/to/photoswipe.min.js"></script>
<!-- UI JS file -->
<script src="path/to/photoswipe-ui-default.min.js"></script>
```
It doesn't matter how and where will you include JS and CSS files. Code is executed only when you call `new PhotoSwipe()`. So feel free to defer loading of files if you don't need PhotoSwipe to be opened initially.
PhotoSwipe also supports AMD loaders (like RequireJS) and CommonJS, use them like so:
```javascript
require([
'path/to/photoswipe.js',
'path/to/photoswipe-ui-default.js'
], function( PhotoSwipe, PhotoSwipeUI_Default ) {
// var gallery = new PhotoSwipe( someElement, PhotoSwipeUI_Default ...
// gallery.init()
// ...
});
```
And also, you can install it via Bower (`bower install photoswipe`), or [NPM](https://www.npmjs.com/package/photoswipe) (`npm install photoswipe`).
### <a name="init-add-pswp-to-dom"></a>Step 2: add PhotoSwipe (.pswp) element to DOM
You can add HTML code dynamically via JS (directly before the initialization), or have it in the page initially (like it's done on the demo page). This code can be appended anywhere, but ideally before the closing `</body>`. You may reuse it across multiple galleries (as long as you use same UI class).
```html
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
```
Order of `pswp__bg`, `pswp__scroll-wrap`, `pswp__container` and `pswp__item` elements should not be changed.
You might ask, why PhotoSwipe doesn't add this code automatically via JS, reason is simple &ndash; just to save file size, in case if you need some modification of layout.
### Step 3: initialize
Execute `PhotoSwipe` constructor. It accepts 4 arguments:
1. `.pswp` element from step 2 (it must be added to DOM).
2. PhotoSwipe UI class. If you included default `photoswipe-ui-default.js`, class will be `PhotoSwipeUI_Default`. Can be `false`.
3. Array with objects (slides).
4. [Options](options.html).
```javascript
var pswpElement = document.querySelectorAll('.pswp')[0];
// build items array
var items = [
{
src: 'https://placekitten.com/600/400',
w: 600,
h: 400
},
{
src: 'https://placekitten.com/1200/900',
w: 1200,
h: 900
}
];
// define options (if needed)
var options = {
// optionName: 'option value'
// for example:
index: 0 // start at first slide
};
// Initializes and opens PhotoSwipe
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
```
At the end you should get something like this:
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="gbadPv" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/gbadPv/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
<!-- <script async src="//assets.codepen.io/assets/embed/ei.js"></script> -->
</div>
## <a name="creating-slide-objects-array"></a> Creating an Array of Slide Objects
Each object in the array should contain data about slide, it can be anything that you wish to display in PhotoSwipe - path to image, caption string, number of shares, comments, etc.
By default PhotoSwipe uses just 5 properties: `src` (path to image), `w` (image width), `h` (image height), `msrc` (path to small image placeholder, large image will be loaded on top), `html` (custom HTML, [more about it](custom-html-in-slides.html)).
During the navigation, PhotoSwipe adds its own properties to this object (like `minZoom` or `loaded`).
```javascript
var slides = [
// slide 1
{
src: 'path/to/image1.jpg', // path to image
w: 1024, // image width
h: 768, // image height
msrc: 'path/to/small-image.jpg', // small image placeholder,
// main (large) image loads on top of it,
// if you skip this parameter - grey rectangle will be displayed,
// try to define this property only when small image was loaded before
title: 'Image Caption' // used by Default PhotoSwipe UI
// if you skip it, there won't be any caption
// You may add more properties here and use them.
// For example, demo gallery uses "author" property, which is used in the caption.
// author: 'John Doe'
},
// slide 2
{
src: 'path/to/image2.jpg',
w: 600,
h: 600
// etc.
}
// etc.
];
```
You may dynamically define slide object properties directly before PhotoSwipe reads them, use `gettingData` event (more info in [API section of docs](api.html)). For example, this technique can be used to [serve different images](responsive-images.html) for different screen sizes.
## <a class="anchor" name="dom-to-slide-objects"></a> How to build an array of slides from a list of links
Let's assume that you have a list of links/thumbnails that look like this ([more info about markup of gallery](seo.html)):
```html
<div class="my-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl" data-size="600x400">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption</figcaption>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl" data-size="600x400">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption</figcaption>
</figure>
</div>
```
... and you want click on the thumbnail to open PhotoSwipe with large image (like it's done on a demo page). All you need to do is:
1. Bind click event to links/thumbnails.
2. After user clicked on thumbnail, find its index.
3. Create an array of slide objects from DOM elements – loop through all links and retrieve `href` attribute (large image url), `data-size` attribute (its size), `src` of thumbnail, and contents of caption.
PhotoSwipe doesn't really care how will you do this. If you use frameworks like jQuery or MooTools, or if you don't need to support IE8, code can be simplified dramatically.
Here is pure Vanilla JS implementation with IE8 support:
```javascript
var initPhotoSwipeFromDOM = function(gallerySelector) {
// parse slide data (url, title, size ...) from DOM elements
// (children of gallerySelector)
var parseThumbnailElements = function(el) {
var thumbElements = el.childNodes,
numNodes = thumbElements.length,
items = [],
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i]; // <figure> element
// include only element nodes
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0]; // <a> element
size = linkEl.getAttribute('data-size').split('x');
// create slide object
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
if(figureEl.children.length > 1) {
// <figcaption> content
item.title = figureEl.children[1].innerHTML;
}
if(linkEl.children.length > 0) {
// <img> thumbnail element, retrieving thumbnail url
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
// find nearest parent element
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
// triggers when user clicks on thumbnail
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define index via data- attribute
var clickedGallery = clickedListItem.parentNode,
childNodes = clickedListItem.parentNode.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
// parse picture index and gallery index from URL (#&pid=1&gid=2)
var photoswipeParseHash = function() {
var hash = window.location.hash.substring(1),
params = {};
if(hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if(!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if(pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
if(params.gid) {
params.gid = parseInt(params.gid, 10);
}
return params;
};
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
var pswpElement = document.querySelectorAll('.pswp')[0],
gallery,
options,
items;
items = parseThumbnailElements(galleryElement);
// define options (if needed)
options = {
// define gallery index (for URL)
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function(index) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}
};
// PhotoSwipe opened from URL
if(fromURL) {
if(options.galleryPIDs) {
// parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
options.index = j;
break;
}
}
} else {
// in URL indexes start from 1
options.index = parseInt(index, 10) - 1;
}
} else {
options.index = parseInt(index, 10);
}
// exit if index not found
if( isNaN(options.index) ) {
return;
}
if(disableAnimation) {
options.showAnimationDuration = 0;
}
// Pass data to PhotoSwipe and initialize it
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll( gallerySelector );
for(var i = 0, l = galleryElements.length; i < l; i++) {
galleryElements[i].setAttribute('data-pswp-uid', i+1);
galleryElements[i].onclick = onThumbnailsClick;
}
// Parse URL and open gallery if it contains #&pid=3&gid=1
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid - 1 ], true, true );
}
};
// execute above function
initPhotoSwipeFromDOM('.my-gallery');
```
Example on CodePen (`focus` & `history` options are disabled due to embed issues):
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="ZYbPJM" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/ZYbPJM/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
</div>
Tip: you may download example from CodePen to play with it locally (`Edit on CodePen` -> `Share` -> `Export .zip`).
- If you're using markup that differs from this example, you'll need to edit function `parseThumbnailElements`.
- If you're not experienced in pure JavaScript and don't know how to parse DOM, refer to [QuirksMode](http://quirksmode.org/dom/core/#gettingelements) and [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element.getElementsByTagName).
- Note that IE8 does not support HTML5 `<figure>` and `<figcaption>` elements, so you need to include [html5shiv](https://github.com/aFarkas/html5shiv) in `<head>` section ([cdnjs hosted version](http://cdnjs.com/libraries/html5shiv/) is used in example):
```html
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
```
## About
Please [keep script updated](faq.html#keep-updated), report bugs through [GitHub](https://github.com/dimsemenov/PhotoSwipe), suggest features on [UserVoice](https://photoswipe.uservoice.com/forums/275302-feature-requests-ideas) and ask questions through [StackOverflow](http://stackoverflow.com/questions/ask?tags=javascript,photoswipe).
Know how this page can be improved? Found a typo? [Suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/getting-started.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
---
layout: default
title: PhotoSwipe Options
h1_title: Options
description: Complete list of PhotoSwipe options (including PhotoSwipeUI_Default options).
addjs: true
canonical_url: http://photoswipe.com/documentation/options.html
buildtool: true
markdownpage: true
---
Options are added in key-value pairs and passed as an argument to `PhotoSwipe` constructor, e.g.:
```javascript
var options = {
index: 3,
escKey: false,
// ui option
timeToIdle: 4000
};
var gallery = new PhotoSwipe( someElement, PhotoSwipeUI_Default, someItems, options);
gallery.init();
// Note that options object is cloned during the initialization.
// But you can access it via `gallery.options`.
// For example, to dynamically change `escKey`:
gallery.options.escKey = false;
// `options.escKey = false` will not work
```
## Core
### `index` <code class="default">integer</code> <code class="default">0</code>
Start slide index. `0` is the first slide. Must be integer, not a string.
### `getThumbBoundsFn` <code class="default">function</code> <code class="default">undefined</code>
Function should return an object with coordinates from which initial zoom-in animation will start (or zoom-out animation will end).
Object should contain three properties: `x` (X position, relative to document), `y` (Y position, relative to document), `w` (width of the element). Height will be calculated automatically based on size of large image. For example if you return `{x:0,y:0,w:50}` zoom animation will start in top left corner of your page.
Function has one argument - `index` of the item that is opening or closing.
In non-modal mode, the template's position relative to the viewport should be subtracted from `x` and `y`. Look at [the FAQ](faq.html#inline-gallery) for more information.
Example that calculates position of thumbnail:
```javascript
getThumbBoundsFn: function(index) {
// find thumbnail element
var thumbnail = document.querySelectorAll('.my-gallery-thumbnails')[index];
// get window scroll Y
var pageYScroll = window.pageYOffset || document.documentElement.scrollTop;
// optionally get horizontal scroll
// get position of element relative to viewport
var rect = thumbnail.getBoundingClientRect();
// w = width
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
// Good guide on how to get element coordinates:
// http://javascript.info/tutorial/coordinates
}
```
If dimensions of your small thumbnail don't match dimensions of large image, consider enabling zoom+fade transition. You can do this by adding option `showHideOpacity:true` (try adding it to [above CodePen](http://codepen.io/dimsemenov/pen/ZYbPJM) to test how it looks). Or disable transition entirely by adding `hideAnimationDuration:0, showAnimationDuration:0`. [More info about this in FAQ](faq.html#different-thumbnail-dimensions).
If you want to "hide" small thumbnail during the animation use `opacity:0`, not `visibility:hidden` or `display:none`. Don't force Paint and Layout at the beginning of the animation to avoid lag.
### `showHideOpacity` <code class="default">boolean</code> <code class="default">false</code>
If set to `false`: background `opacity` and image `scale` will be animated (image opacity is always 1).
If set to `true`: root PhotoSwipe element `opacity` and image `scale` will be animated.
To enable just `opacity` transition (without `scale`), do not define `getThumbBoundsFn` option.
### `showAnimationDuration` <code class="default">integer</code> <code class="default">333</code>
Initial zoom-in transition duration in milliseconds. Set to `0` to disable.
Besides this JS option, you need also to change transition duration in PhotoSwipe CSS file:
```css
.pswp--animate_opacity,
.pswp__bg,
.pswp__caption,
.pswp__top-bar,
.pswp--has_mouse .pswp__button--arrow--left,
.pswp--has_mouse .pswp__button--arrow--right{
-webkit-transition: opacity 333ms cubic-bezier(.4,0,.22,1);
transition: opacity 333ms cubic-bezier(.4,0,.22,1);
}
```
If you're using Sass, you just need to change transition-duration variables in [_main-settings.scss](https://github.com/dimsemenov/PhotoSwipe/blob/master/src/css/_main-settings.scss).
### `hideAnimationDuration` <code class="default">integer</code> <code class="default">333</code>
The same as the previous option, just for closing (zoom-out) transition. After PhotoSwipe is opened `pswp--open` class will be added to the root element, you may use it to apply different transition duration in CSS.
### `bgOpacity` <code class="default">number</code> <code class="default">1</code>
Background (`.pswp__bg`) opacity. Should be a number from 0 to 1, e.g. `0.7`. This style is defined via JS, not via CSS, as this value is used for a few gesture-based transitions.
### `spacing` <code class="default">number</code> <code class="default">0.12</code>
Spacing ratio between slides. For example, `0.12` will render as a 12% of sliding viewport width (rounded).
### `allowPanToNext` <code class="default">boolean</code> <code class="default">true</code>
Allow swipe navigation to next/prev item when current item is zoomed. Option is always `false` on devices that don't have hardware touch support.
### `maxSpreadZoom` <code class="default">number</code> <code class="default">2</code>
Maximum zoom level when performing spread (zoom) gesture. `2` means that image can be zoomed 2x from original size. Try to avoid huge values here, as too big image may cause memory issues on mobile (especially on iOS).
### `getDoubleTapZoom` <code class="default">function</code>
Function should return zoom level to which image will be zoomed after double-tap gesture, or when user clicks on zoom icon, or mouse-click on image itself. If you return `1` image will be zoomed to its original size.
Default value:
```javascript
getDoubleTapZoom: function(isMouseClick, item) {
// isMouseClick - true if mouse, false if double-tap
// item - slide object that is zoomed, usually current
// item.initialZoomLevel - initial scale ratio of image
// e.g. if viewport is 700px and image is 1400px,
// initialZoomLevel will be 0.5
if(isMouseClick) {
// is mouse click on image or zoom icon
// zoom to original
return 1;
// e.g. for 1400px image:
// 0.5 - zooms to 700px
// 2 - zooms to 2800px
} else {
// is double-tap
// zoom to original if initial zoom is less than 0.7x,
// otherwise to 1.5x, to make sure that double-tap gesture always zooms image
return item.initialZoomLevel < 0.7 ? 1 : 1.5;
}
}
```
Function is called each time zoom-in animation is initiated. So feel free to return different values for different images based on their size or screen DPI.
### `loop` <code class="default">boolean</code> <code class="default">true</code>
Loop slides when using swipe gesture. If set to `true` you'll be able to swipe from last to first image. Option is always `false` when there are less than 3 slides.
This option has no relation to arrows navigation. Arrows loop is turned on permanently. You can modify this behavior by making custom UI.
### `pinchToClose` <code class="default">boolean</code> <code class="default">true</code>
Pinch to close gallery gesture. The gallery’s background will gradually fade out as the user zooms out. When the gesture is complete, the gallery will close.
### `closeOnScroll` <code class="default">boolean</code> <code class="default">true</code>
Close gallery on page scroll. Option works just for devices without hardware touch support.
### `closeOnVerticalDrag` <code class="default">boolean</code> <code class="default">true</code>
Close gallery when dragging vertically and when image is not zoomed. Always `false` when mouse is used.
### `mouseUsed` <code class="default">boolean</code> <code class="default">false</code>
Option allows you to predefine if mouse was used or not. Some PhotoSwipe feature depend on it, for example default UI left/right arrows will be displayed only after mouse is used. If set to `false`, PhotoSwipe will start detecting when mouse is used by itself, `mouseUsed` event triggers when mouse is found.
### `escKey` <code class="default">boolean</code> <code class="default">true</code>
`esc` keyboard key to close PhotoSwipe. Option can be changed dynamically (`yourPhotoSwipeInstance.options.escKey = false;`).
### `arrowKeys` <code class="default">boolean</code> <code class="default">true</code>
Keyboard left or right arrow key navigation. Option can be changed dynamically (`yourPhotoSwipeInstance.options.arrowKeys = false;`).
### `history` <code class="default">boolean</code> <code class="default">true</code>
If set to `false` disables history module (back button to close gallery, unique URL for each slide). You can also just exclude `history.js` module from your build.
### `galleryUID` <code class="default">integer</code> <code class="default">1</code>
Gallery unique ID. Used by History module when forming URL. For example, second picture of gallery with UID 1 will have URL: `http://example.com/#&gid=1&pid=2`.
### <a name="galleryPIDs"></a> `galleryPIDs` <code class="default">boolean</code> <code class="default">false</code>
Enables custom IDs for each slide object that are used when forming URL. If option set set to `true`, slide objects must have `pid` (picture identifier) property that can be a string or an integer. For example:
```js
var slides = [
{
src: 'path/to/1.jpg',
w:500,
h:400,
pid: 'image-one'
},
{
src: 'path/to/2.jpg',
w:300,
h:700,
pid: 'image-two'
},
...
];
```
... second slide will have URL `http://example.com/#&gid=1&pid=image-two`.
Read more about how to implement custom PID in [the FAQ section](faq.html#custom-pid-in-url).
### `errorMsg` <code class="default">string</code>
Error message when image was not loaded. `%url%` will be replaced by URL of image.
Default value:
```html
<div class="pswp__error-msg"><a href="%url%" target="_blank">The image</a> could not be loaded.</div>
```
### `preload` <code class="default">array</code> <code class="default">[1,1]</code>
Lazy loading of nearby slides based on direction of movement. Should be an array with two integers, first one - number of items to preload before current image, second one - after the current image. E.g. if you set it to [1,3], it'll load 1 image before the current, and 3 images after current. Values can not be less than 1.
### `mainClass` <code class="default">string</code> <code class="default">undefined</code>
String with name of class that will be added to root element of PhotoSwipe (`.pswp`). Can contain multiple classes separated by space.
### `getNumItemsFn` <code class="default">function</code>
Function that should return total number of items in gallery. By default it returns length of slides array. Don't put very complex code here, function is executed very often.
### `focus` <code class="default">boolean</code> <code class="default">true</code>
Will set focus on PhotoSwipe element after it's open.
### `isClickableElement` <code class="default">function</code>
Default value:
```javascript
isClickableElement: function(el) {
return el.tagName === 'A';
}
```
Function should check if the element (`el`) is clickable. If it is &ndash; PhotoSwipe will not call `preventDefault` and `click` event will pass through. Function should be as light is possible, as it's executed multiple times on drag start and drag release.
### `modal` <code class="default">boolean</code> <code class="default">true</code>
Controls whether PhotoSwipe should expand to take up the entire viewport. If false, the PhotoSwipe element will take the size of the positioned parent of the template. Take a look at [the FAQ](faq.html#inline-gallery) for more information.
## Default UI Options
Options for `PhotoSwipeUI_Default` (`dist/ui/photoswipe-ui-default.js`) are added the same way and to the same object as core options.
```javascript
// Size of top & bottom bars in pixels,
// "bottom" parameter can be 'auto' (will calculate height of caption)
// option applies only when mouse is used,
// or width of screen is more than 1200px
//
// (Also refer to `parseVerticalMargin` event)
barsSize: {top:44, bottom:'auto'},
// Adds class pswp__ui--idle to pswp__ui element when mouse isn't moving for 4000ms
timeToIdle: 4000,
// Same as above, but this timer applies when mouse leaves the window
timeToIdleOutside: 1000,
// Delay until loading indicator is displayed
loadingIndicatorDelay: 1000,
// Function builds caption markup
addCaptionHTMLFn: function(item, captionEl, isFake) {
// item - slide object
// captionEl - caption DOM element
// isFake - true when content is added to fake caption container
// (used to get size of next or previous caption)
if(!item.title) {
captionEl.children[0].innerHTML = '';
return false;
}
captionEl.children[0].innerHTML = item.title;
return true;
},
// Buttons/elements
closeEl:true,
captionEl: true,
fullscreenEl: true,
zoomEl: true,
shareEl: true,
counterEl: true,
arrowEl: true,
preloaderEl: true,
// Tap on sliding area should close gallery
tapToClose: false,
// Tap should toggle visibility of controls
tapToToggleControls: true,
// Mouse click on image should close the gallery,
// only when image is smaller than size of the viewport
clickToCloseNonZoomable: true,
// Element classes click on which should close the PhotoSwipe.
// In HTML markup, class should always start with "pswp__", e.g.: "pswp__item", "pswp__caption".
//
// "pswp__ui--over-close" class will be added to root element of UI when mouse is over one of these elements
// By default it's used to highlight the close button.
closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'],
// Separator for "1 of X" counter
indexIndicatorSep: ' / ',
{% raw %}
// Share buttons
//
// Available variables for URL:
// {{url}} - url to current page
// {{text}} - title
// {{image_url}} - encoded image url
// {{raw_image_url}} - raw image url
shareButtons: [
{id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
{id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
{id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/?url={{url}}&media={{image_url}}&description={{text}}'},
{id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
],
{% endraw %}
// Next 3 functions return data for share links
//
// functions are triggered after click on button that opens share modal,
// which means that data should be about current (active) slide
getImageURLForShare: function( shareButtonData ) {
// `shareButtonData` - object from shareButtons array
//
// `pswp` is the gallery instance object,
// you should define it by yourself
//
return pswp.currItem.src || '';
},
getPageURLForShare: function( shareButtonData ) {
return window.location.href;
},
getTextForShare: function( shareButtonData ) {
return pswp.currItem.title || '';
},
// Parse output of share links
parseShareButtonOut: function(shareButtonData, shareButtonOut) {
// `shareButtonData` - object from shareButtons array
// `shareButtonOut` - raw string of share link element
return shareButtonOut;
}
```
Know how this page can be improved? Found a typo? [Suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
---
layout: default
title: PhotoSwipe Performance Tips
h1_title: Performance Tips
description: Suggestions on how to make gallery faster.
addjs: true
canonical_url: http://photoswipe.com/documentations/performance-tips.html
buildtool: true
markdownpage: true
---
## Animations
- Animation performance dramatically depends on the size of an image. The smaller image &ndash; the smoother animation. So don't be lazy and [serve responsive images](responsive-images.html), or at least don't serve images larger than 1200x1200 for phones.
- Don't do anything during the animations that can cause Paint or Layout. Don't append new elements to the DOM. Don't change `display` or `visibility`. Don't breath. You can only change `transform` and `opacity`. Delay all your changes after animation ends &ndash; use events: `beforeChange` (slide switched), `initialZoomInEnd` (initial zoom in animation ended) and `initialZoomOutEnd` (initial zoom out animation ended).
- Try to avoid complex `:hover` and `:active` effects on thumbnails that open PhotoSwipe if you have zoom-in/out animation enabled (apply the first rule).
- Make sure that you don't have complex styles on UI over PhotoSwipe sliding area. For example, `text-shadow` on caption text can cause issues.
If you followed above steps and performance of your gallery differs from [PhotoSwipe home page](http://photoswipe.com), start isolating PhotoSwipe on page by excluding all JS/CSS/HTML code not related to it. Make sure that you don't have any kind of banner rotators that continuously run some animation behind the PhotoSwipe.
If it doesn't work fast even after you isolated PhotoSwipe &ndash; open an [issue on GitHub](https://github.com/dimsemenov/PhotoSwipe/issues) and provide a link to [reduced test case](http://css-tricks.com/reduced-test-cases/).
## Including Files
- Default PhotoSwipe UI has `png` and `svg` sprite. By default, it's loaded only after PhotoSwipe is opened. To make controls appear instantly, you may merge gallery sprite with your site "main" sprite, or preload it via CSS.
- Defer the loading of PhotoSwipe JS file(s) if gallery is not the main feature of your page.
- Combine JS, minify and combine CSS files.
Know how this page can be improved? [Suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
\ No newline at end of file
---
layout: default
title: Serving responsive images in PhotoSwipe
h1_title: Responsive Images
description: The complete guide on how to serve responsive images in PhotoSwipe.
addjs: true
canonical_url: http://photoswipe.com/documentation/responsive-images.html
buildtool: true
markdownpage: true
---
PhotoSwipe does not support `<picture>` or `srcset`, as it requires defined image dimensions and uses lazy-loading. But as images are loaded dynamically, it's quite easy to switch sources, even in old browsers that don't support `srcset`.
Let's assume that you have just "medium" images and "original" ("large") images. First of all, you need to store path and size of the image in slide object, for example like so:
```javascript
var items = [
// Slide 1
{
mediumImage: {
src: 'path/to/medium-image-1.jpg',
w:800,
h:600
},
originalImage: {
src: 'path/to/large-image-1.jpg',
w: 1400,
h: 1050
}
},
// Slide 2
// {
// mediumImage: {
// src: 'path/to/medium-image-2.jpg',
// ...
//
// ...
];
```
Then:
```javascript
// initialise as usual
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
// create variable that will store real size of viewport
var realViewportWidth,
useLargeImages = false,
firstResize = true,
imageSrcWillChange;
// beforeResize event fires each time size of gallery viewport updates
gallery.listen('beforeResize', function() {
// gallery.viewportSize.x - width of PhotoSwipe viewport
// gallery.viewportSize.y - height of PhotoSwipe viewport
// window.devicePixelRatio - ratio between physical pixels and device independent pixels (Number)
// 1 (regular display), 2 (@2x, retina) ...
// calculate real pixels when size changes
realViewportWidth = gallery.viewportSize.x * window.devicePixelRatio;
// Code below is needed if you want image to switch dynamically on window.resize
// Find out if current images need to be changed
if(useLargeImages && realViewportWidth < 1000) {
useLargeImages = false;
imageSrcWillChange = true;
} else if(!useLargeImages && realViewportWidth >= 1000) {
useLargeImages = true;
imageSrcWillChange = true;
}
// Invalidate items only when source is changed and when it's not the first update
if(imageSrcWillChange && !firstResize) {
// invalidateCurrItems sets a flag on slides that are in DOM,
// which will force update of content (image) on window.resize.
gallery.invalidateCurrItems();
}
if(firstResize) {
firstResize = false;
}
imageSrcWillChange = false;
});
// gettingData event fires each time PhotoSwipe retrieves image source & size
gallery.listen('gettingData', function(index, item) {
// Set image source & size based on real viewport width
if( useLargeImages ) {
item.src = item.originalImage.src;
item.w = item.originalImage.w;
item.h = item.originalImage.h;
} else {
item.src = item.mediumImage.src;
item.w = item.mediumImage.w;
item.h = item.mediumImage.h;
}
// It doesn't really matter what will you do here,
// as long as item.src, item.w and item.h have valid values.
//
// Just avoid http requests in this listener, as it fires quite often
});
// Note that init() method is called after gettingData event is bound
gallery.init();
```
- You are not obliged to use structure of slide object that looks exactly like above (with `mediumImage` and `largeImage` objects). For example, you may store size of image directly in image filename (`/path/to/large-image-600x500.jpg`) and then parse size in `gettingData` event. Only `item.src`, `item.w`, and `item.h` properties are read by PhotoSwipe and only after `gettingData` event is fired.
- The larger the image, the less smooth animations will look.
- Try to avoid serving images just based on devicePixelRatio or just based on viewport size, always combine both.
- Feel free to use `srcset` on thumbnails that open PhotoSwipe.
Know how this guide can be improved? [Suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
---
layout: default
title: SEO Friendly JavaScript Image Gallery Markup
h1_title: Image Gallery SEO
description: Ideal HTML markup for JavaScript image gallery (lightbox type).
addjs: true
canonical_url: http://photoswipe.com/documentation/seo.html
buildtool: true
markdownpage: true
---
PhotoSwipe does not force any HTML markup, you have full control. Simplest markup is a list of thumbnails that link to large image, simplest example:
```html
<a href="large-image.jpg">
<img src="small-image.jpg" alt="Image description" />
</a>
...
```
If you have long caption that doesn't fit in `alt` or it just contains HTML tags, you may use `<figure>` and `<figcaption>`:
```html
<figure>
<a href="large-image.jpg">
<img src="small-image.jpg" alt="Image description" />
</a>
<figcaption>Long image description</figcaption>
</figure>
...
```
You can go further and use [Schema.org markup for ImageGallery](http://schema.org/ImageGallery) and [ImageObject](http://schema.org/ImageObject), it should look like this:
```html
<div itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<!-- optionally use this method to store image dimensions for PhotoSwipe -->
<meta itemprop="width" content="300">
<meta itemprop="height" content="600">
<figcaption itemprop="caption description">
Long image description
<!-- optionally define copyright -->
<span itemprop="copyrightHolder">Photo: AP</span>
</figcaption>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Long image description</figcaption>
</figure>
...
</div>
```
If you don't want thumbnails to be visible on page, e.g. you have 50 images in gallery and you show just first 3 thumbnails + link "view all images (50)", you definitely should use [Schema.org markup](http://schema.org/ImageGallery) and you should have all 50 links (with text in contents of link element instead of thumbnail) in DOM (you may hide them with `display:none`). Example:
```html
<div itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image-1.jpg" itemprop="contentUrl">
<figcaption itemprop="caption description">Long image description 1</figcaption>
</a>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image-2.jpg" itemprop="contentUrl">
<figcaption itemprop="caption description">Long image description 2</figcaption>
</a>
</figure>
...
</div>
```
In all above cases, `large-image.jpg` will be perfectly indexed. The caption element will be crawled even if you hide it with `display:none`, just keep the text relevant, non-spammy &ndash; don't stuff it with keywords.
### Additional recommendations
- Keep `alt` attribute short and descriptive. Leave long description for caption element.
- [Google image publishing guidelines](https://support.google.com/webmasters/answer/114016).
- Use [Google](https://developers.google.com/webmasters/structured-data/testing-tool/) or [Yandex](https://webmaster.yandex.com/microtest.xml) structured data testing tool to validate your Schema.org markup.
- High-resolution images rank better, usually 1680px on a wider side is more than enough.
- Image caption that is visible on initial page load will always rank better than hidden one. A good example of gallery layout that manages to keep both thumbnails and caption visible initially on page is [the new Guardian gallery page](http://www.theguardian.com/science/gallery/2015/mar/13/satellites-as-youve-never-seen-them-before-in-pictures).
- Optimize images size and format:
- [Good guide by Ilya Grigorik](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization).
- Tools: for Mac there is [ImageOptim](https://imageoptim.com/), for Windows &ndash; [FileOptimizer](http://nikkhokkho.sourceforge.net/static.php?page=FileOptimizer) or [JPEGmini](http://www.jpegmini.com/windows) (limited lite version). Also, there are a lot of server-side/command-line tools like [ImageMagick](http://www.imagemagick.org/) or [jpegtran](http://jpegclub.org/jpegtran/).
- If you serve different images for high-DPI (e.g. retina) screens, reduce their JPEG quality to 20-40% to save file size, [good article about this](http://www.netvlies.nl/blog/design-interactie/retina-revolution).
- You don't need to create image sitemap if you have links to images or/and valid Schema.org markup, but it can help you [track how well they are indexed](http://webmasters.stackexchange.com/a/5151).
- Feel free to use `srcset` or `<picture>` for thumbnails.
- Be careful with number of thumbnails on a gallery page, slow page load speed can hurt rankings.
- Search engines index the direct link to the image file quite well, especially with Schema.org markup. But having a separate HTML page for each image is better when it has a descriptive and unique title, description and comments.
Know how this page can be improved? [Please suggest an edit!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/seo.md)
---
layout: default
title: PhotoSwipe Update Notifications &amp; Changelog
h1_title: Update Notifications
description: Instructions on how to keep PhotoSwipe gallery up-do-date.
addjs: true
canonical_url: http://photoswipe.com/documentation/updates.html
buildtool: true
markdownpage: true
---
It's very important to keep PhotoSwipe updated, especially during the beta period.
Each time PhotoSwipe gets an update - [GitHub releases](https://github.com/dimsemenov/PhotoSwipe/releases) page is updated with details about release.
Releases page has an [Atom feed](https://github.com/dimsemenov/PhotoSwipe/releases.atom), you may setup email notifications when feed is updated [using IFTTT](https://ifttt.com/recipes/230902-photoswipe-update-notification):
<div>
<a href="https://ifttt.com/view_embed_recipe/230902-photoswipe-update-notification" target = "_blank" class="embed_recipe embed_recipe-l_30" id= "embed_recipe-230902"><img src= 'https://ifttt.com/recipe_embed_img/230902' alt="IFTTT Recipe: PhotoSwipe update notification connects feed to email" width="370px" style="max-width:100%"/></a><script async type="text/javascript" src= "//ifttt.com/assets/embed_recipe.js"></script>
</div>
Altervatively, you can follow [@PhotoSwipe on Twitter](http://twitter.com/photoswipe), or join my tiny email newsletter:
<div>
<div id="mc_embed_signup" class="embed-form">
<form action="http://dimsemenov.us1.list-manage.com/subscribe/post?u=ef6026d946a7b5d41d92c02e4&amp;id=54fae727da" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate="">
<p>Get notified about important update or new release.</p>
<div class="mc-field-group">
<input type="email" value="" name="EMAIL" placeholder="Your email" class="required email" id="mce-EMAIL">
<input type="hidden" id="group_2" name="group[2065][2]" value="true">
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button">
</div>
<p style="font-size: 12px; margin: 4px 0 0 0;">Newsletter is sent 3 times a year at max. Powered by Mailchimp.</p>
</form>
</div>
</div>
---
layout: default
title: PhotoSwipe FAQ
h1_title: FAQ
description: Frequently asked questions and known issues about PhotoSwipe image gallery.
addjs: true
canonical_url: http://photoswipe.com/documentation/faq.html
buildtool: true
markdownpage: true
---
## 执行情况
### <a name="image-size"></a> 我无法预先定义图像大小,该怎么办?
使用另一个图库脚本([1](http://dimsemenov.com/plugins/magnific-popup/)[2](http://dimsemenov.com/plugins/royal-slider/gallery/)),或找到一种方法:
- 只需下载一小部分图像([PHP version](http://stackoverflow.com/questions/4635936/super-fast-getimagesize-in-php)[Ruby](https://github.com/sdsykes/fastimage)[Node.js](http://stackoverflow.com/a/20111234/331460)),就可以读取图像的大小。
- 你可以直接将图像的大小存储在其文件名中,并在 PhotoSwipe 初始化期间(API 部分中的“gettingdata”事件)在前端对其进行解析。
- 大多数 CMS 将图像的大小存储在数据库中,并具有检索图像的 API。
- 大多数 Web API(Facebook、500px、Instagram、Flickr、Twitter、YouTube、Vimeo 等)都会返回一定大小的图片。
尺寸用于逐步加载、拉伸占位符、初始放大转换、平移、缩放、字幕定位。在 GitHub[issue #741](https://github.com/dimsemenov/PhotoSwipe/issues/741) 中进行讨论。
### <a name="different-thumbnail-dimensions"></a> 我的缩略图是正方形的,但是大的图像有不同的尺寸,那么打开 / 关闭过渡怎么办?
1. 如果缩略图长宽比与大图像不匹配,请不要为幻灯片对象定义 `msrc` 属性并启用不透明度转换选项(“showhideopacity:true,getthumbboundsfn:false”)。
2. 如果缩略图图像文件的长宽比匹配大图像,但缩略图区域是通过 CSS 裁剪的,只需添加 `showHideOpacity:true` 并确保 `getThumbBoundsFn` 选项返回考虑裁剪区域的坐标。
我强烈建议显示与大图像长宽比匹配的缩略图,或者通过 CSS(2)裁剪可见区域。
我将试着解释为什么这一点还没有实现。制作扩展区域动画有两种方法:
1. Animate`clip` 属性。但每次 [it forces Paint](http://csstriggers.com/#clip),这使得动画生涩。
2. 用两个 div 展开的图像进行包装,这两个 div 具有 `overflow:hidden`,并在动画期间通过 `transform:translate` 重新定位它们,这样它们就会在正确的部分剪辑它。这种方法不强制绘制或布局,但需要在每个幻灯片的标记中添加两个元素。测试原型表明,它只能在高端移动设备(如 Nexus5 和 Chrome )上流畅地工作。也许有一天我会实现它。
### <a name="scroll-in-caption"></a> 我的字幕很大,我可以添加滚动吗?
参考 [issue #657](https://github.com/dimsemenov/PhotoSwipe/issues/657)
### <a name="inline-gallery"></a> 如何实现内联图库显示
请注意,这是一个实验性的功能,目前它不允许在移动设备上在图库上垂直滚动页面(在 Touch Events 上它调用 `prevetDefault()`)。如果发现问题,请报告。要实现与文档其余部分一起运行的嵌入式图库,请遵循以下步骤:
1.`.pswp` 模板放入定位的父元素中。
2. 设置 `modal: false, closeOnScroll: false` 选项。
3. 修改 `getThumbBoundsFn`(如果你正在使用它)以减去模板父级的边界 rect。
4. 构造 PhotoSwipe 。
5. 监听 `updateScrollOffset` 事件,并将模板的边界矩形添加到偏移量。
6. `init()`the PhotoSwipe 。
[**CodePen→上的实时示例 **](http://codepen.io/dimsemenov/pen/JogxWM)
```html
<div style="position: relative;" class="parent">
<div id="gallery" class="pswp"> ... </div>
</div>
```
```javascript
var items = [...];
var template = document.getElementById("gallery"); // .pswp
var options = {
...,
modal: false,
closeOnScroll: false,
getThumbBoundsFn: function(index) {
// rect was the original bounds
var rect = {x: ..., y: ..., w: ...},
var templateBounds = template.parentElement.getBoundingClientRect();
rect.x -= templateBounds.left;
rect.y -= templateBounds.top;
return rect;
}
};
var photoSwipe = new PhotoSwipe(template, PhotoSwipeUI_Default, items, options);
photoSwipe.listen('updateScrollOffset', function(_offset) {
var r = template.getBoundingClientRect();
_offset.x += r.left;
_offset.y += r.top;
});
photoSwipe.init();
```
### <a name="custom-pid-in-url"></a> 如何在 URL 中使用自定义标识符而不是索引
要使 URL 到单个图像看起来像这样:
```
http://example.com/#&gid=1&pid=custom-first-id
http://example.com/#&gid=1&pid=custom-second-id
```
而不是:
```
http://example.com/#&gid=1&pid=1
http://example.com/#&gid=1&pid=2
```
...启用选项 `history:true, galleryPIDs:true` 并将 `pid`(唯一图片标识符)属性添加到幻灯片对象(`pid’可以是整数或字符串),例如:
```js
var slides = [
{
src: 'path/to/1.jpg',
w:500,
h:400,
pid: 'custom-first-id'
},
{
src: 'path/to/2.jpg',
w:300,
h:700,
pid: 'custom-second-id'
},
...
];
```
- 请注意, PhotoSwipe 不执行任何代码,直到你初始化并打开它。这就是为什么在初始页面加载时需要自己解析 URL 的原因。文档的 [Getting Started](http://photoswipe.com/documentation/getting-started.html#dom-to-slide-objects) 部分中的默认代码包括此功能(如果需要进行一些修改,请检查 `photoswipeParseHash`函数)。
- 选项 `galleryPIDs` 自 PhotoSwipe v4.0.8([选项描述](options.html#galleryPIDs))起可用。
## 虫子
### <a name="gif-freeze-ios"></a>GIF 图像有时会在 iOS8 上冻结
iOS Safari 有一个 bug,它会冻结移动到窗口之外(或带有 `overflow:hidden` 的元素之外)的 GIF 图像。我的建议是完全避免在 PhotoSwipe 中使用动画 GIF,因为它们会降低任何移动浏览器中的动画性能。但如果你确实需要使用它,请参考 [this hack](https://github.com/dimsemenov/PhotoSwipe/issues/662#issuecomment-66420874)
### <a name="mobile-crash"></a> 打开带有大型图片的图库时,移动浏览器会崩溃
大多数情况下,它可以发生在内存限制较低的移动设备上 –iOS Safari,这是旧 Android(KitKat 之前)的默认浏览器。最常见的崩溃原因是太大的图像(通常大于 2000x1500px)。 PhotoSwipe 在图像上应用硬件加速,这比页面上的常规图像消耗更多的内存,因此当你超出限制时,浏览器开始滞后甚至崩溃。
所以 [提供响应图像](responsive-images.html),或者至少不提供巨大的图像。理想情况下,对于一部平均 900x600 的手机,你应该提供 1200 像素宽的图像。请注意,如果在 iOS 模拟器中一切顺利,这并不意味着崩溃不会发生在真正的设备上。
在更罕见的情况下,如果在页面的某些过程中打开 PhotoSwipe (这可以是初始的页面加载 / 呈现,或者是页面上的某些复杂动画),则可能会发生崩溃,请尝试延迟 PhotoSwipe 初始化,直到页面呈现(在 document.ready.ready 之后的 18-300ms),特别是如果你正在显示大型图像。
Upd.:在 [v4.1.0](https://github.com/dimsemenov/PhotoSwipe/releases/tag/v4.1.0) 中,这是部分固定的。
## 杂项
### <a name="keep-updated"></a> 变更日志在哪里,如何获得更新通知?
每次 PhotoSwipe 获得更新时-[GitHub releases](https://github.com/dimsemenov/PhotoSwipe/releases) 页面都会更新详细信息。发布页面有一个 [Atom feed](https://github.com/dimsemenov/PhotoSwipe/releases.atom),你可以在提要更新 [using IFTTT](https://ifttt.com/recipes/230902-photoswipe-update-notification) 时设置电子邮件通知。
还有,你可以加入我的 [电子邮件通讯](http://dimsemenov.com/subscribe.html?i=pswp)(一年发送 3-4 次),关注 [@PhotoSwipe on Twitter](http://twitter.com/photoswipe),和 star/watch[PhotoSwipe on GitHub](https://github.com/dimsemenov/PhotoSwipe/)
### <a name="wordpress-release"></a>WordPress 插件何时发布?
Plugin 正在开发中,将于 2015 年发布。以获得通知 [订阅我的时事通讯](http://dimsemenov.com/subscribe.html?i=pswp-wp)
### <a name="can-i-use-in-theme"></a> 我想在 wordpress/magento/joomla...模板中使用 PhotoSwipe ,可以吗?
是的,你可以使用 PhotoSwipe 中的免费或商业主题,没有任何限制。如果可以,请在主题描述或 / 和管理区域中留下信用额度(链接到 PhotoSwipe 主页)。
<div style="margin-top:30px;"><p> 知道如何改进这个页面吗?发现了语法错误?<a href="https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md"> 请编辑!</a></p></div>
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
<style type="text/css">
body {
overflow-y:scroll;
}
h3 {
cursor: pointer;
font-weight: normal;
-webkit-user-select:none;
-moz-user-select:none;
user-select:none;
color: #3169B3;
padding-left: 18px;
position: relative;
}
h3:hover {
color: #C00;
}
h3:before {
content:'▼';
font-size: 12px;
position: absolute;
left: 0;
top: 2px;
}
h3.tab-closed:before {
content: '►';
}
</style>
<script>
(function() {
// tabs
if(!document.addEventListener) {
return;
}
var els = document.getElementsByClassName('row--docs')[0].children,
el;
var isContentEl = function(el) {
if(!el) {
return;
}
if( (/(P|UL|OL)/i).test(el.tagName) || el.className === 'highlight' ) {
return true;
}
return;
},
toggleTab = function(el) {
var dStyle = el.classList.contains('tab-closed') ? 'block' : 'none';
el.classList.toggle('tab-closed');
var s = el.nextElementSibling;
while( isContentEl(s) ) {
s.style.display = dStyle;
s = s.nextElementSibling;
}
};
for(var i = 0; i < els.length; i++) {
el = els[i];
if(el.tagName === 'H3') {
if(window.location.hash !== '#' + el.firstElementChild.name) {
toggleTab(el);
}
el.onclick = function() {
toggleTab(this);
};
}
}
})();
</script>
---
layout: default
title: "PhotoSwipe Documentation: Getting Started"
h1_title: Getting Started
description: PhotoSwipe image gallery getting started guide.
addjs: true
canonical_url: http://photoswipe.com/documentation/getting-started.html
buildtool: true
markdownpage: true
---
开始之前应该知道的第一件事:
- PhotoSwipe 不是一个简单的 jQuery 插件,至少需要基本的 JavaScript 知识才能安装。
- PhotoSwipe 需要预定义的图像尺寸([more about this](faq.html#image-size))。
- 如果你在无响应的网站上使用 PhotoSwipe –控件将在移动设备上进行缩放(当整个页面被缩放时)。因此,你将需要实现自定义控件(例如,在右上角的单个大型关闭按钮)。
- 文档中的所有代码都是纯 VanillaJS,并支持 IE8 及以上版本。如果你的网站或应用程序使用了一些 JavaScript framework (比如 jQuery 或 MooTools),或者你不需要支持旧的浏览器——请随意简化代码。
- 避免为移动设备提供大图片(大于 2000x1500px),因为它们会大大降低动画性能,并可能导致崩溃(尤其是在 iOS Safari 上)。可能的解决方案:[提供响应图像](responsive-images.html),或在单独的页面上打开图像,或使用支持图像平铺的库(例如 [Leaflet](http://leafletjs.com/))([more in FAQ](faq.html#mobile-crash))。
## <a name="initialization"></a> 初始化
### <a name="init-include-files"></a> 第一步:包含 JS 和 CSS 文件
你可以在 [dist/](https://github.com/dimsemenov/PhotoSwipe/tree/master/dist)[GitHub](https://github.com/dimsemenov/PhotoSwipe)库文件夹中找到它们。Sass 和未编译的 JS 文件在 [src/](https://github.com/dimsemenov/PhotoSwipe/tree/master/src) 文件夹中。如果你计划修改现有的样式,我建议你使用 Sass,因为那里的代码是结构化和注释的。
```html
<!-- Core CSS file -->
<link rel="stylesheet" href="path/to/photoswipe.css">
<!-- Skin CSS file (styling of UI - buttons, caption, etc.)
In the folder of skin CSS file there are also:
- .png and .svg icons sprite,
- preloader.gif (for browsers that do not support CSS animations) -->
<link rel="stylesheet" href="path/to/default-skin/default-skin.css">
<!-- Core JS file -->
<script src="path/to/photoswipe.min.js"></script>
<!-- UI JS file -->
<script src="path/to/photoswipe-ui-default.min.js"></script>
```
不管你将如何以及在哪里包含 JS 和 CSS 文件。只有在调用 `new PhotoSwipe()` 时,才执行代码。所以,如果你不需要 PhotoSwipe 一开始就打开文件,可以随时推迟加载。
PhotoSwipe 还支持 AMD 加载程序(如 RequireJS)和 CommonJS,可以这样使用它们:
```javascript
require([
'path/to/photoswipe.js',
'path/to/photoswipe-ui-default.js'
], function( PhotoSwipe, PhotoSwipeUI_Default ) {
// var gallery = new PhotoSwipe( someElement, PhotoSwipeUI_Default ...
// gallery.init()
// ...
});
```
此外,你还可以通过 bower(“bower install PhotoSwipe ”)或 [NPM](https://www.npmjs.com/package/photoswipe)(“npm install PhotoSwipe ”)安装它。
### <a name="init-add-pswp-to-dom"></a> 步骤 2:添加 PhotoSwipe (。pswp)元素到 DOM
你可以通过 JS 动态地添加 HTML 代码(直接在初始化之前),或者最初将其放在页面中(就像在演示页面中所做的那样)。这段代码可以附加到任何地方,但理想的情况是在结束 `</body>` 之前。你可以跨多个图库重用它(只要你使用相同的 UI 类)。
```html
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
```
不应更改 `pswp__bg``pswp__scroll-wrap``pswp__container``pswp__item` 元素的顺序。
你可能会问,为什么 PhotoSwipe 不通过 JS 自动添加此代码,原因很简单 –只是为了节省文件大小,以防你需要对布局进行一些修改。
### 步骤 3:初始化
执行 `PhotoSwipe` 构造函数。它接受 4 个论点:
1. 步骤 2 中的 `.pswp` 元素(必须将其添加到 DOM 中)。
2. PhotoSwipe UI 类。如果包含默认的 `photoswipe-ui-default.js`,则类将是 `PhotoSwipeUI_Default`。可以 `false`
3. 带有对象(幻灯片)的数组。
4. [Options](options.html).
```javascript
var pswpElement = document.querySelectorAll('.pswp')[0];
// build items array
var items = [
{
src: 'https://placekitten.com/600/400',
w: 600,
h: 400
},
{
src: 'https://placekitten.com/1200/900',
w: 1200,
h: 900
}
];
// define options (if needed)
var options = {
// optionName: 'option value'
// for example:
index: 0 // start at first slide
};
// Initializes and opens PhotoSwipe
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
```
最后,你应该得到这样的结论:
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="gbadPv" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/gbadPv/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
<!-- <script async src="//assets.codepen.io/assets/embed/ei.js"></script> -->
</div>
## <a name="creating-slide-objects-array"></a> 创建幻灯片对象数组
数组中的每个对象都应该包含有关幻灯片的数据,它可以是你希望在 PhotoSwipe 中显示的任何内容-图像路径、标题字符串、共享数量、注释等。
默认情况下 PhotoSwipe 只使用 5 个属性:`src`(图像路径),`w`(图像宽度),`h`(图像高度),`msrc`(小图像占位符路径,大图像将被加载在顶部),`html`(自定义 HTML,[more about it](custom-html-in-slides.html))。
在导航过程中, PhotoSwipe 将其自身的属性添加到此对象(例如 `minZoom``loaded`)。
```javascript
var slides = [
// slide 1
{
src: 'path/to/image1.jpg', // path to image
w: 1024, // image width
h: 768, // image height
msrc: 'path/to/small-image.jpg', // small image placeholder,
// main (large) image loads on top of it,
// if you skip this parameter - grey rectangle will be displayed,
// try to define this property only when small image was loaded before
title: 'Image Caption' // used by Default PhotoSwipe UI
// if you skip it, there won't be any caption
// You may add more properties here and use them.
// For example, demo gallery uses "author" property, which is used in the caption.
// author: 'John Doe'
},
// slide 2
{
src: 'path/to/image2.jpg',
w: 600,
h: 600
// etc.
}
// etc.
];
```
你可以在 PhotoSwipe 读取幻灯片对象属性之前直接动态地定义它们,使用 `gettingData` 事件(更多信息在 [API section of docs](api.html) 中)。例如,这种技术可以用来 [服务不同的形象](responsive-images.html) 用于不同的屏幕尺寸。
## <a class="anchor" name="dom-to-slide-objects"></a> 如何从链接列表中构建幻灯片数组
假设你有一个看起来像这样的链接 / 缩略图列表([更多关于图库标记的信息](seo.html)):
```html
<div class="my-gallery" itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl" data-size="600x400">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption</figcaption>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl" data-size="600x400">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Image caption</figcaption>
</figure>
</div>
```
...你想要点击缩略图来打开大图片的 PhotoSwipe (就像在演示页面上做的那样)。你需要做的就是:
1. 将单击事件绑定到链接 / 缩略图。
2. 用户点击缩略图后,找到它的索引。
3. 从 DOM 元素创建一个幻灯片对象数组——循环所有链接并检索 `href` 属性(大图像 URL)、`data-size` 属性(其大小)、`src` 缩略图和标题内容。
PhotoSwipe 其实并不在乎你将如何做到这一点。如果你使用像 jQuery 或 MooTools 这样的框架,或者如果你不需要支持 IE8,那么代码可以大大简化。
下面是支持 IE8 的纯 Vanilla JS 实现:
```javascript
var initPhotoSwipeFromDOM = function(gallerySelector) {
// parse slide data (url, title, size ...) from DOM elements
// (children of gallerySelector)
var parseThumbnailElements = function(el) {
var thumbElements = el.childNodes,
numNodes = thumbElements.length,
items = [],
figureEl,
linkEl,
size,
item;
for(var i = 0; i < numNodes; i++) {
figureEl = thumbElements[i]; // <figure> element
// include only element nodes
if(figureEl.nodeType !== 1) {
continue;
}
linkEl = figureEl.children[0]; // <a> element
size = linkEl.getAttribute('data-size').split('x');
// create slide object
item = {
src: linkEl.getAttribute('href'),
w: parseInt(size[0], 10),
h: parseInt(size[1], 10)
};
if(figureEl.children.length > 1) {
// <figcaption> content
item.title = figureEl.children[1].innerHTML;
}
if(linkEl.children.length > 0) {
// <img> thumbnail element, retrieving thumbnail url
item.msrc = linkEl.children[0].getAttribute('src');
}
item.el = figureEl; // save link to element for getThumbBoundsFn
items.push(item);
}
return items;
};
// find nearest parent element
var closest = function closest(el, fn) {
return el && ( fn(el) ? el : closest(el.parentNode, fn) );
};
// triggers when user clicks on thumbnail
var onThumbnailsClick = function(e) {
e = e || window.event;
e.preventDefault ? e.preventDefault() : e.returnValue = false;
var eTarget = e.target || e.srcElement;
// find root element of slide
var clickedListItem = closest(eTarget, function(el) {
return (el.tagName && el.tagName.toUpperCase() === 'FIGURE');
});
if(!clickedListItem) {
return;
}
// find index of clicked item by looping through all child nodes
// alternatively, you may define index via data- attribute
var clickedGallery = clickedListItem.parentNode,
childNodes = clickedListItem.parentNode.childNodes,
numChildNodes = childNodes.length,
nodeIndex = 0,
index;
for (var i = 0; i < numChildNodes; i++) {
if(childNodes[i].nodeType !== 1) {
continue;
}
if(childNodes[i] === clickedListItem) {
index = nodeIndex;
break;
}
nodeIndex++;
}
if(index >= 0) {
// open PhotoSwipe if valid index found
openPhotoSwipe( index, clickedGallery );
}
return false;
};
// parse picture index and gallery index from URL (#&pid=1&gid=2)
var photoswipeParseHash = function() {
var hash = window.location.hash.substring(1),
params = {};
if(hash.length < 5) {
return params;
}
var vars = hash.split('&');
for (var i = 0; i < vars.length; i++) {
if(!vars[i]) {
continue;
}
var pair = vars[i].split('=');
if(pair.length < 2) {
continue;
}
params[pair[0]] = pair[1];
}
if(params.gid) {
params.gid = parseInt(params.gid, 10);
}
return params;
};
var openPhotoSwipe = function(index, galleryElement, disableAnimation, fromURL) {
var pswpElement = document.querySelectorAll('.pswp')[0],
gallery,
options,
items;
items = parseThumbnailElements(galleryElement);
// define options (if needed)
options = {
// define gallery index (for URL)
galleryUID: galleryElement.getAttribute('data-pswp-uid'),
getThumbBoundsFn: function(index) {
// See Options -> getThumbBoundsFn section of documentation for more info
var thumbnail = items[index].el.getElementsByTagName('img')[0], // find thumbnail
pageYScroll = window.pageYOffset || document.documentElement.scrollTop,
rect = thumbnail.getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}
};
// PhotoSwipe opened from URL
if(fromURL) {
if(options.galleryPIDs) {
// parse real index when custom PIDs are used
// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
for(var j = 0; j < items.length; j++) {
if(items[j].pid == index) {
options.index = j;
break;
}
}
} else {
// in URL indexes start from 1
options.index = parseInt(index, 10) - 1;
}
} else {
options.index = parseInt(index, 10);
}
// exit if index not found
if( isNaN(options.index) ) {
return;
}
if(disableAnimation) {
options.showAnimationDuration = 0;
}
// Pass data to PhotoSwipe and initialize it
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
};
// loop through all gallery elements and bind events
var galleryElements = document.querySelectorAll( gallerySelector );
for(var i = 0, l = galleryElements.length; i < l; i++) {
galleryElements[i].setAttribute('data-pswp-uid', i+1);
galleryElements[i].onclick = onThumbnailsClick;
}
// Parse URL and open gallery if it contains #&pid=3&gid=1
var hashData = photoswipeParseHash();
if(hashData.pid && hashData.gid) {
openPhotoSwipe( hashData.pid , galleryElements[ hashData.gid - 1 ], true, true );
}
};
// execute above function
initPhotoSwipeFromDOM('.my-gallery');
```
CodePen 示例(由于嵌入问题,禁用了 `focus`&`history` 选项):
<div class="codepen-embed">
<p data-height="600" data-theme-id="10447" data-slug-hash="ZYbPJM" data-default-tab="result" data-user="dimsemenov" class='codepen'>
<a href="http://codepen.io/dimsemenov/pen/ZYbPJM/" target="_blank"><strong>View example on CodePen &rarr;</strong></a>
</p>
</div>
提示:你可以从 CodePen 下载示例,以便在本地使用它(“在 CodePen 上编辑 `->`Share`->`Export .zip`)。
- 如果使用与本例不同的标记,则需要编辑函数`parseThumbnailElements`。
- 如果你对纯 JavaScript 没有经验,也不知道如何解析 DOM,请参考 [QuirksMode](http://quirksmode.org/dom/core/#gettingelements) 和 [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element.getElementsByTagName)。
- 注意,IE8 不支持 HTML5`<figure>` 和 `<figcaption>` 元素,因此你需要在 `<head>` 部分中包含 [html5shiv](https://github.com/aFarkas/html5shiv)([CDNJS 托管版本](http://cdnjs.com/libraries/html5shiv/) 在示例中使用):
```html
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js"></script>
<![endif]-->
```
## 关于
请 [保持脚本更新](faq.html#keep-updated),通过 [GitHub](https://github.com/dimsemenov/PhotoSwipe) 报告错误,在 [UserVoice](https://photoswipe.uservoice.com/forums/275302-feature-requests-ideas) 上建议功能,并通过 [StackOverflow](http://stackoverflow.com/questions/ask?tags=javascript,photoswipe) 提问。
知道如何改进这个页面吗?找到了一个错别字?[建议编辑一下!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/getting-started.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
---
layout: default
title: PhotoSwipe Options
h1_title: Options
description: Complete list of PhotoSwipe options (including PhotoSwipeUI_Default options).
addjs: true
canonical_url: http://photoswipe.com/documentation/options.html
buildtool: true
markdownpage: true
---
选项以键值对的形式添加,并作为参数传递到 `PhotoSwipe` 构造函数,例如:
```javascript
var options = {
index: 3,
escKey: false,
// ui option
timeToIdle: 4000
};
var gallery = new PhotoSwipe( someElement, PhotoSwipeUI_Default, someItems, options);
gallery.init();
// Note that options object is cloned during the initialization.
// But you can access it via `gallery.options`.
// For example, to dynamically change `escKey`:
gallery.options.escKey = false;
// `options.escKey = false` will not work
```
## 核心
### `index`<code class="default"> 整数 </code><code class="default">0</code>
开始幻灯片索引。`0` 是第一张幻灯片。必须是整数,而不是字符串。
### `getThumbBoundsFn`<code class="default">函数</code><code class="default"> 未定义</code>
函数应该返回一个具有初始放大动画将从其开始(或缩小动画将结束)的坐标的对象。
对象应该包含三个属性:`x`(x 位置,相对于文档),`y`(y 位置,相对于文档),`w`(元素的宽度)。高度将根据大型图像的大小自动计算。例如,如果你返回 `{x:0,y:0,w:50}`,缩放动画将在页面的左上角开始。
函数有一个参数-`index` 的项目是打开或关闭。
在非模态模式下,模板相对于视口的位置应该从 `x``y` 中减去。有关更多信息,请参见 [the FAQ](faq.html#inline-gallery)
计算缩略图位置的示例:
```javascript
getThumbBoundsFn: function(index) {
// find thumbnail element
var thumbnail = document.querySelectorAll('.my-gallery-thumbnails')[index];
// get window scroll Y
var pageYScroll = window.pageYOffset || document.documentElement.scrollTop;
// optionally get horizontal scroll
// get position of element relative to viewport
var rect = thumbnail.getBoundingClientRect();
// w = width
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
// Good guide on how to get element coordinates:
// http://javascript.info/tutorial/coordinates
}
```
如果你的小缩略图的尺寸与大图片的尺寸不匹配,可以考虑启用缩放 + 渐变转换。你可以通过添加选项 `showHideOpacity:true`(尝试将其添加到 [above CodePen](http://codepen.io/dimsemenov/pen/ZYbPJM) 以测试其外观)来实现此目的。或者通过添加 `hideAnimationDuration:0, showAnimationDuration:0` 完全禁用转换。[常见问题解答中有关此的更多信息](faq.html#different-thumbnail-dimensions)
如果要在动画制作过程中“隐藏”小缩略图,请使用 `opacity:0`,而不是 `visibility:hidden``display:none`。不要在动画开始时强行进行绘图和布局,以避免滞后。
### `showHideOpacity`<code class="default"> 布尔 </code><code class="default"> 假的</code>
如果设置为 `false`:背景 `opacity` 和图像 `scale` 将被动画处理(图像不透明度始终为 1)。如果设置为 `true`:根 PhotoSwipe 元素 `opacity` 和图像 `scale` 将被动画。
要仅启用 `opacity` 转换(不使用 `scale`),请不要定义 `getThumbBoundsFn` 选项。
### `showAnimationDuration`<code class="default"> 整数 </code><code class="default">333</code>
初始放大转换持续时间(以毫秒为单位)。设置为 `0` 可禁用。除了这个 JS 选项,你还需要在 PhotoSwipe CSS 文件中更改转换持续时间:
```css
.pswp--animate_opacity,
.pswp__bg,
.pswp__caption,
.pswp__top-bar,
.pswp--has_mouse .pswp__button--arrow--left,
.pswp--has_mouse .pswp__button--arrow--right{
-webkit-transition: opacity 333ms cubic-bezier(.4,0,.22,1);
transition: opacity 333ms cubic-bezier(.4,0,.22,1);
}
```
如果使用 Sass,只需在 [_main-settings.scss ](https://github.com/dimsemenov/PhotoSwipe/blob/master/src/css/_main-settings.scss) 中更改转换持续时间变量。
### `hideAnimationDuration`<code class="default"> 整数 </code><code class="default">333</code>
与前一个选项相同,仅用于关闭(缩小)转换。在 PhotoSwipe 被打开 `pswp--open` 类将被添加到根元素之后,你可以使用它来在 CSS 中应用不同的转换持续时间。
### `bgOpacity`<code class="default">number</code><code class="default">1</code>
背景(`。pswp__bg`)不透明度。应该是从 0 到 1 的数字,例如 `0.7`。这种样式是通过 JS 而不是 CSS 定义的,因为该值用于一些基于手势的转换。
### `spacing`<code class="default">number</code><code class="default">0.12</code>
幻灯片之间的间距比。例如,`0.12` 将呈现为 12% 的滑动视口宽度(四舍五入)。
### `allowPanToNext`<code class="default"> 布尔 </code><code class="default"> 为真</code>
当当前项目被放大时,允许滑动导航到下一个 / 上一个项目。在没有硬件触控支持的设备上,选项始终是 `false`
### `maxSpreadZoom`<code class="default">number</code><code class="default">2</code>
执行扩展(缩放)手势时的最大缩放级别。`2` 表示图像可以从原始尺寸缩放 2 倍。在这里尽量避免使用过大的值,因为太大的图像可能会在移动设备(尤其是 iOS)上导致内存问题。
### `getDoubleTapZoom`<code class="default">函数</code>
函数应该返回缩放级别,在双击手势后,或者当用户单击缩放图标时,或者在图像本身上单击鼠标时,图像将被缩放到该级别。如果你返回 `1`,图像将被放大到其原始大小。
默认值:
```javascript
getDoubleTapZoom: function(isMouseClick, item) {
// isMouseClick - true if mouse, false if double-tap
// item - slide object that is zoomed, usually current
// item.initialZoomLevel - initial scale ratio of image
// e.g. if viewport is 700px and image is 1400px,
// initialZoomLevel will be 0.5
if(isMouseClick) {
// is mouse click on image or zoom icon
// zoom to original
return 1;
// e.g. for 1400px image:
// 0.5 - zooms to 700px
// 2 - zooms to 2800px
} else {
// is double-tap
// zoom to original if initial zoom is less than 0.7x,
// otherwise to 1.5x, to make sure that double-tap gesture always zooms image
return item.initialZoomLevel < 0.7 ? 1 : 1.5;
}
}
```
函数每次启动放大动画时都被调用。因此,可以根据不同图像的大小或屏幕 DPI 返回不同的值。
### `loop`<code class="default"> 布尔 </code><code class="default"> 为真</code>
使用滑动手势时循环幻灯片。如果设置为 `true`,你将能够从最后一张图像滑动到第一张图像。当幻灯片少于 3 张时,选项总是 `false`
此选项与箭头导航无关。箭头循环将永久打开。你可以通过创建自定义 UI 来修改此行为。
### `pinchToClose`<code class="default"> 布尔 </code><code class="default"> 为真</code>
捏以关闭画廊的手势。随着用户的放大,图库的背景将逐渐淡出。当手势完成时,画廊将关闭。
### `closeOnScroll`<code class="default"> 布尔 </code><code class="default"> 为真</code>
在页面滚动中关闭图库。该选项仅适用于不支持硬件触控的设备。
### `closeOnVerticalDrag`<code class="default"> 布尔 </code><code class="default"> 为真</code>
当图像垂直拖动或未缩放时,关闭图库.当使用鼠标时,总是 `false`
### `mouseUsed`<code class="default"> 布尔 </code><code class="default"> 假的</code>
选项允许你预先定义是否使用了鼠标。 PhotoSwipe 一些功能依赖于它,例如,只有在使用鼠标之后才会显示默认的 UI 左 / 右箭头。如果设置为 `false`, PhotoSwipe 将在自己使用鼠标时开始检测,当找到鼠标时触发 `mouseUsed` 事件。
### `escKey`<code class="default"> 布尔 </code><code class="default"> 为真</code>
`esc` 键盘键关闭 PhotoSwipe 。选项可以动态更改(`yourphotoswipeinstance.options.esckey=false;`)。
### `arrowKeys`<code class="default"> 布尔 </code><code class="default"> 为真</code>
键盘左或右方向键导航.选项可以动态更改(`yourphotoswipeInstance.options.arrowkeys=false;`)。
### `history`<code class="default"> 布尔 </code><code class="default"> 为真</code>
如果设置为 `false`,则禁用历史模块(关闭图库的后退按钮,每个幻灯片的唯一 URL)。你也可以将 `history.js` 模块从你的构建中排除。
### `galleryUID`<code class="default"> 整数 </code><code class="default">1</code>
画廊唯一的 ID。历史模块在形成 URL 时使用.例如,使用 UID1 的 Gallery 的第二张图片将具有 URL:`http://example.com/#&gid=1&pid=2`
### <a name="galleryPIDs"></a>`galleryPIDs`<code class="default"> 布尔 </code><code class="default"> 假的</code>
为形成 URL 时使用的每个幻灯片对象启用自定义 ID。如果选项集设置为 `true`,则幻灯片对象必须具有 `pid`(图片标识符)属性,该属性可以是字符串或整数。例如:
```js
var slides = [
{
src: 'path/to/1.jpg',
w:500,
h:400,
pid: 'image-one'
},
{
src: 'path/to/2.jpg',
w:300,
h:700,
pid: 'image-two'
},
...
];
```
第二张幻灯片将有 URL`http://example.com/#&gid=1&pid=image-two`
[the FAQ section](faq.html#custom-pid-in-url) 中阅读有关如何实现自定义 PID 的更多信息。
### `errorMsg`<code class="default"> 字符串</code>
图像未加载时的错误消息.`%url%` 将被图像的 URL 替换。
默认值:
```html
<div class="pswp__error-msg"><a href="%url%" target="_blank">The image</a> could not be loaded.</div>
```
### `preload`<code class="default"> 数组 </code><code class="default">[1,1]</code>
根据移动方向对附近的幻灯片进行延迟加载。应该是一个有两个整数的数组,第一个是在当前图像之前预加载的数项,第二个是在当前图像之后预加载的数项。例如,如果你将它设置为[1,3],它将在当前之前加载 1 个图像,在当前之后加载 3 个图像。值不能小于 1。
### `mainClass`<code class="default"> 字符串 </code><code class="default"> 未定义</code>
带有类名称的字符串,它将被添加到 PhotoSwipe (`)的根元素中。pswp`)。可以包含由空间分隔的多个类。
### `getNumItemsFn`<code class="default">函数</code>
函数应该返回图库中的项目总数。默认情况下,它返回幻灯片数组的长度。不要把非常复杂的代码放在这里,函数是经常执行的。
### `focus`<code class="default"> 布尔 </code><code class="default"> 为真</code>
打开 PhotoSwipe 元素后将设置焦点。
### `isClickableElement`<code class="default">函数</code>
默认值:
```javascript
isClickableElement: function(el) {
return el.tagName === 'A';
}
```
函数应检查元素是否可单击。如果是 – PhotoSwipe 将不会调用 `preventDefault` 并且 `click` 事件将通过。函数应该尽可能地轻,因为它在拖动启动和拖动释放上执行了多次。
### `modal`<code class="default"> 布尔 </code><code class="default"> 为真</code>
控制 PhotoSwipe 是否应该展开以占据整个视口。如果为假, PhotoSwipe 元素将占用模板的定位父元素的大小。查看 [the FAQ](faq.html#inline-gallery) 了解更多信息。
## 默认 UI 选项
`PhotoSwipeUI_Default``dist/ui/ PhotoSwipe -ui-default.js`)的选项以与核心选项相同的方式添加到相同的对象中。
```javascript
// Size of top & bottom bars in pixels,
// "bottom" parameter can be 'auto' (will calculate height of caption)
// option applies only when mouse is used,
// or width of screen is more than 1200px
//
// (Also refer to `parseVerticalMargin` event)
barsSize: {top:44, bottom:'auto'},
// Adds class pswp__ui--idle to pswp__ui element when mouse isn't moving for 4000ms
timeToIdle: 4000,
// Same as above, but this timer applies when mouse leaves the window
timeToIdleOutside: 1000,
// Delay until loading indicator is displayed
loadingIndicatorDelay: 1000,
// Function builds caption markup
addCaptionHTMLFn: function(item, captionEl, isFake) {
// item - slide object
// captionEl - caption DOM element
// isFake - true when content is added to fake caption container
// (used to get size of next or previous caption)
if(!item.title) {
captionEl.children[0].innerHTML = '';
return false;
}
captionEl.children[0].innerHTML = item.title;
return true;
},
// Buttons/elements
closeEl:true,
captionEl: true,
fullscreenEl: true,
zoomEl: true,
shareEl: true,
counterEl: true,
arrowEl: true,
preloaderEl: true,
// Tap on sliding area should close gallery
tapToClose: false,
// Tap should toggle visibility of controls
tapToToggleControls: true,
// Mouse click on image should close the gallery,
// only when image is smaller than size of the viewport
clickToCloseNonZoomable: true,
// Element classes click on which should close the PhotoSwipe.
// In HTML markup, class should always start with "pswp__", e.g.: "pswp__item", "pswp__caption".
//
// "pswp__ui--over-close" class will be added to root element of UI when mouse is over one of these elements
// By default it's used to highlight the close button.
closeElClasses: ['item', 'caption', 'zoom-wrap', 'ui', 'top-bar'],
// Separator for "1 of X" counter
indexIndicatorSep: ' / ',
{% raw %}
// Share buttons
//
// Available variables for URL:
// {{url}} - url to current page
// {{text}} - title
// {{image_url}} - encoded image url
// {{raw_image_url}} - raw image url
shareButtons: [
{id:'facebook', label:'Share on Facebook', url:'https://www.facebook.com/sharer/sharer.php?u={{url}}'},
{id:'twitter', label:'Tweet', url:'https://twitter.com/intent/tweet?text={{text}}&url={{url}}'},
{id:'pinterest', label:'Pin it', url:'http://www.pinterest.com/pin/create/button/?url={{url}}&media={{image_url}}&description={{text}}'},
{id:'download', label:'Download image', url:'{{raw_image_url}}', download:true}
],
{% endraw %}
// Next 3 functions return data for share links
//
// functions are triggered after click on button that opens share modal,
// which means that data should be about current (active) slide
getImageURLForShare: function( shareButtonData ) {
// `shareButtonData` - object from shareButtons array
//
// `pswp` is the gallery instance object,
// you should define it by yourself
//
return pswp.currItem.src || '';
},
getPageURLForShare: function( shareButtonData ) {
return window.location.href;
},
getTextForShare: function( shareButtonData ) {
return pswp.currItem.title || '';
},
// Parse output of share links
parseShareButtonOut: function(shareButtonData, shareButtonOut) {
// `shareButtonData` - object from shareButtons array
// `shareButtonOut` - raw string of share link element
return shareButtonOut;
}
```
知道如何改进这个页面吗?找到了一个错别字?[建议编辑一下!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
---
layout: default
title: PhotoSwipe Performance Tips
h1_title: Performance Tips
description: Suggestions on how to make gallery faster.
addjs: true
canonical_url: http://photoswipe.com/documentations/performance-tips.html
buildtool: true
markdownpage: true
---
## 动画
- 动画的表现极大地取决于图像的大小。较小的图像 –更平滑的动画。因此,不要偷懒和 [提供响应图像](responsive-images.html),或者至少不要为手机提供大于 1200x1200 的图像。
- 不要在动画期间做任何可能导致油漆或布局的事情。不要在 DOM 中添加新元素。不要更改 `display``visibility`。别呼吸。你只能更改 `transform``opacity`。在动画结束后延迟所有更改 –use 事件:`beforeChange`(幻灯片切换),`initialZoomInEnd`(初始放大动画结束)和 `initialZoomOutEnd`(初始缩小动画结束)。
- 如果启用了放大 / 缩小动画,则在打开 PhotoSwipe 的缩略图上尽量避免复杂的 `:hover``:active` 效果(应用第一条规则)。
- 确保在滑动区域的 UI 上没有复杂的样式。例如,标题文本上的 `text-shadow` 可能会导致问题。
如果你遵循了上面的步骤,并且你的图库的性能与 [PhotoSwipe home page](http://photoswipe.com) 不同,那么开始在 Page 上隔离 PhotoSwipe ,排除所有与其无关的 JS/CSS/HTML 代码。确保没有任何类型的横幅旋转器在 PhotoSwipe 后面持续运行一些动画。
如果在隔离了 PhotoSwipe –之后仍然无法快速工作,则打开 [issue on GitHub](https://github.com/dimsemenov/PhotoSwipe/issues) 并提供到 [简化测试用例](http://css-tricks.com/reduced-test-cases/) 的链接。
## 包括文件
- 默认的 PhotoSwipe UI 有 `png``svg` 精灵。默认情况下,只有在打开 PhotoSwipe 后才加载它。为了使控件立即出现,你可以将 Gallery Sprite 与你的网站“主”Sprite 合并,或者通过 CSS 预装它。
- 如果 Gallery 不是页面的主要功能,请推迟 PhotoSwipe JS 文件的加载。
- 合并 JS、Minify 和合并 CSS 文件。
知道如何改进这个页面吗?[建议编辑一下!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
<iframe src="http://ghbtns.com/github-btn.html?user=dimsemenov&amp;repo=photoswipe&amp;type=watch&amp;count=true&amp;size=large" allowtransparency="true" frameborder="0" scrolling="0" width="155" height="30" style=""></iframe>
---
layout: default
title: Serving responsive images in PhotoSwipe
h1_title: Responsive Images
description: The complete guide on how to serve responsive images in PhotoSwipe.
addjs: true
canonical_url: http://photoswipe.com/documentation/responsive-images.html
buildtool: true
markdownpage: true
---
PhotoSwipe 不支持 `<picture>``srcset`,因为它需要定义的图像尺寸并使用惰性加载。但是,由于图像是动态加载的,所以很容易切换数据源,即使在不支持 `srcset` 的旧浏览器中也是如此。
让我们假设你只有“中等”图像和“原始”(“大”)图像。首先,你需要在幻灯片对象中存储图像的路径和大小,例如如下所示:
```javascript
var items = [
// Slide 1
{
mediumImage: {
src: 'path/to/medium-image-1.jpg',
w:800,
h:600
},
originalImage: {
src: 'path/to/large-image-1.jpg',
w: 1400,
h: 1050
}
},
// Slide 2
// {
// mediumImage: {
// src: 'path/to/medium-image-2.jpg',
// ...
//
// ...
];
```
然后:
```javascript
// initialise as usual
var gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
// create variable that will store real size of viewport
var realViewportWidth,
useLargeImages = false,
firstResize = true,
imageSrcWillChange;
// beforeResize event fires each time size of gallery viewport updates
gallery.listen('beforeResize', function() {
// gallery.viewportSize.x - width of PhotoSwipe viewport
// gallery.viewportSize.y - height of PhotoSwipe viewport
// window.devicePixelRatio - ratio between physical pixels and device independent pixels (Number)
// 1 (regular display), 2 (@2x, retina) ...
// calculate real pixels when size changes
realViewportWidth = gallery.viewportSize.x * window.devicePixelRatio;
// Code below is needed if you want image to switch dynamically on window.resize
// Find out if current images need to be changed
if(useLargeImages && realViewportWidth < 1000) {
useLargeImages = false;
imageSrcWillChange = true;
} else if(!useLargeImages && realViewportWidth >= 1000) {
useLargeImages = true;
imageSrcWillChange = true;
}
// Invalidate items only when source is changed and when it's not the first update
if(imageSrcWillChange && !firstResize) {
// invalidateCurrItems sets a flag on slides that are in DOM,
// which will force update of content (image) on window.resize.
gallery.invalidateCurrItems();
}
if(firstResize) {
firstResize = false;
}
imageSrcWillChange = false;
});
// gettingData event fires each time PhotoSwipe retrieves image source & size
gallery.listen('gettingData', function(index, item) {
// Set image source & size based on real viewport width
if( useLargeImages ) {
item.src = item.originalImage.src;
item.w = item.originalImage.w;
item.h = item.originalImage.h;
} else {
item.src = item.mediumImage.src;
item.w = item.mediumImage.w;
item.h = item.mediumImage.h;
}
// It doesn't really matter what will you do here,
// as long as item.src, item.w and item.h have valid values.
//
// Just avoid http requests in this listener, as it fires quite often
});
// Note that init() method is called after gettingData event is bound
gallery.init();
```
- 你不必使用与上面完全相同的幻灯片对象结构(使用 `mediumImage``largeImage` 对象)。例如,你可以将图像的大小直接存储在图像文件名(`/path/to/large-image-600x500)中。然后在 `gettingData` 事件中解析大小。只有 `item.src`、`item.w` 和 `item.h` 属性被 PhotoSwipe 读取,并且只有在 `gettingData` 事件被触发之后。
- 图像越大,动画看起来就越不流畅。
- 尽量避免仅基于 DeviceXelRatio 或仅基于视口大小提供图像,始终将两者结合起来。
- 在打开 PhotoSwipe 的缩略图上随意使用 `srcset`
知道如何改进这本指南吗?[建议编辑一下!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/responsive-images.md)
---
layout: default
title: SEO Friendly JavaScript Image Gallery Markup
h1_title: Image Gallery SEO
description: Ideal HTML markup for JavaScript image gallery (lightbox type).
addjs: true
canonical_url: http://photoswipe.com/documentation/seo.html
buildtool: true
markdownpage: true
---
PhotoSwipe 不强制任何 HTML 标记,你可以完全控制。最简单的标记是链接到大图片的缩略图列表,最简单的例子:
```html
<a href="large-image.jpg">
<img src="small-image.jpg" alt="Image description" />
</a>
...
```
如果你的长标题不适合 `alt`,或者它只包含 HTML 标记,则可以使用 `<figure>``<figcaption>`:
```html
<figure>
<a href="large-image.jpg">
<img src="small-image.jpg" alt="Image description" />
</a>
<figcaption>Long image description</figcaption>
</figure>
...
```
你可以进一步使用 [ImageGallery 的 schema.org 标记](http://schema.org/ImageGallery)[ImageObject](http://schema.org/ImageObject),它应该是这样的:
```html
<div itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<!-- optionally use this method to store image dimensions for PhotoSwipe -->
<meta itemprop="width" content="300">
<meta itemprop="height" content="600">
<figcaption itemprop="caption description">
Long image description
<!-- optionally define copyright -->
<span itemprop="copyrightHolder">Photo: AP</span>
</figcaption>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image.jpg" itemprop="contentUrl">
<img src="small-image.jpg" itemprop="thumbnail" alt="Image description" />
</a>
<figcaption itemprop="caption description">Long image description</figcaption>
</figure>
...
</div>
```
如果你不想在页面上看到缩略图,例如,你在图库中有 50 张图片,你只显示前 3 张缩略图 + 链接“查看所有图片(50)”,你肯定应该使用 [schema.org 标记](http://schema.org/ImageGallery),并且在 DOM 中应该有所有 50 个链接(链接元素的内容中包含文本,而不是缩略图)(你可以用 `display:none` 隐藏它们)。示例:
```html
<div itemscope itemtype="http://schema.org/ImageGallery">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image-1.jpg" itemprop="contentUrl">
<figcaption itemprop="caption description">Long image description 1</figcaption>
</a>
</figure>
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<a href="large-image-2.jpg" itemprop="contentUrl">
<figcaption itemprop="caption description">Long image description 2</figcaption>
</a>
</figure>
...
</div>
```
在上述所有情况下,`large-image.jpg` 都将被完美地编入索引。即使你用 `display:none` 隐藏 caption 元素,它也会被抓取,只需保持文本的相关性,非垃圾邮件 –不要用关键字填充它。
### 补充建议
- 保持 `alt` 属性的简短和描述性。为 caption 元素保留较长的描述。
- [谷歌图片发布指南](https://support.google.com/webmasters/answer/114016).
- 使用 [Google](https://developers.google.com/webmasters/structured-data/testing-tool/)[Yandex](https://webmaster.yandex.com/microtest.xml) 结构化数据测试工具来验证你的 schema.org 标记。
- 高分辨率的图像排名更好,通常 1680px 在更宽的一面是绰绰有余的。
- 在初始页面加载时可见的图片说明将总是比隐藏的排名更好。设法使缩略图和标题在页面上保持可见的图库布局的一个很好的例子是 [新的卫报画廊页面](http://www.theguardian.com/science/gallery/2015/mar/13/satellites-as-youve-never-seen-them-before-in-pictures)
- 优化图像大小和格式:
- [导游:Ilya Grigorik ](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization).
- 工具:对于 Mac 有 [ImageOptim](https://imageoptim.com/),对于 Windows–[FileOptimizer](http://nikkhokkho.sourceforge.net/static.php?page=FileOptimizer)[JPEGmini](http://www.jpegmini.com/windows)(精简版)。此外,还有很多服务器端 / 命令行工具,比如 [ImageMagick](http://www.imagemagick.org/)[jpegtran](http://jpegclub.org/jpegtran/)
- 如果你为高 DPI(例如 Retina)屏幕提供不同的图像,请将它们的 JPEG 质量降低到 20-40%,以节省文件大小,[这方面的好文章](http://www.netvlies.nl/blog/design-interactie/retina-revolution)
- 如果你有指向图像或 / 和 valid schema.org 标记的链接,则不需要创建图像站点地图,但是它可以帮助你 [track how well they are indexed](http://webmasters.stackexchange.com/a/5151)
- 对于缩略图,可以使用 `srcset``<picture>`
- 要小心画廊页面上的缩略图数量,缓慢的页面加载速度可能会损害排名。
- 搜索引擎可以很好地索引到图像文件的直接链接,特别是使用 schema.org 标记。但是,当每一张图片都有一个描述性的和唯一的标题、描述和注释时,为每一张图片设置一个单独的 HTML 页面会更好。
知道如何改进这个页面吗?[请建议编辑!](https://github.com/dimsemenov/PhotoSwipe/blob/master/website/documentation/seo.md)
---
layout: default
title: PhotoSwipe Update Notifications &amp; Changelog
h1_title: Update Notifications
description: Instructions on how to keep PhotoSwipe gallery up-do-date.
addjs: true
canonical_url: http://photoswipe.com/documentation/updates.html
buildtool: true
markdownpage: true
---
保持更新是非常重要的,尤其是在测试阶段。
每次 PhotoSwipe 获得更新时-[GitHub releases](https://github.com/dimsemenov/PhotoSwipe/releases) 页面都会更新有关发布的详细信息。发布页面有一个 [Atom feed](https://github.com/dimsemenov/PhotoSwipe/releases.atom),你可以在提要更新 [using IFTTT](https://ifttt.com/recipes/230902-photoswipe-update-notification) 时设置电子邮件通知:
<div>
<a href="https://ifttt.com/view_embed_recipe/230902-photoswipe-update-notification" target = "_blank" class="embed_recipe embed_recipe-l_30" id= "embed_recipe-230902"><img src= 'https://ifttt.com/recipe_embed_img/230902' alt="IFTTT Recipe: PhotoSwipe update notification connects feed to email" width="370px" style="max-width:100%"/></a><script async type="text/javascript" src= "//ifttt.com/assets/embed_recipe.js"></script>
</div>
交替地,你可以关注 [@PhotoSwipe on Twitter](http://twitter.com/photoswipe),或加入我的小电子邮件时事通讯:
<div>
<div id="mc_embed_signup" class="embed-form">
<form action="http://dimsemenov.us1.list-manage.com/subscribe/post?u=ef6026d946a7b5d41d92c02e4&amp;id=54fae727da" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate="">
<p>Get notified about important update or new release.</p>
<div class="mc-field-group">
<input type="email" value="" name="EMAIL" placeholder="Your email" class="required email" id="mce-EMAIL">
<input type="hidden" id="group_2" name="group[2065][2]" value="true">
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button">
</div>
<p style="font-size: 12px; margin: 4px 0 0 0;">Newsletter is sent 3 times a year at max. Powered by Mailchimp.</p>
</form>
</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="341.737" height="277.725"><defs><clipPath id="a"><path d="M0 2221.78V0h2733.9v2221.78H0z"/></clipPath></defs><g><g><g><g clip-path="url(#a)" transform="matrix(.125 0 0 -.125 0 277.725)"><path d="M859.797 0C543.047 0 248.223 92.852 0 251.988c43.88-5.18 88.527-7.828 133.8-7.828 262.782 0 504.63 89.672 696.59 240.102C584.95 488.79 377.813 650.95 306.44 873.79c34.246-6.552 69.382-10.06 105.527-10.06 51.148 0 100.703 6.852 147.77 19.668-256.59 51.524-449.93 278.222-449.93 549.982 0 2.37.007 4.71.047 7.05 75.628-42.01 162.113-67.24 254.054-70.15-150.5 100.58-249.52 272.26-249.52 466.85 0 102.8 27.653 199.14 75.934 281.98 276.645-339.34 689.934-562.64 1156.09-586.03-9.56 41.05-14.53 83.86-14.53 127.82 0 309.75 251.14 560.88 560.91 560.88 161.32 0 307.09-68.12 409.41-177.13 127.76 25.16 247.8 71.84 356.17 136.12-41.88-130.98-130.81-240.9-246.62-310.32 113.46 13.56 221.56 43.71 322.15 88.32-75.2-112.48-170.3-211.27-279.88-290.35 1.08-24.05 1.62-48.24 1.62-72.56C2455.64 854.672 1891.48 0 859.797 0" fill="#6babe1"/></g></g></g></g></svg>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册