当前位置:   article > 正文

uni-app 上传图片_uniapp上传图片

uniapp上传图片

一、效果图

 二、components/Upload-image.vue

  1. <template>
  2. <view class="con">
  3. <template v-if="viewWidth">
  4. <movable-area class="area" :style="{ height: areaHeight }" @mouseenter="mouseenter" @mouseleave="mouseleave">
  5. <movable-view v-for="(item, index) in imageList" :key="item.id" class="view" direction="all" :y="item.y"
  6. :x="item.x" :damping="40" :disabled="item.disable" @change="onChange($event, item)"
  7. @touchstart="touchstart(item)" @mousedown="touchstart(item)" @touchend="touchend(item)"
  8. @mouseup="touchend(item)" :style="{
  9. width: viewWidth + 'px',
  10. height: viewWidth + 'px',
  11. 'z-index': item.zIndex,
  12. opacity: item.opacity
  13. }">
  14. <view class="area-con" :style="{
  15. width: childWidth,
  16. height: childWidth,
  17. borderRadius: borderRadius + 'rpx',
  18. transform: 'scale(' + item.scale + ')'
  19. }">
  20. <image class="pre-image" :src="item.src" mode="aspectFill"></image>
  21. <view class="del-con" @click="delImages(item, index)" @touchstart.stop="delImageMp(item, index)"
  22. @touchend.stop="nothing()" @mousedown.stop="nothing()" @mouseup.stop="nothing()">
  23. <view class="del-wrap">
  24. <image class="del-image"
  25. src="https://img0.baidu.com/it/u=2175764168,623834946&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500">
  26. </image>
  27. </view>
  28. </view>
  29. </view>
  30. </movable-view>
  31. <view class="add" v-if="imageList.length < number"
  32. :style="{ top: add.y, left: add.x, width: viewWidth + 'px', height: viewWidth + 'px' }" @click="addImages">
  33. <view class="add-wrap" :style="{ width: childWidth, height: childWidth, borderRadius: borderRadius + 'rpx' }">
  34. <image style="width: 54rpx;height: 54rpx;"
  35. src="https://bpic.51yuansu.com/pic3/cover/01/01/66/58de765c7abf3_610.jpg">
  36. </image>
  37. </view>
  38. </view>
  39. </movable-area>
  40. </template>
  41. </view>
  42. </template>
  43. <script>
  44. export default {
  45. emits: ['input', 'update:modelValue'],
  46. props: {
  47. // 排序图片
  48. value: {
  49. type: Array,
  50. default: function() {
  51. return []
  52. }
  53. },
  54. // 排序图片
  55. modelValue: {
  56. type: Array,
  57. default: function() {
  58. return []
  59. }
  60. },
  61. // 从 list 元素对象中读取的键名
  62. keyName: {
  63. type: String,
  64. default: null
  65. },
  66. // 选择图片数量限制
  67. number: {
  68. type: Number,
  69. default: 6
  70. },
  71. // 图片父容器宽度(实际显示的图片宽度为 imageWidth / 1.1 ),单位 rpx
  72. // imageWidth > 0 则 cols 无效
  73. imageWidth: {
  74. type: Number,
  75. default: 0
  76. },
  77. // 图片列数
  78. cols: {
  79. type: Number,
  80. default: 3
  81. },
  82. // 图片圆角,单位 rpx
  83. borderRadius: {
  84. type: Number,
  85. default: 0
  86. },
  87. // 图片周围空白填充,单位 rpx
  88. padding: {
  89. type: Number,
  90. default: 10
  91. },
  92. // 拖动图片时放大倍数 [0, ∞)
  93. scale: {
  94. type: Number,
  95. default: 1.1
  96. },
  97. // 拖动图片时不透明度
  98. opacity: {
  99. type: Number,
  100. default: 0.7
  101. },
  102. // 自定义添加
  103. addImage: {
  104. type: Function,
  105. default: null
  106. },
  107. // 删除确认
  108. delImage: {
  109. type: Function,
  110. default: null
  111. }
  112. },
  113. data() {
  114. return {
  115. imageList: [],
  116. width: 0,
  117. add: {
  118. x: 0,
  119. y: 0
  120. },
  121. colsValue: 0,
  122. viewWidth: 0,
  123. tempItem: null,
  124. timer: null,
  125. changeStatus: true,
  126. preStatus: true,
  127. first: true,
  128. }
  129. },
  130. computed: {
  131. areaHeight() {
  132. let height = ''
  133. // return '355px'
  134. if (this.imageList.length < this.number) {
  135. height = (Math.ceil((this.imageList.length + 1) / this.colsValue) * this.viewWidth).toFixed() + 'px'
  136. } else {
  137. height = (Math.ceil(this.imageList.length / this.colsValue) * this.viewWidth).toFixed() + 'px'
  138. }
  139. console.log('areaHeight', height)
  140. return height
  141. },
  142. childWidth() {
  143. return this.viewWidth - this.rpx2px(this.padding) * 2 + 'px'
  144. },
  145. },
  146. watch: {
  147. value: {
  148. handler(n) {
  149. if (!this.first && this.changeStatus) {
  150. console.log('watch', n)
  151. let flag = false
  152. for (let i = 0; i < n.length; i++) {
  153. if (flag) {
  154. this.addProperties(this.getSrc(n[i]))
  155. continue
  156. }
  157. if (this.imageList.length === i || this.imageList[i].src !== this.getSrc(n[i])) {
  158. flag = true
  159. this.imageList.splice(i)
  160. this.addProperties(this.getSrc(n[i]))
  161. }
  162. }
  163. }
  164. },
  165. deep: true
  166. },
  167. modelValue: {
  168. handler(n) {
  169. if (!this.first && this.changeStatus) {
  170. console.log('watch', n)
  171. let flag = false
  172. for (let i = 0; i < n.length; i++) {
  173. if (flag) {
  174. this.addProperties(this.getSrc(n[i]))
  175. continue
  176. }
  177. if (this.imageList.length === i || this.imageList[i].src !== this.getSrc(n[i])) {
  178. flag = true
  179. this.imageList.splice(i)
  180. this.addProperties(this.getSrc(n[i]))
  181. }
  182. }
  183. }
  184. },
  185. deep: true
  186. },
  187. },
  188. created() {
  189. this.width = uni.getSystemInfoSync().windowWidth
  190. },
  191. mounted() {
  192. const query = uni.createSelectorQuery().in(this)
  193. query.select('.con').boundingClientRect(data => {
  194. this.colsValue = this.cols
  195. this.viewWidth = data.width / this.cols
  196. if (this.imageWidth > 0) {
  197. this.viewWidth = this.rpx2px(this.imageWidth)
  198. this.colsValue = Math.floor(data.width / this.viewWidth)
  199. }
  200. let list = this.value
  201. // #ifdef VUE3
  202. list = this.modelValue
  203. // #endif
  204. for (let item of list) {
  205. this.addProperties(this.getSrc(item))
  206. }
  207. this.first = false
  208. })
  209. query.exec()
  210. },
  211. methods: {
  212. getSrc(item) {
  213. if(this.keyName !== null) {
  214. return item[this.keyName]
  215. }
  216. return item
  217. },
  218. onChange(e, item) {
  219. if (!item) return
  220. item.oldX = e.detail.x
  221. item.oldY = e.detail.y
  222. if (e.detail.source === 'touch') {
  223. if (item.moveEnd) {
  224. item.offset = Math.sqrt(Math.pow(item.oldX - item.absX * this.viewWidth, 2) + Math.pow(item.oldY - item
  225. .absY * this.viewWidth, 2))
  226. }
  227. let x = Math.floor((e.detail.x + this.viewWidth / 2) / this.viewWidth)
  228. if (x >= this.colsValue) return
  229. let y = Math.floor((e.detail.y + this.viewWidth / 2) / this.viewWidth)
  230. let index = this.colsValue * y + x
  231. if (item.index != index && index < this.imageList.length) {
  232. this.changeStatus = false
  233. for (let obj of this.imageList) {
  234. if (item.index > index && obj.index >= index && obj.index < item.index) {
  235. this.change(obj, 1)
  236. } else if (item.index < index && obj.index <= index && obj.index > item.index) {
  237. this.change(obj, -1)
  238. } else if (obj.id != item.id) {
  239. obj.offset = 0
  240. obj.x = obj.oldX
  241. obj.y = obj.oldY
  242. setTimeout(() => {
  243. this.$nextTick(() => {
  244. obj.x = obj.absX * this.viewWidth
  245. obj.y = obj.absY * this.viewWidth
  246. })
  247. }, 0)
  248. }
  249. }
  250. item.index = index
  251. item.absX = x
  252. item.absY = y
  253. if (!item.moveEnd) {
  254. setTimeout(() => {
  255. this.$nextTick(() => {
  256. item.x = item.absX * this.viewWidth
  257. item.y = item.absY * this.viewWidth
  258. })
  259. }, 0)
  260. }
  261. // console.log('bbb', JSON.parse(JSON.stringify(item)));
  262. this.sortList()
  263. }
  264. }
  265. },
  266. change(obj, i) {
  267. obj.index += i
  268. obj.offset = 0
  269. obj.x = obj.oldX
  270. obj.y = obj.oldY
  271. obj.absX = obj.index % this.colsValue
  272. obj.absY = Math.floor(obj.index / this.colsValue)
  273. setTimeout(() => {
  274. this.$nextTick(() => {
  275. obj.x = obj.absX * this.viewWidth
  276. obj.y = obj.absY * this.viewWidth
  277. })
  278. }, 0)
  279. },
  280. touchstart(item) {
  281. this.imageList.forEach(v => {
  282. v.zIndex = v.index + 9
  283. })
  284. item.zIndex = 99
  285. item.moveEnd = true
  286. this.tempItem = item
  287. this.timer = setTimeout(() => {
  288. item.scale = this.scale
  289. item.opacity = this.opacity
  290. clearTimeout(this.timer)
  291. this.timer = null
  292. }, 200)
  293. },
  294. touchend(item) {
  295. this.previewImage(item)
  296. item.scale = 1
  297. item.opacity = 1
  298. item.x = item.oldX
  299. item.y = item.oldY
  300. item.offset = 0
  301. item.moveEnd = false
  302. setTimeout(() => {
  303. this.$nextTick(() => {
  304. item.x = item.absX * this.viewWidth
  305. item.y = item.absY * this.viewWidth
  306. this.tempItem = null
  307. this.changeStatus = true
  308. })
  309. // console.log('ccc', JSON.parse(JSON.stringify(item)));
  310. }, 0)
  311. // console.log('ddd', JSON.parse(JSON.stringify(item)));
  312. },
  313. previewImage(item) {
  314. if (this.timer && this.preStatus && this.changeStatus && item.offset < 28.28) {
  315. clearTimeout(this.timer)
  316. this.timer = null
  317. const list = this.value || this.modelValue
  318. let srcList = list.map(v => this.getSrc(v))
  319. console.log(list, srcList);
  320. uni.previewImage({
  321. urls: srcList,
  322. current: item.src,
  323. success: () => {
  324. this.preStatus = false
  325. setTimeout(() => {
  326. this.preStatus = true
  327. }, 600)
  328. },
  329. fail: (e) => {
  330. console.log(e);
  331. }
  332. })
  333. } else if (this.timer) {
  334. clearTimeout(this.timer)
  335. this.timer = null
  336. }
  337. },
  338. mouseenter() {
  339. //#ifdef H5
  340. this.imageList.forEach(v => {
  341. v.disable = false
  342. })
  343. //#endif
  344. },
  345. mouseleave() {
  346. //#ifdef H5
  347. if (this.tempItem) {
  348. this.imageList.forEach(v => {
  349. v.disable = true
  350. v.zIndex = v.index + 9
  351. v.offset = 0
  352. v.moveEnd = false
  353. if (v.id == this.tempItem.id) {
  354. if (this.timer) {
  355. clearTimeout(this.timer)
  356. this.timer = null
  357. }
  358. v.scale = 1
  359. v.opacity = 1
  360. v.x = v.oldX
  361. v.y = v.oldY
  362. this.$nextTick(() => {
  363. v.x = v.absX * this.viewWidth
  364. v.y = v.absY * this.viewWidth
  365. this.tempItem = null
  366. })
  367. }
  368. })
  369. this.changeStatus = true
  370. }
  371. //#endif
  372. },
  373. addImages() {
  374. if (typeof this.addImage === 'function') {
  375. this.addImage.bind(this.$parent)()
  376. } else {
  377. let checkNumber = this.number - this.imageList.length
  378. uni.chooseImage({
  379. count: checkNumber,
  380. sourceType: ['album', 'camera'],
  381. success: res => {
  382. let count = checkNumber <= res.tempFilePaths.length ? checkNumber : res.tempFilePaths.length
  383. for (let i = 0; i < count; i++) {
  384. this.addProperties(res.tempFilePaths[i])
  385. }
  386. this.sortList()
  387. }
  388. })
  389. }
  390. },
  391. delImages(item, index) {
  392. if (typeof this.delImage === 'function') {
  393. this.delImage.bind(this.$parent)(() => {
  394. this.delImageHandle(item, index)
  395. })
  396. } else {
  397. this.delImageHandle(item, index)
  398. }
  399. },
  400. delImageHandle(item, index) {
  401. this.imageList.splice(index, 1)
  402. for (let obj of this.imageList) {
  403. if (obj.index > item.index) {
  404. obj.index -= 1
  405. obj.x = obj.oldX
  406. obj.y = obj.oldY
  407. obj.absX = obj.index % this.colsValue
  408. obj.absY = Math.floor(obj.index / this.colsValue)
  409. this.$nextTick(() => {
  410. obj.x = obj.absX * this.viewWidth
  411. obj.y = obj.absY * this.viewWidth
  412. })
  413. }
  414. }
  415. this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'
  416. this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'
  417. this.sortList()
  418. },
  419. delImageMp(item, index) {
  420. //#ifdef MP
  421. this.delImages(item, index)
  422. //#endif
  423. },
  424. sortList() {
  425. console.log('sortList');
  426. const result = []
  427. let source = this.value
  428. // #ifdef VUE3
  429. source = this.modelValue
  430. // #endif
  431. let list = this.imageList.slice()
  432. list.sort((a, b) => {
  433. return a.index - b.index
  434. })
  435. for (let s of list) {
  436. let item = source.find(d => this.getSrc(d) == s.src)
  437. if (item) {
  438. result.push(item)
  439. } else {
  440. if(this.keyName !== null) {
  441. result.push({
  442. [this.keyName]: s.src
  443. })
  444. } else {
  445. result.push(s.src)
  446. }
  447. }
  448. }
  449. this.$emit("input", result);
  450. this.$emit("update:modelValue", result);
  451. },
  452. addProperties(item) {
  453. console.log(item);
  454. let absX = this.imageList.length % this.colsValue
  455. let absY = Math.floor(this.imageList.length / this.colsValue)
  456. let x = absX * this.viewWidth
  457. let y = absY * this.viewWidth
  458. this.imageList.push({
  459. src: item,
  460. x,
  461. y,
  462. oldX: x,
  463. oldY: y,
  464. absX,
  465. absY,
  466. scale: 1,
  467. zIndex: 9,
  468. opacity: 1,
  469. index: this.imageList.length,
  470. id: this.guid(16),
  471. disable: false,
  472. offset: 0,
  473. moveEnd: false
  474. })
  475. this.add.x = (this.imageList.length % this.colsValue) * this.viewWidth + 'px'
  476. this.add.y = Math.floor(this.imageList.length / this.colsValue) * this.viewWidth + 'px'
  477. },
  478. nothing() {},
  479. rpx2px(v) {
  480. return this.width * v / 750
  481. },
  482. guid(len = 32) {
  483. const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  484. const uuid = []
  485. const radix = chars.length
  486. for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
  487. uuid.shift()
  488. return `u${uuid.join('')}`
  489. }
  490. }
  491. }
  492. </script>
  493. <style lang="scss" scoped>
  494. .con {
  495. // padding: 30rpx;
  496. .area {
  497. width: 100%;
  498. .view {
  499. display: flex;
  500. justify-content: center;
  501. align-items: center;
  502. .area-con {
  503. position: relative;
  504. overflow: hidden;
  505. .pre-image {
  506. width: 100%;
  507. height: 100%;
  508. }
  509. .del-con {
  510. position: absolute;
  511. top: 0rpx;
  512. right: 0rpx;
  513. padding: 0 0 20rpx 20rpx;
  514. .del-wrap {
  515. width: 36rpx;
  516. height: 36rpx;
  517. background-color: rgba(0, 0, 0, 0.4);
  518. border-radius: 0 0 0 10rpx;
  519. display: flex;
  520. justify-content: center;
  521. align-items: center;
  522. .del-image {
  523. width: 20rpx;
  524. height: 20rpx;
  525. }
  526. }
  527. }
  528. }
  529. }
  530. .add {
  531. position: absolute;
  532. display: flex;
  533. justify-content: center;
  534. align-items: center;
  535. .add-wrap {
  536. display: flex;
  537. justify-content: center;
  538. align-items: center;
  539. background-color: #eeeeee;
  540. }
  541. }
  542. }
  543. }
  544. </style>

三、使用

  1. <template>
  2. <view class="container">
  3. <uploadImage v-model="list"></uploadImage>
  4. <view style="margin-top: 30rpx;">
  5. <u-button type="primary" shape="circle" text="上传图片" @click="uploadImg()"></u-button>
  6. </view>
  7. </view>
  8. </template>
  9. <script>
  10. import uploadImage from '@/components/Upload-image.vue'
  11. export default {
  12. components:{uploadImage},
  13. data() {
  14. return {
  15. list: []
  16. }
  17. },
  18. onLoad(){
  19. },
  20. methods: {
  21. uploadImg() {
  22. this.list.forEach((v,i)=>{
  23. uni.uploadFile({
  24. url: 'https://www.example.com/upload', //仅为示例,非真实的接口地址
  25. filePath: v,
  26. name: 'file',
  27. formData: {
  28. 'user': 'test'
  29. },
  30. success: (uploadFileRes) => {
  31. console.log(uploadFileRes.data);
  32. }
  33. });
  34. })
  35. }
  36. }
  37. }
  38. </script>
  39. <style>
  40. </style>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/190293
推荐阅读
相关标签
  

闽ICP备14008679号