Skip to content

Instantly share code, notes, and snippets.

@davo
Created August 1, 2019 23:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davo/4cedb46b171a5545f90c6a1e67a8fa77 to your computer and use it in GitHub Desktop.
Save davo/4cedb46b171a5545f90c6a1e67a8fa77 to your computer and use it in GitHub Desktop.
ScratchCard for Framer X
// 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;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment