Skip to content

Commit

Permalink
feat: reworked image shape, now supports multiple colors in svg repla…
Browse files Browse the repository at this point in the history
…ce color, random value too
  • Loading branch information
matteobruni committed Aug 4, 2022
1 parent c28bc85 commit 3173ebc
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 99 deletions.
2 changes: 1 addition & 1 deletion demo/vanilla/public/presets/svgReplace.json
Expand Up @@ -57,7 +57,7 @@
},
"particles": {
"color": {
"value": ["#000", "#f00", "#00f"]
"value": "#00f"
},
"lineLinked": {
"blink": false,
Expand Down
14 changes: 7 additions & 7 deletions engine/src/Core/Particle.ts
Expand Up @@ -474,11 +474,11 @@ export class Particle implements IParticle {
mover.init?.(this);
}

if (drawer && drawer.particleInit) {
if (drawer?.particleInit) {
drawer.particleInit(container, this);
}

for (const [, plugin] of container.plugins) {
for (const [ , plugin ] of container.plugins) {
plugin.particleCreated?.(this);
}
}
Expand All @@ -491,7 +491,7 @@ export class Particle implements IParticle {
this.destroyed = true;
this.bubble.inRange = false;

for (const [, plugin] of this.container.plugins) {
for (const [ , plugin ] of this.container.plugins) {
if (plugin.particleDestroyed) {
plugin.particleDestroyed(this, override);
}
Expand All @@ -511,7 +511,7 @@ export class Particle implements IParticle {
draw(delta: IDelta): void {
const container = this.container;

for (const [, plugin] of container.plugins) {
for (const [ , plugin ] of container.plugins) {
container.canvas.drawParticlePlugin(plugin, this, delta);
}

Expand Down Expand Up @@ -593,7 +593,7 @@ export class Particle implements IParticle {
zIndex: number,
tryCount = 0
): Vector3d {
for (const [, plugin] of container.plugins) {
for (const [ , plugin ] of container.plugins) {
const pluginPos =
plugin.particlePosition !== undefined ? plugin.particlePosition(position, this) : undefined;

Expand All @@ -614,7 +614,7 @@ export class Particle implements IParticle {
fixHorizontal = (outMode: OutMode | keyof typeof OutMode | OutModeAlt): void => {
fixOutMode({
outMode,
checkModes: [OutMode.bounce, OutMode.bounceHorizontal],
checkModes: [ OutMode.bounce, OutMode.bounceHorizontal ],
coord: pos.x,
maxCoord: container.canvas.size.width,
setCb: (value: number) => (pos.x += value),
Expand All @@ -624,7 +624,7 @@ export class Particle implements IParticle {
fixVertical = (outMode: OutMode | keyof typeof OutMode | OutModeAlt): void => {
fixOutMode({
outMode,
checkModes: [OutMode.bounce, OutMode.bounceVertical],
checkModes: [ OutMode.bounce, OutMode.bounceVertical ],
coord: pos.y,
maxCoord: container.canvas.size.height,
setCb: (value: number) => (pos.y += value),
Expand Down
5 changes: 2 additions & 3 deletions engine/src/Types/ShapeDrawerFunctions.ts
@@ -1,6 +1,5 @@
import type { Container } from "../Core/Container";
import type { IDelta } from "../Core/Interfaces/IDelta";
import type { IParticle } from "../Core/Interfaces/IParticle";
import type { Particle } from "../Core/Particle";

/**
Expand All @@ -15,7 +14,7 @@ import type { Particle } from "../Core/Particle";
*/
export type ShapeDrawerDrawFunction = (
context: CanvasRenderingContext2D,
particle: IParticle,
particle: Particle,
radius: number,
opacity: number,
delta: IDelta,
Expand Down Expand Up @@ -49,7 +48,7 @@ export type ShapeDrawerParticleInitFunction = (container: Container, particle: P
*/
export type ShapeDrawerAfterEffectFunction = (
context: CanvasRenderingContext2D,
particle: IParticle,
particle: Particle,
radius: number,
opacity: number,
delta: IDelta,
Expand Down
6 changes: 3 additions & 3 deletions engine/src/Utils/CanvasUtils.ts
Expand Up @@ -100,7 +100,7 @@ interface DrawParticleParams {
/**
* The particle to draw
*/
particle: IParticle;
particle: Particle;
/**
* The radius of the particle
*/
Expand Down Expand Up @@ -236,7 +236,7 @@ export function drawParticle(data: DrawParticleParams): void {
export function drawShape(
container: Container,
context: CanvasRenderingContext2D,
particle: IParticle,
particle: Particle,
radius: number,
opacity: number,
delta: IDelta
Expand Down Expand Up @@ -266,7 +266,7 @@ export function drawShape(
export function drawShapeAfterEffect(
container: Container,
context: CanvasRenderingContext2D,
particle: IParticle,
particle: Particle,
radius: number,
opacity: number,
delta: IDelta
Expand Down
117 changes: 68 additions & 49 deletions shapes/image/src/ImageDrawer.ts
@@ -1,5 +1,5 @@
import type { Container, IHsl, IShapeDrawer, Particle } from "tsparticles-engine";
import type { ContainerImage, IImage, IImageParticle, IParticleImage } from "./Utils";
import type { Container, IShapeDrawer } from "tsparticles-engine";
import type { ContainerImage, IImage, IParticleImage, ImageParticle } from "./Utils";
import { downloadSvgImage, loadImage, replaceImageColor } from "./Utils";
import type { IImageShape } from "./IImageShape";

Expand Down Expand Up @@ -45,9 +45,9 @@ export class ImageDrawer implements IShapeDrawer {
* @param radius the particle radius
* @param opacity the particle opacity
*/
draw(context: CanvasRenderingContext2D, particle: IImageParticle, radius: number, opacity: number): void {
draw(context: CanvasRenderingContext2D, particle: ImageParticle, radius: number, opacity: number): void {
const image = particle.image,
element = image?.data?.element;
element = image?.element;

if (!element) {
return;
Expand Down Expand Up @@ -94,31 +94,19 @@ export class ImageDrawer implements IShapeDrawer {
return 12;
}

/**
* Loads the image shape to the given particle
* @param container the particles container
* @param particle the particle loading the image shape
*/
particleInit(container: Container, particle: Particle): void {
loadShape(particle: ImageParticle): void {
if (particle.shape !== "image" && particle.shape !== "images") {
return;
}

const images = this.getImages(container).images,
const container = particle.container,
images = this.getImages(container).images,
imageData = particle.shapeData as IImageShape,
color = particle.getFillColor(),
replaceColor = imageData.replaceColor ?? imageData.replace_color,
image = images.find(
(t) =>
t.source === imageData.src &&
(!replaceColor || (t.color?.h === color?.h && t.color?.s === color?.s && t.color?.l === color?.l))
);

let imageRes: IParticleImage;
image = images.find((t) => t.source === imageData.src);

if (!image) {
this.loadImageShape(container, imageData, color).then(() => {
this.particleInit(container, particle);
this.loadImageShape(container, imageData).then(() => {
this.loadShape(particle);
});

return;
Expand All @@ -127,46 +115,78 @@ export class ImageDrawer implements IShapeDrawer {
if (image.error) {
return;
}
}

if (image.svgData && replaceColor && color) {
imageRes = replaceImageColor(image, imageData, color, particle);
} else {
imageRes = {
color,
data: image,
loaded: true,
ratio: imageData.width / imageData.height,
replaceColor: replaceColor,
source: imageData.src,
};
/**
* Loads the image shape to the given particle
* @param container the particles container
* @param particle the particle loading the image shape
*/
particleInit(container: Container, particle: ImageParticle): void {
if (particle.shape !== "image" && particle.shape !== "images") {
return;
}

if (!imageRes.ratio) {
imageRes.ratio = 1;
const images = this.getImages(container).images,
imageData = particle.shapeData as IImageShape,
color = particle.getFillColor(),
replaceColor = imageData.replaceColor ?? imageData.replace_color,
image = images.find((t) => t.source === imageData.src);

if (!image) {
return;
}

const fill = imageData.fill ?? particle.fill,
close = imageData.close ?? particle.close,
imageShape = {
image: imageRes,
fill,
close,
};
if (image.loading) {
setTimeout((): void => {
this.particleInit(container, particle);
});

(particle as IImageParticle).image = imageShape.image;
return;
}

particle.fill = imageShape.fill;
particle.close = imageShape.close;
(async (): Promise<void> => {
let imageRes: IParticleImage;

if (image.svgData && replaceColor && color) {
imageRes = await replaceImageColor(image, imageData, color, particle);
} else {
imageRes = {
color,
data: image,
element: image.element,
loaded: true,
ratio: imageData.width / imageData.height,
replaceColor: replaceColor,
source: imageData.src,
};
}

if (!imageRes.ratio) {
imageRes.ratio = 1;
}

const fill = imageData.fill ?? particle.fill,
close = imageData.close ?? particle.close,
imageShape = {
image: imageRes,
fill,
close,
};

particle.image = imageShape.image;
particle.fill = imageShape.fill;
particle.close = imageShape.close;
})();
}

/**
* Loads the image shape
* @param container the container used for searching images
* @param imageShape the image shape to load
* @param color the color to use for replace, if needed
* @private
*/
private async loadImageShape(container: Container, imageShape: IImageShape, color?: IHsl): Promise<void> {
private async loadImageShape(container: Container, imageShape: IImageShape): Promise<void> {
const source = imageShape.src;

if (!source) {
Expand All @@ -175,9 +195,8 @@ export class ImageDrawer implements IShapeDrawer {

try {
const image: IImage = {
color,
source: source,
type: source.substr(source.length - 3),
type: source.substring(source.length - 3),
error: false,
loading: true,
};
Expand Down

0 comments on commit 3173ebc

Please sign in to comment.