Merge pull request #1785 from petkir/petkir-react-image-editor

This commit is contained in:
Hugo Bernier 2021-03-25 02:18:18 -04:00 committed by GitHub
commit d0213def6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 101 deletions

View File

@ -20,7 +20,7 @@ import ItemOrder from './components/ItemOrder';
import { GrayscaleFilter } from './Filter/GrayscaleFilter';
import { SepiaFilter } from './Filter/SepiaFilter';
import { historyItem } from './historyItem';
import styles from './ImageManipulation.module.scss';
import {
FilterType,
@ -45,6 +45,7 @@ const flipVerticalIcon: any = require('../../svg/flipVertical.svg');
const flipHorizontalIcon: any = require('../../svg/flipHorizontal.svg');
import * as strings from 'ImageManipulationStrings';
import { historyItem } from './HistoryItem';
export interface IImageManipulationConfig {
rotateButtons: number[];
@ -53,11 +54,11 @@ export interface IImageManipulationConfig {
export interface IImageManipulationProps {
src: string;
settings?: IImageManipulationSettings[];
settingschanged?: (settings: IImageManipulationSettings[]) => void;
settingsChanged?: (settings: IImageManipulationSettings[]) => void;
imgLoadError?: () => void;
editMode?: (mode: boolean) => void;
configsettings: IImageManipulationConfig;
displyMode: DisplayMode;
configSettings: IImageManipulationConfig;
displayMode: DisplayMode;
}
export interface IImageManipulationState {
@ -104,32 +105,6 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
}
}
public render(): React.ReactElement<IImageManipulationProps> {
return (
<div className={styles.imageEditor} style={{
marginTop: this.props.displyMode === DisplayMode.Edit ? '40px' : '0px'
}} >
{this.props.displyMode === DisplayMode.Edit && this.getCommandBar()}
<div className={styles.imageplaceholder + ' ' + this.getMaxWidth()}
ref={(element: HTMLDivElement) => { this.wrapperRef = element; }}
style={this.canvasRef && { width: '' + this.canvasRef.width + 'px' }}
>
<canvas className={this.getMaxWidth()}
style={{ display: 'none' }}
ref={this.setBufferRef}></canvas>
<canvas className={this.getMaxWidth()}
style={{ display: 'none' }}
ref={this.setManipulateRef}></canvas>
<canvas className={this.getMaxWidth()} ref={this.setCanvasRef} ></canvas>
{this.state.settingPanel === SettingPanelType.Crop && (this.getCropGrid())}
{this.state.settingPanel === SettingPanelType.Resize && (this.getResizeGrid())}
</div>
</div>
);
}
private imageChanged(url: string): void {
this.img = new Image();
this.img.src = url;
@ -167,6 +142,7 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
this.manipulateRef.height = currentheight;
this.manipulateCtx.save();
let nothingToDo: boolean = false;
switch (element.type) {
case ManipulationType.Flip:
const filp: IFlipSettings = element as IFlipSettings;
@ -187,11 +163,12 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
break;
}
if (rotate.rotate) {
const angelcalc: number = rotate.rotate * Math.PI / 180;
const oldwidth: number = currentwidth;
const oldheight: number = currentheight;
let offsetwidth: number = 0;
let offsetheight: number = 0;
const angelcalc = rotate.rotate * Math.PI / 180;
const oldwidth = currentwidth;
const oldheight = currentheight;
let offsetwidth = 0;
let offsetheight = 0;
const a: number = oldwidth * Math.abs(Math.cos(angelcalc));
const b: number = oldheight * Math.abs(Math.sin(angelcalc));
@ -224,20 +201,6 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
this.manipulateCtx.drawImage(this.bufferRef, 0, 0);
}
break;
case ManipulationType.Filter:
nothingToDo = true;
const filter: IFilterSettings = element as IFilterSettings;
let imageData: ImageData = this.bufferCtx.getImageData(0, 0, currentwidth, currentheight);
switch (filter.filterType) {
case FilterType.Grayscale:
imageData = new GrayscaleFilter().process(imageData, currentwidth, currentheight, undefined, undefined);
break;
case FilterType.Sepia:
imageData = new SepiaFilter().process(imageData, currentwidth, currentheight, undefined, undefined);
break;
}
this.bufferCtx.putImageData(imageData, 0, 0);
break;
case ManipulationType.Crop:
const last: boolean = this.props.settings.length === index + 1;
if (last && this.state.settingPanel === SettingPanelType.Crop) {
@ -263,12 +226,27 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
newheight);
}
break;
case ManipulationType.Resize:
const resize: IResizeSettings = element as IResizeSettings;
newwidth = resize.width;
newheight = resize.height;
this.manipulateCtx.drawImage(this.bufferRef, 0, 0);
break;
case ManipulationType.Filter:
nothingToDo = true;
const filter = element as IFilterSettings;
var imageData = this.bufferCtx.getImageData(0, 0, currentwidth, currentheight);
switch (filter.filterType) {
case FilterType.Grayscale:
imageData = new GrayscaleFilter().process(imageData, currentwidth, currentheight, undefined, undefined);
break;
case FilterType.Sepia:
imageData = new SepiaFilter().process(imageData, currentwidth, currentheight, undefined, undefined);
break;
}
this.bufferCtx.putImageData(imageData, 0, 0);
break;
}
this.manipulateCtx.restore();
@ -310,6 +288,31 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
// this.canvasctx.translate(this.canvasRef.width / 2 * -1, this.canvasRef.height / 2 * -1);
}
public render(): React.ReactElement<IImageManipulationProps> {
return (
<div className={styles.imageEditor} style={{
marginTop: this.props.displayMode === DisplayMode.Edit ? '40px' : '0px',
}} >
{this.props.displayMode === DisplayMode.Edit && this.getCommandBar()}
<div className={styles.imageplaceholder + ' ' + this.getMaxWidth()}
ref={(element: HTMLDivElement) => { this.wrapperRef = element; }}
style={this.canvasRef && { width: '' + this.canvasRef.width + 'px' }}
>
<canvas className={this.getMaxWidth()}
style={{ display: 'none' }}
ref={this.setBufferRef}></canvas>
<canvas className={this.getMaxWidth()}
style={{ display: 'none' }}
ref={this.setManipulateRef}></canvas>
<canvas className={this.getMaxWidth()} ref={this.setCanvasRef} ></canvas>
{this.state.settingPanel === SettingPanelType.Crop && (this.getCropGrid())}
{this.state.settingPanel === SettingPanelType.Resize && (this.getResizeGrid())}
</div>
</div>
);
}
private getCropGrid(): JSX.Element {
const lastset: ICropSettings = this.getLastManipulation() as ICropSettings;
let lastdata: ICrop = { sx: 0, sy: 0, width: 0, height: 0 };
@ -430,14 +433,14 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
if (this.state.redosettings && this.state.redosettings.length > 0) {
this.setState({ redosettings: [] }, () => {
if (this.props.settingschanged) {
this.props.settingschanged(newhist);
if (this.props.settingsChanged) {
this.props.settingsChanged(newhist);
}
});
} else {
if (this.props.settingschanged) {
this.props.settingschanged(newhist);
if (this.props.settingsChanged) {
this.props.settingsChanged(newhist);
}
}
}}
@ -476,8 +479,8 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
svalue: svalue
});
}
if (this.props.settingschanged) {
this.props.settingschanged(tmpsettings);
if (this.props.settingsChanged) {
this.props.settingsChanged(tmpsettings);
}
}
@ -540,7 +543,7 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
}
return (<div>
<div>
{this.props.configsettings.rotateButtons.map((value: number, index: number) => {
{this.props.configSettings.rotateButtons.map((value: number, index: number) => {
let icon: string = 'CompassNW';
if (value !== 0) { icon = 'Rotate'; }
@ -884,13 +887,13 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
if (this.state.redosettings && this.state.redosettings.length > 0) {
this.setState({ redosettings: [] }, () => {
if (this.props.settingschanged) {
this.props.settingschanged(state);
if (this.props.settingsChanged) {
this.props.settingsChanged(state);
}
});
} else {
if (this.props.settingschanged) {
this.props.settingschanged(state);
if (this.props.settingsChanged) {
this.props.settingsChanged(state);
}
}
}
@ -899,8 +902,8 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
if (this.props.settings && this.props.settings.length > 0) {
const state: IImageManipulationSettings[] = clone(this.props.settings);
state.splice(state.length - 1, 1);
if (this.props.settingschanged) {
this.props.settingschanged(clone(state));
if (this.props.settingsChanged) {
this.props.settingsChanged(clone(state));
}
}
}
@ -942,8 +945,8 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
redo.push(last);
this.setState({ redosettings: redo },
() => {
if (this.props.settingschanged) {
this.props.settingschanged(settings);
if (this.props.settingsChanged) {
this.props.settingsChanged(settings);
}
});
@ -961,8 +964,8 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
settings.push(redo);
this.setState({ redosettings: redosettings },
() => {
if (this.props.settingschanged) {
this.props.settingschanged(settings);
if (this.props.settingsChanged) {
this.props.settingsChanged(settings);
}
});
@ -976,8 +979,8 @@ export class ImageManipulation extends React.Component<IImageManipulationProps,
onClick={() => {
this.setState({ redosettings: [] },
() => {
if (this.props.settingschanged) {
this.props.settingschanged([]);
if (this.props.settingsChanged) {
this.props.settingsChanged([]);
}
});

View File

@ -10,14 +10,7 @@ const flipVerticalIcon: any = require('../../svg/flipVertical.svg');
const resizeIcon: any = require('../../svg/resize.svg');
import * as strings from 'ImageManipulationStrings';
export enum ManipulationType {
Crop,
Scale,
Rotate,
Flip,
Filter,
Resize
}
export enum SettingPanelType {
Closed = 1,
@ -46,10 +39,6 @@ export enum FilterType {
ColorOverLay*/
}
export interface IManipulationBase {
type: ManipulationType;
}
export interface ICrop {
sx: number;
sy: number;
@ -64,8 +53,18 @@ export interface IResize {
aspect?: number;
}
export enum ManipulationType {
Crop,
Scale,
Rotate,
Flip,
Filter,
Resize
}
export interface IManipulationBase {
type: ManipulationType;
}
export interface ICropSettings extends IManipulationBase, ICrop {
}
export interface IFlipSettings extends IManipulationBase {
flipX: boolean;
@ -77,23 +76,16 @@ export interface IScaleSettings extends IManipulationBase {
export interface IRotateSettings extends IManipulationBase {
rotate: number;
}
export interface IFilterSettings extends IManipulationBase {
filterType: FilterType;
nvalue?: number;
svalue?: string;
}
export interface IResizeSettings extends IManipulationBase, IResize {
}
export type IImageManipulationSettings = IFilterSettings | IRotateSettings |
IScaleSettings | IFlipSettings | ICropSettings | IResizeSettings;
export type IImageManipulationSettings =
IFilterSettings
| IRotateSettings
| IScaleSettings
| IFlipSettings
| ICropSettings
| IResizeSettings;
export const filterTypeData: IFilterTypeData = {
0: strings.FilterTypeGrayscale,

View File

@ -0,0 +1,31 @@
<html>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;"></canvas>
<script>
const img= new Image()
img.crossOrigin = "Anonymous";
img.addEventListener("load", imageReceived, false);
img.src = 'https://pnp.github.io/images/hero-parker-p-800.png';
function imageReceived() {
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
c.width = img.width;
c.height = img.height;
ctx.translate(0, c.height);
ctx.scale(1, -1);
ctx.drawImage(img, 0, 0);
ctx.font = "30px Arial";
ctx.strokeText("Hello PnP-Community",10,50);
}
</script>
</body>
</html>

View File

@ -1,7 +1,4 @@
/*ImageManipulation
FilterType
*/
export { ImageManipulation, IImageManipulationConfig } from './ImageManipulation';

View File

@ -72,16 +72,18 @@ export default class ReactImageEditor extends React.Component<IReactImageEditorP
description='Please configure the web part.'
buttonLabel='Configure'
onConfigure={this._onConfigure} />) :
(<ImageManipulation
settings={settings}
configsettings={{
(
<ImageManipulation
settings={this.props.settings}
configSettings={{
rotateButtons: [-90, -45, -30, 0, 30, 45, 90]
}
}
displyMode={DisplayMode.Edit}
settingschanged={this.props.updateManipulationSettingsProperty}
src={url}
/>)}
displayMode={this.props.displayMode}
settingsChanged={this._onSettingsChanged}
src={this.props.url}
/>
)}
</div >
);