Odoo 17's effect system allows developers to create engaging visual feedback for user actions. This blog post demonstrates how to implement a custom firework effect using Odoo's OWL framework, JavaScript, and SCSS. The firework effect displays an animated burst of particles to celebrate events like successful form submissions or milestone achievements.
Prerequisites
* Basic understanding of Odoo 17 module development.
* Familiarity with JavaScript, OWL framework, and SCSS.
* Odoo development environment configured.
Step 1: Setting Up the Module Structure
Create a custom Odoo module with the following structure:
custom_firework_effect/
+-- static/
¦ +-- src/
¦ ¦ +-- js/
¦ ¦ ¦ +-- effect.js
¦ ¦ ¦ +-- firework_effect.js
¦ ¦ +-- scss/
¦ ¦ ¦ +-- firework_effect.scss
¦ ¦ +-- xml/
¦ ¦ ¦ +-- templates.xml
+-- __manifest__.py
Update __manifest__.py to include dependencies and assets:
{
'name': "Custom Firework Effect",
'depends': ['web'],
'assets': {
'web.assets_backend': [
'custom_firework_effect/static/src/js/effect.js',
'custom_firework_effect/static/src/js/firework_effect.js',
'custom_firework_effect/static/src/scss/firework_effect.scss',
'custom_firework_effect/static/src/xml/templates.xml',
],
},
}
Step 2: Registering the Firework Effect
Define the firework effect in effect.js to register it in Odoo's effect registry.
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { FireworkEffect } from "./firework_effect";
const effectRegistry = registry.category("effects");
function fireworkEffect(env, params = {}) {
const message = params.message || "Congratulations!";
const duration = params.duration || 3000;
if (env.services.user.showEffect) {
return {
Component: FireworkEffect,
props: { message, duration },
};
}
env.services.notification.add(message, { type: "success", title: "Success" });
}
effectRegistry.add("firework_effect", fireworkEffect);
This code:
* Imports the registry and FireworkEffect component.
* Defines a fireworkEffect function that accepts a message and duration.
* Returns the FireworkEffect component with props or falls back to a notification.
* Registers the effect as firework_effect.
Step 3: Creating the Firework Effect Component
The FireworkEffect component, defined in firework_effect.js, manages the particle animation and message display.
/** @odoo-module **/
import { Component, useState, useEffect } from "@odoo/owl";
import { browser } from "@web/core/browser/browser";
export class FireworkEffect extends Component {
setup() {
this.state = useState({
particles: [],
isAnimating: true,
});
this.particleCount = 30;
this.duration = this.props.duration || 3000;
useEffect(() => {
// Generate particles
const particles = Array.from({ length: this.particleCount }, () => ({
x: Math.random() * 100,
y: Math.random() * 100,
angle: Math.random() * 360,
speed: Math.random() * 5 + 2,
color: `hsl(${Math.random() * 360}, 70%, 50%)`,
}));
this.state.particles = particles;
// Animate particles
const animationInterval = browser.setInterval(() => {
this.state.particles = this.state.particles.map(particle => ({
...particle,
x: particle.x + Math.cos(particle.angle * Math.PI / 180) * particle.speed,
y: particle.y + Math.sin(particle.angle * Math.PI / 180) * particle.speed,
speed: particle.speed * 0.98, // Slow down particles
}));
}, 30);
// Close effect after duration
const closeTimeout = browser.setTimeout(() => {
this.state.isAnimating = false;
browser.clearInterval(animationInterval);
this.props.close();
}, this.duration);
return () => {
browser.clearInterval(animationInterval);
browser.clearTimeout(closeTimeout);
};
}, () => []);
}
}
FireworkEffect.template = "custom_firework_effect.FireworkEffect";
FireworkEffect.props = {
close: Function,
message: String,
duration: { type: Number, optional: true },
};
Key features:
* Generates random particles with position, angle, speed, and color.
* Animates particles using a setInterval loop.
* Closes the effect after the specified duration.
* Uses OWL's useState and useEffect for state and lifecycle management.
Step 4: Defining the Template
The template, defined in templates.xml, renders the firework particles and message.
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="custom_firework_effect.FireworkEffect">
<div class="o_firework_effect" t-att-class="{ 'o_animating': state.isAnimating }">
<div class="o_firework_container">
<div class="o_firework_message"><t t-esc="props.message"/></div>
<t t-foreach="state.particles" t-as="particle" t-key="particle_index">
<div class="o_firework_particle"
t-att-style="'transform: translate(' + particle.x + 'vw, ' + particle.y + 'vh); background-color: ' + particle.color + ';'"/>
</t>
</div>
</div>
</t>
</templates>
This template:
* Renders a container with a centered message.
* Dynamically creates particle elements with position and color styles.
* Applies an animation class for fade-in/out effects.
Step 5: Styling the Firework Effect
Style the firework effect in firework_effect.scss for visual appeal.
.o_firework_effect {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1200;
display: flex;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.5s ease;
&.o_animating {
opacity: 1;
}
}
.o_firework_container {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.o_firework_message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 24px;
font-weight: bold;
color: #fff;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
z-index: 1;
}
.o_firework_particle {
position: absolute;
width: 8px;
height: 8px;
border-radius: 50%;
opacity: 0.8;
transition: transform 0.1s linear, opacity 0.5s ease;
}
The SCSS:
* Positions the effect full-screen with a semi-transparent background.
* Styles the message to be centered and prominent.
* Defines particles as small, colored circles with dynamic positioning.
* Applies a fade-in/out transition for the animation.
Step 6: Using the Firework Effect
Trigger the effect from any Odoo service or component using:
In Js:
this.env.services.effect.add({
message: "Task Completed Successfully!",
type: "firework_effect",
duration: 4000,
});
In Python:
return {
'effect': {
'type': 'firework_effect',
'message': _("Task Completed Successfully!"),
'duration': 4000,
}
}
This displays a firework animation with the specified message for 4 seconds.
Conclusion
Creating a custom firework effect in Odoo 17 involves registering an effect, building an OWL component with particle animations, defining a template, and styling it with SCSS. This effect adds a celebratory touch to user interactions. You can extend this approach to create other visual effects like confetti, sparkles, or progress animations to enhance the Odoo user experience.
To read more about How to Create a Rainbow Man Effect in Odoo 17, refer to our blog How to Create a Rainbow Man Effect in Odoo 17.