فهرست منبع

add draft basic cropping to a weird place

Artur Paikin 5 سال پیش
والد
کامیت
5f28e40dbf

+ 5 - 0
package-lock.json

@@ -13892,6 +13892,11 @@
         "moment-timezone": "^0.5.25"
       }
     },
+    "cropperjs": {
+      "version": "1.5.6",
+      "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.6.tgz",
+      "integrity": "sha512-eAgWf4j7sNJIG329qUHIFi17PSV0VtuWyAu9glZSgu/KlQSrfTQOC2zAz+jHGa5fAB+bJldEnQwvJEaJ8zRf5A=="
+    },
     "cross-spawn": {
       "version": "6.0.5",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",

+ 2 - 1
package.json

@@ -61,6 +61,7 @@
     "@uppy/react-native": "file:packages/@uppy/react-native",
     "@uppy/redux-dev-tools": "file:packages/@uppy/redux-dev-tools",
     "@uppy/robodog": "file:packages/@uppy/robodog",
+    "@uppy/screen-capture": "file:packages/@uppy/screen-capture",
     "@uppy/status-bar": "file:packages/@uppy/status-bar",
     "@uppy/store-default": "file:packages/@uppy/store-default",
     "@uppy/store-redux": "file:packages/@uppy/store-redux",
@@ -70,8 +71,8 @@
     "@uppy/url": "file:packages/@uppy/url",
     "@uppy/utils": "file:packages/@uppy/utils",
     "@uppy/webcam": "file:packages/@uppy/webcam",
-    "@uppy/screen-capture": "file:packages/@uppy/screen-capture",
     "@uppy/xhr-upload": "file:packages/@uppy/xhr-upload",
+    "cropperjs": "^1.5.6",
     "remark-lint-uppy": "file:private/remark-lint-uppy",
     "uppy": "file:packages/uppy",
     "uppy.io": "file:website"

+ 304 - 0
packages/@uppy/dashboard/src/components/FileCard/cropper.scss

@@ -0,0 +1,304 @@
+/*!
+ * Cropper.js v1.5.6
+ * https://fengyuanchen.github.io/cropperjs
+ *
+ * Copyright 2015-present Chen Fengyuan
+ * Released under the MIT license
+ *
+ * Date: 2019-10-04T04:33:44.164Z
+ */
+
+ .cropper-container {
+  direction: ltr;
+  font-size: 0;
+  line-height: 0;
+  position: relative;
+  -ms-touch-action: none;
+  touch-action: none;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+}
+
+.cropper-container img {
+  display: block;
+  height: 100%;
+  image-orientation: 0deg;
+  max-height: none !important;
+  max-width: none !important;
+  min-height: 0 !important;
+  min-width: 0 !important;
+  width: 100%;
+}
+
+.cropper-wrap-box,
+.cropper-canvas,
+.cropper-drag-box,
+.cropper-crop-box,
+.cropper-modal {
+  bottom: 0;
+  left: 0;
+  position: absolute;
+  right: 0;
+  top: 0;
+}
+
+.cropper-wrap-box,
+.cropper-canvas {
+  overflow: hidden;
+}
+
+.cropper-drag-box {
+  background-color: #fff;
+  opacity: 0;
+}
+
+.cropper-modal {
+  background-color: #000;
+  opacity: 0.5;
+}
+
+.cropper-view-box {
+  display: block;
+  height: 100%;
+  outline: 1px solid #39f;
+  outline-color: rgba(51, 153, 255, 0.75);
+  overflow: hidden;
+  width: 100%;
+}
+
+.cropper-dashed {
+  border: 0 dashed #eee;
+  display: block;
+  opacity: 0.5;
+  position: absolute;
+}
+
+.cropper-dashed.dashed-h {
+  border-bottom-width: 1px;
+  border-top-width: 1px;
+  height: calc(100% / 3);
+  left: 0;
+  top: calc(100% / 3);
+  width: 100%;
+}
+
+.cropper-dashed.dashed-v {
+  border-left-width: 1px;
+  border-right-width: 1px;
+  height: 100%;
+  left: calc(100% / 3);
+  top: 0;
+  width: calc(100% / 3);
+}
+
+.cropper-center {
+  display: block;
+  height: 0;
+  left: 50%;
+  opacity: 0.75;
+  position: absolute;
+  top: 50%;
+  width: 0;
+}
+
+.cropper-center::before,
+.cropper-center::after {
+  background-color: #eee;
+  content: ' ';
+  display: block;
+  position: absolute;
+}
+
+.cropper-center::before {
+  height: 1px;
+  left: -3px;
+  top: 0;
+  width: 7px;
+}
+
+.cropper-center::after {
+  height: 7px;
+  left: 0;
+  top: -3px;
+  width: 1px;
+}
+
+.cropper-face,
+.cropper-line,
+.cropper-point {
+  display: block;
+  height: 100%;
+  opacity: 0.1;
+  position: absolute;
+  width: 100%;
+}
+
+.cropper-face {
+  background-color: #fff;
+  left: 0;
+  top: 0;
+}
+
+.cropper-line {
+  background-color: #39f;
+}
+
+.cropper-line.line-e {
+  cursor: ew-resize;
+  right: -3px;
+  top: 0;
+  width: 5px;
+}
+
+.cropper-line.line-n {
+  cursor: ns-resize;
+  height: 5px;
+  left: 0;
+  top: -3px;
+}
+
+.cropper-line.line-w {
+  cursor: ew-resize;
+  left: -3px;
+  top: 0;
+  width: 5px;
+}
+
+.cropper-line.line-s {
+  bottom: -3px;
+  cursor: ns-resize;
+  height: 5px;
+  left: 0;
+}
+
+.cropper-point {
+  background-color: #39f;
+  height: 5px;
+  opacity: 0.75;
+  width: 5px;
+}
+
+.cropper-point.point-e {
+  cursor: ew-resize;
+  margin-top: -3px;
+  right: -3px;
+  top: 50%;
+}
+
+.cropper-point.point-n {
+  cursor: ns-resize;
+  left: 50%;
+  margin-left: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-w {
+  cursor: ew-resize;
+  left: -3px;
+  margin-top: -3px;
+  top: 50%;
+}
+
+.cropper-point.point-s {
+  bottom: -3px;
+  cursor: s-resize;
+  left: 50%;
+  margin-left: -3px;
+}
+
+.cropper-point.point-ne {
+  cursor: nesw-resize;
+  right: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-nw {
+  cursor: nwse-resize;
+  left: -3px;
+  top: -3px;
+}
+
+.cropper-point.point-sw {
+  bottom: -3px;
+  cursor: nesw-resize;
+  left: -3px;
+}
+
+.cropper-point.point-se {
+  bottom: -3px;
+  cursor: nwse-resize;
+  height: 20px;
+  opacity: 1;
+  right: -3px;
+  width: 20px;
+}
+
+@media (min-width: 768px) {
+  .cropper-point.point-se {
+    height: 15px;
+    width: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .cropper-point.point-se {
+    height: 10px;
+    width: 10px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .cropper-point.point-se {
+    height: 5px;
+    opacity: 0.75;
+    width: 5px;
+  }
+}
+
+.cropper-point.point-se::before {
+  background-color: #39f;
+  bottom: -50%;
+  content: ' ';
+  display: block;
+  height: 200%;
+  opacity: 0;
+  position: absolute;
+  right: -50%;
+  width: 200%;
+}
+
+.cropper-invisible {
+  opacity: 0;
+}
+
+.cropper-bg {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
+}
+
+.cropper-hide {
+  display: block;
+  height: 0;
+  position: absolute;
+  width: 0;
+}
+
+.cropper-hidden {
+  display: none !important;
+}
+
+.cropper-move {
+  cursor: move;
+}
+
+.cropper-crop {
+  cursor: crosshair;
+}
+
+.cropper-disabled .cropper-drag-box,
+.cropper-disabled .cropper-face,
+.cropper-disabled .cropper-line,
+.cropper-disabled .cropper-point {
+  cursor: not-allowed;
+}

+ 1 - 1
packages/@uppy/dashboard/src/components/FileCard/index.js

@@ -111,7 +111,7 @@ class FileCard extends Component {
 
         <div class="uppy-Dashboard-FileCard-inner">
           <div class="uppy-Dashboard-FileCard-preview" style={{ backgroundColor: getFileTypeIcon(file.type).color }}>
-            <FilePreview file={file} />
+            <FilePreview file={file} uppy={this.props.uppy} />
           </div>
 
           <div class="uppy-Dashboard-FileCard-info">

+ 70 - 12
packages/@uppy/dashboard/src/components/FilePreview.js

@@ -1,19 +1,77 @@
 const getFileTypeIcon = require('../utils/getFileTypeIcon')
-const { h } = require('preact')
+const { h, Component } = require('preact')
 
-module.exports = function FilePreview (props) {
-  const file = props.file
+const Cropper = require('cropperjs')
 
-  if (file.preview) {
-    return <img class="uppy-DashboardItem-previewImg" alt={file.name} src={file.preview} />
+// module.exports = function FilePreview (props) {
+//   const file = props.file
+
+//   if (file.preview) {
+//     return <img class="uppy-DashboardItem-previewImg" alt={file.name} src={file.preview} />
+//   }
+
+//   const { color, icon } = getFileTypeIcon(file.type)
+
+//   return (
+//     <div class="uppy-DashboardItem-previewIconWrap">
+//       <span class="uppy-DashboardItem-previewIcon" style={{ color: color }}>{icon}</span>
+//       <svg aria-hidden="true" focusable="false" class="uppy-DashboardItem-previewIconBg" width="58" height="76" viewBox="0 0 58 76"><rect fill="#FFF" width="58" height="76" rx="3" fill-rule="evenodd" /></svg>
+//     </div>
+//   )
+// }
+
+module.exports = class FilePreview extends Component {
+  componentDidMount () {
+    const file = this.props.file
+    if (file.preview) {
+      const cropper = new Cropper(this.img, {
+        aspectRatio: 16 / 9,
+        crop (event) {
+          console.log(event.detail.x)
+          console.log(event.detail.y)
+          console.log(event.detail.width)
+          console.log(event.detail.height)
+          console.log(event.detail.rotate)
+          console.log(event.detail.scaleX)
+          console.log(event.detail.scaleY)
+        }
+      })
+
+      setTimeout(() => {
+        cropper.getCroppedCanvas().toBlob((blob) => {
+          console.log(blob)
+          this.props.uppy.setFileState(file.id, {
+            data: blob,
+            preview: null
+          })
+          const updatedFile = this.props.uppy.getFile(file.id)
+          this.props.uppy.emit('thumbnail:request', updatedFile)
+        })
+      }, 5000)
+    }
   }
 
-  const { color, icon } = getFileTypeIcon(file.type)
+  render () {
+    const file = this.props.file
+
+    if (file.preview) {
+      return (
+        <img
+          class="uppy-DashboardItem-previewImg"
+          alt={file.name}
+          src={file.preview}
+          ref={(ref) => { this.img = ref }}
+        />
+      )
+    }
 
-  return (
-    <div class="uppy-DashboardItem-previewIconWrap">
-      <span class="uppy-DashboardItem-previewIcon" style={{ color: color }}>{icon}</span>
-      <svg aria-hidden="true" focusable="false" class="uppy-DashboardItem-previewIconBg" width="58" height="76" viewBox="0 0 58 76"><rect fill="#FFF" width="58" height="76" rx="3" fill-rule="evenodd" /></svg>
-    </div>
-  )
+    const { color, icon } = getFileTypeIcon(file.type)
+
+    return (
+      <div class="uppy-DashboardItem-previewIconWrap">
+        <span class="uppy-DashboardItem-previewIcon" style={{ color: color }}>{icon}</span>
+        <svg aria-hidden="true" focusable="false" class="uppy-DashboardItem-previewIconBg" width="58" height="76" viewBox="0 0 58 76"><rect fill="#FFF" width="58" height="76" rx="3" fill-rule="evenodd" /></svg>
+      </div>
+    )
+  }
 }

+ 1 - 0
packages/@uppy/dashboard/src/index.js

@@ -832,6 +832,7 @@ module.exports = class Dashboard extends Plugin {
       i18n: this.i18n,
       i18nArray: this.i18nArray,
       removeFile: this.uppy.removeFile,
+      uppy: this.uppy,
       info: this.uppy.info,
       note: this.opts.note,
       metaFields: pluginState.metaFields,

+ 2 - 0
packages/@uppy/dashboard/src/style.scss

@@ -8,6 +8,8 @@
 @import './components/FileItem/index.scss';
 @import './components/FileCard/index.scss';
 
+@import './components/FileCard/cropper.scss';
+
 // Transitions //
 
 .uppy-transition-slideDownUp-enter {