Began building out screenshot capture feature.

This commit is contained in:
Frank Noirot
2021-02-25 01:50:03 -05:00
parent a2b69ece29
commit 6e6425735f
5 changed files with 113 additions and 0 deletions

View File

@@ -3,6 +3,8 @@ import CascadeController from 'src/helpers/cascadeController'
import IdeToolbar from 'src/components/IdeToolbar'
import { useEffect, useState } from 'react'
import { threejsViewport } from 'src/cascade/js/MainPage/CascadeState'
import { element } from 'prop-types'
import { uploadToCloudinary } from 'src/helpers/cloudinary'
const defaultExampleCode = `// Welcome to Cascade Studio! Here are some useful functions:
// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()
@@ -70,6 +72,18 @@ const IdeCascadeStudio = ({ part, saveCode, loading }) => {
partTitle: part?.title,
image: part?.user?.image,
}}
onCapture={ async () => {
// Get the canvas image as a Data URL
const imgBlob = await CascadeController.capture(threejsViewport.environment)
const imgURL = window.URL.createObjectURL(imgBlob)
// TODO: Upload the image to Cloudinary
// uploadToCloudinary(imgBlob)
// TODO: Save the screenshot as the mainImage if none has been set
// If it has been set, pass along the Blob without uploading
// onSave(part?.id, { ...input, mainImage: cloudinaryPublicId })
}}
/>
</div>
</>

View File

@@ -23,6 +23,7 @@ const IdeToolbar = ({
userNamePart,
isDraft,
code,
onCapture,
}) => {
const [anchorEl, setAnchorEl] = useState(null)
const [whichPopup, setWhichPopup] = useState(null)
@@ -104,6 +105,10 @@ const IdeToolbar = ({
setIsLoginModalOpen(true)
}
const captureScreenshot = async () => {
console.log({ forkPart, onCapture: onCapture() })
}
const anchorOrigin = {
vertical: 'bottom',
horizontal: 'center',
@@ -219,6 +224,31 @@ const IdeToolbar = ({
</Popover>
</div>
<div className="ml-auto flex items-center">
{/* Capture Screenshot link. Should only appear if part has been saved and is editable. */}
{ !isDraft && canEdit && <div>
<button
onClick={(event) => {
captureScreenshot()
handleClick({ event, whichPopup: 'capture' })
}}
className="text-indigo-300 flex items-center pr-6"
>
Capture <Svg name="camera" className="pl-2 w-8" />
</button>
<Popover
id={id}
open={whichPopup === 'capture'}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={anchorOrigin}
transformOrigin={transformOrigin}
className="material-ui-overrides transform translate-y-4"
>
<div className="text-sm p-2 text-gray-500">
Saving...
</div>
</Popover>
</div> }
<div>
<button
onClick={(event) => handleClick({ event, whichPopup: 'tips' })}

View File

@@ -30,6 +30,29 @@ const Svg = ({ name, className: className2, strokeWidth = 2 }) => {
/>
</svg>
),
'camera': (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 21">
<path
d="M6 5H4C2.34315 5 1 6.34315 1 8V17C1 18.6569 2.34315 20 4 20H20C21.6569 20 23 18.6569 23 17V8C23 6.34315 21.6569 5 20 5H18"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"/>
<circle
cx="12"
cy="11"
r="5"
stroke="currentColor"
stroke-width="2"/>
<path
d="M16 2.68641C14.8716 1.61443 13.5582 1 12.1563 1C10.6229 1 9.19532 1.7351 8 3"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"/>
</svg>
),
'chevron-down': (
<svg
xmlns="http://www.w3.org/2000/svg"

View File

@@ -23,6 +23,29 @@ class CascadeController {
}
onInit()
}
capture(environment) {
let width = 512, height = 384;
environment.camera.aspect = width / height;
environment.camera.updateProjectionMatrix();
environment.renderer.setSize(width, height);
environment.renderer.render(environment.scene, environment.camera, null, false);
let imgBlob = new Promise((resolve, reject) => {
environment.renderer.domElement.toBlob(
(blob) => {
blob.name = `part_capture-${ Date.now() }`
resolve(blob)
},
'image/jpeg',
1
);
})
// Return to original dimensions
environment.onWindowResize();
return imgBlob
}
}
export default new CascadeController()

View File

@@ -0,0 +1,23 @@
// TODO: create a tidy util for uploading to Cloudinary and returning the public ID
import axios from 'axios'
const CLOUDINARY_UPLOAD_PRESET = 'CadHub_project_images'
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/irevdev/upload'
export async function uploadToCloudinary(imgBlob) {
// const imageData = new FormData()
// imageData.append('upload_preset', CLOUDINARY_UPLOAD_PRESET)
// imageData.append('file', croppedFile)
// let upload = axios.post(CLOUDINARY_UPLOAD_URL, imageData)
// try {
// const { data } = await upload
// if (data && data.public_id !== '') {
// onImageUpload({ cloudinaryPublicId: data.public_id })
// setCloudinaryId(data.public_id)
// setIsModalOpen(false)
// }
// } catch (e) {
// console.error('ERROR', e)
// }
}