Skip to content

Commit

Permalink
Release/0.0.15 (#41)
Browse files Browse the repository at this point in the history
* Add opacity menu
* Add colour picker
  • Loading branch information
micahg authored Jul 13, 2023
1 parent 6a237e9 commit f3e0e66
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 19 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@micahg/ntt",
"version": "0.0.14",
"version": "0.0.15",
"files": [
"build"
],
Expand Down
31 changes: 26 additions & 5 deletions src/components/ContentEditor/ContentEditor.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,29 @@
left: 0;
}

.BackgroundMenu {
.OpacitySlider {
right: 37.5em;
bottom: 3em;
z-index: 3;
position: absolute;
background-color: gray;
}

.BackgroundMenu {
right: 2.25em;
}

.OpacityMenu {
right: 37.5em;
}

.Menu {
bottom: 3em;
z-index: 3;
position: absolute;
}

.BackgroundMenu button {
.Menu button {
background-color: gray;
color: black;
display: block;
Expand All @@ -42,12 +57,12 @@
border: 1px solid black;
}

.BackgroundMenu button:hover {
.Menu button:hover {
background-color: lightgray;
color: black;
}

.BackgroundMenu button:active {
.Menu button:active {
background-color: whitesmoke;
color: black;
}
Expand All @@ -62,7 +77,13 @@
z-index: 1;
}

.ControlsContainer input {
.ControlsContainer input[type=color]{
margin: 0.5em;
padding: 0;
height: 2.5em;
}

.ControlsContainer input[type=text] {
margin: 0.5em;
padding: 0.5em;
height: 1em;
Expand Down
58 changes: 50 additions & 8 deletions src/components/ContentEditor/ContentEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { createRef, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AppReducerState } from '../../reducers/AppReducer';
import { loadImage, obscureOverlay, renderImage, setupOverlayCanvas, selectOverlay, storeOverlay, clearOverlaySelection, revealOverlay, getRect, clearOverlay} from '../../utils/drawing';
import { loadImage, obscureOverlay, renderImage, setupOverlayCanvas,
selectOverlay, storeOverlay, clearOverlaySelection, revealOverlay,
getRect, clearOverlay, setOverlayOpacity,
setOverlayColour } from '../../utils/drawing';
import { rotateRect, scaleSelection } from '../../utils/geometry';
import { MouseStateMachine } from '../../utils/mousestatemachine';
import { setCallback } from '../../utils/statemachine';
Expand All @@ -17,7 +20,9 @@ const ContentEditor = () => {
const [contentCtx, setContentCtx] = useState<CanvasRenderingContext2D|null>(null);
const [overlayCtx, setOverlayCtx] = useState<CanvasRenderingContext2D|null>(null);
const [backgroundLoaded, setBackgroundLoaded] = useState<boolean>(false);
const [showMenu, setShowMenu] = useState<boolean>(false);
const [showBackgroundMenu, setShowBackgroundMenu] = useState<boolean>(false);
const [showOpacityMenu, setShowOpacityMenu] = useState<boolean>(false);
const [showOpacitySlider, setShowOpacitySlider] = useState<boolean>(false);
const [canObscure, setCanObscure] = useState<boolean>(false);
const [canLink, setCanLink] = useState<boolean>(false);
const [link, setLink] = useState<string>('');
Expand Down Expand Up @@ -153,25 +158,28 @@ const ContentEditor = () => {
setCallback(sm, 'wait', () => {
sm.resetCoordinates();
setLink('');
setShowMenu(false);
setShowBackgroundMenu(false);
setShowOpacityMenu(false);
setCanLink(false);
setCanObscure(false);
clearOverlaySelection.bind(overlayCtx)();
});

setCallback(sm, 'record', () => {
setShowMenu(false)
setShowBackgroundMenu(false)
setShowOpacityMenu(false);
setCanObscure(true);
setShowOpacitySlider(false);
});
setCallback(sm, 'background_select', () => {
clearOverlaySelection.bind(overlayCtx)();
sm.resetCoordinates();
setCanObscure(false);
setShowMenu(true);
setShowBackgroundMenu(true);
});
setCallback(sm, 'background_link', () => {
setCanLink(true);
setShowMenu(false);
setShowBackgroundMenu(false);
});
setCallback(sm, 'background_upload', selectFile);
setCallback(sm, 'obscure', () => {
Expand All @@ -197,14 +205,36 @@ const ContentEditor = () => {
sm.transition('wait');
}
});
setCallback(sm, 'opacity_select', () => {
clearOverlaySelection.bind(overlayCtx)();
sm.resetCoordinates();
setCanObscure(false);
setShowOpacityMenu(true);
});
setCallback(sm, 'opacity_display', () => {
setShowOpacityMenu(false);
setShowOpacitySlider(true);
});
setCallback(sm, 'opacity_render', () => {
setShowOpacityMenu(false);
setShowOpacitySlider(true);
});
setCallback(sm, 'update_display_opacity', (args) => {
const opacity: string = args[0];
if (overlayCanvasRef.current) {
overlayCanvasRef.current.style.opacity=opacity;
}
});
setCallback(sm, 'update_render_opacity', (args) => setOverlayOpacity(args[0]));

sm.setMoveCallback(selectOverlay.bind(overlayCtx));
sm.setStartCallback(storeOverlay.bind(overlayCtx));
setCallback(sm, 'push', () => dispatch({type: 'content/push'}));
setCallback(sm, 'clear', () => {
clearOverlay(overlayCtx);
updateOverlay();
sm.transition('done');
})
});

overlayCanvasRef.current.addEventListener('mousedown', (evt: MouseEvent) => {
sm.transition('down', evt)
Expand Down Expand Up @@ -278,17 +308,29 @@ const ContentEditor = () => {
<canvas className={styles.ContentCanvas} ref={contentCanvasRef}>Sorry, your browser does not support canvas.</canvas>
<canvas className={styles.OverlayCanvas} ref={overlayCanvasRef}/>
</div>
{showMenu && <div className={styles.BackgroundMenu}>
{showBackgroundMenu && <div className={`${styles.Menu} ${styles.BackgroundMenu}`}>
<button onClick={() => sm.transition('upload')}>Upload</button>
<button onClick={() => sm.transition('link')}>Link</button>
</div>}
{showOpacityMenu && <div className={`${styles.Menu} ${styles.OpacityMenu}`}>
<button onClick={() => sm.transition('display')}>Display Opacity</button>
<button onClick={() => sm.transition('render')}>Render Opacity</button>
</div>}
{showOpacitySlider && <div className={styles.OpacitySlider}>
<input type="range" min="0" max="1" defaultValue="1" step="0.01"
onChange={(evt) => sm.transition('change', evt.target.value)}>
</input>
</div>}
<div className={styles.ControlsContainer}>
<input type='color' defaultValue='#ff0000' onChange={(evt) => setOverlayColour(evt.target.value)}/>
<button disabled={canObscure} onClick={() => sm.transition('opacity')}>Opacity</button>
<button hidden={zoomedIn} disabled={!canObscure} onClick={() => sm.transition('zoomIn')}>Zoom In</button>
<button hidden={!zoomedIn} onClick={() => sm.transition('zoomOut')}>Zoom Out</button>
<button disabled={!canObscure} onClick={() => sm.transition('obscure')}>Obscure</button>
<button disabled={!canObscure} onClick={() => sm.transition('reveal')}>Reveal</button>
<button disabled={canObscure} onClick={() => sm.transition('clear')}>Clear</button>
<input
type="text"
value={link}
disabled={!canLink}
onChange={(e) => setLink(e.target.value)}
Expand Down
14 changes: 13 additions & 1 deletion src/utils/drawing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { calculateBounds, ImageBound, Rect } from "./geometry";

export const CONTROLS_HEIGHT = 46;
let baseData: ImageData | null = null;
let red: string = '255';
let green: string = '0';
let blue: string = '0';
let opacity: string = '1';

export function getRect(x1: number, y1: number, x2: number, y2: number): Rect {
let x: number;
Expand Down Expand Up @@ -119,10 +123,18 @@ export function setupOverlayCanvas(bounds: ImageBound, ctx: CanvasRenderingConte
return Promise.resolve();
}

export function setOverlayOpacity(overlayOpacity: string) { opacity = overlayOpacity; }

export function setOverlayColour(colour: string) {
[red, green, blue] = [parseInt(colour.slice(1, 3), 16).toString(),
parseInt(colour.slice(3, 5), 16).toString(),
parseInt(colour.slice(5, 7), 16).toString()];
}

export function obscureOverlay(this: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number) {
if (baseData === null) return;
this.putImageData(baseData, 0, 0);
this.fillStyle = "rgba(255, 0, 0, 1)";
this.fillStyle = `rgba(${red}, ${green}, ${blue}, ${opacity})`;
this.fillRect(x1,y1,x2-x1,y2-y1);
baseData = this.getImageData(0, 0, this.canvas.width, this.canvas.height);
}
Expand Down
25 changes: 23 additions & 2 deletions src/utils/mousestatemachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class MouseStateMachine implements StateMachine {
'push': 'push',
'zoomOut': 'zoomOut',
'clear': 'clear',
'opacity': 'opacity_select',
},
'push': {
'done': 'wait',
Expand Down Expand Up @@ -55,7 +56,6 @@ export class MouseStateMachine implements StateMachine {
'link': 'background_link',
'upload': 'background_upload',
'down': 'record_mouse',
'cancel': 'wait',
},
'background_link': {
'done': 'wait',
Expand All @@ -65,7 +65,28 @@ export class MouseStateMachine implements StateMachine {
},
'clear': {
'done': 'wait',
}
},
'opacity_select': {
'display': 'opacity_display',
'render': 'opacity_render',
'down': 'record_mouse',
},
'opacity_display': {
'down': 'record_mouse',
'change': 'update_display_opacity',
},
'update_display_opacity': {
'down': 'record_mouse',
'change': 'update_display_opacity',
},
'opacity_render': {
'down': 'record_mouse',
'change': 'update_render_opacity',
},
'update_render_opacity': {
'down': 'record_mouse',
'change': 'update_render_opacity',
},
};
setCallback(this, 'record_mouse', this.doRecord);
}
Expand Down

0 comments on commit f3e0e66

Please sign in to comment.