Skip to content

Commit

Permalink
Remove async/await, add drag drop of HTMLImageElement, fix tweakpane …
Browse files Browse the repository at this point in the history
…version issue, switch to es module build, v1.1.404
repalash committed Aug 11, 2023
1 parent 981bc3d commit 34d1e4b
Showing 6 changed files with 74 additions and 61 deletions.
22 changes: 11 additions & 11 deletions package-lock.json

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

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tweakpane-image-plugin",
"version": "1.1.403",
"version": "1.1.404",
"description": "Image input plugin for Tweakpane",
"main": "dist/index.js",
"module": "dist/index.js",
@@ -43,7 +43,6 @@
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-replace": "^2.4.1",
"@rollup/plugin-typescript": "^8.2.0",
"@tweakpane/core": "^1.1.5",
"@typescript-eslint/eslint-plugin": "^4.15.2",
"@typescript-eslint/parser": "^4.15.2",
"autoprefixer": "^10.2.4",
@@ -62,5 +61,8 @@
"sass": "^1.59.2",
"tweakpane": "^3.1.9",
"typescript": "^5.0.4"
},
"dependencies": {
"@tweakpane/core": "1.1.8"
}
}
9 changes: 5 additions & 4 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -87,10 +87,11 @@ export default async () => {
external: ['tweakpane'],
output: {
file: `dist/${distName}${postfix}.js`,
format: 'umd',
globals: {
tweakpane: 'Tweakpane',
},
format: 'es',
sourcemap: true,
// globals: {
// tweakpane: 'Tweakpane',
// },
name: getUmdName('index'),
},
plugins: getPlugins(css, production),
53 changes: 34 additions & 19 deletions src/controller.ts
Original file line number Diff line number Diff line change
@@ -31,22 +31,25 @@ export class PluginController implements Controller<PluginView> {

this.onFile = this.onFile.bind(this);
this.onDrop = this.onDrop.bind(this);
this.onDragStart = this.onDragStart.bind(this);
this.onDragOver = this.onDragOver.bind(this);
this.onDragLeave = this.onDragLeave.bind(this);

this.view.input.addEventListener('change', this.onFile);
this.view.element.addEventListener('drop', this.onDrop);
this.view.element.addEventListener('dragstart', this.onDragStart);
this.view.element.addEventListener('dragover', this.onDragOver);
this.view.element.addEventListener('dragleave', this.onDragLeave);

this.viewProps.handleDispose(() => {
this.view.input.removeEventListener('change', this.onFile);
this.view.input.removeEventListener('drop', this.onDrop);
this.view.input.removeEventListener('dragover', this.onDragOver);
this.view.input.removeEventListener('dragleave', this.onDragLeave);
this.view.element.removeEventListener('drop', this.onDrop);
this.view.element.removeEventListener('dragstart', this.onDragStart);
this.view.element.removeEventListener('dragover', this.onDragOver);
this.view.element.removeEventListener('dragleave', this.onDragLeave);
});

this.value.emitter.on('change', this.handleValueChange.bind(this));
this.value.emitter.on('change', () => this.handleValueChange());

this.handleValueChange();
}
@@ -60,7 +63,7 @@ export class PluginController implements Controller<PluginView> {
// this.updateImage(url);
}

private async onDrop(event: DragEvent) {
private onDrop(event: DragEvent) {
event.preventDefault();
try {
const {dataTransfer} = event;
@@ -70,9 +73,15 @@ export class PluginController implements Controller<PluginView> {
// this.updateImage(url);
this.setValue(file);
} else {
const url = dataTransfer?.getData('url');
if (!url) throw new Error('No url');
this.setValue(url);
const imgId = dataTransfer?.getData('img-id');
if (imgId) {
const img = document.getElementById(imgId) as HTMLImageElement;
this.setValue(img);
} else {
const url = dataTransfer?.getData('url');
if (!url) throw new Error('No url');
this.setValue(url);
}
// loadImage(url).then(async (image) => {
// console.log('drop', image);
// const clone = await cloneImage(image);
@@ -87,6 +96,11 @@ export class PluginController implements Controller<PluginView> {
}
}

private onDragStart(event: DragEvent) {
event.dataTransfer?.setData('img-id', this.view.image_.id);
event.dataTransfer?.setDragImage(this.view.image_, 0, 0);
}

private onDragOver(event: Event) {
event.preventDefault();
this.view.changeDraggingState(true);
@@ -96,48 +110,49 @@ export class PluginController implements Controller<PluginView> {
this.view.changeDraggingState(false);
}

private async handleImage(image: ImageResolvable) {
private handleImage(image: ImageResolvable) {
if (image instanceof HTMLImageElement) {
this.updateImage(image.src);
} else if (typeof image === 'string' || !image) {
if (image === 'placeholder' || !image) {
image = (await this.handlePlaceholderImage()).src;
image = this.handlePlaceholderImage().src;
}
this.updateImage(image);
} else {
await this.setValue(image);
this.setValue(image);
}
}

private updateImage(src: string) {
this.view.changeImage(src);
}

private async setValue(src: ImageResolvable) {
private setValue(src: ImageResolvable) {
if (src instanceof HTMLImageElement) {
this.value.setRawValue(src);
} else if (src instanceof File) {
const url = URL.createObjectURL(src) + '#' + src.name;
(src as any).src = url;
const img = await loadImage(url).catch(() => {
// URL.revokeObjectURL(url);
});
const img = loadImage(url);
// .catch(() => {
// // URL.revokeObjectURL(url);
// });
// URL.revokeObjectURL(url); //todo: revoke sometime.
this.value.setRawValue(img || src);
} else if (src) {
this.value.setRawValue(await loadImage(src));
this.value.setRawValue(loadImage(src));
} else {
this.value.setRawValue(await this.handlePlaceholderImage());
this.value.setRawValue(this.handlePlaceholderImage());
}
}

private handleValueChange() {
this.handleImage(this.value.rawValue);
}

private async handlePlaceholderImage(): Promise<HTMLImageElement> {
private handlePlaceholderImage(): HTMLImageElement {
if (!placeholderImage) {
placeholderImage = await createPlaceholderImage();
placeholderImage = createPlaceholderImage();
}
return placeholderImage;
}
42 changes: 18 additions & 24 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function createPlaceholderImage(): Promise<HTMLImageElement> {
export function createPlaceholderImage(): HTMLImageElement {
const canvas = document.createElement('canvas');
canvas.width = 320;
canvas.height = 50;
@@ -13,33 +13,27 @@ export function createPlaceholderImage(): Promise<HTMLImageElement> {
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('No image', canvas.width * 0.5, canvas.height * 0.5);

return new Promise((resolve) => {
canvas.toBlob((blob) => {
const image = new Image();
if (!blob) {
resolve(image);
return;
}
image.src = URL.createObjectURL(blob);
(image as any).isPlaceholder = true;
image.onload = () => {
resolve(image);
};
});
});
const image = new Image();
// if (!blob) {
// resolve(image);
// return;
// }
image.src = canvas.toDataURL('image/png', 0.8);
(image as any).isPlaceholder = true;
// image.onload = () => {
// resolve(image);
// };
return image;
}

export async function loadImage(src: string): Promise<HTMLImageElement> {
export function loadImage(src: string): HTMLImageElement {
const image = new Image();
image.crossOrigin = 'anonymous';
return new Promise((resolve, reject) => {
image.src = src;
image.onload = () => {
resolve(image);
};
image.onerror = reject;
});
image.src = src;
// image.onload = () => {
// };
// image.onerror = reject;
return image;
}

export function cloneImage(
3 changes: 2 additions & 1 deletion src/view.ts
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ const className = ClassName('img');
export class PluginView implements View {
public readonly element: HTMLElement;
public readonly input: HTMLInputElement;
private image_: HTMLImageElement;
public readonly image_: HTMLImageElement;

constructor(doc: Document, config: Config) {
this.element = doc.createElement('div');
@@ -25,6 +25,7 @@ export class PluginView implements View {
this.input.setAttribute('accept', config.extensions.join(','));

this.image_ = doc.createElement('img');
this.image_.id = 'tpimg_' + Math.random().toString(36).slice(2); // need unique for drop
this.image_.classList.add(className('image'));
this.image_.classList.add(className(`image_${config.imageFit}`));
this.image_.crossOrigin = 'anonymous';

0 comments on commit 34d1e4b

Please sign in to comment.