├── src ├── index.js └── preview.vue ├── postcss.config.js ├── .babelrc ├── .gitignore ├── .eslintrc.js ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── package.json ├── webpack.config.js └── README.md /src/index.js: -------------------------------------------------------------------------------- 1 | import vuePicturePreview from './preview.vue'; 2 | 3 | export default vuePicturePreview; 4 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer') // 引用autoprefixer模块 4 | ] 5 | }; 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "modules": false 7 | } 8 | ] 9 | ] 10 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | /test/unit/coverage/ 7 | demo.gif 8 | dist/ 9 | 10 | # Editor directories and files 11 | .idea 12 | .vscode 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | es6: true 7 | }, 8 | extends: [ 9 | 'plugin:vue/essential', 10 | 'eslint:recommended' 11 | ], 12 | parserOptions: { 13 | parser: 'babel-eslint' 14 | }, 15 | rules: {} 16 | }; 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 xLogic 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-picture-preview", 3 | "version": "2.0.1", 4 | "description": "移动端、PC 端 Vue.js 图片预览插件 | Mobile-friendly picture file preview Vue.js plugin with horizontal nav and bottom title.", 5 | "main": "dist/vue-picture-preview.js", 6 | "scripts": { 7 | "build": "webpack --config webpack.config.js --mode=production", 8 | "lint": "eslint --ext .js --ext .vue src/", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/xlogiccc/vue-picture-preview.git" 14 | }, 15 | "keywords": [ 16 | "Vue", 17 | "Plugin", 18 | "Picture", 19 | "Img", 20 | "Preview", 21 | "Photo" 22 | ], 23 | "author": "xLogic", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/xlogiccc/vue-picture-preview/issues" 27 | }, 28 | "homepage": "https://github.com/xlogiccc/vue-picture-preview#readme", 29 | "devDependencies": { 30 | "@babel/core": "^7.5.4", 31 | "@babel/preset-env": "^7.5.4", 32 | "autoprefixer": "^9.7.2", 33 | "babel-eslint": "^10.0.1", 34 | "babel-loader": "^8.0.6", 35 | "clean-webpack-plugin": "^3.0.0", 36 | "css-loader": "^3.2.0", 37 | "eslint": "^5.16.0", 38 | "eslint-friendly-formatter": "^4.0.1", 39 | "eslint-loader": "^3.0.2", 40 | "eslint-plugin-vue": "^5.2.3", 41 | "file-loader": "^4.2.0", 42 | "postcss-loader": "^3.0.0", 43 | "style-loader": "^1.0.0", 44 | "url-loader": "^2.2.0", 45 | "vue": "^2.6.10", 46 | "vue-loader": "^15.7.2", 47 | "vue-template-compiler": "^2.6.10", 48 | "webpack": "^4.41.2", 49 | "webpack-cli": "^3.3.10" 50 | }, 51 | "browserslist": [ 52 | "iOS >= 7", 53 | "Android >= 4" 54 | ], 55 | "dependencies": { 56 | "x-photoswipe": "^4.1.3-rc.1" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); // webpack 4版本之后加的,之前的版本不需要这个 4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 引入CleanWebpackPlugin插件 5 | 6 | let config = { 7 | entry: path.resolve(__dirname, './src/index.js'), // 以join拼接path的形式配置绝对路径,相对路径打包后找不到会报错 8 | output: { 9 | path: path.join(__dirname, 'dist'), 10 | filename: 'vue-picture-preview.js', 11 | library: 'vue-picture-preview', 12 | libraryTarget: 'umd', 13 | umdNamedDefine: true 14 | }, 15 | resolve: { 16 | extensions: ['.js', '.vue', '.json'], 17 | alias: { 18 | vue$: 'vue/dist/vue.esm.js', 19 | '@': path.resolve('src') 20 | } 21 | }, 22 | devtool: 'hidden-source-map', 23 | module: { 24 | rules: [ 25 | { 26 | test: /\.(js|vue)$/, 27 | loader: 'eslint-loader', 28 | enforce: 'pre', 29 | include: [path.resolve('src'), path.resolve('test')], 30 | options: { 31 | formatter: require('eslint-friendly-formatter') 32 | } 33 | }, 34 | { 35 | test: /\.vue$/, 36 | loader: 'vue-loader' 37 | }, 38 | { 39 | test: /\.js$/, 40 | loader: 'babel-loader', 41 | include: [path.resolve('src'), path.resolve('test')] 42 | }, 43 | { 44 | test: /\.css$/, 45 | use: ['style-loader', 'css-loader', 'postcss-loader'] 46 | }, 47 | { 48 | test: /\.(png|jpg|jpeg|gif|svg)$/, 49 | use: { 50 | loader: 'url-loader', 51 | options: { 52 | limit: 10000, // 判断图片的大小 如果小于10000就会转换成base64 53 | name: '[name].[ext]' // 输出图片的名字 ext是扩展名 54 | } 55 | } 56 | } 57 | ] 58 | }, 59 | plugins: [ 60 | new VueLoaderPlugin(), 61 | new webpack.BannerPlugin(`Vue-Picture-Preview v2.0.0\n(c) 2018-${new Date().getFullYear()} xLogic\nReleased under the MIT License.`), // new一个插件的实例 62 | new webpack.ProgressPlugin(), 63 | new CleanWebpackPlugin() 64 | ] 65 | }; 66 | 67 | module.exports = config; 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-picture-preview 2 | 3 | 移动端、PC 端 Vue.js 图片预览插件 | Friendly picture file preview Vue.js plugin based on PhotoSwipe. 4 | 5 | [![Github](https://img.shields.io/github/stars/xlogiccc/vue-picture-preview.svg?style=social&label=Star)](https://github.com/xlogiccc/vue-picture-preview) [![Github](https://img.shields.io/github/forks/xlogiccc/vue-picture-preview.svg?style=social&label=Fork)](https://github.com/xlogiccc/vue-picture-preview) [![Github](https://img.shields.io/github/watchers/xlogiccc/vue-picture-preview.svg?style=social&label=Watch)](https://github.com/xlogiccc/vue-picture-preview) 6 | 7 | [![License](https://img.shields.io/npm/l/vue-picture-preview.svg?style=flat-square)](https://www.npmjs.org/package/vue-picture-preview) [![vue-picture-preview](https://img.shields.io/npm/v/vue-picture-preview.svg?style=flat-square)](https://www.npmjs.org/package/vue-picture-preview) [![NPM downloads](http://img.shields.io/npm/dm/vue-picture-preview.svg?style=flat-square)](https://npmjs.org/package/vue-picture-preview) [![NPM downloads](http://img.shields.io/npm/dt/vue-picture-preview.svg?style=flat-square)](https://npmjs.org/package/vue-picture-preview) 8 | 9 | 10 | 11 | ![demo](https://tva1.sinaimg.cn/large/006y8mN6ly1g95s5gzoc5j30xr0u00tk.jpg) 12 | 13 | 14 | 15 | ## 安装 16 | 17 | ```sh 18 | npm install --save vue-picture-preview 19 | ``` 20 | 21 | 22 | 23 | ## 使用 24 | 25 | 入口文件中全局引入 26 | 27 | ```javascript 28 | import Vue from 'vue' 29 | import vuePicturePreview from 'vue-picture-preview'; 30 | 31 | Vue.component('Previewer', vuePicturePreview); 32 | ``` 33 | 34 | 按需局部引入 35 | 36 | ```javascript 37 | import vuePicturePreview from 'vue-picture-preview'; 38 | 39 | export default { 40 | components: { 41 | Previewer: vuePicturePreview 42 | } 43 | } 44 | ``` 45 | 46 | 示例 47 | 48 | ```HTML 49 |
50 | 58 | 59 |
60 | ``` 61 | 62 | ```javascript 63 | export default { 64 | data() { 65 | return { 66 | list: [ 67 | { 68 | msrc: 69 | 'https://tva1.sinaimg.cn/thumbnail/006y8mN6ly1g95rjyub5bj30go0b40wc.jpg', 70 | src: 71 | 'https://tva1.sinaimg.cn/large/006y8mN6ly1g95rjyub5bj30go0b40wc.jpg', 72 | w: 600, 73 | h: 400 74 | }, 75 | { 76 | msrc: 77 | 'https://tva1.sinaimg.cn/thumbnail/006y8mN6ly1g95rmt8pq4j30go0b4n28.jpg', 78 | src: 79 | 'https://tva1.sinaimg.cn/large/006y8mN6ly1g95rmt8pq4j30go0b4n28.jpg', 80 | w: 600, 81 | h: 400 82 | }, 83 | { 84 | msrc: 85 | 'https://tva1.sinaimg.cn/thumbnail/006y8mN6ly1g95rn3grt6j30go0b4n0w.jpg', 86 | src: 87 | 'https://tva1.sinaimg.cn/large/006y8mN6ly1g95rn3grt6j30go0b4n0w.jpg', 88 | w: 600, 89 | h: 400 90 | } 91 | ], 92 | options: { 93 | getThumbBoundsFn(index) { 94 | // find thumbnail element 95 | let thumbnail = document.querySelectorAll('.previewer-demo-img')[ 96 | index 97 | ]; 98 | // get window scroll Y 99 | let pageYScroll = 100 | window.pageYOffset || document.documentElement.scrollTop; 101 | // optionally get horizontal scroll 102 | // get position of element relative to viewport 103 | let rect = thumbnail.getBoundingClientRect(); 104 | // w = width 105 | return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; 106 | // Good guide on how to get element coordinates: 107 | // http://javascript.info/tutorial/coordinates 108 | } 109 | } 110 | }; 111 | }, 112 | methods: { 113 | show(index) { 114 | // 显示特定index的图片,使用ref 115 | this.$refs.previewer.show(index); 116 | } 117 | } 118 | }; 119 | ``` 120 | 121 | 122 | 123 | ## 属性 124 | 125 | | 名字 | 类型 | 默认值 | 说明 | 版本要求 | 126 | | ------- | -------- | ------ | ------------------------------------------------------------ | -------- | 127 | | list | `array` | | 图片列表 | 2.0.1 | 128 | | options | `object` | | [PhotoSwipe的配置](https://photoswipe.com/documentation/options.html) | 2.0.1 | 129 | 130 | 131 | 132 | ## 事件 133 | 134 | | 名字 | 参数 | 说明 | 版本要求 | 135 | | ---------------- | ---- | -------------------------------- | -------- | 136 | | @on-close | - | 关闭时触发 | 2.0.1 | 137 | | @on-index-change | - | 切换图片后触发(首次打开不会触发) | 2.0.1 | 138 | 139 | 140 | 141 | ## 插槽 142 | 143 | | 名字 | 说明 | 版本要求 | 144 | | ------------- | -------------------------------- | -------- | 145 | | button-after | 操作按钮之后,可以添加自定义图标 | 2.0.1 | 146 | | button-before | 操作按钮之前,可以添加自定义图标 | 2.0.1 | 147 | 148 | 149 | 150 | ## 方法 151 | 152 | | 名字 | 参数 | 说明 | 版本要求 | 153 | | --------------- | ----- | ---------------- | -------- | 154 | | goTo | index | 跳转到特定图片 | 2.0.1 | 155 | | prev | - | 跳转到上一张 | 2.0.1 | 156 | | next | - | 跳转到下一张 | 2.0.1 | 157 | | getCurrentIndex | - | 获取当前图片索引 | 2.0.1 | 158 | 159 | 160 | 161 | ## 重要提示 162 | 163 | - **注意避免使用过大图片**: 否则可能会出现卡顿黑屏的情况(尤其是在 Android 机子上) 164 | - **建议为所有图片定义尺寸**: PhotoSwipe 本身要求设置宽高,本组件会尝试对没有设置宽高的图片先加载再显示,可能会造成性能问题或者宽带浪费。 165 | 166 | -------------------------------------------------------------------------------- /src/preview.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 209 | 210 | --------------------------------------------------------------------------------