add blend mode, clear canvas before redraw, various improvements
This commit is contained in:
parent
1c3b9c7c46
commit
4b102137f7
3 changed files with 40 additions and 10 deletions
|
@ -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
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)];
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue