You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

140 lines
3.5 KiB

  1. <template>
  2. <div class="cropper-wrapper">
  3. <div class="img-box">
  4. <img class="cropper-image" :id="imgId" alt="">
  5. </div>
  6. <div class="right-con">
  7. <div v-if="preview" class="preview-box" :id="previewId"></div>
  8. <div class="button-box">
  9. <slot>
  10. <Upload action="image/upload" :before-upload="beforeUpload">
  11. <Button style="width: 150px;" type="primary">上传图片</Button>
  12. </Upload>
  13. </slot>
  14. <div v-show="insideSrc">
  15. <Button type="primary" @click="rotate">
  16. <Icon type="md-refresh" :size="18"/>
  17. </Button>
  18. <Button type="primary" @click="shrink">
  19. <Icon type="md-remove" :size="18"/>
  20. </Button>
  21. <Button type="primary" @click="magnify">
  22. <Icon type="md-add" :size="18"/>
  23. </Button>
  24. <Button type="primary" @click="scale('X')">
  25. <Icon custom="iconfont icon-shuipingfanzhuan" :size="18"/>
  26. </Button>
  27. <Button type="primary" @click="scale('Y')">
  28. <Icon custom="iconfont icon-chuizhifanzhuan" :size="18"/>
  29. </Button>
  30. <Button type="primary" @click="move(0, -moveStep)">
  31. <Icon type="md-arrow-round-up" :size="18"/>
  32. </Button>
  33. <Button type="primary" @click="move(-moveStep, 0)">
  34. <Icon type="md-arrow-round-back" :size="18"/>
  35. </Button>
  36. <Button type="primary" @click="move(0, moveStep)">
  37. <Icon type="md-arrow-round-down" :size="18"/>
  38. </Button>
  39. <Button type="primary" @click="move(moveStep, 0)">
  40. <Icon type="md-arrow-round-forward" :size="18"/>
  41. </Button>
  42. <Button style="width: 150px;margin-top: 10px;" type="primary" @click="crop">{{ cropButtonText }}</Button>
  43. </div>
  44. </div>
  45. </div>
  46. </div>
  47. </template>
  48. <script>
  49. import Cropper from 'cropperjs'
  50. import './index.less'
  51. import 'cropperjs/dist/cropper.min.css'
  52. export default {
  53. name: 'Cropper',
  54. props: {
  55. src: {
  56. type: String,
  57. default: ''
  58. },
  59. preview: {
  60. type: Boolean,
  61. default: true
  62. },
  63. moveStep: {
  64. type: Number,
  65. default: 4
  66. },
  67. cropButtonText: {
  68. type: String,
  69. default: '裁剪'
  70. }
  71. },
  72. data () {
  73. return {
  74. cropper: null,
  75. insideSrc: ''
  76. }
  77. },
  78. computed: {
  79. imgId () {
  80. return `cropper${this._uid}`
  81. },
  82. previewId () {
  83. return `cropper_preview${this._uid}`
  84. }
  85. },
  86. watch: {
  87. src (src) {
  88. this.replace(src)
  89. },
  90. insideSrc (src) {
  91. this.replace(src)
  92. }
  93. },
  94. methods: {
  95. beforeUpload (file) {
  96. const reader = new FileReader()
  97. reader.readAsDataURL(file)
  98. reader.onload = (event) => {
  99. this.insideSrc = event.srcElement.result
  100. }
  101. return false
  102. },
  103. replace (src) {
  104. this.cropper.replace(src)
  105. this.insideSrc = src
  106. },
  107. rotate () {
  108. this.cropper.rotate(90)
  109. },
  110. shrink () {
  111. this.cropper.zoom(-0.1)
  112. },
  113. magnify () {
  114. this.cropper.zoom(0.1)
  115. },
  116. scale (d) {
  117. this.cropper[`scale${d}`](-this.cropper.getData()[`scale${d}`])
  118. },
  119. move (...argu) {
  120. this.cropper.move(...argu)
  121. },
  122. crop () {
  123. this.cropper.getCroppedCanvas().toBlob(blob => {
  124. this.$emit('on-crop', blob)
  125. })
  126. }
  127. },
  128. mounted () {
  129. this.$nextTick(() => {
  130. let dom = document.getElementById(this.imgId)
  131. this.cropper = new Cropper(dom, {
  132. preview: `#${this.previewId}`,
  133. checkCrossOrigin: true
  134. })
  135. })
  136. }
  137. }
  138. </script>