I'm creating an image editor in vuejs with fabricjs. In the code below you can see we can already Paint and Add text to the image. Now I want to create an eraser which only erases the paint and not the image in the background. Currently I have this code:
<template>
<div class="clipboard">
<div class="clipboard-head">
<div class="flex-center">
<input class="clipboard-input" type="text">
<div class="clipboard-btn">
<VButton
@clickHandler="$emit('convertToBlob', canvasEl)"
theme="light-blue"
active
>Save</VButton>
<VButton
theme="light-blue"
>Cancel</VButton>
</div>
</div>
<div class="clipboard-controllers">
<button @click="changeDrawingMode(true)" :class="['clipboard__text', { 'active': isBrushMode }]" style="width: auto;">Paint</button>
<button @click="changeDrawingMode(false)" :class="['clipboard__text', { 'active': isTextMode }]" style="width: auto;">Select/Drag</button>
<button @click="erase" :class="[{ 'active': isEraserMode }]" style="width: auto">Eraser</button>
|
<button @click="addText" class="clipboard__text-xl">Aa</button>
<button @click="toggleBrush(5)">
<div class="clipboard__brash-xs brash"></div>
</button>
<button @click="toggleBrush(10)">
<div class="clipboard__brash-md brash"></div>
</button>
<button @click="toggleBrush(20)">
<div class="clipboard__brash-xl brash"></div>
</button>
<button @click="showClipboardColors =!showClipboardColors" class="clipboard__color">
<div class="clipboard__field" :style="{ backgroundColor: selectedColor }"></div>
<div v-if="showClipboardColors" class="clipboard__colors">
<button v-for="(color, index) in colors" @click="canvas.freeDrawingBrush.color = color, selectedColor = color">
<div
class="clipboard__field"
:key="index"
:style="{ backgroundColor: color }"
></div>
</button>
</div>
</button>
</div>
</div>
<div>
<img class="clipboard-image" ref="image" :src="clipboard_img" alt="">
<canvas :width="canvasWidth" :height="canvasHeight" ref="canvas"></canvas>
</div>
</div>
</template>
<script>
import VButton from "@/components/atoms/VButton";
import { fabric } from 'fabric';
export default {
name: 'ImageEditor',
components: { VButton },
props: ['clipboard_img'],
data() {
return {
showClipboardColors: false,
canvasEl: null,
canvas: null,
canvasWidth: 300,
canvasHeight: 300,
isBrushMode: true,
isTextMode: false,
isEraserMode: false,
selectedColor: '#000000',
brushSize: 5
colors: ['#ffffff', '#ff0000', '#00ff00', '#0000ff'],
}
},
mounted() {
setTimeout(() => {
this.canvas = new fabric.Canvas(this.$refs.canvas, {
selection: false,
});
this.canvas.isDrawingMode = this.isBrushMode;
this.canvas.freeDrawingBrush.color = this.selectedColor;
this.canvas.freeDrawingBrush.width = this.brushSize;
this.canvas.on('path:created', (opt) => {
if (this.isBrushMode) {
opt.path.globalCompositeOperation = 'source-over';
} else if (this.isEraserMode) {
opt.path.globalCompositeOperation = 'destination-out';
}
});
fabric.Image.fromURL(this.clipboard_img, (img) => {
this.canvasWidth = this.$refs.image.width
this.canvasHeight = this.$refs.image.height
this.canvas.setBackgroundImage(img, this.canvas.renderAll.bind(this.canvas), {
scaleX: this.canvasWidth / img.width,
scaleY: this.canvasHeight / img.height,
});
this.canvas.setDimensions({ width: this.canvasWidth, height: this.canvasHeight });
this.canvasEl = document.querySelector('.lower-canvas')
});
}, 100)
},
methods: {
addText() {
this.isBrushMode = false
this.isTextMode = true
this.isEraserMode = false
const text = new fabric.IText('Type here', {
left: 100,
top: 100,
fill: this.selectedColor
});
this.canvas.add(text);
text.set({
selectable: true,
});
this.canvas.setActiveObject(text)
this.canvas.isDrawingMode = false;
},
toggleBrush(size) {
this.isBrushMode = true
this.isTextMode = false
this.isEraserMode = false
this.canvas.freeDrawingBrush.width = size;
this.canvas.isDrawingMode = this.isBrushMode;
this.canvas.selection = false;
},
erase() {
this.isEraserMode = true
this.isBrushMode = false;
this.isTextMode = false;
this.canvas.isDrawingMode = true;
this.canvas.selection = false;
this.selectedColor = '#ffffff'
this.canvas.freeDrawingBrush.color = this.selectedColor
},
changeDrawingMode(type) {
this.isBrushMode = type
this.isTextMode = !type
this.isEraserMode = false
this.canvas.isDrawingMode = type
}
}
}
</script>
I used the code below but it erases everything, I tried adding the real image in the background so when we erase the canvas the image supports that part of the canvas and it does the job if it was just for drawing but I also need to convert the canvas to blob and upload etc...
this.canvas.on('path:created', (opt) => {
if (this.isBrushMode) {
opt.path.globalCompositeOperation = 'source-over';
} else if (this.isEraserMode) {
opt.path.globalCompositeOperation = 'destination-out';
}
});
I've spent the last 3 days trying to create and eraser but no luck so I'd appreciate if you could give me a hand. I know the code needs some polishing but after creating the eraser. Thank you in advance