add blend mode, clear canvas before redraw, various improvements

This commit is contained in:
Tomáš Mládek 2020-07-17 11:57:11 +02:00
parent 1c3b9c7c46
commit 4b102137f7
3 changed files with 40 additions and 10 deletions

View file

@ -1,7 +1,13 @@
import {CollageMode} from "@/types"; import {CollageMode} from "@/types";
import {randint, shuffle} from "@/utils"; import {choice, randint, shuffle} from "@/utils";
const collageModeType = ["clean_grid", "chaos_grid", "row", "irow", "col", "icol", "concentric_factor", "concentric_spaced"] as const; const collageModeType = [
"clean_grid", "chaos_grid",
"row", "irow",
"col", "icol",
"concentric_factor", "concentric_spaced",
"blend"
] as const;
export type CollageModeType = typeof collageModeType[number]; export type CollageModeType = typeof collageModeType[number];
function cleanDraw(ctx: CanvasRenderingContext2D, image: ImageBitmap, function cleanDraw(ctx: CanvasRenderingContext2D, image: ImageBitmap,
@ -140,8 +146,7 @@ const modes: { [key in CollageModeType]: CollageMode } = {
let factor: number; let factor: number;
if (Math.random() > .5) { if (Math.random() > .5) {
const factors = [1 / Math.sqrt(2), .5, .88]; factor = choice([1 / Math.sqrt(2), .5, .88]);
factor = factors[Math.floor(Math.random() * factors.length)];
} else { } else {
factor = 1 - (1 / selectedImages.length); factor = 1 - (1 / selectedImages.length);
} }
@ -156,17 +161,32 @@ const modes: { [key in CollageModeType]: CollageMode } = {
minImages: 2, minImages: 2,
place: (ctx, images, config) => { place: (ctx, images, config) => {
const selectedImages = shuffle(images).slice(0, config.numImages || randint(4) + 2); const selectedImages = shuffle(images).slice(0, config.numImages || randint(4) + 2);
const x = ctx.canvas.width / 2;
const y = ctx.canvas.height / 2;
selectedImages.forEach((image, idx) => { selectedImages.forEach((image, idx) => {
cleanDraw( cleanDraw(
ctx, image, x, y, ctx, image,
ctx.canvas.width / 2,
ctx.canvas.height / 2,
ctx.canvas.width - (ctx.canvas.width / selectedImages.length * idx), ctx.canvas.width - (ctx.canvas.width / selectedImages.length * idx),
ctx.canvas.height - (ctx.canvas.height / selectedImages.length * idx), ctx.canvas.height - (ctx.canvas.height / selectedImages.length * idx),
); );
}); });
} }
},
"blend": {
name: "Blending",
minImages: 2,
place: (ctx, images, config) => {
const selectedImages = shuffle(images).slice(0, config.numImages || randint(2) + 2);
ctx.globalCompositeOperation = choice(["difference", "saturation", "soft-light", "overlay"]);
selectedImages.forEach((image) => {
cleanDraw(
ctx, image,
ctx.canvas.width / 2, ctx.canvas.height / 2,
ctx.canvas.width, ctx.canvas.height
);
});
}
} }
}; };

View file

@ -91,10 +91,8 @@ export default class Collage extends Vue {
return this.lastMode ? this.lastMode.forceConfig || {} : {}; return this.lastMode ? this.lastMode.forceConfig || {} : {};
} }
private mounted() { private mounted() {
const canvas = (this.$refs.canvas as HTMLCanvasElement); this.reset();
this.context = canvas.getContext("2d") as CanvasRenderingContext2D;
} }
@Watch("images") @Watch("images")
@ -103,6 +101,7 @@ export default class Collage extends Vue {
private renderCollage() { private renderCollage() {
if (this.images.length >= this.currentMode.minImages) { if (this.images.length >= this.currentMode.minImages) {
this.lastActiveModeType = this.currentModeType; this.lastActiveModeType = this.currentModeType;
this.reset();
this.currentMode.place(this.context, this.images, this.collageConfig); this.currentMode.place(this.context, this.images, this.collageConfig);
} }
} }
@ -113,10 +112,17 @@ export default class Collage extends Vue {
this.renderCollage(); this.renderCollage();
}); });
} }
private reset() {
const canvas = (this.$refs.canvas as HTMLCanvasElement);
this.context = canvas.getContext("2d") as CanvasRenderingContext2D;
this.context.clearRect(0, 0, canvas.width, canvas.height);
}
} }
</script> </script>
<!-- Add "scoped" attribute to limit CSS to this component only --> <!-- Add "scoped" attribute to limit CSS to this component only -->
<!--suppress CssUnusedSymbol -->
<style scoped> <style scoped>
.collage { .collage {
margin: 2rem; margin: 2rem;

View file

@ -17,3 +17,7 @@ export function shuffle<T>(a: T[]): T[] {
export function randint(n: number) { export function randint(n: number) {
return Math.floor(Math.random() * n); return Math.floor(Math.random() * n);
} }
export function choice<T>(arr: T[]): T {
return arr[randint(arr.length)];
}