Replace sticker background image
We can use the willRenderShapeControls
property to add a "select image" button above a sticker shape.
We'll use a custom browse()
function to select a new image from the file sytem.
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="./pintura.css" />
</head>
<img src="" alt="" />
<style>
.pintura-editor {
height: 600px;
}
</style>
<div id="editor"></div>
<script type="module">
import { appendDefaultEditor, createNode } from './pintura.js';
const browse = (options) => {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
const editor = appendDefaultEditor('#editor', {
src: 'image.jpeg',
imageAnnotation: [
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
],
willRenderShapeControls: (controls, selectedShapeId) => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations = editor.imageAnnotation;
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = URL.createObjectURL(file);
// redraw annotations
editor.imageAnnotation = annotations;
},
})
);
return controls;
},
});
editor.on('process', (imageState) => {
document.querySelector('img').src = URL.createObjectURL(
imageState.dest
);
});
</script>
import '@pqina/pintura/pintura.css';
import './App.css';
import { useRef, useState } from 'react';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults, createNode } from '@pqina/pintura';
const editorDefaults = getEditorDefaults();
const browse = (options) => {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
function App() {
const [editorResult, setEditorResult] = useState(undefined);
const editorRef = useRef(null);
const willRenderShapeControls = (controls, selectedShapeId) => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations =
editorRef.current.editor.imageAnnotation;
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = URL.createObjectURL(file);
// redraw annotations
editorRef.current.editor.imageAnnotation = annotations;
},
})
);
return controls;
};
const handleEditorProcess = (imageState) => {
setEditorResult(URL.createObjectURL(imageState.dest));
};
return (
<div className="App">
{editorResult && <img alt="" src={editorResult} />}
<PinturaEditor
ref={editorRef}
{...editorDefaults}
src={'image.jpeg'}
imageAnnotation={[
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
]}
willRenderShapeControls={willRenderShapeControls}
onProcess={handleEditorProcess}
/>
</div>
);
}
export default App;
.pintura-editor {
height: 600px;
}
<template>
<div>
<img v-if="editorResult" alt="" :src="editorResult" />
<PinturaEditor
ref="editor"
v-bind="editorDefaults"
src="image.jpeg"
:imageAnnotation="imageAnnotation"
:willRenderShapeControls="willRenderShapeControls"
v-on:pintura:process="handleEditorProcess($event)"
/>
</div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults, createNode } from '@pqina/pintura';
const browse = function (options) {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
export default {
name: 'App',
components: {
PinturaEditor,
},
data() {
return {
editorResult: undefined,
editorDefaults: getEditorDefaults(),
imageAnnotation: [
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
],
willRenderShapeControls: (controls, selectedShapeId) => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations =
this.$refs.editor.editor.imageAnnotation;
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = URL.createObjectURL(file);
// redraw annotations
this.$refs.editor.editor.imageAnnotation =
annotations;
},
})
);
return controls;
},
};
},
methods: {
handleEditorProcess: function (imageState) {
this.editorResult = URL.createObjectURL(imageState.dest);
},
},
};
</script>
<style>
@import '@pqina/pintura/pintura.css';
.pintura-editor {
height: 600px;
}
</style>
<script>
import { PinturaEditor } from '@pqina/svelte-pintura';
import { getEditorDefaults, createNode } from '@pqina/pintura';
import '@pqina/pintura/pintura.css';
const browse = (options) => {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
let editorResult = undefined;
let editorDefaults = getEditorDefaults();
let editor;
const willRenderShapeControls = (controls, selectedShapeId) => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations = editor.imageAnnotation;
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = URL.createObjectURL(file);
// redraw annotations
editor.imageAnnotation = annotations;
},
})
);
return controls;
};
const handleEditorProcess = (event) => {
const imageState = event.detail;
editorResult = URL.createObjectURL(imageState.dest);
};
</script>
<div>
{#if editorResult} <img alt="" src={editorResult} /> {/if}
<PinturaEditor
bind:this={editor}
{...editorDefaults}
src={'image.jpeg'}
imageAnnotation={[
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
]}
{willRenderShapeControls}
on:process={handleEditorProcess}
/>
</div>
<style>
div :global(.pintura-editor) {
height: 600px;
}
</style>
import { Component, ViewChild } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { getEditorDefaults, createNode, PinturaNode } from '@pqina/pintura';
const browse = (options: { accept: string }): Promise<File | undefined> => {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
constructor(private domSanitizer: DomSanitizer) {}
@ViewChild('editor') editor?: any;
editorResult?: string = undefined;
editorDefaults: any = getEditorDefaults();
imageAnnotation: any = [
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
];
willRenderShapeControls = (
controls: PinturaNode[],
selectedShapeId: string
): PinturaNode[] => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations = this.editor.editor.imageAnnotation;
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = <string>(
this.domSanitizer.bypassSecurityTrustResourceUrl(
URL.createObjectURL(file)
)
);
// redraw annotations
this.editor.editor.imageAnnotation = annotations;
},
})
);
return controls;
};
handleEditorProcess(imageState: any): void {
this.editorResult = <string>(
this.domSanitizer.bypassSecurityTrustResourceUrl(
URL.createObjectURL(imageState.dest)
)
);
}
}
<img *ngIf="editorResult" [src]="editorResult" alt="" />
<pintura-editor
#editor
[options]="editorDefaults"
src="image.jpeg"
[imageAnnotation]="imageAnnotation"
[willRenderShapeControls]="willRenderShapeControls"
(process)="handleEditorProcess($event)"
></pintura-editor>
::ng-deep .pintura-editor {
height: 600px;
}
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularPinturaModule } from '@pqina/angular-pintura';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AngularPinturaModule],
exports: [AppComponent],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="./pintura/pintura.css" />
</head>
<script src="./jquery.js"></script>
<script src="./jquery-pintura/useEditorWithJQuery-iife.js"></script>
<script src="./pintura/pintura-iife.js"></script>
<img src="" alt="" />
<style>
.pintura-editor {
height: 600px;
}
</style>
<div id="editor"></div>
<script>
useEditorWithJQuery(jQuery, pintura);
$(function () {
var { createNode } = $.fn.pintura;
const browse = (options) => {
return new Promise((resolve) => {
const element = document.createElement('input');
element.type = 'file';
element.accept = options.accept;
element.onchange = () => {
const [file] = element.files;
if (!file) return resolve();
resolve(file);
};
element.click();
});
};
var editor = $('#editor').pinturaDefault({
src: 'image.jpeg',
imageAnnotation: [
{
x: 128,
y: 128,
width: 512,
height: 384,
backgroundSize: 'contain',
backgroundImage: './my-sticker.jpeg',
},
],
willRenderShapeControls: (controls, selectedShapeId) => {
controls[0][3].push(
// Add a "Select image" button
createNode('Button', 'my-button', {
label: 'Select image',
onclick: async () => {
// Find the currently selected shape
const annotations =
$(editor).pintura('imageAnnotation');
const shape = annotations.find(
(shape) => shape.id === selectedShapeId
);
// browse for an image
const file = await browse({
accept: 'image/*',
});
// no file selected
if (!file) return;
// update background image
shape.backgroundImage = URL.createObjectURL(file);
// redraw annotations
$(editor).pintura('imageAnnotation', annotations);
},
})
);
return controls;
},
});
editor.on('pintura:process', function (event) {
const imageState = event.detail;
$('img').attr('src', URL.createObjectURL(imageState.dest));
});
});
</script>