Showing a circular crop overlay
We can use the willRenderCanvas
property to adjust the preview output of the editor.
To apply a circular mask to the output image see the circular mask example.
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="./pintura.css" />
</head>
<style>
.pintura-editor {
height: 600px;
}
</style>
<div id="editor"></div>
<script type="module">
import { appendDefaultEditor } from './pintura.js';
const editor = appendDefaultEditor('#editor', {
src: 'image.jpeg',
// We'll request a square crop
imageCropAspectRatio: 1,
// Let's draw a circle on top of the editor preview when in the crop util
willRenderCanvas: (shapes, state) => {
const {
utilVisibility,
selectionRect,
lineColor,
backgroundColor,
} = state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
},
});
</script>
import '@pqina/pintura/pintura.css';
import './App.css';
import { PinturaEditor } from '@pqina/react-pintura';
import { getEditorDefaults } from '@pqina/pintura';
const editorDefaults = getEditorDefaults();
function App() {
return (
<div className="App">
<PinturaEditor
{...editorDefaults}
src={'image.jpeg'}
// We'll request a square crop
imageCropAspectRatio={1}
// Let's draw a circle on top of the editor preview when in the crop util
willRenderCanvas={(shapes, state) => {
const {
utilVisibility,
selectionRect,
lineColor,
backgroundColor,
} = state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
}}
/>
</div>
);
}
export default App;
.pintura-editor {
height: 600px;
}
<template>
<div>
<PinturaEditor
v-bind="editorDefaults"
src="image.jpeg"
:imageCropAspectRatio="1"
:willRenderCanvas="willRenderCanvas"
/>
</div>
</template>
<script>
import { PinturaEditor } from '@pqina/vue-pintura';
import { getEditorDefaults } from '@pqina/pintura';
export default {
name: 'App',
components: {
PinturaEditor,
},
data() {
return {
editorDefaults: getEditorDefaults(),
// Let's draw a circle on top of the editor preview when in the crop util
willRenderCanvas: (shapes, state) => {
const {
utilVisibility,
selectionRect,
lineColor,
backgroundColor,
} = state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
},
};
},
methods: {},
};
</script>
<style>
@import '@pqina/pintura/pintura.css';
.pintura-editor {
height: 600px;
}
</style>
<script>
import { PinturaEditor } from '@pqina/svelte-pintura';
import { getEditorDefaults } from '@pqina/pintura';
import '@pqina/pintura/pintura.css';
let editorDefaults = getEditorDefaults();
</script>
<div>
<PinturaEditor
{...editorDefaults}
src={'image.jpeg'}
imageCropAspectRatio={/* We'll request a square crop */
1}
willRenderCanvas={/* Let's draw a circle on top of the editor preview when in the crop util */
(shapes, state) => {
const {
utilVisibility,
selectionRect,
lineColor,
backgroundColor,
} = state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
}}
/>
</div>
<style>
div :global(.pintura-editor) {
height: 600px;
}
</style>
import { Component } from '@angular/core';
import { getEditorDefaults } from '@pqina/pintura';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
editorDefaults: any = getEditorDefaults();
// Let's draw a circle on top of the editor preview when in the crop util
willRenderCanvas: any = (shapes, state) => {
const { utilVisibility, selectionRect, lineColor, backgroundColor } =
state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
};
}
<pintura-editor
[options]="editorDefaults"
src="image.jpeg"
[imageCropAspectRatio]="1"
[willRenderCanvas]="willRenderCanvas"
></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>
<style>
.pintura-editor {
height: 600px;
}
</style>
<div id="editor"></div>
<script>
useEditorWithJQuery(jQuery, pintura);
$(function () {
var editor = $('#editor').pinturaDefault({
src: 'image.jpeg',
// We'll request a square crop
imageCropAspectRatio: 1,
// Let's draw a circle on top of the editor preview when in the crop util
willRenderCanvas: (shapes, state) => {
const {
utilVisibility,
selectionRect,
lineColor,
backgroundColor,
} = state;
// Exit if crop utils is not visible
if (utilVisibility.crop <= 0) return shapes;
// Get variable shortcuts to the crop selection rect
const { x, y, width, height } = selectionRect;
return {
// Copy all props from current shapes
...shapes,
// Now we add an inverted ellipse shape to the interface shapes array
interfaceShapes: [
{
x: x + width * 0.5,
y: y + height * 0.5,
rx: width * 0.5,
ry: height * 0.5,
opacity: utilVisibility.crop,
inverted: true,
backgroundColor: [...backgroundColor, 0.5],
strokeWidth: 1,
strokeColor: [...lineColor],
},
// Spread all existing interface shapes onto the array
...shapes.interfaceShapes,
],
};
},
});
});
</script>