Created
          August 1, 2019 23:46 
        
      - 
      
- 
        Save davo/4cedb46b171a5545f90c6a1e67a8fa77 to your computer and use it in GitHub Desktop. 
Revisions
- 
        davo created this gist Aug 1, 2019 .There are no files selected for viewingThis file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,348 @@ // WIP Refactored from https://github.com/aleksik/react-scratchcard/ import * as React from 'react' import { Frame, addPropertyControls, ControlType } from 'framer' export function ScratchCard({ width, height, children, image: source, finishPercent }) { const [loaded, setLoaded] = React.useState(false) const [context, setContext] = React.useState(false) const [isDrawing, setIsDrawing] = React.useState(false) const [lastPoint, updateLastPoint] = React.useState(null) const canvasRef = React.useRef(null) React.useLayoutEffect(() => { const ctx = canvasRef.current.getContext('2d') const image = new Image() image.crossOrigin = 'Anonymous' image.onload = () => { ctx.drawImage(image, 0, 0) setLoaded(true) } image.src = 'https://source.unsplash.com/random' console.log(ctx) // const image = new Image() // image.crossOrigin = "Anonymous" // image.onload = () => { // // @ts-ignore // this.ctx.drawImage(image, 0, 0) // this.setState({ loaded: true }) // } // // @ts-ignore // image.src = this.props.image }, []) function getFilledInPixels(stride) { if (!stride || stride < 1) { stride = 1 } const ctx = canvasRef.current.getContext('2d') const pixels = ctx.getImageData(0, 0, canvasRef.current.width, canvasRef.current.height) const total = pixels.data.length / stride let count = 0 for (let i = 0; i < pixels.data.length; i += stride) { if (parseInt(pixels.data[i], 10) === 0) { count++ } } return Math.round((count / total) * 100) } function getMouse(e, canvas) { const { top, left } = canvas.getBoundingClientRect() const scrollTop = window.pageYOffset || document.documentElement.scrollTop const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft return { x: (e.pageX || e.touches[0].clientX) - left - scrollLeft, y: (e.pageY || e.touches[0].clientY) - top - scrollTop, } } function distanceBetween(point1, point2) { return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2)) } function angleBetween(point1, point2) { return Math.atan2(point2.x - point1.x, point2.y - point1.y) } function handlePercentage(filledInPixels = 0) { // @ts-ignore // if (filledInPixels > finishPercent) { // // @ts-ignore // this.canvas.parentNode.removeChild(this.canvas) // this.setState({ finished: true }) // // @ts-ignore // if (this.props.onComplete) { // // @ts-ignore // this.props.onComplete() // } } function handleMouseDown(e) { // @ts-ignore setIsDrawing(true) // @ts-ignore // this.lastPoint = this.getMouse(e, this.canvas) } const canvasProps = { width: width, height: height, // @ts-ignore // ref: ref => (this.canvas = ref), // className: 'ScratchCard__Canvas', // style: canvasStyle, // // @ts-ignore // width: this.props.width, // // @ts-ignore // height: this.props.height, // onMouseDown: this.handleMouseDown.bind(this), // onTouchStart: this.handleMouseDown.bind(this), // onMouseMove: this.handleMouseMove.bind(this), // onTouchMove: this.handleMouseMove.bind(this), // onMouseUp: this.handleMouseUp.bind(this), // onTouchEnd: this.handleMouseUp.bind(this), } return ( <> <div style={{ ...containerStyle, width: width, height: height }}> {/* <Frame image='https://source.unsplash.com/random' width={width} height={height} /> */} <canvas ref={canvasRef} style={canvasStyle} {...canvasProps} /> <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', position: 'absolute', width: '100%', height: '100%', color: '#fff', background: '#000', visibility: loaded ? 'visible' : 'hidden', }}> {children} </div> </div> </> ) } ScratchCard.defaultProps = { width: 640, height: 480, image: '', finishPercent: 0, onComplete: () => null, } addPropertyControls(ScratchCard, { image: { type: ControlType.Image, title: 'Image', }, }) const containerStyle: React.CSSProperties = { position: 'relative', WebkitUserSelect: 'none', MozUserSelect: 'none', msUserSelect: 'none', userSelect: 'none', } const canvasStyle: React.CSSProperties = { position: 'absolute', top: 0, zIndex: 1, } // const resultStyle: React.CSSProperties = { // visibility: this.state.loaded ? 'visible' : 'hidden', // } // export class ScratchCardClass extends React.Component { // constructor(props) { // super(props) // this.state = { loaded: false } // } // componentDidMount() { // // @ts-ignore // this.isDrawing = false // // @ts-ignore // this.lastPoint = null // // @ts-ignore // this.ctx = this.canvas.getContext("2d") // const image = new Image() // image.crossOrigin = "Anonymous" // image.onload = () => { // // @ts-ignore // this.ctx.drawImage(image, 0, 0) // this.setState({ loaded: true }) // } // // @ts-ignore // image.src = this.props.image // } // getFilledInPixels(stride) { // if (!stride || stride < 1) { // stride = 1 // } // // @ts-ignore // const pixels = this.ctx.getImageData( // 0, // 0, // // @ts-ignore // this.canvas.width, // // @ts-ignore // this.canvas.height // ) // const total = pixels.data.length / stride // let count = 0 // for (let i = 0; i < pixels.data.length; i += stride) { // if (parseInt(pixels.data[i], 10) === 0) { // count++ // } // } // return Math.round((count / total) * 100) // } // getMouse(e, canvas) { // const { top, left } = canvas.getBoundingClientRect() // const scrollTop = // window.pageYOffset || document.documentElement.scrollTop // const scrollLeft = // window.pageXOffset || document.documentElement.scrollLeft // return { // x: (e.pageX || e.touches[0].clientX) - left - scrollLeft, // y: (e.pageY || e.touches[0].clientY) - top - scrollTop, // } // } // distanceBetween(point1, point2) { // return Math.sqrt( // Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2) // ) // } // angleBetween(point1, point2) { // return Math.atan2(point2.x - point1.x, point2.y - point1.y) // } // handlePercentage(filledInPixels = 0) { // // @ts-ignore // if (filledInPixels > this.props.finishPercent) { // // @ts-ignore // this.canvas.parentNode.removeChild(this.canvas) // this.setState({ finished: true }) // // @ts-ignore // if (this.props.onComplete) { // // @ts-ignore // this.props.onComplete() // } // } // } // handleMouseDown(e) { // // @ts-ignore // this.isDrawing = true // // @ts-ignore // this.lastPoint = this.getMouse(e, this.canvas) // } // handleMouseMove(e) { // // @ts-ignore // if (!this.isDrawing) { // return // } // e.preventDefault() // // @ts-ignore // const currentPoint = this.getMouse(e, this.canvas) // // @ts-ignore // const distance = this.distanceBetween(this.lastPoint, currentPoint) // // @ts-ignore // const angle = this.angleBetween(this.lastPoint, currentPoint) // let x, y // for (let i = 0; i < distance; i++) { // // @ts-ignore // x = this.lastPoint.x + Math.sin(angle) * i // // @ts-ignore // y = this.lastPoint.y + Math.cos(angle) * i // // @ts-ignore // this.ctx.globalCompositeOperation = "destination-out" // // @ts-ignore // this.ctx.beginPath() // // @ts-ignore // this.ctx.arc(x, y, 25, 0, 2 * Math.PI, false) // // @ts-ignore // this.ctx.fill() // } // // @ts-ignore // this.lastPoint = currentPoint // this.handlePercentage(this.getFilledInPixels(32)) // } // handleMouseUp() { // // @ts-ignore // this.isDrawing = false // } // render() { // const containerStyle = { // // @ts-ignore // width: this.props.width + "px", // // @ts-ignore // height: this.props.height + "px", // position: "relative", // WebkitUserSelect: "none", // MozUserSelect: "none", // msUserSelect: "none", // userSelect: "none", // } // const canvasStyle = { // position: "absolute", // top: 0, // zIndex: 1, // } // const resultStyle = { // // @ts-ignore // visibility: this.state.loaded ? "visible" : "hidden", // } // const canvasProps = { // // @ts-ignore // ref: ref => (this.canvas = ref), // className: "ScratchCard__Canvas", // style: canvasStyle, // // @ts-ignore // width: this.props.width, // // @ts-ignore // height: this.props.height, // onMouseDown: this.handleMouseDown.bind(this), // onTouchStart: this.handleMouseDown.bind(this), // onMouseMove: this.handleMouseMove.bind(this), // onTouchMove: this.handleMouseMove.bind(this), // onMouseUp: this.handleMouseUp.bind(this), // onTouchEnd: this.handleMouseUp.bind(this), // } // return ( // // @ts-ignore // <div className="ScratchCard__Container" style={containerStyle}> // { // // @ts-ignore // <canvas {...canvasProps}></canvas> // } // { // // @ts-ignore // <div className="ScratchCard__Result" style={resultStyle}> // {this.props.children} // </div> // } // </div> // ) // } // } // // ScratchCard.propTypes = { // // image: React.PropTypes.string.isRequired, // // width: React.PropTypes.number.isRequired, // // height: React.PropTypes.number.isRequired, // // finishPercent: React.PropTypes.number.isRequired, // // onComplete: React.PropTypes.func // // } // // export default ScratchCard;