├── .babelrc ├── .csscomb.json ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .node-version ├── LICENSE ├── circle.yml ├── css ├── smartphoto.css └── smartphoto.min.css ├── examples ├── assets │ ├── bear.jpg │ ├── camel.jpg │ ├── castle.jpg │ ├── hippo.jpg │ ├── koala.jpg │ ├── large-bear.jpg │ ├── large-camel.jpg │ ├── large-hippo.jpg │ ├── large-koala.jpg │ ├── large-lion.jpg │ ├── large-rhino.jpg │ ├── lion.jpg │ ├── rhino.jpg │ ├── sample.png │ ├── style.css │ └── test.png ├── event.html ├── jquery.html ├── lazy.html ├── multiple.html ├── noimage.html ├── resizeFit.html └── vanilla.html ├── images ├── icon_arrow_next.svg ├── icon_arrow_prev.svg └── icon_close.svg ├── index.d.ts ├── js ├── jquery-smartphoto.js ├── jquery-smartphoto.min.js ├── smartphoto.js └── smartphoto.min.js ├── lib ├── adaptor │ └── jquery.js ├── core │ └── index.js ├── index.js └── lib │ └── util.js ├── package-lock.json ├── package.json ├── readme.md ├── scss └── smartphoto.scss ├── src ├── .DS_Store ├── adaptor │ └── jquery.js ├── core │ ├── index.js │ └── viwer.html ├── index.js └── lib │ └── util.js ├── test ├── preload.js └── test.js └── tools └── index.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ], 5 | "plugins": [ 6 | "transform-html-import-to-string", 7 | "add-module-exports" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.csscomb.json: -------------------------------------------------------------------------------- 1 | { 2 | "remove-empty-rulesets": true, 3 | "always-semicolon": true, 4 | "color-case": "upper", 5 | "block-indent": " ", 6 | "color-shorthand": true, 7 | "element-case": "lower", 8 | "eof-newline": false, 9 | "leading-zero": false, 10 | "quotes": "double", 11 | "sort-order-fallback": "abc", 12 | "space-before-colon": "", 13 | "space-after-colon": " ", 14 | "space-before-combinator": " ", 15 | "space-after-combinator": " ", 16 | "space-between-declarations": "\n", 17 | "space-before-opening-brace": " ", 18 | "space-after-opening-brace": "\n", 19 | "space-after-selector-delimiter": "\n", 20 | "space-before-selector-delimiter": "", 21 | "space-before-closing-brace": "\n", 22 | "strip-spaces": true, 23 | "tab-size": true, 24 | "unitless-zero": true, 25 | "vendor-prefix-align": true, 26 | "sort-order": [ 27 | [ 28 | "display", 29 | "visibility", 30 | "overflow", 31 | "overflow-x", 32 | "overflow-y", 33 | "-ms-overflow-x", 34 | "-ms-overflow-y", 35 | "flex-direction", 36 | "flex-order", 37 | "flex-pack", 38 | "flex-align", 39 | "-webkit-box-sizing", 40 | "-moz-box-sizing", 41 | "box-sizing", 42 | "table-layout", 43 | "empty-cells", 44 | "caption-side", 45 | "border-spacing", 46 | "border-collapse", 47 | "list-style", 48 | "list-style-position", 49 | "list-style-type", 50 | "list-style-image", 51 | "position", 52 | "z-index", 53 | "top", 54 | "right", 55 | "bottom", 56 | "left", 57 | "float", 58 | "clear", 59 | "min-width", 60 | "max-width", 61 | "width", 62 | "min-height", 63 | "max-height", 64 | "height", 65 | "margin", 66 | "margin-top", 67 | "margin-right", 68 | "margin-bottom", 69 | "margin-left", 70 | "padding", 71 | "padding-top", 72 | "padding-right", 73 | "padding-bottom", 74 | "padding-left", 75 | "border", 76 | "border-width", 77 | "border-style", 78 | "border-color", 79 | "border-top", 80 | "border-top-width", 81 | "border-top-style", 82 | "border-top-color", 83 | "border-right", 84 | "border-right-width", 85 | "border-right-style", 86 | "border-right-color", 87 | "border-bottom", 88 | "border-bottom-width", 89 | "border-bottom-style", 90 | "border-bottom-color", 91 | "border-left", 92 | "border-left-width", 93 | "border-left-style", 94 | "border-left-color", 95 | "-webkit-border-radius", 96 | "-moz-border-radius", 97 | "border-radius", 98 | "-webkit-border-top-left-radius", 99 | "-moz-border-radius-topleft", 100 | "border-top-left-radius", 101 | "-webkit-border-top-right-radius", 102 | "-moz-border-radius-topright", 103 | "border-top-right-radius", 104 | "-webkit-border-bottom-right-radius", 105 | "-moz-border-radius-bottomright", 106 | "border-bottom-right-radius", 107 | "-webkit-border-bottom-left-radius", 108 | "-moz-border-radius-bottomleft", 109 | "border-bottom-left-radius", 110 | "-webkit-border-image", 111 | "-moz-border-image", 112 | "-o-border-image", 113 | "border-image", 114 | "-webkit-border-image-source", 115 | "-moz-border-image-source", 116 | "-o-border-image-source", 117 | "border-image-source", 118 | "-webkit-border-image-slice", 119 | "-moz-border-image-slice", 120 | "-o-border-image-slice", 121 | "border-image-slice", 122 | "-webkit-border-image-width", 123 | "-moz-border-image-width", 124 | "-o-border-image-width", 125 | "border-image-width", 126 | "-webkit-border-image-outset", 127 | "-moz-border-image-outset", 128 | "-o-border-image-outset", 129 | "border-image-outset", 130 | "-webkit-border-image-repeat", 131 | "-moz-border-image-repeat", 132 | "-o-border-image-repeat", 133 | "border-image-repeat", 134 | "background", 135 | "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", 136 | "background-color", 137 | "background-image", 138 | "background-repeat", 139 | "background-attachment", 140 | "background-position", 141 | "background-position-x", 142 | "-ms-background-position-x", 143 | "background-position-y", 144 | "-ms-background-position-y", 145 | "-webkit-background-clip", 146 | "-moz-background-clip", 147 | "background-clip", 148 | "background-origin", 149 | "-webkit-background-size", 150 | "-moz-background-size", 151 | "-o-background-size", 152 | "background-size", 153 | "opacity", 154 | "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", 155 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", 156 | "-ms-interpolation-mode", 157 | "outline", 158 | "outline-width", 159 | "outline-style", 160 | "outline-color", 161 | "outline-offset", 162 | "box-decoration-break", 163 | "-webkit-box-shadow", 164 | "-moz-box-shadow", 165 | "box-shadow", 166 | "filter:progid:DXImageTransform.Microsoft.gradient", 167 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", 168 | "text-shadow", 169 | "color", 170 | "font", 171 | "font-family", 172 | "font-size", 173 | "font-weight", 174 | "font-style", 175 | "font-variant", 176 | "font-size-adjust", 177 | "font-stretch", 178 | "font-effect", 179 | "font-emphasize", 180 | "font-emphasize-position", 181 | "font-emphasize-style", 182 | "font-smooth", 183 | "text-decoration", 184 | "text-emphasis", 185 | "text-emphasis-color", 186 | "text-emphasis-style", 187 | "text-emphasis-position", 188 | "text-indent", 189 | "text-align", 190 | "-webkit-text-align-last", 191 | "-moz-text-align-last", 192 | "-ms-text-align-last", 193 | "text-align-last", 194 | "vertical-align", 195 | "line-height", 196 | "white-space", 197 | "-ms-text-justify", 198 | "text-justify", 199 | "letter-spacing", 200 | "word-spacing", 201 | "-ms-writing-mode", 202 | "text-outline", 203 | "text-transform", 204 | "text-wrap", 205 | "text-overflow", 206 | "-ms-text-overflow", 207 | "text-overflow-ellipsis", 208 | "text-overflow-mode", 209 | "-ms-word-wrap", 210 | "word-wrap", 211 | "word-break", 212 | "-ms-word-break", 213 | "-moz-tab-size", 214 | "-o-tab-size", 215 | "tab-size", 216 | "-webkit-hyphens", 217 | "-moz-hyphens", 218 | "hyphens", 219 | "pointer-events", 220 | "content", 221 | "quotes", 222 | "counter-reset", 223 | "counter-increment", 224 | "resize", 225 | "cursor", 226 | "-webkit-user-select", 227 | "-moz-user-select", 228 | "-ms-user-select", 229 | "user-select", 230 | "nav-index", 231 | "nav-up", 232 | "nav-right", 233 | "nav-down", 234 | "nav-left", 235 | "-webkit-transition", 236 | "-moz-transition", 237 | "-ms-transition", 238 | "-o-transition", 239 | "transition", 240 | "-webkit-transition-delay", 241 | "-moz-transition-delay", 242 | "-ms-transition-delay", 243 | "-o-transition-delay", 244 | "transition-delay", 245 | "-webkit-transition-timing-function", 246 | "-moz-transition-timing-function", 247 | "-ms-transition-timing-function", 248 | "-o-transition-timing-function", 249 | "transition-timing-function", 250 | "-webkit-transition-duration", 251 | "-moz-transition-duration", 252 | "-ms-transition-duration", 253 | "-o-transition-duration", 254 | "transition-duration", 255 | "-webkit-transition-property", 256 | "-moz-transition-property", 257 | "-ms-transition-property", 258 | "-o-transition-property", 259 | "transition-property", 260 | "-webkit-transform", 261 | "-moz-transform", 262 | "-ms-transform", 263 | "-o-transform", 264 | "transform", 265 | "-webkit-transform-origin", 266 | "-moz-transform-origin", 267 | "-ms-transform-origin", 268 | "-o-transform-origin", 269 | "transform-origin", 270 | "-webkit-animation", 271 | "-moz-animation", 272 | "-ms-animation", 273 | "-o-animation", 274 | "animation", 275 | "-webkit-animation-name", 276 | "-moz-animation-name", 277 | "-ms-animation-name", 278 | "-o-animation-name", 279 | "animation-name", 280 | "-webkit-animation-duration", 281 | "-moz-animation-duration", 282 | "-ms-animation-duration", 283 | "-o-animation-duration", 284 | "animation-duration", 285 | "-webkit-animation-play-state", 286 | "-moz-animation-play-state", 287 | "-ms-animation-play-state", 288 | "-o-animation-play-state", 289 | "animation-play-state", 290 | "-webkit-animation-timing-function", 291 | "-moz-animation-timing-function", 292 | "-ms-animation-timing-function", 293 | "-o-animation-timing-function", 294 | "animation-timing-function", 295 | "-webkit-animation-delay", 296 | "-moz-animation-delay", 297 | "-ms-animation-delay", 298 | "-o-animation-delay", 299 | "animation-delay", 300 | "-webkit-animation-iteration-count", 301 | "-moz-animation-iteration-count", 302 | "-ms-animation-iteration-count", 303 | "-o-animation-iteration-count", 304 | "animation-iteration-count", 305 | "-webkit-animation-direction", 306 | "-moz-animation-direction", 307 | "-ms-animation-direction", 308 | "-o-animation-direction", 309 | "animation-direction", 310 | "clip", 311 | "zoom" 312 | ] 313 | ] 314 | } 315 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*.js,*.json] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.html] 13 | # すべてのファイルに適用する 14 | charset = utf-8 15 | # 文字コードを統一 16 | indent_style = tab 17 | #インデントを統一する。「tab」か「 space」 18 | indent_size = 2 19 | # インデントの数を統一 20 | trim_trailing_whitespace = true 21 | # 行末のホワイトスペースを削除 22 | insert_final_newline = true 23 | # フォルダの最後の行に改行 24 | end_of_line = lf 25 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb/base" 4 | ], 5 | "env": { 6 | "browser": true 7 | }, 8 | "globals": { 9 | "document": true, 10 | "window": true, 11 | "event": true 12 | }, 13 | "rules":{ 14 | "comma-dangle": 0, 15 | "no-underscore-dangle": 0, 16 | "class-methods-use-this": 0, 17 | "no-param-reassign": 0, 18 | "no-mixed-operators": 0, 19 | "max-len": 0, 20 | "no-continue": 0, 21 | "no-undef": ["error", { "typeof": true }], 22 | "no-restricted-properties": 0 23 | } 24 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | v8.9.4 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 appleple 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 6.9.2 4 | post: 5 | general: 6 | branches: 7 | ignore: 8 | - gh-pages 9 | dependencies: 10 | override: 11 | - "npm install extract-zip@1.6.0" 12 | - "npm install" 13 | test: 14 | override: 15 | - "npm run test" -------------------------------------------------------------------------------- /css/smartphoto.css: -------------------------------------------------------------------------------- 1 | @keyframes smartphoto { 2 | from { 3 | opacity: 0; 4 | } 5 | to { 6 | opacity: 1; 7 | } 8 | } 9 | 10 | @keyframes smartphoto-img-wrap { 11 | from { 12 | opacity: 0; 13 | } 14 | to { 15 | opacity: 1; 16 | } 17 | } 18 | 19 | @keyframes smartphoto-inner { 20 | from { 21 | transform: translate(0, 100px); 22 | } 23 | to { 24 | transform: translate(0, 0); 25 | } 26 | } 27 | 28 | @keyframes smartphoto-loader { 29 | 0% { 30 | opacity: .4; 31 | transform: rotate(0deg); 32 | } 33 | 50% { 34 | opacity: 1; 35 | transform: rotate(180deg); 36 | } 37 | 100% { 38 | opacity: .4; 39 | transform: rotate(360deg); 40 | } 41 | } 42 | 43 | @keyframes smartphoto-appear { 44 | 0% { 45 | display: none; 46 | opacity: 0; 47 | } 48 | 1% { 49 | display: block; 50 | opacity: 0; 51 | } 52 | 100% { 53 | display: block; 54 | opacity: 1; 55 | } 56 | } 57 | 58 | @keyframes smartphoto-hide { 59 | 0% { 60 | display: block; 61 | opacity: 1; 62 | } 63 | 99% { 64 | display: block; 65 | opacity: 0; 66 | } 67 | 100% { 68 | display: none; 69 | opacity: 0; 70 | } 71 | } 72 | 73 | .smartphoto { 74 | position: fixed; 75 | z-index: 100; 76 | top: 0; 77 | left: 0; 78 | width: 100%; 79 | height: 100%; 80 | overflow: hidden; 81 | background-color: black; 82 | opacity: 1; 83 | font-family: sans-serif; 84 | cursor: pointer; 85 | -webkit-transition: opacity 0.3s ease-out; 86 | -moz-transition: opacity 0.3s ease-out; 87 | -ms-transition: opacity 0.3s ease-out; 88 | -o-transition: opacity 0.3s ease-out; 89 | transition: opacity 0.3s ease-out; 90 | transition: all 0.3s ease-out; 91 | animation-name: smartphoto; 92 | animation-duration: 0.3s; 93 | animation-timing-function: ease-out; 94 | } 95 | 96 | .smartphoto[aria-hidden="true"] { 97 | display: none; 98 | } 99 | 100 | .smartphoto-close { 101 | opacity: 0; 102 | } 103 | 104 | .smartphoto-count { 105 | display: inline-block; 106 | color: #FFF; 107 | font-size: 16px; 108 | } 109 | 110 | .smartphoto-header { 111 | display: block; 112 | box-sizing: border-box; 113 | position: fixed; 114 | z-index: 102; 115 | top: 0; 116 | left: 0; 117 | width: 100%; 118 | height: 50px; 119 | padding: 15px; 120 | background-color: rgba(0, 0, 0, 0.2); 121 | } 122 | 123 | .smartphoto-content { 124 | display: block; 125 | position: absolute; 126 | top: 0; 127 | left: 0; 128 | width: 100%; 129 | height: 100%; 130 | } 131 | 132 | .smartphoto-dismiss { 133 | display: block; 134 | position: absolute; 135 | top: 15px; 136 | right: 10px; 137 | width: 20px; 138 | height: 20px; 139 | padding: 0; 140 | border: none; 141 | background-color: transparent; 142 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik0xNTc2LjQyLDE0MDYuNzYsMjc4NCwxOTkuMTlhNTYuODYsNTYuODYsMCwwLDAsMC04MC4xOGwtNzguOTItNzguOTJhNTYuODYsNTYuODYsMCwwLDAtODAuMTgsMEwxNDE3LjMyLDEyNDcuNjYsMjA5Ljc1LDQwLjA5YTU2Ljg2LDU2Ljg2LDAsMCwwLTgwLjE4LDBMNTAuNjUsMTE5YTU2Ljg2LDU2Ljg2LDAsMCwwLDAsODAuMThMMTI1OC4yMywxNDA2Ljc2LDUwLjY1LDI2MTQuMzRhNTYuODYsNTYuODYsMCwwLDAsMCw4MC4xOGw3OC45Miw3OC45MmE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwTDE0MTcuMzIsMTU2NS44NiwyNjI0LjksMjc3My40NGE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwbDc4LjkyLTc4LjkyYTU2Ljg2LDU2Ljg2LDAsMCwwLDAtODAuMThaIi8+PC9zdmc+); 143 | text-shadow: 0 1px 0 #FFF; 144 | color: #FFF; 145 | font-size: 30px; 146 | text-decoration: none; 147 | cursor: pointer; 148 | line-height: 1; 149 | } 150 | 151 | .smartphoto-body { 152 | position: relative; 153 | z-index: 102; 154 | width: 100%; 155 | height: 100%; 156 | margin: 0 auto; 157 | } 158 | 159 | .smartphoto-inner { 160 | position: relative; 161 | width: 100%; 162 | height: 100%; 163 | vertical-align: top; 164 | } 165 | 166 | .smartphoto-img { 167 | display: none; 168 | max-width: none; 169 | width: auto; 170 | height: auto; 171 | cursor: zoom-in; 172 | -webkit-user-select: none; 173 | -moz-user-select: none; 174 | -ms-user-select: none; 175 | user-select: none; 176 | transition: transform 0.3s ease-out; 177 | -webkit-user-drag: none; 178 | } 179 | 180 | .smartphoto-img.active { 181 | display: block; 182 | } 183 | 184 | .smartphoto-img-onmove { 185 | cursor: grab; 186 | cursor: -webkit-grab; 187 | transition: none; 188 | } 189 | 190 | .smartphoto-img-elasticmove { 191 | transition: transform 0.3s ease-out; 192 | } 193 | 194 | .smartphoto-img-wrap { 195 | display: inline-block; 196 | opacity: 1; 197 | -webkit-transition: opacity 0.3s ease-out; 198 | -moz-transition: opacity 0.3s ease-out; 199 | -ms-transition: opacity 0.3s ease-out; 200 | -o-transition: opacity 0.3s ease-out; 201 | transition: opacity 0.3s ease-out; 202 | animation-name: smartphoto-img-wrap; 203 | animation-duration: 0.3s; 204 | animation-timing-function: ease-out; 205 | } 206 | 207 | .smartphoto-img-left { 208 | transform: translateX(150%) !important; 209 | } 210 | 211 | .smartphoto-img-right { 212 | transform: translateX(-150%) !important; 213 | } 214 | 215 | .smartphoto-arrows { 216 | list-style-type: none; 217 | margin: 0; 218 | padding: 0; 219 | position: relative; 220 | z-index: 1002; 221 | top: 50%; 222 | left: 0; 223 | opacity: 1; 224 | animation-name: smartphoto-appear; 225 | animation-duration: 0.3s; 226 | animation-timing-function: ease-out; 227 | } 228 | 229 | .smartphoto-arrows[aria-hidden="true"] { 230 | animation-name: smartphoto-hide; 231 | display: none; 232 | } 233 | 234 | .smartphoto-arrows li { 235 | display: block; 236 | position: absolute; 237 | top: 50%; 238 | width: 30px; 239 | height: 30px; 240 | margin-top: -20px; 241 | box-sizing: content-box; 242 | animation-duration: 0.3s; 243 | animation-timing-function: ease-out; 244 | animation-name: smartphoto-appear; 245 | } 246 | 247 | .smartphoto-arrows li:focus { 248 | outline: none; 249 | } 250 | 251 | .smartphoto-arrows [aria-hidden="true"] { 252 | animation-name: smartphoto-hide; 253 | display: none; 254 | } 255 | 256 | .smartphoto-arrows a { 257 | display: block; 258 | width: 100%; 259 | height: 100%; 260 | text-decoration: none; 261 | } 262 | 263 | .smartphoto-arrow-right { 264 | right: 0; 265 | padding: 5px 0; 266 | background-color: rgba(0, 0, 0, 0.5); 267 | } 268 | 269 | .smartphoto-arrow-right a { 270 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiAiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNMTgzNy44OCwxNDE3LjMyLDY0My41OSwyMjNhNzIuMjEsNzIuMjEsMCwwLDEsMC0xMDEuODJMNzQzLjgyLDIxYTcyLjIxLDcyLjIxLDAsMCwxLDEwMS44MiwwTDIwOTAuODMsMTI2Ni4xOWwxMDAuMjMsMTAwLjIzYTcyLjIxLDcyLjIxLDAsMCwxLDAsMTAxLjgyTDg0NS42NCwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwxLTEwMS44MiwwTDY0My41OSwyNzEzLjQyYTcyLjIxLDcyLjIxLDAsMCwxLDAtMTAxLjgyWiIvPjwvc3ZnPg==); 271 | } 272 | 273 | .smartphoto-arrow-left { 274 | left: 0; 275 | padding: 5px 0; 276 | background-color: rgba(0, 0, 0, 0.5); 277 | } 278 | 279 | .smartphoto-arrow-left a { 280 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik05OTYuNzcsMTQxNy4zMiwyMTkxLjA2LDIyM2E3Mi4yMSw3Mi4yMSwwLDAsMCwwLTEwMS44MkwyMDkwLjgzLDIxQTcyLjIxLDcyLjIxLDAsMCwwLDE5ODksMjFMNzQzLjgyLDEyNjYuMTksNjQzLjU5LDEzNjYuNDJhNzIuMjEsNzIuMjEsMCwwLDAsMCwxMDEuODJMMTk4OSwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwwLDEwMS44MiwwbDEwMC4yMy0xMDAuMjNhNzIuMjEsNzIuMjEsMCwwLDAsMC0xMDEuODJaIi8+PC9zdmc+); 281 | } 282 | 283 | .smartPhotoArrowHideIcon { 284 | display: none; 285 | } 286 | 287 | .smartphoto-nav { 288 | position: absolute; 289 | bottom: 0; 290 | left: 0; 291 | width: 100%; 292 | opacity: 1; 293 | animation-name: smartphoto-appear; 294 | animation-duration: 0.3s; 295 | animation-timing-function: ease-out; 296 | } 297 | 298 | .smartphoto-nav[aria-hidden="true"] { 299 | animation-name: smartphoto-hide; 300 | display: none; 301 | } 302 | 303 | .smartphoto-nav ul { 304 | display: block; 305 | overflow-x: auto; 306 | list-style: none; 307 | margin: 0; 308 | padding: 0; 309 | text-align: center; 310 | white-space: nowrap; 311 | -webkit-overflow-scrolling: touch; 312 | } 313 | 314 | .smartphoto-nav li { 315 | display: inline-block; 316 | overflow: hidden; 317 | width: 50px; 318 | height: 50px; 319 | } 320 | 321 | .smartphoto-nav a { 322 | display: block; 323 | width: 100%; 324 | height: 100%; 325 | background-color: #FFF; 326 | background-position: center center; 327 | background-size: cover; 328 | opacity: .5; 329 | } 330 | 331 | .smartphoto-nav a:focus { 332 | opacity: .8; 333 | } 334 | 335 | .smartphoto-nav a.current { 336 | opacity: 1; 337 | } 338 | 339 | .smartphoto-nav img { 340 | width: auto; 341 | height: 100%; 342 | } 343 | 344 | .smartphoto-list { 345 | list-style-type: none; 346 | position: absolute; 347 | z-index: 101; 348 | top: 0; 349 | left: 0; 350 | margin: 0; 351 | padding: 0; 352 | white-space: nowrap; 353 | } 354 | 355 | .smartphoto-list li { 356 | display: block; 357 | position: absolute; 358 | top: 0; 359 | left: 0; 360 | width: 100%; 361 | height: 100%; 362 | transition: all 0.3s ease-out; 363 | } 364 | 365 | .smartphoto-list li:focus { 366 | outline: none; 367 | } 368 | 369 | .smartphoto-list-onmove { 370 | transition: all 0.3s ease-out; 371 | } 372 | 373 | .smartphoto-caption { 374 | overflow: hidden; 375 | box-sizing: border-box; 376 | position: absolute; 377 | top: 0; 378 | left: 0; 379 | width: 100%; 380 | height: 50px; 381 | padding: 0 50px; 382 | color: #FFF; 383 | font-size: 12px; 384 | text-align: center; 385 | line-height: 50px; 386 | white-space: nowrap; 387 | text-overflow: ellipsis; 388 | } 389 | 390 | .smartphoto-caption:focus { 391 | outline: none; 392 | } 393 | 394 | .smartphoto-loader-wrap { 395 | display: block; 396 | position: relative; 397 | z-index: 103; 398 | width: 0; 399 | height: 0; 400 | transform: translate(50vw, 50vh); 401 | } 402 | 403 | .smartphoto-loader { 404 | position: absolute; 405 | z-index: 101; 406 | top: 0; 407 | left: 0; 408 | width: 30px; 409 | height: 30px; 410 | margin-top: -25px; 411 | margin-left: -25px; 412 | border: 8px solid #17CDDD; 413 | border-right-color: transparent; 414 | border-radius: 50%; 415 | animation: smartphoto-loader .5s infinite linear; 416 | } 417 | 418 | .smartphoto-img-clone { 419 | position: fixed; 420 | z-index: 100; 421 | top: 0; 422 | left: 0; 423 | transition: all 0.3s ease-out; 424 | } 425 | 426 | .smartphoto-sr-only { 427 | overflow: hidden; 428 | position: absolute; 429 | width: 1px; 430 | height: 1px; 431 | margin: -1px; 432 | padding: 0; 433 | border: 0; 434 | clip: rect(0, 0, 0, 0); 435 | } 436 | -------------------------------------------------------------------------------- /css/smartphoto.min.css: -------------------------------------------------------------------------------- 1 | @keyframes smartphoto{from{opacity:0}to{opacity:1}}@keyframes smartphoto-img-wrap{from{opacity:0}to{opacity:1}}@keyframes smartphoto-inner{from{transform:translate(0, 100px)}to{transform:translate(0, 0)}}@keyframes smartphoto-loader{0%{opacity:.4;transform:rotate(0deg)}50%{opacity:1;transform:rotate(180deg)}100%{opacity:.4;transform:rotate(360deg)}}@keyframes smartphoto-appear{0%{display:none;opacity:0}1%{display:block;opacity:0}100%{display:block;opacity:1}}@keyframes smartphoto-hide{0%{display:block;opacity:1}99%{display:block;opacity:0}100%{display:none;opacity:0}}.smartphoto{position:fixed;z-index:100;top:0;left:0;width:100%;height:100%;overflow:hidden;background-color:#000;opacity:1;font-family:sans-serif;cursor:pointer;-webkit-transition:opacity .3s ease-out;-moz-transition:opacity .3s ease-out;-ms-transition:opacity .3s ease-out;-o-transition:opacity .3s ease-out;transition:opacity .3s ease-out;transition:all 0.3s ease-out;animation-name:smartphoto;animation-duration:.3s;animation-timing-function:ease-out}.smartphoto[aria-hidden="true"]{display:none}.smartphoto-close{opacity:0}.smartphoto-count{display:inline-block;color:#FFF;font-size:16px}.smartphoto-header{display:block;box-sizing:border-box;position:fixed;z-index:102;top:0;left:0;width:100%;height:50px;padding:15px;background-color:rgba(0,0,0,0.2)}.smartphoto-content{display:block;position:absolute;top:0;left:0;width:100%;height:100%}.smartphoto-dismiss{display:block;position:absolute;top:15px;right:10px;width:20px;height:20px;padding:0;border:none;background-color:transparent;background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik0xNTc2LjQyLDE0MDYuNzYsMjc4NCwxOTkuMTlhNTYuODYsNTYuODYsMCwwLDAsMC04MC4xOGwtNzguOTItNzguOTJhNTYuODYsNTYuODYsMCwwLDAtODAuMTgsMEwxNDE3LjMyLDEyNDcuNjYsMjA5Ljc1LDQwLjA5YTU2Ljg2LDU2Ljg2LDAsMCwwLTgwLjE4LDBMNTAuNjUsMTE5YTU2Ljg2LDU2Ljg2LDAsMCwwLDAsODAuMThMMTI1OC4yMywxNDA2Ljc2LDUwLjY1LDI2MTQuMzRhNTYuODYsNTYuODYsMCwwLDAsMCw4MC4xOGw3OC45Miw3OC45MmE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwTDE0MTcuMzIsMTU2NS44NiwyNjI0LjksMjc3My40NGE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwbDc4LjkyLTc4LjkyYTU2Ljg2LDU2Ljg2LDAsMCwwLDAtODAuMThaIi8+PC9zdmc+);text-shadow:0 1px 0 #FFF;color:#FFF;font-size:30px;text-decoration:none;cursor:pointer;line-height:1}.smartphoto-body{position:relative;z-index:102;width:100%;height:100%;margin:0 auto}.smartphoto-inner{position:relative;width:100%;height:100%;vertical-align:top}.smartphoto-img{display:none;max-width:none;width:auto;height:auto;cursor:zoom-in;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transition:transform 0.3s ease-out;-webkit-user-drag:none}.smartphoto-img.active{display:block}.smartphoto-img-onmove{cursor:grab;cursor:-webkit-grab;transition:none}.smartphoto-img-elasticmove{transition:transform 0.3s ease-out}.smartphoto-img-wrap{display:inline-block;opacity:1;-webkit-transition:opacity .3s ease-out;-moz-transition:opacity .3s ease-out;-ms-transition:opacity .3s ease-out;-o-transition:opacity .3s ease-out;transition:opacity .3s ease-out;animation-name:smartphoto-img-wrap;animation-duration:.3s;animation-timing-function:ease-out}.smartphoto-img-left{transform:translateX(150%) !important}.smartphoto-img-right{transform:translateX(-150%) !important}.smartphoto-arrows{list-style-type:none;margin:0;padding:0;position:relative;z-index:1002;top:50%;left:0;opacity:1;animation-name:smartphoto-appear;animation-duration:.3s;animation-timing-function:ease-out}.smartphoto-arrows[aria-hidden="true"]{animation-name:smartphoto-hide;display:none}.smartphoto-arrows li{display:block;position:absolute;top:50%;width:30px;height:30px;margin-top:-20px;box-sizing:content-box;animation-duration:.3s;animation-timing-function:ease-out;animation-name:smartphoto-appear}.smartphoto-arrows li:focus{outline:none}.smartphoto-arrows [aria-hidden="true"]{animation-name:smartphoto-hide;display:none}.smartphoto-arrows a{display:block;width:100%;height:100%;text-decoration:none}.smartphoto-arrow-right{right:0;padding:5px 0;background-color:rgba(0,0,0,0.5)}.smartphoto-arrow-right a{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiAiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNMTgzNy44OCwxNDE3LjMyLDY0My41OSwyMjNhNzIuMjEsNzIuMjEsMCwwLDEsMC0xMDEuODJMNzQzLjgyLDIxYTcyLjIxLDcyLjIxLDAsMCwxLDEwMS44MiwwTDIwOTAuODMsMTI2Ni4xOWwxMDAuMjMsMTAwLjIzYTcyLjIxLDcyLjIxLDAsMCwxLDAsMTAxLjgyTDg0NS42NCwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwxLTEwMS44MiwwTDY0My41OSwyNzEzLjQyYTcyLjIxLDcyLjIxLDAsMCwxLDAtMTAxLjgyWiIvPjwvc3ZnPg==)}.smartphoto-arrow-left{left:0;padding:5px 0;background-color:rgba(0,0,0,0.5)}.smartphoto-arrow-left a{background-image:url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik05OTYuNzcsMTQxNy4zMiwyMTkxLjA2LDIyM2E3Mi4yMSw3Mi4yMSwwLDAsMCwwLTEwMS44MkwyMDkwLjgzLDIxQTcyLjIxLDcyLjIxLDAsMCwwLDE5ODksMjFMNzQzLjgyLDEyNjYuMTksNjQzLjU5LDEzNjYuNDJhNzIuMjEsNzIuMjEsMCwwLDAsMCwxMDEuODJMMTk4OSwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwwLDEwMS44MiwwbDEwMC4yMy0xMDAuMjNhNzIuMjEsNzIuMjEsMCwwLDAsMC0xMDEuODJaIi8+PC9zdmc+)}.smartPhotoArrowHideIcon{display:none}.smartphoto-nav{position:absolute;bottom:0;left:0;width:100%;opacity:1;animation-name:smartphoto-appear;animation-duration:.3s;animation-timing-function:ease-out}.smartphoto-nav[aria-hidden="true"]{animation-name:smartphoto-hide;display:none}.smartphoto-nav ul{display:block;overflow-x:auto;list-style:none;margin:0;padding:0;text-align:center;white-space:nowrap;-webkit-overflow-scrolling:touch}.smartphoto-nav li{display:inline-block;overflow:hidden;width:50px;height:50px}.smartphoto-nav a{display:block;width:100%;height:100%;background-color:#FFF;background-position:center center;background-size:cover;opacity:.5}.smartphoto-nav a:focus{opacity:.8}.smartphoto-nav a.current{opacity:1}.smartphoto-nav img{width:auto;height:100%}.smartphoto-list{list-style-type:none;position:absolute;z-index:101;top:0;left:0;margin:0;padding:0;white-space:nowrap}.smartphoto-list li{display:block;position:absolute;top:0;left:0;width:100%;height:100%;transition:all 0.3s ease-out}.smartphoto-list li:focus{outline:none}.smartphoto-list-onmove{transition:all 0.3s ease-out}.smartphoto-caption{overflow:hidden;box-sizing:border-box;position:absolute;top:0;left:0;width:100%;height:50px;padding:0 50px;color:#FFF;font-size:12px;text-align:center;line-height:50px;white-space:nowrap;text-overflow:ellipsis}.smartphoto-caption:focus{outline:none}.smartphoto-loader-wrap{display:block;position:relative;z-index:103;width:0;height:0;transform:translate(50vw, 50vh)}.smartphoto-loader{position:absolute;z-index:101;top:0;left:0;width:30px;height:30px;margin-top:-25px;margin-left:-25px;border:8px solid #17CDDD;border-right-color:transparent;border-radius:50%;animation:smartphoto-loader .5s infinite linear}.smartphoto-img-clone{position:fixed;z-index:100;top:0;left:0;transition:all .3s ease-out}.smartphoto-sr-only{overflow:hidden;position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;clip:rect(0, 0, 0, 0)} 2 | -------------------------------------------------------------------------------- /examples/assets/bear.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/bear.jpg -------------------------------------------------------------------------------- /examples/assets/camel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/camel.jpg -------------------------------------------------------------------------------- /examples/assets/castle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/castle.jpg -------------------------------------------------------------------------------- /examples/assets/hippo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/hippo.jpg -------------------------------------------------------------------------------- /examples/assets/koala.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/koala.jpg -------------------------------------------------------------------------------- /examples/assets/large-bear.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-bear.jpg -------------------------------------------------------------------------------- /examples/assets/large-camel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-camel.jpg -------------------------------------------------------------------------------- /examples/assets/large-hippo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-hippo.jpg -------------------------------------------------------------------------------- /examples/assets/large-koala.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-koala.jpg -------------------------------------------------------------------------------- /examples/assets/large-lion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-lion.jpg -------------------------------------------------------------------------------- /examples/assets/large-rhino.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/large-rhino.jpg -------------------------------------------------------------------------------- /examples/assets/lion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/lion.jpg -------------------------------------------------------------------------------- /examples/assets/rhino.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/rhino.jpg -------------------------------------------------------------------------------- /examples/assets/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/sample.png -------------------------------------------------------------------------------- /examples/assets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, Helvetica, sans-serif; 3 | background-color: #eee; 4 | } 5 | .title { 6 | text-align: center; 7 | font-weight: bold; 8 | font-size: 48px; 9 | color: #333; 10 | } 11 | .wrapper{ 12 | max-width: 940px; 13 | margin: 0 auto; 14 | } 15 | .masonry { 16 | -moz-transition: all .5s ease-in-out; 17 | -webkit-transition: all .5s ease-in-out; 18 | transition: all .5s ease-in-out; 19 | -moz-column-gap: 30px; 20 | -webkit-column-gap: 30px; 21 | column-gap: 30px; 22 | -moz-column-fill: initial; 23 | -webkit-column-fill: initial; 24 | column-fill: initial; 25 | } 26 | .masonry .brick { 27 | margin-bottom: 30px; 28 | overflow: hidden; 29 | } 30 | .masonry .brick img { 31 | -moz-transition: all .5s ease-in-out; 32 | -webkit-transition: all .5s ease-in-out; 33 | transition: all .5s ease-in-out; 34 | } 35 | .masonry .brick:hover img { 36 | opacity: .75; 37 | } 38 | .masonry.bordered { 39 | -moz-column-rule: 1px solid #eee; 40 | -webkit-column-rule: 1px solid #eee; 41 | column-rule: 1px solid #eee; 42 | -moz-column-gap: 50px; 43 | -webkit-column-gap: 50px; 44 | column-gap: 50px; 45 | } 46 | .masonry.bordered .brick { 47 | padding-bottom: 25px; 48 | margin-bottom: 25px; 49 | border-bottom: 1px solid #eee; 50 | } 51 | .masonry.gutterless { 52 | -moz-column-gap: 0; 53 | -webkit-column-gap: 0; 54 | column-gap: 0; 55 | } 56 | .masonry.gutterless .brick { 57 | margin-bottom: 0; 58 | } 59 | 60 | .span { 61 | -moz-column-span: all; 62 | -webkit-column-span: all; 63 | column-span: all; 64 | *margin: 30px 0; 65 | } 66 | 67 | @media only screen and (min-width: 1024px) { 68 | .desc { 69 | font-size: 1.25em; 70 | } 71 | 72 | .intro { 73 | letter-spacing: 1px; 74 | } 75 | 76 | .wrapper { 77 | width: 80%; 78 | padding: 2em; 79 | } 80 | 81 | .masonry { 82 | -moz-column-count: 3; 83 | -webkit-column-count: 3; 84 | column-count: 3; 85 | } 86 | } 87 | @media only screen and (min-width: 768px) and (max-width: 1023px) { 88 | .wrapper { 89 | width: 85%; 90 | padding: 1.5em; 91 | } 92 | 93 | .masonry { 94 | -moz-column-count: 2; 95 | -webkit-column-count: 2; 96 | column-count: 2; 97 | } 98 | } -------------------------------------------------------------------------------- /examples/assets/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/examples/assets/test.png -------------------------------------------------------------------------------- /examples/event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SmartPhoto.js 9 | 10 | 11 | 12 |
13 |

SmartPhoto.js

14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /examples/jquery.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | jquery-smartphoto.js 10 | 11 | 12 |
13 |

jquery-smartphoto.js

14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 |
45 |
46 | 47 | 48 | 49 |
50 |
51 | 52 | 53 | 54 |
55 |
56 | 57 | 58 | 59 |
60 |
61 | 62 | 63 | 64 |
65 |
66 |
67 | 68 | 69 | 73 | 74 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /examples/lazy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | jquery-smartphoto.js 9 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |
28 |
29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 | 37 |
38 |
39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 |
53 |
54 | 55 | 56 | 57 |
58 |
59 | 60 | 61 | 62 |
63 |
64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /examples/multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SmartPhoto.js 10 | 11 | 12 |
13 |

SmartPhoto.js

14 |

resizeStyle = Fill

15 |
16 |
17 | 18 | 19 | 20 |
21 |
22 | 23 | 24 | 25 |
26 |
27 | 28 | 29 | 30 |
31 |
32 | 33 | 34 | 35 |
36 |
37 | 38 | 39 | 40 |
41 |
42 | 43 | 44 | 45 |
46 |
47 |

resizeStyle = Fit

48 |
49 |
50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 |
59 |
60 | 61 | 62 | 63 |
64 |
65 | 66 | 67 | 68 |
69 |
70 | 71 | 72 | 73 |
74 |
75 | 76 | 77 | 78 |
79 |
80 |
81 | 82 | 83 | 84 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /examples/noimage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SmartPhoto.js 9 | 10 | 11 | 12 |
13 |

SmartPhoto.js

14 |
15 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /examples/resizeFit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SmartPhoto.js 10 | 11 | 12 |
13 |

SmartPhoto.js

14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /examples/vanilla.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | SmartPhoto.js 9 | 10 | 11 | 12 |
13 |

SmartPhoto.js

14 |
15 |
16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 |
30 |
31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 |
41 | 42 | 43 | 44 |
45 |
46 |
47 | 48 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /images/icon_arrow_next.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /images/icon_arrow_prev.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /images/icon_close.svg: -------------------------------------------------------------------------------- 1 | icon -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare module "smartphoto" { 2 | 3 | type SmartPhotoEvent = 'open'|'close'|'change'|'swipestart'|'swipeend'|'zoomin'|'zoomout'|'gesturestart'|'gestureend'; 4 | 5 | interface SmartPhotoOption { 6 | classNames?: { 7 | smartPhoto: string, 8 | smartPhotoClose: string, 9 | smartPhotoBody: string, 10 | smartPhotoInner: string, 11 | smartPhotoContent: string, 12 | smartPhotoImg: string, 13 | smartPhotoImgOnMove: string, 14 | smartPhotoImgElasticMove: string, 15 | smartPhotoImgWrap: string, 16 | smartPhotoArrows: string, 17 | smartPhotoNav: string, 18 | smartPhotoArrowRight: string, 19 | smartPhotoArrowLeft: string, 20 | smartPhotoImgLeft: string, 21 | smartPhotoImgRight: string, 22 | smartPhotoList: string, 23 | smartPhotoListOnMove: string, 24 | smartPhotoHeader: string, 25 | smartPhotoCount: string, 26 | smartPhotoCaption: string, 27 | smartPhotoDismiss: string, 28 | smartPhotoLoader: string, 29 | smartPhotoLoaderWrap: string, 30 | smartPhotoImgClone: string 31 | }, 32 | message?: { 33 | gotoNextImage: string, 34 | gotoPrevImage: string, 35 | closeDialog: string 36 | }, 37 | arrows?: boolean, 38 | nav?: boolean, 39 | showAnimation?: boolean, 40 | verticalGravity?: boolean, 41 | useOrientationApi?: boolean, 42 | useHistoryApi?: boolean, 43 | swipeTopToClose?: boolean, 44 | swipeBottomToClose?: boolean, 45 | swipeOffset?: number, 46 | headerHeight?: number, 47 | footerHeight?: number, 48 | forceInterval?: number, 49 | registance?: number, 50 | loadOffset?: number, 51 | resizeStyle?: 'fit'|'cover', 52 | } 53 | 54 | export default class SmartPhoto { 55 | constructor(selector: string | NodeListOf, option?:SmartPhotoOption); 56 | on(event: SmartPhotoEvent, eventListener: EventListenerOrEventListenerObject) :void; 57 | destroy(): void; 58 | addNewItem(element: HTMLElement): void; 59 | hidePhoto(dir: 'bottom'|'top'): void; 60 | gotoSlide(index: number): void; 61 | zoomPhoto(): void; 62 | zoomOutPhoto(): void; 63 | } 64 | } -------------------------------------------------------------------------------- /js/smartphoto.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Modules in this bundle 3 | * @license 4 | * 5 | * smartphoto: 6 | * license: MIT (http://opensource.org/licenses/MIT) 7 | * author: appleple 8 | * homepage: http://developer.a-blogcms.jp 9 | * version: 1.6.4 10 | * 11 | * a-template: 12 | * license: MIT (http://opensource.org/licenses/MIT) 13 | * author: steelydylan 14 | * version: 0.6.1 15 | * 16 | * custom-event-polyfill: 17 | * license: MIT (http://opensource.org/licenses/MIT) 18 | * contributors: Frank Panetta, Mikhail Reenko , Joscha Feth 19 | * homepage: https://github.com/krambuhl/custom-event-polyfill#readme 20 | * version: 0.3.0 21 | * 22 | * es6-promise-polyfill: 23 | * license: MIT (http://opensource.org/licenses/MIT) 24 | * author: Roman Dvornov 25 | * homepage: https://github.com/lahmatiy/es6-promise-polyfill#readme 26 | * version: 1.2.0 27 | * 28 | * ie-array-find-polyfill: 29 | * license: MIT (http://opensource.org/licenses/MIT) 30 | * author: Carlos Abdalla 31 | * homepage: https://github.com/abdalla/ie-array-find-polyfill#readme 32 | * version: 1.1.0 33 | * 34 | * morphdom: 35 | * license: MIT (http://opensource.org/licenses/MIT) 36 | * author: Patrick Steele-Idem 37 | * homepage: https://github.com/patrick-steele-idem/morphdom#readme 38 | * version: 2.5.12 39 | * 40 | * process: 41 | * license: MIT (http://opensource.org/licenses/MIT) 42 | * author: Roman Shtylman 43 | * homepage: https://github.com/shtylman/node-process#readme 44 | * version: 0.11.10 45 | * 46 | * timers-browserify: 47 | * licenses: MIT (http://opensource.org/licenses/MIT) 48 | * author: J. Ryan Stinnett 49 | * contributors: Guy Bedford , Ionut-Cristian Florescu , James Halliday , Jan Schär , Johannes Ewald , Jonathan Prins , Matt Esch 50 | * homepage: https://github.com/jryans/timers-browserify 51 | * version: 1.4.2 52 | * 53 | * This header is generated by licensify (https://github.com/twada/licensify) 54 | */ 55 | !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.SmartPhoto=t()}}(function(){var t;return function(){function t(e,a,o){function n(r,s){if(!a[r]){if(!e[r]){var c="function"==typeof require&&require;if(!s&&c)return c(r,!0);if(i)return i(r,!0);var d=new Error("Cannot find module '"+r+"'");throw d.code="MODULE_NOT_FOUND",d}var u=a[r]={exports:{}};e[r][0].call(u.exports,function(t){return n(e[r][1][t]||t)},u,u.exports,t,e,a,o)}return a[r].exports}for(var i="function"==typeof require&&require,r=0;r1;)a=a[o.shift()];a[o.shift()]=e}},{key:"removeDataByString",value:function(t){for(var e=this.data,a=t.split(".");a.length>1;)e=e[a.shift()];var o=a.shift();o.match(/^\d+$/)?e.splice(Number(o),1):delete e[o]}},{key:"resolveBlock",value:function(t,e,a){var o=this,n=t.match(//g),i=t.match(//g),r=t.match(//g),s=t.match(//g);if(n)for(var c=0,d=n.length;c/g;return t=t.replace(e,function(t,e){return(0,c.selector)("#"+e).innerHTML})}},{key:"resolveWith",value:function(t){var e=/(([\n\r\t]|.)*?)/g;return t=t.replace(e,function(t,e){return t=t.replace(/data\-bind=['"](.*?)['"]/g,"data-bind='"+e+".$1'")})}},{key:"resolveLoop",value:function(t){var e=/(([\n\r\t]|.)*?)/g,a=this;return t=t.replace(e,function(t,e,o){var n=a.getDataByString(e),i=[];i="function"==typeof n?n.apply(a):n;var r="";if(i instanceof Array)for(var s=0,c=i.length;s(([\n\r\t]|.)*?)/g;return!!t.match(e)}},{key:"getHtml",value:function(t,e){var a=this.atemplate.find(function(e){return e.id===t}),o="";if(a&&a.html&&(o=a.html),e&&(o=t),!o)return"";var n=this.data;for(o=this.resolveInclude(o),o=this.resolveWith(o);this.hasLoop(o);)o=this.resolveLoop(o);return o=this.resolveBlock(o,n),o=o.replace(/\\([^\\])/g,"$1"),o=this.resolveAbsBlock(o),o.replace(/^([\t ])*\n/gm,"")}},{key:"update",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"html",a=arguments[1],o=this.templates;this.beforeUpdated&&this.beforeUpdated();for(var n=0,i=o.length;n"+u+"");else(0,c.selector)(d).insertAdjacentHTML("afterend",'
'),"text"===e?(0,c.selector)("[data-id='"+r+"']").innerText=u:(0,c.selector)("[data-id='"+r+"']").innerHTML=u;var p=t.atemplate.find(function(t){return t.id===r});p.binded||(p.binded=!0,t.addDataBind((0,c.selector)("[data-id='"+r+"']")),t.addActionBind((0,c.selector)("[data-id='"+r+"']")))}(n);return this.updateBindingData(a),this.onUpdated&&this.onUpdated(a),this}},{key:"updateBindingData",value:function(t){for(var e=this,a=this.templates,o=0,n=a.length;o1?a-1:0),n=1;n1;)e=e[a.shift()];var o=a.shift();return o.match(/^\d+$/)?e.splice(Number(o),1):delete e[o],this}}]),t}();a.default=h,e.exports=a.default},{"./util":2,"ie-array-find-polyfill":5,morphdom:6}],2:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var o=a.matches=function(t,e){for(var a=(t.document||t.ownerDocument).querySelectorAll(e),o=a.length;--o>=0&&a.item(o)!==t;);return o>-1},n=(a.selector=function(t){return document.querySelector(t)},a.findAncestor=function(t,e){if("function"==typeof t.closest)return t.closest(e)||null;for(;t&&t!==document;){if(o(t,e))return t;t=t.parentElement}return null}),i=[];a.on=function(t,e,a,o){var r=arguments.length>4&&void 0!==arguments[4]&&arguments[4];a.split(" ").forEach(function(a){var s=function(t){var a=n(t.target,e);a&&(t.delegateTarget=a,o(t))};i.push({listener:s,element:t,query:e,event:a,capture:r}),t.addEventListener(a,s,r)})},a.off=function(t,e,a){a.split(" ").forEach(function(a){i.forEach(function(o,n){o.element===t&&o.query===e&&o.event===a&&(t.removeEventListener(a,o.listener,o.capture),i.splice(n,1))})})}},{}],3:[function(t,e,a){try{var o=new window.CustomEvent("test");if(o.preventDefault(),!0!==o.defaultPrevented)throw new Error("Could not prevent default")}catch(t){var n=function(t,e){var a,o;return e=e||{bubbles:!1,cancelable:!1,detail:void 0},a=document.createEvent("CustomEvent"),a.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),o=a.preventDefault,a.preventDefault=function(){o.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(t){this.defaultPrevented=!0}},a};n.prototype=window.Event.prototype,window.CustomEvent=n}},{}],4:[function(e,a,o){(function(e,a){!function(e){function n(t){return"[object Array]"===Object.prototype.toString.call(t)}function i(){for(var t=0;t>>0;if("function"!=typeof t)throw new TypeError("predicate must be a function");for(var o=arguments[1],n=0;n=0;s--)a=r[s],o=a.name,n=a.namespaceURI,i=a.value,n?(o=a.localName||o,t.getAttributeNS(n,o)!==i&&("xmlns"===a.prefix&&(o=a.name),t.setAttributeNS(n,o,i))):t.getAttribute(o)!==i&&t.setAttribute(o,i);for(var c=t.attributes,d=c.length-1;d>=0;d--)a=c[d],o=a.name,n=a.namespaceURI,n?(o=a.localName||o,e.hasAttributeNS(n,o)||t.removeAttributeNS(n,o)):e.hasAttribute(o)||t.removeAttribute(o)}}function n(t){var e=g.createElement("template");return e.innerHTML=t,e.content.childNodes[0]}function i(t){return p||(p=g.createRange(),p.selectNode(g.body)),p.createContextualFragment(t).childNodes[0]}function r(t){var e=g.createElement("body");return e.innerHTML=t,e.childNodes[0]}function s(t){return t=t.trim(),y?n(t):x?i(t):r(t)}function c(t,e){var a=t.nodeName,o=e.nodeName;return a===o||!!(e.actualize&&a.charCodeAt(0)<91&&o.charCodeAt(0)>90)&&a===o.toUpperCase()}function d(t,e){return e&&e!==v?g.createElementNS(e,t):g.createElement(t)}function u(t,e){for(var a=t.firstChild;a;){var o=a.nextSibling;e.appendChild(a),a=o}return e}function l(t,e,a){t[a]!==e[a]&&(t[a]=e[a],t[a]?t.setAttribute(a,""):t.removeAttribute(a))}function h(){}function f(t){if(t)return t.getAttribute&&t.getAttribute("id")||t.id}var p,m=11,v="http://www.w3.org/1999/xhtml",g="undefined"==typeof document?void 0:document,y=!!g&&"content"in g.createElement("template"),x=!!g&&g.createRange&&"createContextualFragment"in g.createRange(),w={OPTION:function(t,e){var a=t.parentNode;if(a){var o=a.nodeName.toUpperCase();"OPTGROUP"===o&&(a=a.parentNode,o=a&&a.nodeName.toUpperCase()),"SELECT"!==o||a.hasAttribute("multiple")||(t.hasAttribute("selected")&&!e.selected&&(t.setAttribute("selected","selected"),t.removeAttribute("selected")),a.selectedIndex=-1)}l(t,e,"selected")},INPUT:function(t,e){l(t,e,"checked"),l(t,e,"disabled"),t.value!==e.value&&(t.value=e.value),e.hasAttribute("value")||t.removeAttribute("value")},TEXTAREA:function(t,e){var a=e.value;t.value!==a&&(t.value=a);var o=t.firstChild;if(o){var n=o.nodeValue;if(n==a||!a&&n==t.placeholder)return;o.nodeValue=a}},SELECT:function(t,e){if(!e.hasAttribute("multiple")){for(var a,o,n=-1,i=0,r=t.firstChild;r;)if("OPTGROUP"===(o=r.nodeName&&r.nodeName.toUpperCase()))a=r,r=a.firstChild;else{if("OPTION"===o){if(r.hasAttribute("selected")){n=i;break}i++}r=r.nextSibling,!r&&a&&(r=a.nextSibling,a=null)}t.selectedIndex=n}}},P=1,E=11,b=3,_=8,I=function(t){return function(e,a,o){function n(t){G.push(t)}function i(t,e){if(t.nodeType===P)for(var a=t.firstChild;a;){var o=void 0;e&&(o=I(a))?n(o):(T(a),a.firstChild&&i(a,e)),a=a.nextSibling}}function r(t,e,a){!1!==B(t)&&(e&&e.removeChild(t),T(t),i(t,a))}function l(t){if(t.nodeType===P||t.nodeType===E)for(var e=t.firstChild;e;){var a=I(e);a&&(C[a]=e),l(e),e=e.nextSibling}}function p(t){S(t);for(var e=t.firstChild;e;){var a=e.nextSibling,o=I(e);if(o){var n=C[o];n&&c(e,n)&&(e.parentNode.replaceChild(n,e),v(n,e))}p(e),e=a}}function m(t,e,a){for(;e;){var o=e.nextSibling;(a=I(e))?n(a):r(e,t,!0),e=o}}function v(e,a,o){var n=I(a);if(n&&delete C[n],!o){if(!1===k(e,a))return;if(t(e,a),A(e),!1===D(e,a))return}"TEXTAREA"!==e.nodeName?y(e,a):w.TEXTAREA(e,a)}function y(t,e){var a,o,i,s,d,u=e.firstChild,l=t.firstChild;t:for(;u;){for(s=u.nextSibling,a=I(u);l;){if(i=l.nextSibling,u.isSameNode&&u.isSameNode(l)){u=s,l=i;continue t}o=I(l);var h=l.nodeType,f=void 0;if(h===u.nodeType&&(h===P?(a?a!==o&&((d=C[a])?i===d?f=!1:(t.insertBefore(d,l),o?n(o):r(l,t,!0),l=d):f=!1):o&&(f=!1),(f=!1!==f&&c(l,u))&&v(l,u)):h!==b&&h!=_||(f=!0,l.nodeValue!==u.nodeValue&&(l.nodeValue=u.nodeValue))),f){u=s,l=i;continue t}o?n(o):r(l,t,!0),l=i}if(a&&(d=C[a])&&c(d,u))t.appendChild(d),v(d,u);else{var y=N(u);!1!==y&&(y&&(u=y),u.actualize&&(u=u.actualize(t.ownerDocument||g)),t.appendChild(u),p(u))}u=s,l=i}m(t,l,o);var x=w[t.nodeName];x&&x(t,e)}if(o||(o={}),"string"==typeof a)if("#document"===e.nodeName||"HTML"===e.nodeName){var x=a;a=g.createElement("html"),a.innerHTML=x}else a=s(a);var I=o.getNodeKey||f,N=o.onBeforeNodeAdded||h,S=o.onNodeAdded||h,k=o.onBeforeElUpdated||h,A=o.onElUpdated||h,B=o.onBeforeNodeDiscarded||h,T=o.onNodeDiscarded||h,D=o.onBeforeElChildrenUpdated||h,O=!0===o.childrenOnly,C=Object.create(null),G=[];l(e);var L=e,z=L.nodeType,X=a.nodeType;if(!O)if(z===P)X===P?c(e,a)||(T(e),L=u(e,d(a.nodeName,a.namespaceURI))):L=a;else if(z===b||z===_){if(X===z)return L.nodeValue!==a.nodeValue&&(L.nodeValue=a.nodeValue),L;L=a}if(L===a)T(e);else{if(a.isSameNode&&a.isSameNode(L))return;if(v(L,a,O),G)for(var M=0,Y=G.length;M1)for(var a=1;a=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},a.setImmediate="function"==typeof e?e:function(t){var e=d++,o=!(arguments.length<2)&&s.call(arguments,1);return c[e]=!0,i(function(){c[e]&&(o?t.apply(null,o):t.call(null),a.clearImmediate(e))}),e},a.clearImmediate="function"==typeof o?o:function(t){delete c[t]}}).call(this,t("timers").setImmediate,t("timers").clearImmediate)},{"process/browser.js":7,timers:8}],9:[function(t,e,a){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var a=0;ago to {caption}\n\t\t\t\t\t\t\x3c!-- END groupItems:loop --\x3e\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\x3c!-- END nav:exist --\x3e\n\t\t\n\t\t\x3c!-- BEGIN appearEffect:exist --\x3e\n\t\t\n\t\t\x3c!-- END appearEffect:exist --\x3e\n\t\n\n',p=t("../lib/util"),m=t("es6-promise-polyfill"),v=m.Promise,g={classNames:{smartPhoto:"smartphoto",smartPhotoClose:"smartphoto-close",smartPhotoBody:"smartphoto-body",smartPhotoInner:"smartphoto-inner",smartPhotoContent:"smartphoto-content",smartPhotoImg:"smartphoto-img",smartPhotoImgOnMove:"smartphoto-img-onmove",smartPhotoImgElasticMove:"smartphoto-img-elasticmove",smartPhotoImgWrap:"smartphoto-img-wrap",smartPhotoArrows:"smartphoto-arrows",smartPhotoNav:"smartphoto-nav",smartPhotoArrowRight:"smartphoto-arrow-right",smartPhotoArrowLeft:"smartphoto-arrow-left",smartPhotoArrowHideIcon:"smartphoto-arrow-hide",smartPhotoImgLeft:"smartphoto-img-left",smartPhotoImgRight:"smartphoto-img-right",smartPhotoList:"smartphoto-list",smartPhotoListOnMove:"smartphoto-list-onmove",smartPhotoHeader:"smartphoto-header",smartPhotoCount:"smartphoto-count",smartPhotoCaption:"smartphoto-caption",smartPhotoDismiss:"smartphoto-dismiss",smartPhotoLoader:"smartphoto-loader",smartPhotoLoaderWrap:"smartphoto-loader-wrap",smartPhotoImgClone:"smartphoto-img-clone"},message:{gotoNextImage:"go to the next image",gotoPrevImage:"go to the previous image",closeDialog:"close the image dialog"},arrows:!0,nav:!0,showAnimation:!0,verticalGravity:!1,useOrientationApi:!1,useHistoryApi:!0,swipeTopToClose:!1,swipeBottomToClose:!0,swipeOffset:100,headerHeight:60,footerHeight:60,forceInterval:10,registance:.5,loadOffset:2,resizeStyle:"fit",lazyAttribute:"data-src"},y=function(t){function e(t,a){var o;n(this,e),o=s(this,d(e).call(this)),o.data=p.extend({},g,a),o.data.currentIndex=0,o.data.oldIndex=0,o.data.hide=!0,o.data.group={},o.data.scaleSize=1,o.data.scale=!1,o.pos={x:0,y:0},o.data.photoPosX=0,o.data.photoPosY=0,o.handlers=[],o.convert={increment:o.increment,virtualPos:o.virtualPos,round:o.round},o.data.groupItems=o.groupItems,o.elements="string"==typeof t?document.querySelectorAll(t):t;var i=new Date;o.tapSecond=i.getTime(),o.onListMove=!1,o.clicked=!1,o.id=o._getUniqId(),o.vx=0,o.vy=0,o.data.appearEffect=null,o.addTemplate(o.id,f),o.data.isSmartPhone=o._isSmartPhone();var r=document.querySelector("body");p.append(r,"
")),[].forEach.call(o.elements,function(t){o.addNewItem(t)}),o.update();var c=o._getCurrentItemByHash();if(c&&p.triggerEvent(c.element,"click"), 56 | o.interval=setInterval(function(){o._doAnim()},o.data.forceInterval),!o.data.isSmartPhone){var u=function(){o.groupItems()&&(o._resetTranslate(),o._setPosByCurrentIndex(),o._setSizeByScreen(),o.update())},l=function(t){var e=t.keyCode||t.which;!0!==o.data.hide&&(37===e?o.gotoSlide(o.data.prev):39===e?o.gotoSlide(o.data.next):27===e&&o.hidePhoto())};return window.addEventListener("resize",u),window.addEventListener("keydown",l),o._registerRemoveEvent(window,"resize",u),o._registerRemoveEvent(window,"keydown",l),s(o)}var h=function(){if(o.groupItems()){o._resetTranslate(),o._setPosByCurrentIndex(),o._setHashByCurrentIndex(),o._setSizeByScreen(),o.update();var t=o._getWindowWidth();!function e(a){new v(function(t){setTimeout(function(){t()},25)}).then(function(){t!==o._getWindowWidth()?(o._resetTranslate(),o._setPosByCurrentIndex(),o._setHashByCurrentIndex(),o._setSizeByScreen(),o.update()):a<=500&&e(a+25)})}(0)}};if(window.addEventListener("orientationchange",h),o._registerRemoveEvent(window,"orientationchange",h),!o.data.useOrientationApi)return s(o);var m=function(t){var e=window,a=e.orientation;t&&t.gamma&&!o.data.appearEffect&&(o.isBeingZoomed||o.photoSwipable||o.data.elastic||!o.data.scale||(0===a?o._calcGravity(t.gamma,t.beta):90===a?o._calcGravity(t.beta,t.gamma):-90===a?o._calcGravity(-t.beta,-t.gamma):180===a&&o._calcGravity(-t.gamma,-t.beta)))};return window.addEventListener("deviceorientation",m),o._registerRemoveEvent(window,"deviceorientation",m),o}return u(e,t),r(e,[{key:"on",value:function(t,e){var a=this._getElementByClass(this.data.classNames.smartPhoto),o=function(t){e.call(a,t)};a.addEventListener(t,o),this._registerRemoveEvent(a,t,o)}},{key:"_registerRemoveEvent",value:function(t,e,a){this.handlers.push({target:t,event:e,handler:a})}},{key:"destroy",value:function(){this.handlers.forEach(function(t){t.target.removeEventListener(t.event,t.handler)});var t=document.querySelector('[data-id="'.concat(this.id,'"]'));p.removeElement(t),clearInterval(this.interval),this.removeTemplateEvents()}},{key:"increment",value:function(t){return t+1}},{key:"round",value:function(t){return Math.round(t)}},{key:"virtualPos",value:function(t){return(t=parseInt(t,10))/this._getSelectedItem().scale/this.data.scaleSize}},{key:"groupItems",value:function(){return this.data.group[this.data.currentGroup]}},{key:"_resetTranslate",value:function(){var t=this;this.groupItems().forEach(function(e,a){e.translateX=t._getWindowWidth()*a})}},{key:"addNewItem",value:function(t){var e=this,a=t.getAttribute("data-group")||"nogroup",o=this.data.group;"nogroup"===a&&t.setAttribute("data-group","nogroup"),o[a]||(o[a]=[]);var n=o[a].length,i=document.querySelector("body"),r=t.getAttribute("href"),s=t.querySelector("img"),c=r;s&&(c=s.getAttribute(this.data.lazyAttribute)?s.getAttribute(this.data.lazyAttribute):s.currentSrc?s.currentSrc:s.src);var d={src:r,thumb:c,caption:t.getAttribute("data-caption"),groupId:a,translateX:this._getWindowWidth()*n,index:n,translateY:0,width:50,height:50,id:t.getAttribute("data-id")||n,loaded:!1,processed:!1,element:t};o[a].push(d),this.data.currentGroup=a,t.getAttribute("data-id")||t.setAttribute("data-id",n),t.setAttribute("data-index",n);var u=function(a){a.preventDefault(),e.data.currentGroup=t.getAttribute("data-group"),e.data.currentIndex=parseInt(t.getAttribute("data-index"),10),e._setHashByCurrentIndex();var o=e._getSelectedItem();o.loaded?(e._initPhoto(),e.addAppearEffect(t,o),e.clicked=!0,e.update(),i.style.overflow="hidden",e._fireEvent("open")):e._loadItem(o).then(function(){e._initPhoto(),e.addAppearEffect(t,o),e.clicked=!0,e.update(),i.style.overflow="hidden",e._fireEvent("open")})};t.addEventListener("click",u),this._registerRemoveEvent(t,"click",u)}},{key:"_initPhoto",value:function(){this.data.total=this.groupItems().length,this.data.hide=!1,this.data.photoPosX=0,this.data.photoPosY=0,this._setPosByCurrentIndex(),this._setSizeByScreen(),this.setArrow(),"fill"===this.data.resizeStyle&&this.data.isSmartPhone&&(this.data.scale=!0,this.data.hideUi=!0,this.data.scaleSize=this._getScaleBoarder())}},{key:"onUpdated",value:function(){var t=this;if(this.data.appearEffect&&this.data.appearEffect.once&&(this.data.appearEffect.once=!1,this.execEffect().then(function(){t.data.appearEffect=null,t.data.appear=!0,t.update()})),this.clicked){this.clicked=!1;var e=this.data.classNames;this._getElementByClass(e.smartPhotoCaption).focus()}}},{key:"execEffect",value:function(){var t=this;return new v(function(e){p.isOldIE()&&e();var a=t.data,o=a.appearEffect,n=a.classNames,i=t._getElementByClass(n.smartPhotoImgClone),r=function t(){i.removeEventListener("transitionend",t,!0),e()};i.addEventListener("transitionend",r,!0),setTimeout(function(){i.style.transform="translate(".concat(o.afterX,"px, ").concat(o.afterY,"px) scale(").concat(o.scale,")")},10)})}},{key:"addAppearEffect",value:function(t,e){if(!1===this.data.showAnimation)return void(this.data.appear=!0);var a=t.querySelector("img"),o=p.getViewPos(a),n={},i=1;n.width=a.offsetWidth,n.height=a.offsetHeight,n.top=o.top,n.left=o.left,n.once=!0,a.getAttribute(this.data.lazyAttribute)?n.img=a.getAttribute(this.data.lazyAttribute):n.img=e.src;var r=this._getWindowWidth(),s=this._getWindowHeight(),c=s-this.data.headerHeight-this.data.footerHeight;"fill"===this.data.resizeStyle&&this.data.isSmartPhone?i=a.offsetWidth>a.offsetHeight?s/a.offsetHeight:r/a.offsetWidth:(n.width>=n.height?i=e.heightn.width&&(i=e.heightr&&(i=r/n.width));var d=(i-1)/2*a.offsetWidth+(r-a.offsetWidth*i)/2,u=(i-1)/2*a.offsetHeight+(s-a.offsetHeight*i)/2;n.afterX=d,n.afterY=u,n.scale=i,this.data.appearEffect=n}},{key:"hidePhoto",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"bottom";this.data.hide=!0,this.data.appear=!1,this.data.appearEffect=null,this.data.hideUi=!1,this.data.scale=!1,this.data.scaleSize=1;var a=void 0!==window.pageXOffset?window.pageXOffset:(document.documentElement||document.body.parentNode||document.body).scrollLeft,o=void 0!==window.pageYOffset?window.pageYOffset:(document.documentElement||document.body.parentNode||document.body).scrollTop,n=document.querySelector("body");window.location.hash&&this._setHash(""),window.scroll(a,o),this._doHideEffect(e).then(function(){t.update(),n.style.overflow="",t._fireEvent("close")})}},{key:"_doHideEffect",value:function(t){var e=this;return new v(function(a){p.isOldIE()&&a();var o=e.data.classNames,n=e._getElementByClass(o.smartPhoto),i=e._getElementByQuery(".current .".concat(o.smartPhotoImg)),r=e._getWindowHeight(),s=function t(){n.removeEventListener("transitionend",t,!0),a()};n.style.opacity=0,"bottom"===t?i.style.transform="translateY(".concat(r,"px)"):"top"===t&&(i.style.transform="translateY(-".concat(r,"px)")),n.addEventListener("transitionend",s,!0)})}},{key:"_getElementByClass",value:function(t){return document.querySelector('[data-id="'.concat(this.id,'"] .').concat(t))}},{key:"_getElementByQuery",value:function(t){return document.querySelector('[data-id="'.concat(this.id,'"] ').concat(t))}},{key:"_getTouchPos",value:function(){var t=0,e=0,a="undefined"==typeof event?this.e:event;return this._isTouched(a)?(t=a.touches[0].pageX,e=a.touches[0].pageY):a.pageX&&(t=a.pageX,e=a.pageY),{x:t,y:e}}},{key:"_getGesturePos",value:function(t){var e=t.touches;return[{x:e[0].pageX,y:e[0].pageY},{x:e[1].pageX,y:e[1].pageY}]}},{key:"_setPosByCurrentIndex",value:function(){var t=this,e=this.groupItems(),a=-1*e[this.data.currentIndex].translateX;this.pos.x=a,setTimeout(function(){t.data.translateX=a,t.data.translateY=0,t._listUpdate()},1)}},{key:"_setHashByCurrentIndex",value:function(){var t=void 0!==window.pageXOffset?window.pageXOffset:(document.documentElement||document.body.parentNode||document.body).scrollLeft,e=void 0!==window.pageYOffset?window.pageYOffset:(document.documentElement||document.body.parentNode||document.body).scrollTop,a=this.groupItems(),o=a[this.data.currentIndex].id,n=this.data.currentGroup,i="group=".concat(n,"&photo=").concat(o);this._setHash(i),window.scroll(t,e)}},{key:"_setHash",value:function(t){window.history&&window.history.pushState&&this.data.useHistoryApi&&(t?window.history.replaceState(null,null,"".concat(location.pathname).concat(location.search,"#").concat(t)):window.history.replaceState(null,null,"".concat(location.pathname).concat(location.search)))}},{key:"_getCurrentItemByHash",value:function(){var t=this.data.group,e=location.hash.substr(1),a=p.parseQuery(e),o=null,n=function(t){a.group===t.groupId&&a.photo===t.id&&(o=t)};return Object.keys(t).forEach(function(e){t[e].forEach(n)}),o}},{key:"_loadItem",value:function(t){return new v(function(e){var a=new Image;a.onload=function(){t.width=a.width,t.height=a.height,t.loaded=!0,e()},a.onerror=function(){e()},a.src=t.src})}},{key:"_getItemByIndex",value:function(t){var e=this.data;return e.group[e.currentGroup][t]?e.group[e.currentGroup][t]:null}},{key:"_loadNeighborItems",value:function(){for(var t=this,e=this.data.currentIndex,a=this.data.loadOffset,o=e-a,n=e+a,i=[],r=o;rt&&(a.scale=t/a.width,a.x=(a.scale-1)/2*a.width))})}},{key:"_slideList",value:function(){var t=this;this.data.scaleSize=1,this.isBeingZoomed=!1,this.data.hideUi=!1,this.data.scale=!1,this.data.photoPosX=0,this.data.photoPosY=0,this.data.onMoveClass=!0,this._setPosByCurrentIndex(),this._setHashByCurrentIndex(),this._setSizeByScreen(),setTimeout(function(){var e=t._getSelectedItem();t.data.onMoveClass=!1,t.setArrow(),t.update(),t.data.oldIndex!==t.data.currentIndex&&t._fireEvent("change"),t.data.oldIndex=t.data.currentIndex,t._loadNeighborItems(),e.loaded||t._loadItem(e).then(function(){t._initPhoto(),t.update()})},200)}},{key:"gotoSlide",value:function(t){this.e&&this.e.preventDefault&&this.e.preventDefault(),this.data.currentIndex=parseInt(t,10),this.data.currentIndex||(this.data.currentIndex=0),this._slideList()}},{key:"setArrow",value:function(){var t=this.groupItems(),e=t.length,a=this.data.currentIndex+1,o=this.data.currentIndex-1;this.data.showNextArrow=!1,this.data.showPrevArrow=!1,a!==e&&(this.data.next=a,this.data.showNextArrow=!0),-1!==o&&(this.data.prev=o,this.data.showPrevArrow=!0)}},{key:"beforeDrag",value:function(){if(this._isGestured(this.e))return void this.beforeGesture();if(this.isBeingZoomed=!1,this.data.scale)return void this.beforePhotoDrag();var t=this._getTouchPos();this.isSwipable=!0,this.dragStart=!0,this.firstPos=t,this.oldPos=t}},{key:"afterDrag",value:function(){var t=this.groupItems(),e=new Date,a=e.getTime(),o=this.tapSecond-a,n=0,i=0;return this.isSwipable=!1,this.onListMove=!1,this.oldPos&&(n=this.oldPos.x-this.firstPos.x,i=this.oldPos.y-this.firstPos.y),this.isBeingZoomed?void this.afterGesture():this.data.scale?void this.afterPhotoDrag():p.isSmartPhone()||0!==n||0!==i?Math.abs(o)<=500&&0===n&&0===i?(this.e.preventDefault(),void this.zoomPhoto()):(this.tapSecond=a,this._fireEvent("swipeend"),"horizontal"===this.moveDir&&(n>=this.data.swipeOffset&&0!==this.data.currentIndex?this.data.currentIndex-=1:n<=-this.data.swipeOffset&&this.data.currentIndex!==t.length-1&&(this.data.currentIndex+=1),this._slideList()),void("vertical"===this.moveDir&&(this.data.swipeBottomToClose&&i>=this.data.swipeOffset?this.hidePhoto("bottom"):this.data.swipeTopToClose&&i<=-this.data.swipeOffset?this.hidePhoto("top"):(this.data.translateY=0,this._slideList())))):void this.zoomPhoto()}},{key:"onDrag",value:function(){if(this.e.preventDefault(),this._isGestured(this.e)&&!1===this.onListMove)return void this.onGesture();if(!this.isBeingZoomed){if(this.data.scale)return void this.onPhotoDrag();if(this.isSwipable){var t=this._getTouchPos(),e=t.x-this.oldPos.x,a=t.y-this.firstPos.y;this.dragStart&&(this._fireEvent("swipestart"),this.dragStart=!1,Math.abs(e)>Math.abs(a)?this.moveDir="horizontal":this.moveDir="vertical"),"horizontal"===this.moveDir?(this.pos.x+=e,this.data.translateX=this.pos.x):this.data.translateY=a,this.onListMove=!0,this.oldPos=t,this._listUpdate()}}}},{key:"zoomPhoto",value:function(){var t=this;this.data.hideUi=!0,this.data.scaleSize=this._getScaleBoarder(),this.data.scaleSize<=1||(this.data.photoPosX=0,this.data.photoPosY=0,this._photoUpdate(),setTimeout(function(){t.data.scale=!0,t._photoUpdate(),t._fireEvent("zoomin")},300))}},{key:"zoomOutPhoto",value:function(){this.data.scaleSize=1,this.isBeingZoomed=!1,this.data.hideUi=!1,this.data.scale=!1,this.data.photoPosX=0,this.data.photoPosY=0,this._photoUpdate(),this._fireEvent("zoomout")}},{key:"beforePhotoDrag",value:function(){var t=this._getTouchPos();this.photoSwipable=!0,this.data.photoPosX||(this.data.photoPosX=0),this.data.photoPosY||(this.data.photoPosY=0),this.oldPhotoPos=t,this.firstPhotoPos=t}},{key:"onPhotoDrag",value:function(){if(this.photoSwipable){this.e.preventDefault();var t=this._getTouchPos(),e=t.x-this.oldPhotoPos.x,a=t.y-this.oldPhotoPos.y,o=this._round(this.data.scaleSize*e,6),n=this._round(this.data.scaleSize*a,6);"number"==typeof o&&(this.data.photoPosX+=o,this.photoVX=o),"number"==typeof n&&(this.data.photoPosY+=n,this.photoVY=n),this.oldPhotoPos=t,this._photoUpdate()}}},{key:"afterPhotoDrag",value:function(){if(this.oldPhotoPos.x===this.firstPhotoPos.x&&this.photoSwipable)this.photoSwipable=!1,this.zoomOutPhoto();else{this.photoSwipable=!1;var t=this._getSelectedItem(),e=this._makeBound(t),a=this.data.swipeOffset*this.data.scaleSize,o=0,n=0;if(this.data.photoPosX>e.maxX?o=-1:this.data.photoPosXe.maxY?n=-1:this.data.photoPosYa&&0!==this.data.currentIndex)return void this.gotoSlide(this.data.prev);if(e.minX-this.data.photoPosX>a&&this.data.currentIndex+1!==this.data.total)return void this.gotoSlide(this.data.next);0===o&&0===n?(this.vx=this.photoVX/5,this.vy=this.photoVY/5):this._registerElasticForce(o,n)}}},{key:"beforeGesture",value:function(){this._fireEvent("gesturestart");var t=this._getGesturePos(this.e),e=this._getDistance(t[0],t[1]);this.isBeingZoomed=!0,this.oldDistance=e,this.data.scale=!0,this.e.preventDefault()}},{key:"onGesture",value:function(){var t=this._getGesturePos(this.e),e=this._getDistance(t[0],t[1]),a=(e-this.oldDistance)/100,o=this.data.scaleSize,n=this.data.photoPosX,i=this.data.photoPosY;this.isBeingZoomed=!0,this.data.scaleSize+=this._round(a,6),this.data.scaleSize<.2&&(this.data.scaleSize=.2),this.data.scaleSizethis._getScaleBoarder()?this.data.hideUi=!0:this.data.hideUi=!1,this.oldDistance=e,this.e.preventDefault(),this._photoUpdate()}},{key:"afterGesture",value:function(){this.data.scaleSize>this._getScaleBoarder()||(this.data.photoPosX=0,this.data.photoPosY=0,this.data.scale=!1,this.data.scaleSize=1,this.data.hideUi=!1,this._fireEvent("gestureend"),this._photoUpdate())}},{key:"_getForceAndTheta",value:function(t,e){return{force:Math.sqrt(t*t+e*e),theta:Math.atan2(e,t)}}},{key:"_getScaleBoarder",value:function(){var t=this._getSelectedItem(),e=this._getWindowWidth(),a=this._getWindowHeight();return p.isSmartPhone()?t.width>t.height?a/(t.height*t.scale):e/(t.width*t.scale):1/t.scale}},{key:"_makeBound",value:function(t){var e,a,o,n,i=t.width*t.scale*this.data.scaleSize,r=t.height*t.scale*this.data.scaleSize,s=this._getWindowWidth(),c=this._getWindowHeight();return s>i?(o=(s-i)/2,e=-1*o):(o=(i-s)/2,e=-1*o),c>r?(n=(c-r)/2,a=-1*n):(n=(r-c)/2,a=-1*n),{minX:this._round(e,6)*this.data.scaleSize,minY:this._round(a,6)*this.data.scaleSize,maxX:this._round(o,6)*this.data.scaleSize,maxY:this._round(n,6)*this.data.scaleSize}}},{key:"_registerElasticForce",value:function(t,e){var a=this,o=this._getSelectedItem(),n=this._makeBound(o);this.data.elastic=!0,1===t?this.data.photoPosX=n.minX:-1===t&&(this.data.photoPosX=n.maxX),1===e?this.data.photoPosY=n.minY:-1===e&&(this.data.photoPosY=n.maxY),this._photoUpdate(),setTimeout(function(){a.data.elastic=!1,a._photoUpdate()},300)}},{key:"_getSelectedItem",value:function(){var t=this.data,e=t.currentIndex;return t.group[t.currentGroup][e]}},{key:"_getUniqId",value:function(){return(Date.now().toString(36)+Math.random().toString(36).substr(2,5)).toUpperCase()}},{key:"_getDistance",value:function(t,e){var a=t.x-e.x,o=t.y-e.y;return Math.sqrt(a*a+o*o)}},{key:"_round",value:function(t,e){var a=Math.pow(10,e);return t*=a,t=Math.round(t),t/=a}},{key:"_isTouched",value:function(t){return!(!t||!t.touches)}},{key:"_isGestured",value:function(t){return!!(t&&t.touches&&t.touches.length>1)}},{key:"_isSmartPhone",value:function(){var t=navigator.userAgent;return t.indexOf("iPhone")>0||t.indexOf("iPad")>0||t.indexOf("ipod")>0||t.indexOf("Android")>0}},{key:"_calcGravity",value:function(t,e){(t>5||t<-5)&&(this.vx+=.05*t),!1!==this.data.verticalGravity&&(e>5||e<-5)&&(this.vy+=.05*e)}},{key:"_photoUpdate",value:function(){var t=this.data.classNames,e=this._getElementByQuery(".current"),a=e.querySelector(".".concat(t.smartPhotoImg)),o=this._getElementByQuery(".".concat(t.smartPhotoNav)),n=this._getElementByQuery(".".concat(t.smartPhotoArrows)),i=this.virtualPos(this.data.photoPosX),r=this.virtualPos(this.data.photoPosY),s=this.data.scaleSize,c="translate(".concat(i,"px,").concat(r,"px) scale(").concat(s,")");a.style.transform=c,this.data.scale?p.addClass(a,t.smartPhotoImgOnMove):p.removeClass(a,t.smartPhotoImgOnMove),this.data.elastic?p.addClass(a,t.smartPhotoImgElasticMove):p.removeClass(a,t.smartPhotoImgElasticMove),this.data.hideUi?(o&&o.setAttribute("aria-hidden","true"),n&&n.setAttribute("aria-hidden","true")):(o&&o.setAttribute("aria-hidden","false"),n&&n.setAttribute("aria-hidden","false"))}},{key:"_getWindowWidth",value:function(){return document&&document.documentElement?document.documentElement.clientWidth:window&&window.innerWidth?window.innerWidth:0}},{key:"_getWindowHeight",value:function(){return document&&document.documentElement?document.documentElement.clientHeight:window&&window.innerHeight?window.innerHeight:0}},{key:"_listUpdate",value:function(){var t=this.data.classNames,e=this._getElementByQuery(".".concat(t.smartPhotoList)),a="translate(".concat(this.data.translateX,"px,").concat(this.data.translateY,"px)");e.style.transform=a,this.data.onMoveClass?p.addClass(e,t.smartPhotoListOnMove):p.removeClass(e,t.smartPhotoListOnMove)}},{key:"_fireEvent",value:function(t){var e=this._getElementByClass(this.data.classNames.smartPhoto);p.triggerEvent(e,t)}},{key:"_doAnim",value:function(){if(!(this.isBeingZoomed||this.isSwipable||this.photoSwipable||this.data.elastic)&&this.data.scale){this.data.photoPosX+=this.vx,this.data.photoPosY+=this.vy;var t=this._getSelectedItem(),e=this._makeBound(t);this.data.photoPosXe.maxX&&(this.data.photoPosX=e.maxX,this.vx*=-.2),this.data.photoPosYe.maxY&&(this.data.photoPosY=e.maxY,this.vy*=-.2);var a=this._getForceAndTheta(this.vx,this.vy),o=a.force,n=a.theta;o-=this.data.registance,Math.abs(o)<.5||(this.vx=Math.cos(n)*o,this.vy=Math.sin(n)*o,this._photoUpdate())}}}]),e}(h.default);a.default=y,e.exports=a.default},{"../lib/util":11,"a-template":1,"custom-event-polyfill":3,"es6-promise-polyfill":4}],10:[function(t,e,a){"use strict";e.exports=t("./core/")},{"./core/":9}],11:[function(t,e,a){"use strict";function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function n(t){t=t||{};for(var e=1;e0||t.indexOf("iPad")>0||t.indexOf("ipod")>0||t.indexOf("Android")>0};a.isSmartPhone=i;var r=n;a.extend=r;var s=function(t,e,a){var o;window.CustomEvent?o=new CustomEvent(e,{cancelable:!0}):(o=document.createEvent("CustomEvent"),o.initCustomEvent(e,!1,!1,a)),t.dispatchEvent(o)};a.triggerEvent=s;var c=function(t){for(var e,a,o,n=t.split("&"),i={},r=0,s=n.length;r0;)t.appendChild(a.children[0])};a.append=l;var h=function(t,e){t.classList?t.classList.add(e):t.className+=" ".concat(e)};a.addClass=h;var f=function(t,e){t.classList?t.classList.remove(e):t.className=t.className.replace(new RegExp("(^|\\b)"+e.split(" ").join("|")+"(\\b|$)","gi")," ")};a.removeClass=f;var p=function(){var t=window.navigator.userAgent.toLowerCase(),e=window.navigator.appVersion.toLowerCase(),a="unknown";return-1!=t.indexOf("msie")?a=-1!=e.indexOf("msie 6.")?"ie6":-1!=e.indexOf("msie 7.")?"ie7":-1!=e.indexOf("msie 8.")?"ie8":-1!=e.indexOf("msie 9.")?"ie9":-1!=e.indexOf("msie 10.")?"ie10":"ie":-1!=t.indexOf("trident/7")?a="ie11":-1!=t.indexOf("chrome")?a="chrome":-1!=t.indexOf("safari")?a="safari":-1!=t.indexOf("opera")?a="opera":-1!=t.indexOf("firefox")&&(a="firefox"),a};a.getBrowser=p;var m=function(){var t=p();return-1!==t.indexOf("ie")&&parseInt(t.replace(/[^0-9]/g,""))<=10};a.isOldIE=m},{}]},{},[10])(10)}); -------------------------------------------------------------------------------- /lib/adaptor/jquery.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var SmartPhoto = require('../index'); 4 | 5 | var applyJQuery = function applyJQuery(jQuery) { 6 | jQuery.fn.SmartPhoto = function (settings) { 7 | if (typeof settings === 'strings') {} else { 8 | new SmartPhoto(this, settings); 9 | } 10 | 11 | return this; 12 | }; 13 | }; 14 | 15 | if (typeof define === 'function' && define.amd) { 16 | define(['jquery'], applyJQuery); 17 | } else { 18 | var jq = window.jQuery ? window.jQuery : window.$; 19 | 20 | if (typeof jq !== 'undefined') { 21 | applyJQuery(jq); 22 | } 23 | } 24 | 25 | module.exports = applyJQuery; -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./core/'); -------------------------------------------------------------------------------- /lib/lib/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.isOldIE = exports.getBrowser = exports.removeClass = exports.addClass = exports.append = exports.removeElement = exports.getViewPos = exports.parseQuery = exports.triggerEvent = exports.extend = exports.isSmartPhone = void 0; 7 | 8 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 9 | 10 | var isSmartPhone = function isSmartPhone() { 11 | var agent = navigator.userAgent; 12 | 13 | if (agent.indexOf('iPhone') > 0 || agent.indexOf('iPad') > 0 || agent.indexOf('ipod') > 0 || agent.indexOf('Android') > 0) { 14 | return true; 15 | } else { 16 | return false; 17 | } 18 | }; 19 | 20 | exports.isSmartPhone = isSmartPhone; 21 | 22 | function deepExtend(out) { 23 | out = out || {}; 24 | 25 | for (var i = 1; i < arguments.length; i++) { 26 | var obj = arguments[i]; 27 | 28 | if (!obj) { 29 | continue; 30 | } 31 | 32 | for (var key in obj) { 33 | if (obj.hasOwnProperty(key)) { 34 | if (_typeof(obj[key]) === 'object') out[key] = deepExtend(out[key], obj[key]);else out[key] = obj[key]; 35 | } 36 | } 37 | } 38 | 39 | return out; 40 | } 41 | 42 | ; 43 | var extend = deepExtend; 44 | exports.extend = extend; 45 | 46 | var triggerEvent = function triggerEvent(el, eventName, options) { 47 | var event; 48 | 49 | if (window.CustomEvent) { 50 | event = new CustomEvent(eventName, { 51 | cancelable: true 52 | }); 53 | } else { 54 | event = document.createEvent('CustomEvent'); 55 | event.initCustomEvent(eventName, false, false, options); 56 | } 57 | 58 | el.dispatchEvent(event); 59 | }; 60 | 61 | exports.triggerEvent = triggerEvent; 62 | 63 | var parseQuery = function parseQuery(query) { 64 | var s = query.split('&'), 65 | data = {}, 66 | i = 0, 67 | iz = s.length, 68 | param, 69 | key, 70 | value; 71 | 72 | for (; i < iz; i++) { 73 | param = s[i].split('='); 74 | 75 | if (param[0] !== void 0) { 76 | key = param[0]; 77 | value = param[1] !== void 0 ? param.slice(1).join('=') : key; 78 | data[key] = decodeURIComponent(value); 79 | } 80 | } 81 | 82 | return data; 83 | }; 84 | 85 | exports.parseQuery = parseQuery; 86 | 87 | var getViewPos = function getViewPos(element) { 88 | return { 89 | left: element.getBoundingClientRect().left, 90 | top: element.getBoundingClientRect().top 91 | }; 92 | }; 93 | 94 | exports.getViewPos = getViewPos; 95 | 96 | var removeElement = function removeElement(element) { 97 | if (element && element.parentNode) { 98 | element.parentNode.removeChild(element); 99 | } 100 | }; 101 | 102 | exports.removeElement = removeElement; 103 | 104 | var append = function append(element, string) { 105 | var div = document.createElement('div'); 106 | div.innerHTML = string; 107 | 108 | while (div.children.length > 0) { 109 | element.appendChild(div.children[0]); 110 | } 111 | }; 112 | 113 | exports.append = append; 114 | 115 | var addClass = function addClass(element, className) { 116 | if (element.classList) { 117 | element.classList.add(className); 118 | } else { 119 | element.className += " ".concat(className); 120 | } 121 | }; 122 | 123 | exports.addClass = addClass; 124 | 125 | var removeClass = function removeClass(element, className) { 126 | if (element.classList) { 127 | element.classList.remove(className); 128 | } else { 129 | element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); 130 | } 131 | }; 132 | 133 | exports.removeClass = removeClass; 134 | 135 | var getBrowser = function getBrowser() { 136 | var ua = window.navigator.userAgent.toLowerCase(); 137 | var ver = window.navigator.appVersion.toLowerCase(); 138 | var name = 'unknown'; 139 | 140 | if (ua.indexOf('msie') != -1) { 141 | if (ver.indexOf('msie 6.') != -1) { 142 | name = 'ie6'; 143 | } else if (ver.indexOf('msie 7.') != -1) { 144 | name = 'ie7'; 145 | } else if (ver.indexOf('msie 8.') != -1) { 146 | name = 'ie8'; 147 | } else if (ver.indexOf('msie 9.') != -1) { 148 | name = 'ie9'; 149 | } else if (ver.indexOf('msie 10.') != -1) { 150 | name = 'ie10'; 151 | } else { 152 | name = 'ie'; 153 | } 154 | } else if (ua.indexOf('trident/7') != -1) { 155 | name = 'ie11'; 156 | } else if (ua.indexOf('chrome') != -1) { 157 | name = 'chrome'; 158 | } else if (ua.indexOf('safari') != -1) { 159 | name = 'safari'; 160 | } else if (ua.indexOf('opera') != -1) { 161 | name = 'opera'; 162 | } else if (ua.indexOf('firefox') != -1) { 163 | name = 'firefox'; 164 | } 165 | 166 | return name; 167 | }; 168 | 169 | exports.getBrowser = getBrowser; 170 | 171 | var isOldIE = function isOldIE() { 172 | var browser = getBrowser(); 173 | 174 | if (browser.indexOf('ie') !== -1) { 175 | if (parseInt(browser.replace(/[^0-9]/g, '')) <= 10) { 176 | return true; 177 | } 178 | } 179 | 180 | return false; 181 | }; 182 | 183 | exports.isOldIE = isOldIE; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smartphoto", 3 | "version": "1.6.5", 4 | "description": "smartphoto", 5 | "homepage": "http://developer.a-blogcms.jp", 6 | "main": "lib/index.js", 7 | "scripts": { 8 | "test": "mocha ./test/test.js --timeout 1000000 --exit", 9 | "lint": "eslint ./src/core/index.js --fix", 10 | "build:js": "npm-run-all -p build:lib build:jquery build:global", 11 | "build:lib": "npm run babel", 12 | "build:jquery": "browserify ./src/adaptor/jquery.js -t babelify -p licensify -o ./js/jquery-smartphoto.js && npm run build:jquery:min", 13 | "build:global": "browserify ./src/index.js -t babelify -p licensify --standalone SmartPhoto -o ./js/smartphoto.js && npm run build:global:min", 14 | "build:jquery:min": "uglifyjs ./js/jquery-smartphoto.js -m -c --comments -o ./js/jquery-smartphoto.min.js", 15 | "build:global:min": "uglifyjs ./js/smartphoto.js -m -c --comments -o ./js/smartphoto.min.js", 16 | "build:sass": "npm-run-all -p sass sass:min", 17 | "babel": "babel src --out-dir lib", 18 | "sass": "node-sass ./scss/smartphoto.scss ./css/smartphoto.css --output-style expanded", 19 | "sass:min": "node-sass ./scss/smartphoto.scss ./css/smartphoto.min.css --output-style compressed", 20 | "watch:js": "onchange \"src/\" -- npm run build:js", 21 | "watch:sass": "onchange \"scss\" -- npm run build:sass", 22 | "sync": "browser-sync start --server './' --files './js/*.js' './css/*.css' --startPath '/examples/jquery.html'", 23 | "start": "npm-run-all -p watch:js watch:sass sync", 24 | "deploy": "np --no-cleanup" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/appleple/SmartPhoto/" 29 | }, 30 | "author": "appleple", 31 | "license": "MIT", 32 | "devDependencies": { 33 | "@babel/cli": "^7.5.5", 34 | "@babel/core": "^7.5.5", 35 | "@babel/preset-env": "^7.5.5", 36 | "babel-plugin-add-module-exports": "^0.2.1", 37 | "babel-plugin-transform-html-import-to-string": "^0.0.1", 38 | "babelify": "^10.0.0", 39 | "browser-sync": "^2.26.7", 40 | "browserify": "^16.5.0", 41 | "chokidar": "^2.0.4", 42 | "co": "^4.6.0", 43 | "eslint": "^6.2.0", 44 | "eslint-config-airbnb": "^14.1.0", 45 | "eslint-plugin-import": "^2.2.0", 46 | "fs-extra": "^2.1.2", 47 | "http-server": "^0.11.1", 48 | "licensify": "^3.1.2", 49 | "mocha": "^6.2.0", 50 | "nightmare": "^2.8.1", 51 | "node-cmd": "^2.0.0", 52 | "node-sass": "^4.12.0", 53 | "nodemon": "^1.11.0", 54 | "np": "^2.16.0", 55 | "npm-run-all": "^4.0.2", 56 | "onchange": "^6.0.0", 57 | "power-assert": "^1.4.2", 58 | "uglify-js": "^2.8.22", 59 | "watchify": "^3.11.1" 60 | }, 61 | "dependencies": { 62 | "a-template": "^0.6.1", 63 | "custom-event-polyfill": "^0.3.0", 64 | "es6-promise-polyfill": "^1.2.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # SmartPhoto 2 | [![npm version](https://badge.fury.io/js/smartphoto.svg)](https://badge.fury.io/js/smartphoto) 3 | [![CircleCI](https://circleci.com/gh/appleple/SmartPhoto/tree/master.svg?style=shield)](https://circleci.com/gh/appleple/SmartPhoto/tree/master) 4 | [![npm download](http://img.shields.io/npm/dm/smartphoto.svg)](https://www.npmjs.com/package/smartphoto) 5 | [![GitHub license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://raw.githubusercontent.com/appleple/SmartPhoto/master/LICENSE) 6 | 7 | The most easy to use responsive image viewer especially for mobile devices 8 | 9 | See [https://appleple.github.io/SmartPhoto/](https://appleple.github.io/SmartPhoto/) for complete docs and demos
10 | If you are Japasese, See here [https://www.appleple.com/blog/javascript/smartphoto-js.html](https://www.appleple.com/blog/javascript/smartphoto-js.html) instead. 11 | 12 | ## Feature 13 | - Intuitive gestures such as pinch-in/pinch-out/drag/swipe 14 | - Use Accelerometer to move images 15 | - Accessible from keyboards and screen-readers 16 | - Show pictures via URL hash 17 | - Can make photo groups 18 | 19 | ## Installation 20 | - [npm](https://www.npmjs.com/package/smartphoto) 21 | - [standalone](https://raw.githubusercontent.com/appleple/smart-photo/master/js/smartphoto.js) 22 | 23 | via npm 24 | ```shell 25 | npm install smartphoto --save 26 | ``` 27 | 28 | or yarn 29 | 30 | ```shell 31 | yarn add smartphoto 32 | ``` 33 | 34 | ## Usage 35 | require 36 | ```js 37 | const SmartPhoto = require('smartphoto'); 38 | ``` 39 | 40 | smartphoto.js 41 | ```js 42 | document.addEventListener('DOMContentLoaded',function(){ 43 | new SmartPhoto(".js-smartphoto"); 44 | }); 45 | ``` 46 | 47 | jquery-smartphoto.js 48 | ```js 49 | $(function(){ 50 | $(".js-smartphoto").SmartPhoto(); 51 | }); 52 | ``` 53 | 54 | ### Basic Standalone Usage 55 | 56 | ```html 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 73 | ``` 74 | 75 | ### Option 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
variabledescriptiondefault
arrowsprev/next arrowstrue
navnavigation images at the bottomtrue
useOrientationApiuse accelerometer to move imagestrue
resizeStyleresize images to fill/fit on the screen'fill'
animationSpeedanimation speed when switching images300
forceIntervalfrequency to apply force to images10
114 | 115 | #### Hide parts 116 | ```js 117 | document.addEventListener('DOMContentLoaded',function(){ 118 | new SmartPhoto(".js-smartphoto",{ 119 | arrows: false, 120 | nav: false 121 | }); 122 | }); 123 | ``` 124 | 125 | #### Fit/Fill Option 126 | 127 | You can choose if you want to scale images to fit/fill 128 | 129 | ```js 130 | document.addEventListener('DOMContentLoaded',function(){ 131 | new SmartPhoto(".js-smartphoto",{ 132 | resizeStyle: 'fit' 133 | }); 134 | }); 135 | ``` 136 | 137 | ### Event 138 | 139 | ```js 140 | // when the modal opened 141 | photo.on('open',function(){ 142 | console.log('open'); 143 | }); 144 | // when the modal closed 145 | photo.on('close',function(){ 146 | console.log('close'); 147 | }); 148 | // when all images are loaded 149 | photo.on('loadall',function(){ 150 | console.log('loadall'); 151 | }); 152 | // when photo is changed 153 | photo.on('change',function(){ 154 | console.log('change'); 155 | }); 156 | // when swipe started 157 | photo.on('swipestart',function(){ 158 | console.log('swipestart'); 159 | }); 160 | // when swipe ended 161 | photo.on('swipeend',function(){ 162 | console.log('swipeend'); 163 | }); 164 | // when zoomed in 165 | photo.on('zoomin',function(){ 166 | console.log('zoomin'); 167 | }); 168 | // when zoomed out 169 | photo.on('zoomout',function(){ 170 | console.log('zoomout'); 171 | }); 172 | ``` 173 | 174 | ### SCSS 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 |
variabledescriptiondefault
$animation-speedanimation speed when switching images.3s
$backdrop-colorbackdrop color when viewing imagesrgba(0, 0, 0, 1)
$header-colorheader colorrgba(0, 0, 0, .2)
198 | 199 | 200 | ## Download 201 | [Download ZIP](https://github.com/appleple/SmartPhoto/archive/master.zip) 202 | 203 | ## Github 204 | [https://github.com/appleple/SmartPhoto](https://github.com/appleple/SmartPhoto) 205 | 206 | ## Contributor 207 | [@steelydylan](https://github.com/steelydylan) 208 | 209 | ## License 210 | Code and documentation copyright 2017 by appleple, Inc. Code released under the [MIT License](https://github.com/appleple/SmartPhoto/blob/master/LICENSE). 211 | -------------------------------------------------------------------------------- /scss/smartphoto.scss: -------------------------------------------------------------------------------- 1 | $animation-speed: .3s !default; 2 | $animation-function: ease-out !default; 3 | $backdrop-color: rgba(0, 0, 0, 1) !default; 4 | $header-color: rgba(0, 0, 0, .2) !default; 5 | 6 | @keyframes smartphoto { 7 | from { 8 | opacity: 0; 9 | } 10 | 11 | to { 12 | opacity: 1; 13 | } 14 | } 15 | 16 | @keyframes smartphoto-img-wrap { 17 | from { 18 | opacity: 0; 19 | } 20 | 21 | to { 22 | opacity: 1; 23 | } 24 | } 25 | 26 | @keyframes smartphoto-inner { 27 | from { 28 | transform: translate(0, 100px); 29 | } 30 | 31 | to { 32 | transform: translate(0, 0); 33 | } 34 | } 35 | 36 | @keyframes smartphoto-loader { 37 | 0% { 38 | opacity: .4; 39 | transform: rotate(0deg); 40 | } 41 | 50% { 42 | opacity: 1; 43 | transform: rotate(180deg); 44 | } 45 | 100% { 46 | opacity: .4; 47 | transform: rotate(360deg); 48 | } 49 | } 50 | 51 | @keyframes smartphoto-appear { 52 | 0% { 53 | display: none; 54 | opacity: 0; 55 | } 56 | 57 | 1% { 58 | display: block; 59 | opacity: 0; 60 | } 61 | 62 | 100% { 63 | display: block; 64 | opacity: 1; 65 | } 66 | } 67 | 68 | @keyframes smartphoto-hide { 69 | 0% { 70 | display: block; 71 | opacity: 1; 72 | } 73 | 99% { 74 | display: block; 75 | opacity: 0; 76 | } 77 | 100% { 78 | display: none; 79 | opacity: 0; 80 | } 81 | } 82 | 83 | .smartphoto { 84 | position: fixed; 85 | z-index: 100; 86 | top: 0; 87 | left: 0; 88 | width: 100%; 89 | height: 100%; 90 | overflow: hidden; 91 | background-color: $backdrop-color; 92 | opacity: 1; 93 | font-family: sans-serif; 94 | cursor: pointer; 95 | -webkit-transition: opacity $animation-speed $animation-function; 96 | -moz-transition: opacity $animation-speed $animation-function; 97 | -ms-transition: opacity $animation-speed $animation-function; 98 | -o-transition: opacity $animation-speed $animation-function; 99 | transition: opacity $animation-speed $animation-function; 100 | transition: all .3s $animation-function; 101 | animation-name: smartphoto; 102 | animation-duration: $animation-speed; 103 | animation-timing-function: $animation-function; 104 | } 105 | 106 | .smartphoto[aria-hidden="true"] { 107 | display: none; 108 | } 109 | 110 | .smartphoto-close { 111 | opacity: 0; 112 | } 113 | 114 | .smartphoto-count { 115 | display: inline-block; 116 | color: #FFF; 117 | font-size: 16px; 118 | } 119 | 120 | .smartphoto-header { 121 | display: block; 122 | box-sizing: border-box; 123 | position: fixed; 124 | z-index: 102; 125 | top: 0; 126 | left: 0; 127 | width: 100%; 128 | height: 50px; 129 | padding: 15px; 130 | background-color: $header-color; 131 | } 132 | 133 | .smartphoto-content { 134 | display: block; 135 | position: absolute; 136 | top: 0; 137 | left: 0; 138 | width: 100%; 139 | height: 100%; 140 | } 141 | 142 | .smartphoto-dismiss { 143 | display: block; 144 | position: absolute; 145 | top: 15px; 146 | right: 10px; 147 | width: 20px; 148 | height: 20px; 149 | padding: 0; 150 | border: none; 151 | background-color: transparent; 152 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik0xNTc2LjQyLDE0MDYuNzYsMjc4NCwxOTkuMTlhNTYuODYsNTYuODYsMCwwLDAsMC04MC4xOGwtNzguOTItNzguOTJhNTYuODYsNTYuODYsMCwwLDAtODAuMTgsMEwxNDE3LjMyLDEyNDcuNjYsMjA5Ljc1LDQwLjA5YTU2Ljg2LDU2Ljg2LDAsMCwwLTgwLjE4LDBMNTAuNjUsMTE5YTU2Ljg2LDU2Ljg2LDAsMCwwLDAsODAuMThMMTI1OC4yMywxNDA2Ljc2LDUwLjY1LDI2MTQuMzRhNTYuODYsNTYuODYsMCwwLDAsMCw4MC4xOGw3OC45Miw3OC45MmE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwTDE0MTcuMzIsMTU2NS44NiwyNjI0LjksMjc3My40NGE1Ni44Niw1Ni44NiwwLDAsMCw4MC4xOCwwbDc4LjkyLTc4LjkyYTU2Ljg2LDU2Ljg2LDAsMCwwLDAtODAuMThaIi8+PC9zdmc+); 153 | text-shadow: 0 1px 0 #FFF; 154 | color: #FFF; 155 | font-size: 30px; 156 | text-decoration: none; 157 | cursor: pointer; 158 | line-height: 1; 159 | } 160 | 161 | 162 | .smartphoto-body { 163 | position: relative; 164 | z-index: 102; 165 | width: 100%; 166 | height: 100%; 167 | margin: 0 auto; 168 | } 169 | 170 | .smartphoto-inner { 171 | position: relative; 172 | width: 100%; 173 | height: 100%; 174 | // display: table-cell; 175 | vertical-align: top; 176 | } 177 | 178 | .smartphoto-img { 179 | display: none; 180 | max-width: none; 181 | width: auto; 182 | height: auto; 183 | cursor: zoom-in; 184 | -webkit-user-select: none; 185 | -moz-user-select: none; 186 | -ms-user-select: none; 187 | user-select: none; 188 | transition: transform .3s $animation-function; 189 | 190 | -webkit-user-drag: none; 191 | } 192 | 193 | .smartphoto-img.active { 194 | display: block; 195 | } 196 | 197 | .smartphoto-img-onmove { 198 | cursor: grab; 199 | cursor: -webkit-grab; 200 | transition: none; 201 | } 202 | 203 | .smartphoto-img-elasticmove { 204 | transition: transform .3s $animation-function; 205 | } 206 | 207 | .smartphoto-img-wrap { 208 | display: inline-block; 209 | opacity: 1; 210 | -webkit-transition: opacity $animation-speed $animation-function; 211 | -moz-transition: opacity $animation-speed $animation-function; 212 | -ms-transition: opacity $animation-speed $animation-function; 213 | -o-transition: opacity $animation-speed $animation-function; 214 | transition: opacity $animation-speed $animation-function; 215 | animation-name: smartphoto-img-wrap; 216 | animation-duration: $animation-speed; 217 | animation-timing-function: $animation-function; 218 | } 219 | 220 | .smartphoto-img-left { 221 | transform: translateX(150%) !important; 222 | } 223 | 224 | .smartphoto-img-right { 225 | transform: translateX(-150%) !important; 226 | } 227 | 228 | .smartphoto-arrows { 229 | list-style-type: none; 230 | margin: 0; 231 | padding: 0; 232 | position: relative; 233 | z-index: 1002; 234 | top: 50%; 235 | left: 0; 236 | opacity: 1; 237 | animation-name: smartphoto-appear; 238 | animation-duration: $animation-speed; 239 | animation-timing-function: $animation-function; 240 | } 241 | 242 | .smartphoto-arrows[aria-hidden="true"] { 243 | animation-name: smartphoto-hide; 244 | display: none; 245 | } 246 | 247 | .smartphoto-arrows li { 248 | display: block; 249 | position: absolute; 250 | top: 50%; 251 | width: 30px; 252 | height: 30px; 253 | margin-top: -20px; 254 | box-sizing: content-box; 255 | animation-duration: $animation-speed; 256 | animation-timing-function: $animation-function; 257 | animation-name: smartphoto-appear; 258 | &:focus { 259 | outline: none; 260 | } 261 | } 262 | 263 | .smartphoto-arrows [aria-hidden="true"] { 264 | animation-name: smartphoto-hide; 265 | display: none; 266 | } 267 | 268 | .smartphoto-arrows a { 269 | display: block; 270 | width: 100%; 271 | height: 100%; 272 | text-decoration: none; 273 | } 274 | 275 | .smartphoto-arrow-right { 276 | right: 0; 277 | padding: 5px 0; 278 | background-color: rgba(0, 0, 0, .5); 279 | a { 280 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiAiPjx0aXRsZT5pY29uPC90aXRsZT48cGF0aCBkPSJNMTgzNy44OCwxNDE3LjMyLDY0My41OSwyMjNhNzIuMjEsNzIuMjEsMCwwLDEsMC0xMDEuODJMNzQzLjgyLDIxYTcyLjIxLDcyLjIxLDAsMCwxLDEwMS44MiwwTDIwOTAuODMsMTI2Ni4xOWwxMDAuMjMsMTAwLjIzYTcyLjIxLDcyLjIxLDAsMCwxLDAsMTAxLjgyTDg0NS42NCwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwxLTEwMS44MiwwTDY0My41OSwyNzEzLjQyYTcyLjIxLDcyLjIxLDAsMCwxLDAtMTAxLjgyWiIvPjwvc3ZnPg==); 281 | } 282 | } 283 | 284 | .smartphoto-arrow-left { 285 | left: 0; 286 | padding: 5px 0; 287 | background-color: rgba(0, 0, 0, .5); 288 | a { 289 | background-image: url(data:image/svg+xml;base64,PHN2ZyBpZD0i44Os44Kk44Ok44O8XzEiIGRhdGEtbmFtZT0i44Os44Kk44Ok44O8IDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4MzQuNjUgMjgzNC42NSIgZmlsbD0iI0ZGRiI+PHRpdGxlPmljb248L3RpdGxlPjxwYXRoIGQ9Ik05OTYuNzcsMTQxNy4zMiwyMTkxLjA2LDIyM2E3Mi4yMSw3Mi4yMSwwLDAsMCwwLTEwMS44MkwyMDkwLjgzLDIxQTcyLjIxLDcyLjIxLDAsMCwwLDE5ODksMjFMNzQzLjgyLDEyNjYuMTksNjQzLjU5LDEzNjYuNDJhNzIuMjEsNzIuMjEsMCwwLDAsMCwxMDEuODJMMTk4OSwyODEzLjY1YTcyLjIxLDcyLjIxLDAsMCwwLDEwMS44MiwwbDEwMC4yMy0xMDAuMjNhNzIuMjEsNzIuMjEsMCwwLDAsMC0xMDEuODJaIi8+PC9zdmc+); 290 | } 291 | } 292 | 293 | .smartPhotoArrowHideIcon { 294 | display: none; 295 | } 296 | 297 | .smartphoto-nav { 298 | position: absolute; 299 | bottom: 0; 300 | left: 0; 301 | width: 100%; 302 | opacity: 1; 303 | animation-name: smartphoto-appear; 304 | animation-duration: $animation-speed; 305 | animation-timing-function: $animation-function; 306 | } 307 | 308 | .smartphoto-nav[aria-hidden="true"] { 309 | animation-name: smartphoto-hide; 310 | display: none; 311 | } 312 | 313 | .smartphoto-nav ul { 314 | display: block; 315 | overflow-x: auto; 316 | list-style: none; 317 | margin: 0; 318 | padding: 0; 319 | text-align: center; 320 | white-space: nowrap; 321 | 322 | -webkit-overflow-scrolling: touch; 323 | } 324 | 325 | .smartphoto-nav li { 326 | display: inline-block; 327 | overflow: hidden; 328 | width: 50px; 329 | height: 50px; 330 | } 331 | 332 | .smartphoto-nav a { 333 | display: block; 334 | width: 100%; 335 | height: 100%; 336 | background-color: #FFF; 337 | background-position: center center; 338 | background-size: cover; 339 | opacity: .5; 340 | &:focus { 341 | opacity: .8; 342 | } 343 | } 344 | 345 | .smartphoto-nav a.current { 346 | opacity: 1; 347 | } 348 | 349 | .smartphoto-nav img { 350 | width: auto; 351 | height: 100%; 352 | } 353 | 354 | .smartphoto-list { 355 | list-style-type: none; 356 | position: absolute; 357 | z-index: 101; 358 | top: 0; 359 | left: 0; 360 | margin: 0; 361 | padding: 0; 362 | white-space: nowrap; 363 | li { 364 | display: block; 365 | position: absolute; 366 | top: 0; 367 | left: 0; 368 | width: 100%; 369 | height: 100%; 370 | transition: all .3s $animation-function; 371 | &:focus { 372 | outline: none; 373 | } 374 | } 375 | } 376 | 377 | .smartphoto-list-onmove { 378 | transition: all .3s $animation-function; 379 | } 380 | 381 | .smartphoto-caption { 382 | overflow: hidden; 383 | box-sizing: border-box; 384 | position: absolute; 385 | top: 0; 386 | left: 0; 387 | width: 100%; 388 | height: 50px; 389 | padding: 0 50px; 390 | color: #FFF; 391 | font-size: 12px; 392 | text-align: center; 393 | line-height: 50px; 394 | white-space: nowrap; 395 | text-overflow: ellipsis; 396 | &:focus { 397 | outline: none; 398 | } 399 | } 400 | 401 | .smartphoto-loader-wrap { 402 | display: block; 403 | position: relative; 404 | z-index: 103; 405 | width: 0; 406 | height: 0; 407 | transform: translate(50vw,50vh); 408 | } 409 | 410 | .smartphoto-loader { 411 | position: absolute; 412 | z-index: 101; 413 | top: 0; 414 | left: 0; 415 | width: 30px; 416 | height: 30px; 417 | margin-top: -25px; 418 | margin-left: -25px; 419 | border: 8px solid #17CDDD; 420 | border-right-color: transparent; 421 | border-radius: 50%; 422 | animation: smartphoto-loader .5s infinite linear; 423 | } 424 | 425 | .smartphoto-img-clone { 426 | position: fixed; 427 | z-index: 100; 428 | top: 0; 429 | left: 0; 430 | transition: all $animation-speed $animation-function; 431 | } 432 | 433 | .smartphoto-sr-only { 434 | overflow: hidden; 435 | position: absolute; 436 | width: 1px; 437 | height: 1px; 438 | margin: -1px; 439 | padding: 0; 440 | border: 0; 441 | clip: rect(0,0,0,0); 442 | } 443 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appleple/SmartPhoto/abfd4f071f50b3c170c5ddcbed8c8e966c965eec/src/.DS_Store -------------------------------------------------------------------------------- /src/adaptor/jquery.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const SmartPhoto = require('../index'); 4 | 5 | const applyJQuery = (jQuery) => { 6 | jQuery.fn.SmartPhoto = function(settings) { 7 | if (typeof settings === 'strings'){ 8 | } else { 9 | new SmartPhoto(this, settings); 10 | } 11 | return this; 12 | } 13 | } 14 | 15 | if (typeof define === 'function' && define.amd) { 16 | define(['jquery'], applyJQuery); 17 | } else { 18 | var jq = window.jQuery ? window.jQuery : window.$; 19 | if (typeof jq !== 'undefined') { 20 | applyJQuery(jq); 21 | } 22 | } 23 | 24 | module.exports = applyJQuery; 25 | -------------------------------------------------------------------------------- /src/core/index.js: -------------------------------------------------------------------------------- 1 | import ATemplate from 'a-template'; 2 | import 'custom-event-polyfill'; 3 | 4 | import template from './viwer.html'; 5 | 6 | const util = require('../lib/util'); 7 | const { Promise } = require('es6-promise-polyfill'); 8 | 9 | const defaults = { 10 | classNames: { 11 | smartPhoto: 'smartphoto', 12 | smartPhotoClose: 'smartphoto-close', 13 | smartPhotoBody: 'smartphoto-body', 14 | smartPhotoInner: 'smartphoto-inner', 15 | smartPhotoContent: 'smartphoto-content', 16 | smartPhotoImg: 'smartphoto-img', 17 | smartPhotoImgOnMove: 'smartphoto-img-onmove', 18 | smartPhotoImgElasticMove: 'smartphoto-img-elasticmove', 19 | smartPhotoImgWrap: 'smartphoto-img-wrap', 20 | smartPhotoArrows: 'smartphoto-arrows', 21 | smartPhotoNav: 'smartphoto-nav', 22 | smartPhotoArrowRight: 'smartphoto-arrow-right', 23 | smartPhotoArrowLeft: 'smartphoto-arrow-left', 24 | smartPhotoArrowHideIcon: 'smartphoto-arrow-hide', 25 | smartPhotoImgLeft: 'smartphoto-img-left', 26 | smartPhotoImgRight: 'smartphoto-img-right', 27 | smartPhotoList: 'smartphoto-list', 28 | smartPhotoListOnMove: 'smartphoto-list-onmove', 29 | smartPhotoHeader: 'smartphoto-header', 30 | smartPhotoCount: 'smartphoto-count', 31 | smartPhotoCaption: 'smartphoto-caption', 32 | smartPhotoDismiss: 'smartphoto-dismiss', 33 | smartPhotoLoader: 'smartphoto-loader', 34 | smartPhotoLoaderWrap: 'smartphoto-loader-wrap', 35 | smartPhotoImgClone: 'smartphoto-img-clone' 36 | }, 37 | message: { 38 | gotoNextImage: 'go to the next image', 39 | gotoPrevImage: 'go to the previous image', 40 | closeDialog: 'close the image dialog' 41 | }, 42 | arrows: true, 43 | nav: true, 44 | showAnimation: true, 45 | verticalGravity: false, 46 | useOrientationApi: false, 47 | useHistoryApi: true, 48 | swipeTopToClose: false, 49 | swipeBottomToClose: true, 50 | swipeOffset: 100, 51 | headerHeight: 60, 52 | footerHeight: 60, 53 | forceInterval: 10, 54 | registance: 0.5, 55 | loadOffset: 2, 56 | resizeStyle: 'fit', 57 | lazyAttribute: 'data-src' 58 | }; 59 | 60 | export default class SmartPhoto extends ATemplate { 61 | constructor(selector, settings) { 62 | super(); 63 | this.data = util.extend({}, defaults, settings); 64 | this.data.currentIndex = 0; 65 | this.data.oldIndex = 0; 66 | this.data.hide = true; 67 | this.data.group = {}; 68 | this.data.scaleSize = 1; 69 | this.data.scale = false; 70 | this.pos = { x: 0, y: 0 }; 71 | this.data.photoPosX = 0; 72 | this.data.photoPosY = 0; 73 | this.handlers = []; 74 | this.convert = { 75 | increment: this.increment, 76 | virtualPos: this.virtualPos, 77 | round: this.round 78 | }; 79 | this.data.groupItems = this.groupItems; 80 | this.elements = typeof selector === 'string' ? document.querySelectorAll(selector) : selector; 81 | const date = new Date(); 82 | this.tapSecond = date.getTime(); 83 | this.onListMove = false; 84 | this.clicked = false; 85 | this.id = this._getUniqId(); 86 | this.vx = 0; 87 | this.vy = 0; 88 | this.data.appearEffect = null; 89 | this.addTemplate(this.id, template); 90 | this.data.isSmartPhone = this._isSmartPhone(); 91 | const body = document.querySelector('body'); 92 | util.append(body, `
`); 93 | [].forEach.call(this.elements, (element) => { 94 | this.addNewItem(element); 95 | }); 96 | 97 | this.update(); 98 | const currentItem = this._getCurrentItemByHash(); 99 | if (currentItem) { 100 | util.triggerEvent(currentItem.element, 'click'); 101 | } 102 | 103 | this.interval = setInterval(() => { 104 | this._doAnim(); 105 | }, this.data.forceInterval); 106 | 107 | if (!this.data.isSmartPhone) { 108 | const resizeHandler = () => { 109 | if (!this.groupItems()) { 110 | return; 111 | } 112 | this._resetTranslate(); 113 | this._setPosByCurrentIndex(); 114 | this._setSizeByScreen(); 115 | this.update(); 116 | }; 117 | const keydownHandler = (e) => { 118 | const code = e.keyCode || e.which; 119 | if (this.data.hide === true) { 120 | return; 121 | } 122 | if (code === 37) { 123 | this.gotoSlide(this.data.prev); 124 | } else if (code === 39) { 125 | this.gotoSlide(this.data.next); 126 | } else if (code === 27) { 127 | this.hidePhoto(); 128 | } 129 | }; 130 | window.addEventListener('resize', resizeHandler); 131 | window.addEventListener('keydown', keydownHandler); 132 | this._registerRemoveEvent(window, 'resize', resizeHandler); 133 | this._registerRemoveEvent(window, 'keydown', keydownHandler); 134 | return; 135 | } 136 | 137 | const orientationChangeHandler = () => { 138 | if (!this.groupItems()) { 139 | return; 140 | } 141 | 142 | // 画像の配置をリセット 143 | this._resetTranslate(); 144 | this._setPosByCurrentIndex(); 145 | this._setHashByCurrentIndex(); 146 | this._setSizeByScreen(); 147 | this.update(); 148 | 149 | // orientationchangeが発火するタイミングとwindowのサイズが変化するタイミングが違うデバイスが存在する 150 | // その対策として、一定時間待機し、windowのサイズが変化しないかどうか確かめる 151 | // 変化した場合、もう一度画像の配置をリセットする 152 | const prevWidth = this._getWindowWidth(); // 現在の画面サイズ 153 | const timeout = 500; // 最大待機時間 154 | const photoResizeAfterWindowSizeChange = (time) => { 155 | new Promise((resolve) => { 156 | // 5ms秒待機 157 | setTimeout(() => { 158 | resolve(); 159 | }, 25); 160 | }).then(() => { 161 | if (prevWidth !== this._getWindowWidth()) { 162 | // windowのサイズが変化したら、画像の配置をリセット 163 | this._resetTranslate(); 164 | this._setPosByCurrentIndex(); 165 | this._setHashByCurrentIndex(); 166 | this._setSizeByScreen(); 167 | this.update(); 168 | } else if (time <= timeout) { 169 | // 待機時間内であれば再待機 170 | photoResizeAfterWindowSizeChange(time + 25); 171 | } 172 | }); 173 | }; 174 | photoResizeAfterWindowSizeChange(0); // 待機開始 175 | }; 176 | 177 | window.addEventListener('orientationchange', orientationChangeHandler); 178 | this._registerRemoveEvent(window, 'orientationchange', orientationChangeHandler); 179 | 180 | if (!this.data.useOrientationApi) { 181 | return; 182 | } 183 | 184 | const deviceorientationHandler = (e) => { 185 | const { orientation } = window; 186 | if (!e || !e.gamma || this.data.appearEffect) { 187 | return; 188 | } 189 | if (!this.isBeingZoomed && !this.photoSwipable && !this.data.elastic && this.data.scale) { 190 | if (orientation === 0) { 191 | this._calcGravity(e.gamma, e.beta); 192 | } else if (orientation === 90) { 193 | this._calcGravity(e.beta, e.gamma); 194 | } else if (orientation === -90) { 195 | this._calcGravity(-e.beta, -e.gamma); 196 | } else if (orientation === 180) { 197 | this._calcGravity(-e.gamma, -e.beta); 198 | } 199 | } 200 | }; 201 | 202 | window.addEventListener('deviceorientation', deviceorientationHandler); 203 | this._registerRemoveEvent(window, 'deviceorientation', deviceorientationHandler); 204 | } 205 | 206 | on(event, fn) { 207 | const photo = this._getElementByClass(this.data.classNames.smartPhoto); 208 | const handler = (e) => { 209 | fn.call(photo, e); 210 | }; 211 | photo.addEventListener(event, handler); 212 | this._registerRemoveEvent(photo, event, handler); 213 | } 214 | 215 | _registerRemoveEvent(target, event, handler) { 216 | this.handlers.push({ 217 | target, 218 | event, 219 | handler 220 | }); 221 | } 222 | 223 | destroy() { 224 | this.handlers.forEach((handler) => { 225 | handler.target.removeEventListener(handler.event, handler.handler); 226 | }); 227 | const wrapper = document.querySelector(`[data-id="${this.id}"]`); 228 | util.removeElement(wrapper); 229 | clearInterval(this.interval); 230 | this.removeTemplateEvents(); 231 | } 232 | 233 | increment(item) { 234 | return item + 1; 235 | } 236 | 237 | round(number) { 238 | return Math.round(number); 239 | } 240 | 241 | virtualPos(pos) { 242 | pos = parseInt(pos, 10); 243 | const item = this._getSelectedItem(); 244 | return pos / item.scale / this.data.scaleSize; 245 | } 246 | 247 | groupItems() { 248 | return this.data.group[this.data.currentGroup]; 249 | } 250 | 251 | _resetTranslate() { 252 | const items = this.groupItems(); 253 | items.forEach((item, index) => { 254 | item.translateX = this._getWindowWidth() * index; 255 | }); 256 | } 257 | 258 | addNewItem(element) { 259 | const groupId = element.getAttribute('data-group') || 'nogroup'; 260 | const { group } = this.data; 261 | if (groupId === 'nogroup') { 262 | element.setAttribute('data-group', 'nogroup'); 263 | } 264 | if (!group[groupId]) { 265 | group[groupId] = []; 266 | } 267 | const index = group[groupId].length; 268 | const body = document.querySelector('body'); 269 | const src = element.getAttribute('href'); 270 | const img = element.querySelector('img'); 271 | let thumb = src; 272 | if (img) { 273 | if (img.getAttribute(this.data.lazyAttribute)) { 274 | thumb = img.getAttribute(this.data.lazyAttribute); 275 | } else if (img.currentSrc) { 276 | thumb = img.currentSrc; 277 | } else { 278 | thumb = img.src; 279 | } 280 | } 281 | const item = { 282 | src, 283 | thumb, 284 | caption: element.getAttribute('data-caption'), 285 | groupId, 286 | translateX: this._getWindowWidth() * index, 287 | index, 288 | translateY: 0, 289 | width: 50, 290 | height: 50, 291 | id: element.getAttribute('data-id') || index, 292 | loaded: false, 293 | processed: false, 294 | element 295 | }; 296 | group[groupId].push(item); 297 | this.data.currentGroup = groupId; 298 | const id = element.getAttribute('data-id'); 299 | if (!id) { 300 | element.setAttribute('data-id', index); 301 | } 302 | element.setAttribute('data-index', index); 303 | const clickHandler = (event) => { 304 | event.preventDefault(); 305 | this.data.currentGroup = element.getAttribute('data-group'); 306 | this.data.currentIndex = parseInt(element.getAttribute('data-index'), 10); 307 | this._setHashByCurrentIndex(); 308 | const currentItem = this._getSelectedItem(); 309 | if (currentItem.loaded) { 310 | this._initPhoto(); 311 | this.addAppearEffect(element, currentItem); 312 | this.clicked = true; 313 | this.update(); 314 | body.style.overflow = 'hidden'; 315 | this._fireEvent('open'); 316 | } else { 317 | this._loadItem(currentItem).then(() => { 318 | this._initPhoto(); 319 | this.addAppearEffect(element, currentItem); 320 | this.clicked = true; 321 | this.update(); 322 | body.style.overflow = 'hidden'; 323 | this._fireEvent('open'); 324 | }); 325 | } 326 | }; 327 | element.addEventListener('click', clickHandler); 328 | this._registerRemoveEvent(element, 'click', clickHandler); 329 | } 330 | 331 | _initPhoto() { 332 | this.data.total = this.groupItems().length; 333 | this.data.hide = false; 334 | this.data.photoPosX = 0; 335 | this.data.photoPosY = 0; 336 | this._setPosByCurrentIndex(); 337 | this._setSizeByScreen(); 338 | this.setArrow(); 339 | if (this.data.resizeStyle === 'fill' && this.data.isSmartPhone) { 340 | this.data.scale = true; 341 | this.data.hideUi = true; 342 | this.data.scaleSize = this._getScaleBoarder(); 343 | } 344 | } 345 | 346 | onUpdated() { 347 | if (this.data.appearEffect && this.data.appearEffect.once) { 348 | this.data.appearEffect.once = false; 349 | this.execEffect().then(() => { 350 | this.data.appearEffect = null; 351 | this.data.appear = true; 352 | this.update(); 353 | }); 354 | } 355 | if (this.clicked) { 356 | this.clicked = false; 357 | const { classNames } = this.data; 358 | const caption = this._getElementByClass(classNames.smartPhotoCaption); 359 | caption.focus(); 360 | } 361 | } 362 | 363 | execEffect() { 364 | return new Promise((resolve) => { 365 | if (util.isOldIE()) { 366 | resolve(); 367 | } 368 | const { appearEffect, classNames } = this.data; 369 | const effect = this._getElementByClass(classNames.smartPhotoImgClone); 370 | const handler = () => { 371 | effect.removeEventListener('transitionend', handler, true); 372 | resolve(); 373 | }; 374 | effect.addEventListener('transitionend', handler, true); 375 | setTimeout(() => { 376 | effect.style.transform = `translate(${appearEffect.afterX}px, ${appearEffect.afterY}px) scale(${appearEffect.scale})`; 377 | }, 10); 378 | }); 379 | } 380 | 381 | addAppearEffect(element, item) { 382 | if (this.data.showAnimation === false) { 383 | this.data.appear = true; 384 | return; 385 | } 386 | const img = element.querySelector('img'); 387 | const pos = util.getViewPos(img); 388 | const appear = {}; 389 | let scale = 1; 390 | appear.width = img.offsetWidth; 391 | appear.height = img.offsetHeight; 392 | appear.top = pos.top; 393 | appear.left = pos.left; 394 | appear.once = true; 395 | if (img.getAttribute(this.data.lazyAttribute)) { 396 | appear.img = img.getAttribute(this.data.lazyAttribute); 397 | } else { 398 | appear.img = item.src; 399 | } 400 | const toX = this._getWindowWidth(); 401 | const toY = this._getWindowHeight(); 402 | const screenY = toY - this.data.headerHeight - this.data.footerHeight; 403 | 404 | if (this.data.resizeStyle === 'fill' && this.data.isSmartPhone) { 405 | if (img.offsetWidth > img.offsetHeight) { 406 | scale = toY / img.offsetHeight; 407 | } else { 408 | scale = toX / img.offsetWidth; 409 | } 410 | } else { 411 | if (appear.width >= appear.height) { 412 | if (item.height < screenY) { 413 | scale = item.width / appear.width; 414 | } else { 415 | scale = screenY / appear.height; 416 | } 417 | } else if (appear.height > appear.width) { 418 | if (item.height < screenY) { 419 | scale = item.height / appear.height; 420 | } else { 421 | scale = screenY / appear.height; 422 | } 423 | } 424 | if (appear.width * scale > toX) { 425 | scale = toX / appear.width; 426 | } 427 | } 428 | 429 | const x = (scale - 1) / 2 * img.offsetWidth + (toX - (img.offsetWidth * scale)) / 2; 430 | const y = (scale - 1) / 2 * img.offsetHeight + (toY - (img.offsetHeight * scale)) / 2; 431 | appear.afterX = x; 432 | appear.afterY = y; 433 | appear.scale = scale; 434 | this.data.appearEffect = appear; 435 | } 436 | 437 | hidePhoto(dir = 'bottom') { 438 | this.data.hide = true; 439 | this.data.appear = false; 440 | this.data.appearEffect = null; 441 | this.data.hideUi = false; 442 | this.data.scale = false; 443 | this.data.scaleSize = 1; 444 | const scrollX = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft; 445 | const scrollY = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop; 446 | const body = document.querySelector('body'); 447 | if (window.location.hash) { 448 | this._setHash(''); 449 | } 450 | window.scroll(scrollX, scrollY); 451 | this._doHideEffect(dir).then(() => { 452 | this.update(); 453 | body.style.overflow = ''; 454 | this._fireEvent('close'); 455 | }); 456 | } 457 | 458 | _doHideEffect(dir) { 459 | return new Promise((resolve) => { 460 | if (util.isOldIE()) { 461 | resolve(); 462 | } 463 | const { classNames } = this.data; 464 | const photo = this._getElementByClass(classNames.smartPhoto); 465 | const img = this._getElementByQuery(`.current .${classNames.smartPhotoImg}`); 466 | const height = this._getWindowHeight(); 467 | const handler = () => { 468 | photo.removeEventListener('transitionend', handler, true); 469 | resolve(); 470 | }; 471 | photo.style.opacity = 0; 472 | if (dir === 'bottom') { 473 | img.style.transform = `translateY(${height}px)`; 474 | } else if (dir === 'top') { 475 | img.style.transform = `translateY(-${height}px)`; 476 | } 477 | photo.addEventListener('transitionend', handler, true); 478 | }); 479 | } 480 | 481 | _getElementByClass(className) { 482 | return document.querySelector(`[data-id="${this.id}"] .${className}`); 483 | } 484 | 485 | _getElementByQuery(query) { 486 | return document.querySelector(`[data-id="${this.id}"] ${query}`); 487 | } 488 | 489 | _getTouchPos() { 490 | let x = 0; 491 | let y = 0; 492 | const e = typeof event === 'undefined' ? this.e : event; 493 | if (this._isTouched(e)) { 494 | x = e.touches[0].pageX; 495 | y = e.touches[0].pageY; 496 | } else if (e.pageX) { 497 | x = e.pageX; 498 | y = e.pageY; 499 | } 500 | return { x, y }; 501 | } 502 | 503 | _getGesturePos(e) { 504 | const touches = e.touches; 505 | return [ 506 | { x: touches[0].pageX, y: touches[0].pageY }, 507 | { x: touches[1].pageX, y: touches[1].pageY } 508 | ]; 509 | } 510 | 511 | _setPosByCurrentIndex() { 512 | const items = this.groupItems(); 513 | const moveX = -1 * items[this.data.currentIndex].translateX; 514 | this.pos.x = moveX; 515 | setTimeout(() => { 516 | this.data.translateX = moveX; 517 | this.data.translateY = 0; 518 | this._listUpdate(); 519 | }, 1); 520 | } 521 | 522 | _setHashByCurrentIndex() { 523 | const scrollX = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft; 524 | const scrollY = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop; 525 | const items = this.groupItems(); 526 | const id = items[this.data.currentIndex].id; 527 | const group = this.data.currentGroup; 528 | const hash = `group=${group}&photo=${id}`; 529 | this._setHash(hash); 530 | window.scroll(scrollX, scrollY); 531 | } 532 | 533 | _setHash(hash) { 534 | if (!(window.history && window.history.pushState) || !this.data.useHistoryApi) { 535 | return; 536 | } 537 | if (hash) { 538 | window.history.replaceState(null, null, `${location.pathname}${location.search}#${hash}`); 539 | } else { 540 | window.history.replaceState(null, null, `${location.pathname}${location.search}`); 541 | } 542 | } 543 | 544 | _getCurrentItemByHash() { 545 | const group = this.data.group; 546 | const hash = location.hash.substr(1); 547 | const hashObj = util.parseQuery(hash); 548 | let currentItem = null; 549 | const getCurrentItem = (item) => { 550 | if (hashObj.group === item.groupId && hashObj.photo === item.id) { 551 | currentItem = item; 552 | } 553 | }; 554 | Object.keys(group).forEach((key) => { 555 | group[key].forEach(getCurrentItem); 556 | }); 557 | return currentItem; 558 | } 559 | 560 | _loadItem(item) { 561 | return new Promise((resolve) => { 562 | const img = new Image(); 563 | img.onload = () => { 564 | item.width = img.width; 565 | item.height = img.height; 566 | item.loaded = true; 567 | resolve(); 568 | }; 569 | img.onerror = () => { 570 | resolve(); 571 | }; 572 | img.src = item.src; 573 | }); 574 | } 575 | 576 | _getItemByIndex(index) { 577 | const { data } = this; 578 | if (data.group[data.currentGroup][index]) { 579 | return data.group[data.currentGroup][index]; 580 | } 581 | return null; 582 | } 583 | 584 | _loadNeighborItems() { 585 | const index = this.data.currentIndex; 586 | const { loadOffset } = this.data; 587 | const from = index - loadOffset; 588 | const to = index + loadOffset; 589 | const promises = []; 590 | for (let i = from; i < to; i++) { 591 | const item = this._getItemByIndex(i); 592 | if (item && !item.loaded) { 593 | promises.push(this._loadItem(item)); 594 | } 595 | } 596 | if (promises.length) { 597 | Promise.all(promises).then(() => { 598 | this._initPhoto(); 599 | this.update(); 600 | }); 601 | } 602 | } 603 | 604 | _setSizeByScreen() { 605 | const windowX = this._getWindowWidth(); 606 | const windowY = this._getWindowHeight(); 607 | const headerHeight = this.data.headerHeight; 608 | const footerHeight = this.data.footerHeight; 609 | const screenY = windowY - (headerHeight + footerHeight); 610 | const items = this.groupItems(); 611 | items.forEach((item) => { 612 | if (!item.loaded) { 613 | return; 614 | } 615 | item.processed = true; 616 | item.scale = screenY / item.height; 617 | if (item.height < screenY) { 618 | item.scale = 1; 619 | } 620 | item.x = (item.scale - 1) / 2 * item.width + (windowX - (item.width * item.scale)) / 2; 621 | item.y = (item.scale - 1) / 2 * item.height + (windowY - (item.height * item.scale)) / 2; 622 | if (item.width * item.scale > windowX) { 623 | item.scale = windowX / item.width; 624 | item.x = (item.scale - 1) / 2 * item.width; 625 | } 626 | }); 627 | } 628 | 629 | _slideList() { 630 | this.data.scaleSize = 1; 631 | this.isBeingZoomed = false; 632 | this.data.hideUi = false; 633 | this.data.scale = false; 634 | this.data.photoPosX = 0; 635 | this.data.photoPosY = 0; 636 | this.data.onMoveClass = true; 637 | this._setPosByCurrentIndex(); 638 | this._setHashByCurrentIndex(); 639 | this._setSizeByScreen(); 640 | setTimeout(() => { 641 | const item = this._getSelectedItem(); 642 | this.data.onMoveClass = false; 643 | this.setArrow(); 644 | this.update(); 645 | if (this.data.oldIndex !== this.data.currentIndex) { 646 | this._fireEvent('change'); 647 | } 648 | this.data.oldIndex = this.data.currentIndex; 649 | this._loadNeighborItems(); 650 | if (!item.loaded) { 651 | this._loadItem(item).then(() => { 652 | this._initPhoto(); 653 | this.update(); 654 | }); 655 | } 656 | }, 200); 657 | } 658 | 659 | gotoSlide(index) { 660 | if (this.e && this.e.preventDefault) { 661 | this.e.preventDefault(); 662 | } 663 | this.data.currentIndex = parseInt(index, 10); 664 | if (!this.data.currentIndex) { 665 | this.data.currentIndex = 0; 666 | } 667 | this._slideList(); 668 | } 669 | 670 | setArrow() { 671 | const items = this.groupItems(); 672 | const length = items.length; 673 | const next = this.data.currentIndex + 1; 674 | const prev = this.data.currentIndex - 1; 675 | this.data.showNextArrow = false; 676 | this.data.showPrevArrow = false; 677 | if (next !== length) { 678 | this.data.next = next; 679 | this.data.showNextArrow = true; 680 | } 681 | if (prev !== -1) { 682 | this.data.prev = prev; 683 | this.data.showPrevArrow = true; 684 | } 685 | } 686 | 687 | beforeDrag() { 688 | if (this._isGestured(this.e)) { 689 | this.beforeGesture(); 690 | return; 691 | } 692 | this.isBeingZoomed = false; 693 | if (this.data.scale) { 694 | this.beforePhotoDrag(); 695 | return; 696 | } 697 | const pos = this._getTouchPos(); 698 | this.isSwipable = true; 699 | this.dragStart = true; 700 | this.firstPos = pos; 701 | this.oldPos = pos; 702 | } 703 | 704 | afterDrag() { 705 | const items = this.groupItems(); 706 | const date = new Date(); 707 | const tapSecond = date.getTime(); 708 | const offset = this.tapSecond - tapSecond; 709 | let swipeWidth = 0; 710 | let swipeHeight = 0; 711 | this.isSwipable = false; 712 | this.onListMove = false; 713 | 714 | if (this.oldPos) { 715 | swipeWidth = this.oldPos.x - this.firstPos.x; 716 | swipeHeight = this.oldPos.y - this.firstPos.y; 717 | } 718 | if (this.isBeingZoomed) { 719 | this.afterGesture(); 720 | return; 721 | } 722 | if (this.data.scale) { 723 | this.afterPhotoDrag(); 724 | return; 725 | } else if (!util.isSmartPhone() && swipeWidth === 0 && swipeHeight === 0) { 726 | this.zoomPhoto(); 727 | return; 728 | } 729 | if (Math.abs(offset) <= 500 && swipeWidth === 0 && swipeHeight === 0) { 730 | this.e.preventDefault(); 731 | this.zoomPhoto(); 732 | return; 733 | } 734 | this.tapSecond = tapSecond; 735 | this._fireEvent('swipeend'); 736 | if (this.moveDir === 'horizontal') { 737 | if (swipeWidth >= this.data.swipeOffset && this.data.currentIndex !== 0) { 738 | this.data.currentIndex -= 1; 739 | } else if (swipeWidth <= -this.data.swipeOffset && this.data.currentIndex !== items.length - 1) { 740 | this.data.currentIndex += 1; 741 | } 742 | this._slideList(); 743 | } 744 | if (this.moveDir === 'vertical') { 745 | if (this.data.swipeBottomToClose && swipeHeight >= this.data.swipeOffset) { 746 | this.hidePhoto('bottom'); 747 | } else if (this.data.swipeTopToClose && swipeHeight <= -this.data.swipeOffset) { 748 | this.hidePhoto('top'); 749 | } else { 750 | this.data.translateY = 0; 751 | this._slideList(); 752 | } 753 | } 754 | } 755 | 756 | onDrag() { 757 | this.e.preventDefault(); 758 | if (this._isGestured(this.e) && this.onListMove === false) { 759 | this.onGesture(); 760 | return; 761 | } 762 | if (this.isBeingZoomed) { 763 | return; 764 | } 765 | if (this.data.scale) { 766 | this.onPhotoDrag(); 767 | return; 768 | } 769 | if (!this.isSwipable) { 770 | return; 771 | } 772 | 773 | const pos = this._getTouchPos(); 774 | const x = pos.x - this.oldPos.x; 775 | const y = pos.y - this.firstPos.y; 776 | 777 | if (this.dragStart) { 778 | this._fireEvent('swipestart'); 779 | this.dragStart = false; 780 | if (Math.abs(x) > Math.abs(y)) { 781 | this.moveDir = 'horizontal'; 782 | } else { 783 | this.moveDir = 'vertical'; 784 | } 785 | } 786 | 787 | if (this.moveDir === 'horizontal') { 788 | this.pos.x += x; 789 | this.data.translateX = this.pos.x; 790 | } else { 791 | this.data.translateY = y; 792 | } 793 | this.onListMove = true; 794 | this.oldPos = pos; 795 | this._listUpdate(); 796 | } 797 | 798 | zoomPhoto() { 799 | this.data.hideUi = true; 800 | this.data.scaleSize = this._getScaleBoarder(); 801 | if (this.data.scaleSize <= 1) { 802 | return; 803 | } 804 | this.data.photoPosX = 0; 805 | this.data.photoPosY = 0; 806 | this._photoUpdate(); 807 | setTimeout(() => { 808 | this.data.scale = true; 809 | this._photoUpdate(); 810 | this._fireEvent('zoomin'); 811 | }, 300); 812 | } 813 | 814 | zoomOutPhoto() { 815 | this.data.scaleSize = 1; 816 | this.isBeingZoomed = false; 817 | this.data.hideUi = false; 818 | this.data.scale = false; 819 | this.data.photoPosX = 0; 820 | this.data.photoPosY = 0; 821 | this._photoUpdate(); 822 | this._fireEvent('zoomout'); 823 | } 824 | 825 | beforePhotoDrag() { 826 | const pos = this._getTouchPos(); 827 | this.photoSwipable = true; 828 | if (!this.data.photoPosX) { 829 | this.data.photoPosX = 0; 830 | } 831 | if (!this.data.photoPosY) { 832 | this.data.photoPosY = 0; 833 | } 834 | this.oldPhotoPos = pos; 835 | this.firstPhotoPos = pos; 836 | } 837 | 838 | onPhotoDrag() { 839 | if (!this.photoSwipable) { 840 | return; 841 | } 842 | this.e.preventDefault(); 843 | const pos = this._getTouchPos(); 844 | const x = pos.x - this.oldPhotoPos.x; 845 | const y = pos.y - this.oldPhotoPos.y; 846 | const moveX = this._round(this.data.scaleSize * x, 6); 847 | const moveY = this._round(this.data.scaleSize * y, 6); 848 | if (typeof moveX === 'number') { 849 | this.data.photoPosX += moveX; 850 | this.photoVX = moveX; 851 | } 852 | if (typeof moveY === 'number') { 853 | this.data.photoPosY += moveY; 854 | this.photoVY = moveY; 855 | } 856 | this.oldPhotoPos = pos; 857 | this._photoUpdate(); 858 | } 859 | 860 | afterPhotoDrag() { 861 | if (this.oldPhotoPos.x === this.firstPhotoPos.x && this.photoSwipable) { 862 | this.photoSwipable = false; 863 | this.zoomOutPhoto(); 864 | } else { 865 | this.photoSwipable = false; 866 | const item = this._getSelectedItem(); 867 | const bound = this._makeBound(item); 868 | const offset = this.data.swipeOffset * this.data.scaleSize; 869 | let flagX = 0; 870 | let flagY = 0; 871 | if (this.data.photoPosX > bound.maxX) { 872 | flagX = -1; 873 | } else if (this.data.photoPosX < bound.minX) { 874 | flagX = 1; 875 | } 876 | if (this.data.photoPosY > bound.maxY) { 877 | flagY = -1; 878 | } else if (this.data.photoPosY < bound.minY) { 879 | flagY = 1; 880 | } 881 | 882 | if (this.data.photoPosX - bound.maxX > offset && this.data.currentIndex !== 0) { 883 | this.gotoSlide(this.data.prev); 884 | return; 885 | } 886 | 887 | if (bound.minX - this.data.photoPosX > offset && this.data.currentIndex + 1 !== this.data.total) { 888 | this.gotoSlide(this.data.next); 889 | return; 890 | } 891 | 892 | // todo 893 | // if(this.data.photoPosY - bound.maxY > offset) { 894 | // this.hidePhoto(); 895 | // return; 896 | // } 897 | 898 | if (flagX === 0 && flagY === 0) { 899 | this.vx = this.photoVX / 5; 900 | this.vy = this.photoVY / 5; 901 | } else { 902 | this._registerElasticForce(flagX, flagY); 903 | } 904 | } 905 | } 906 | 907 | beforeGesture() { 908 | this._fireEvent('gesturestart'); 909 | const pos = this._getGesturePos(this.e); 910 | const distance = this._getDistance(pos[0], pos[1]); 911 | this.isBeingZoomed = true; 912 | this.oldDistance = distance; 913 | this.data.scale = true; 914 | this.e.preventDefault(); 915 | } 916 | 917 | onGesture() { 918 | const pos = this._getGesturePos(this.e); 919 | const distance = this._getDistance(pos[0], pos[1]); 920 | const size = (distance - this.oldDistance) / 100; 921 | const oldScaleSize = this.data.scaleSize; 922 | const posX = this.data.photoPosX; 923 | const posY = this.data.photoPosY; 924 | this.isBeingZoomed = true; 925 | this.data.scaleSize += this._round(size, 6); 926 | if (this.data.scaleSize < 0.2) { 927 | this.data.scaleSize = 0.2; 928 | } 929 | // todo 930 | if (this.data.scaleSize < oldScaleSize) { 931 | this.data.photoPosX = (1 + this.data.scaleSize - oldScaleSize) * posX; 932 | this.data.photoPosY = (1 + this.data.scaleSize - oldScaleSize) * posY; 933 | } 934 | 935 | if (this.data.scaleSize < 1 || this.data.scaleSize > this._getScaleBoarder()) { 936 | this.data.hideUi = true; 937 | } else { 938 | this.data.hideUi = false; 939 | } 940 | this.oldDistance = distance; 941 | this.e.preventDefault(); 942 | this._photoUpdate(); 943 | } 944 | 945 | afterGesture() { 946 | if (this.data.scaleSize > this._getScaleBoarder()) { 947 | return; 948 | } 949 | this.data.photoPosX = 0; 950 | this.data.photoPosY = 0; 951 | this.data.scale = false; 952 | this.data.scaleSize = 1; 953 | this.data.hideUi = false; 954 | this._fireEvent('gestureend'); 955 | this._photoUpdate(); 956 | } 957 | 958 | _getForceAndTheta(vx, vy) { 959 | return { 960 | force: Math.sqrt((vx * vx) + (vy * vy)), 961 | theta: Math.atan2(vy, vx) 962 | }; 963 | } 964 | 965 | _getScaleBoarder() { 966 | const item = this._getSelectedItem(); 967 | const windowWidth = this._getWindowWidth(); 968 | const windowHeight = this._getWindowHeight(); 969 | if (!util.isSmartPhone()) { 970 | return 1 / item.scale; 971 | } 972 | if (item.width > item.height) { 973 | return windowHeight / (item.height * item.scale); 974 | } 975 | return windowWidth / (item.width * item.scale); 976 | } 977 | 978 | _makeBound(item) { 979 | const width = item.width * item.scale * this.data.scaleSize; 980 | const height = item.height * item.scale * this.data.scaleSize; 981 | let minX; 982 | let minY; 983 | let maxX; 984 | let maxY; 985 | const windowWidth = this._getWindowWidth(); 986 | const windowHeight = this._getWindowHeight(); 987 | if (windowWidth > width) { 988 | maxX = (windowWidth - width) / 2; 989 | minX = -1 * maxX; 990 | } else { 991 | maxX = (width - windowWidth) / 2; 992 | minX = -1 * maxX; 993 | } 994 | if (windowHeight > height) { 995 | maxY = (windowHeight - height) / 2; 996 | minY = -1 * maxY; 997 | } else { 998 | maxY = (height - windowHeight) / 2; 999 | minY = -1 * maxY; 1000 | } 1001 | return { 1002 | minX: this._round(minX, 6) * this.data.scaleSize, 1003 | minY: this._round(minY, 6) * this.data.scaleSize, 1004 | maxX: this._round(maxX, 6) * this.data.scaleSize, 1005 | maxY: this._round(maxY, 6) * this.data.scaleSize 1006 | }; 1007 | } 1008 | 1009 | _registerElasticForce(x, y) { 1010 | const item = this._getSelectedItem(); 1011 | const bound = this._makeBound(item); 1012 | this.data.elastic = true; 1013 | if (x === 1) { 1014 | this.data.photoPosX = bound.minX; 1015 | } else if (x === -1) { 1016 | this.data.photoPosX = bound.maxX; 1017 | } 1018 | if (y === 1) { 1019 | this.data.photoPosY = bound.minY; 1020 | } else if (y === -1) { 1021 | this.data.photoPosY = bound.maxY; 1022 | } 1023 | this._photoUpdate(); 1024 | setTimeout(() => { 1025 | this.data.elastic = false; 1026 | this._photoUpdate(); 1027 | }, 300); 1028 | } 1029 | 1030 | _getSelectedItem() { 1031 | const data = this.data; 1032 | const index = data.currentIndex; 1033 | return data.group[data.currentGroup][index]; 1034 | } 1035 | 1036 | _getUniqId() { 1037 | return (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase(); 1038 | } 1039 | 1040 | _getDistance(point1, point2) { 1041 | const x = point1.x - point2.x; 1042 | const y = point1.y - point2.y; 1043 | return Math.sqrt((x * x) + (y * y)); 1044 | } 1045 | 1046 | _round(val, precision) { 1047 | const digit = Math.pow(10, precision); 1048 | val *= digit; 1049 | val = Math.round(val); 1050 | val /= digit; 1051 | return val; 1052 | } 1053 | 1054 | _isTouched(e) { 1055 | if (e && e.touches) { 1056 | return true; 1057 | } 1058 | return false; 1059 | } 1060 | 1061 | _isGestured(e) { 1062 | if (e && e.touches && e.touches.length > 1) { 1063 | return true; 1064 | } 1065 | return false; 1066 | } 1067 | 1068 | _isSmartPhone() { 1069 | const agent = navigator.userAgent; 1070 | if (agent.indexOf('iPhone') > 0 || agent.indexOf('iPad') > 0 1071 | || agent.indexOf('ipod') > 0 || agent.indexOf('Android') > 0) { 1072 | return true; 1073 | } 1074 | return false; 1075 | } 1076 | 1077 | _calcGravity(gamma, beta) { 1078 | if (gamma > 5 || gamma < -5) { 1079 | this.vx += gamma * 0.05; 1080 | } 1081 | if (this.data.verticalGravity === false) { 1082 | return; 1083 | } 1084 | if (beta > 5 || beta < -5) { 1085 | this.vy += beta * 0.05; 1086 | } 1087 | } 1088 | 1089 | _photoUpdate() { 1090 | const classNames = this.data.classNames; 1091 | const current = this._getElementByQuery('.current'); 1092 | const img = current.querySelector(`.${classNames.smartPhotoImg}`); 1093 | const nav = this._getElementByQuery(`.${classNames.smartPhotoNav}`); 1094 | const arrows = this._getElementByQuery(`.${classNames.smartPhotoArrows}`); 1095 | const photoPosX = this.virtualPos(this.data.photoPosX); 1096 | const photoPosY = this.virtualPos(this.data.photoPosY); 1097 | const scaleSize = this.data.scaleSize; 1098 | const transform = `translate(${photoPosX}px,${photoPosY}px) scale(${scaleSize})`; 1099 | 1100 | img.style.transform = transform; 1101 | if (this.data.scale) { 1102 | util.addClass(img, classNames.smartPhotoImgOnMove); 1103 | } else { 1104 | util.removeClass(img, classNames.smartPhotoImgOnMove); 1105 | } 1106 | if (this.data.elastic) { 1107 | util.addClass(img, classNames.smartPhotoImgElasticMove); 1108 | } else { 1109 | util.removeClass(img, classNames.smartPhotoImgElasticMove); 1110 | } 1111 | if (this.data.hideUi) { 1112 | if (nav) { 1113 | nav.setAttribute('aria-hidden', 'true'); 1114 | } 1115 | if (arrows) { 1116 | arrows.setAttribute('aria-hidden', 'true'); 1117 | } 1118 | } else { 1119 | if (nav) { 1120 | nav.setAttribute('aria-hidden', 'false'); 1121 | } 1122 | if (arrows) { 1123 | arrows.setAttribute('aria-hidden', 'false'); 1124 | } 1125 | } 1126 | } 1127 | 1128 | _getWindowWidth() { 1129 | if (document && document.documentElement) { 1130 | return document.documentElement.clientWidth; 1131 | } else if (window && window.innerWidth) { 1132 | return window.innerWidth; 1133 | } 1134 | return 0; 1135 | } 1136 | 1137 | _getWindowHeight() { 1138 | if (document && document.documentElement) { 1139 | return document.documentElement.clientHeight; 1140 | } else if (window && window.innerHeight) { 1141 | return window.innerHeight; 1142 | } 1143 | return 0; 1144 | } 1145 | 1146 | _listUpdate() { 1147 | const classNames = this.data.classNames; 1148 | const list = this._getElementByQuery(`.${classNames.smartPhotoList}`); 1149 | const transform = `translate(${this.data.translateX}px,${this.data.translateY}px)`; 1150 | list.style.transform = transform; 1151 | // $list 1152 | if (this.data.onMoveClass) { 1153 | util.addClass(list, classNames.smartPhotoListOnMove); 1154 | } else { 1155 | util.removeClass(list, classNames.smartPhotoListOnMove); 1156 | } 1157 | } 1158 | 1159 | _fireEvent(eventName) { 1160 | const photo = this._getElementByClass(this.data.classNames.smartPhoto); 1161 | util.triggerEvent(photo, eventName); 1162 | } 1163 | 1164 | _doAnim() { 1165 | if (this.isBeingZoomed || 1166 | this.isSwipable || 1167 | this.photoSwipable || 1168 | this.data.elastic || 1169 | !this.data.scale 1170 | ) { 1171 | return; 1172 | } 1173 | this.data.photoPosX += this.vx; 1174 | this.data.photoPosY += this.vy; 1175 | const item = this._getSelectedItem(); 1176 | const bound = this._makeBound(item); 1177 | if (this.data.photoPosX < bound.minX) { 1178 | this.data.photoPosX = bound.minX; 1179 | this.vx *= -0.2; 1180 | } else if (this.data.photoPosX > bound.maxX) { 1181 | this.data.photoPosX = bound.maxX; 1182 | this.vx *= -0.2; 1183 | } 1184 | if (this.data.photoPosY < bound.minY) { 1185 | this.data.photoPosY = bound.minY; 1186 | this.vy *= -0.2; 1187 | } else if (this.data.photoPosY > bound.maxY) { 1188 | this.data.photoPosY = bound.maxY; 1189 | this.vy *= -0.2; 1190 | } 1191 | const power = this._getForceAndTheta(this.vx, this.vy); 1192 | let force = power.force; 1193 | const theta = power.theta; 1194 | force -= this.data.registance; 1195 | if (Math.abs(force) < 0.5) { 1196 | return; 1197 | } 1198 | this.vx = Math.cos(theta) * force; 1199 | this.vy = Math.sin(theta) * force; 1200 | this._photoUpdate(); 1201 | } 1202 | } 1203 | -------------------------------------------------------------------------------- /src/core/viwer.html: -------------------------------------------------------------------------------- 1 |
aria-hidden="true" aria-hidden="false" role="dialog"> 2 |
3 |
4 |
5 | {currentIndex}[increment]/{total} 6 | {caption} 7 | 8 |
9 |
data-action-touchstart="beforeDrag" data-action-touchmove="onDrag" data-action-touchend="afterDrag(false)" data-action-click="hidePhoto()"> 10 |
11 |
    12 | 13 |
  • 14 | 15 |
    data-action-mousemove="onDrag" data-action-mousedown="beforeDrag" data-action-mouseup="afterDrag" data-action-touchstart="beforeDrag" data-action-touchmove="onDrag" data-action-touchend="afterDrag"> 16 | 17 |
    18 | 19 | 20 |
    21 | 22 |
    23 | 24 |
  • 25 | 26 |
27 | 28 | 32 | 33 | 34 | 41 | 42 |
43 | 44 | 47 | 48 |
49 |
50 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./core/'); 4 | -------------------------------------------------------------------------------- /src/lib/util.js: -------------------------------------------------------------------------------- 1 | export const isSmartPhone = () => { 2 | const agent = navigator.userAgent 3 | if (agent.indexOf('iPhone') > 0 || agent.indexOf('iPad') > 0 4 | || agent.indexOf('ipod') > 0 || agent.indexOf('Android') > 0) { 5 | return true 6 | } else { 7 | return false 8 | } 9 | } 10 | 11 | function deepExtend(out){ 12 | out = out || {}; 13 | 14 | for (var i = 1; i < arguments.length; i++) { 15 | var obj = arguments[i]; 16 | if (!obj) { 17 | continue; 18 | } 19 | 20 | for (var key in obj) { 21 | if (obj.hasOwnProperty(key)) { 22 | if (typeof obj[key] === 'object') 23 | out[key] = deepExtend(out[key], obj[key]); 24 | else 25 | out[key] = obj[key]; 26 | } 27 | } 28 | } 29 | 30 | return out; 31 | }; 32 | 33 | export const extend = deepExtend; 34 | 35 | export const triggerEvent = (el, eventName, options) => { 36 | let event; 37 | if (window.CustomEvent) { 38 | event = new CustomEvent(eventName, {cancelable:true}); 39 | } else { 40 | event = document.createEvent('CustomEvent'); 41 | event.initCustomEvent(eventName, false, false, options); 42 | } 43 | el.dispatchEvent(event); 44 | } 45 | 46 | export const parseQuery = (query) => { 47 | var s = query.split('&'), 48 | data = {}, 49 | i = 0, 50 | iz = s.length, 51 | param, key, value; 52 | for (; i < iz; i++) { 53 | param = s[i].split('='); 54 | if (param[0] !== void 0) { 55 | key = param[0]; 56 | value = (param[1] !== void 0) ? param.slice(1).join('=') : key; 57 | data[key] = decodeURIComponent(value); 58 | } 59 | } 60 | return data; 61 | } 62 | 63 | export const getViewPos = (element) => { 64 | return { 65 | left: element.getBoundingClientRect().left, 66 | top: element.getBoundingClientRect().top, 67 | } 68 | } 69 | 70 | export const removeElement = (element) => { 71 | if(element && element.parentNode) { 72 | element.parentNode.removeChild(element); 73 | } 74 | } 75 | 76 | export const append = (element, string) => { 77 | const div = document.createElement('div'); 78 | div.innerHTML = string; 79 | while (div.children.length > 0) { 80 | element.appendChild(div.children[0]); 81 | } 82 | } 83 | 84 | export const addClass = (element,className) => { 85 | if (element.classList) { 86 | element.classList.add(className); 87 | } else { 88 | element.className += ` ${className}`; 89 | } 90 | } 91 | 92 | export const removeClass = (element,className) => { 93 | if (element.classList) { 94 | element.classList.remove(className); 95 | } else { 96 | element.className = element.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); 97 | } 98 | } 99 | 100 | export const getBrowser = () => { 101 | const ua = window.navigator.userAgent.toLowerCase(); 102 | const ver = window.navigator.appVersion.toLowerCase(); 103 | let name = 'unknown'; 104 | 105 | if (ua.indexOf('msie') != -1) { 106 | if (ver.indexOf('msie 6.') != -1) { 107 | name = 'ie6'; 108 | } else if (ver.indexOf('msie 7.') != -1) { 109 | name = 'ie7'; 110 | } else if (ver.indexOf('msie 8.') != -1) { 111 | name = 'ie8'; 112 | } else if (ver.indexOf('msie 9.') != -1) { 113 | name = 'ie9'; 114 | } else if (ver.indexOf('msie 10.') != -1) { 115 | name = 'ie10'; 116 | } else { 117 | name = 'ie'; 118 | } 119 | } else if (ua.indexOf('trident/7') != -1) { 120 | name = 'ie11'; 121 | } else if (ua.indexOf('chrome') != -1) { 122 | name = 'chrome'; 123 | } else if (ua.indexOf('safari') != -1) { 124 | name = 'safari'; 125 | } else if (ua.indexOf('opera') != -1) { 126 | name = 'opera'; 127 | } else if (ua.indexOf('firefox') != -1) { 128 | name = 'firefox'; 129 | } 130 | return name; 131 | } 132 | 133 | export const isOldIE = () => { 134 | const browser = getBrowser(); 135 | if (browser.indexOf('ie') !== -1) { 136 | if (parseInt(browser.replace(/[^0-9]/g, '')) <= 10 ) { 137 | return true; 138 | } 139 | } 140 | return false; 141 | } -------------------------------------------------------------------------------- /test/preload.js: -------------------------------------------------------------------------------- 1 | window.__nightmare = {}; 2 | __nightmare.ipc = require('electron').ipcRenderer; 3 | __nightmare.sliced = require('sliced'); 4 | 5 | // Listen for error events 6 | window.addEventListener('error', function(e) { 7 | __nightmare.ipc.send('page', 'error', e.message, e.error.stack); 8 | }); 9 | 10 | (function(){ 11 | // listen for console.log 12 | var defaultLog = console.log; 13 | console.log = function() { 14 | __nightmare.ipc.send('console', 'log', __nightmare.sliced(arguments)); 15 | return defaultLog.apply(this, arguments); 16 | }; 17 | 18 | // listen for console.warn 19 | var defaultWarn = console.warn; 20 | console.warn = function() { 21 | __nightmare.ipc.send('console', 'warn', __nightmare.sliced(arguments)); 22 | return defaultWarn.apply(this, arguments); 23 | }; 24 | 25 | // listen for console.error 26 | var defaultError = console.error; 27 | console.error = function() { 28 | __nightmare.ipc.send('console', 'error', __nightmare.sliced(arguments)); 29 | return defaultError.apply(this, arguments); 30 | }; 31 | 32 | // overwrite the default alert 33 | window.alert = function(message){ 34 | __nightmare.ipc.send('page', 'alert', message); 35 | }; 36 | 37 | // overwrite the default prompt 38 | window.prompt = function(message, defaultResponse){ 39 | __nightmare.ipc.send('page', 'prompt', message, defaultResponse); 40 | } 41 | 42 | // overwrite the default confirm 43 | window.confirm = function(message, defaultResponse){ 44 | __nightmare.ipc.send('page', 'confirm', message, defaultResponse); 45 | return true; 46 | } 47 | })() -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const Nightmare = require('nightmare'); 2 | const assert = require('assert'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const test_url = "file:///"+path.resolve(__dirname,"../examples/vanilla.html"); 6 | const hash_url = test_url + "#group=nogroup&photo=rhino"; 7 | 8 | const nightmare = Nightmare({ 9 | webPreferences : { 10 | partition : 'nopersist', 11 | preload: path.resolve(__dirname,'./preload.js') 12 | }, 13 | show: true 14 | }); 15 | 16 | describe('test',() => { 17 | it('caption', (done) => { 18 | nightmare.goto(test_url) 19 | .click('[data-caption="Lion"]') 20 | .wait(1000) 21 | .click('.smartphoto-arrow-right a') 22 | .wait(1000) 23 | .evaluate(() => { 24 | return document.querySelector('.smartphoto-caption').innerText; 25 | }) 26 | .then((result) => { 27 | assert.equal(result,'Camel'); 28 | done(); 29 | }) 30 | .catch((error) => { 31 | done(error); 32 | }); 33 | }); 34 | 35 | it('hash', (done) => { 36 | nightmare.goto(hash_url) 37 | .wait(1000) 38 | .evaluate(() => { 39 | return document.querySelector('.smartphoto-caption').innerText; 40 | }) 41 | .then(result => { 42 | assert.equal(result,'Rhino'); 43 | done(); 44 | }) 45 | .catch(error => { 46 | done(error); 47 | }); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /tools/index.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const cmd = require('node-cmd'); 3 | const co = require('co'); 4 | const fs = require('fs-extra'); 5 | const pkg = require('../package.json'); 6 | 7 | const SystemPromise = (cmd_string) => { 8 | return new Promise((resolve, reject) => { 9 | cmd.get( 10 | cmd_string, 11 | (data, err, stderr) => { 12 | if ( err ) { 13 | console.log(err) 14 | } 15 | if ( stderr ) { 16 | console.log(stderr) 17 | } 18 | resolve(data) 19 | } 20 | ) 21 | }) 22 | } 23 | 24 | co(function *() { 25 | try { 26 | yield SystemPromise(`git add -A`); 27 | yield SystemPromise(`git commit -m "v${pkg.version}"`); 28 | yield SystemPromise(`git push origin v${pkg.version}`); 29 | yield SystemPromise(`git push origin master`); 30 | yield SystemPromise(`npm publish`); 31 | } catch ( err ) { 32 | console.log(err) 33 | } 34 | }); --------------------------------------------------------------------------------