.elementor-6027 .elementor-element.elementor-element-1565f792:not(.elementor-motion-effects-element-type-background), .elementor-6027 .elementor-element.elementor-element-1565f792 > .elementor-motion-effects-container > .elementor-motion-effects-layer{background-image:url("https://www.eventek.fr/wp-content/uploads/2024/09/empty-stage-concert-with-lighting-laser-beam-spotl-H34S9C7.jpg");background-position:center center;background-size:cover;}.elementor-6027 .elementor-element.elementor-element-1565f792 > .elementor-background-overlay{background-color:transparent;background-image:linear-gradient(180deg, #69C52F 0%, var( --e-global-color-ba7cab5 ) 75%);opacity:0.7;transition:background 0.3s, border-radius 0.3s, opacity 0.3s;}.elementor-6027 .elementor-element.elementor-element-1565f792 > .elementor-container{min-height:30vh;}.elementor-6027 .elementor-element.elementor-element-1565f792{border-style:solid;border-width:0px 0px 0px 0px;border-color:var( --e-global-color-a83c27c );transition:background 0.3s, border 0.3s, border-radius 0.3s, box-shadow 0.3s;padding:30px 30px 30px 30px;}.elementor-6027 .elementor-element.elementor-element-470892a3 > .elementor-element-populated{padding:1em 1em 1em 1em;}.elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri .elementor-heading-title{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri div{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 > .elementor-widget-container{margin:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-3351e6b2{text-align:center;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 .elementor-heading-title{font-family:"dk lemon yellow sun", Sans-serif;font-size:80px;font-weight:600;line-height:1.2em;color:var( --e-global-color-text );}.elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > div, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h1, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h2, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h3, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h4, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h5, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > h6, .elementor-6027 .elementor-element.elementor-element-3351e6b2.ob-harakiri > p{transform:rotate(0deg);}.elementor-6027 .elementor-element.elementor-element-3351e6b2 > div{text-indent:0px;mix-blend-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-57287454 > .elementor-background-overlay{background-color:var( --e-global-color-8f13fcf );background-image:url("https://www.eventek.fr/wp-content/uploads/2024/10/colorful-wave-with-rainbow-it-scaled.jpg");background-size:cover;opacity:0.2;}.elementor-6027 .elementor-element.elementor-element-57287454 > .elementor-container{max-width:1200px;}.elementor-6027 .elementor-element.elementor-element-57287454{overflow:hidden;padding:60px 30px 60px 30px;}.elementor-bc-flex-widget .elementor-6027 .elementor-element.elementor-element-58cb718.elementor-column .elementor-widget-wrap{align-items:center;}.elementor-6027 .elementor-element.elementor-element-58cb718.elementor-column.elementor-element[data-element_type="column"] > .elementor-widget-wrap.elementor-element-populated{align-content:center;align-items:center;}.elementor-6027 .elementor-element.elementor-element-58cb718 > .elementor-element-populated{padding:0px 60px 0px 0px;}.elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri .elementor-heading-title{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri div{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-78194be5 > .elementor-widget-container{margin:0em 2em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-78194be5{text-align:start;}.elementor-6027 .elementor-element.elementor-element-78194be5 .elementor-heading-title{font-family:var( --e-global-typography-15088bb-font-family ), Sans-serif;font-size:var( --e-global-typography-15088bb-font-size );font-weight:var( --e-global-typography-15088bb-font-weight );line-height:var( --e-global-typography-15088bb-line-height );word-spacing:var( --e-global-typography-15088bb-word-spacing );color:var( --e-global-color-text );}.elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > div, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h1, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h2, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h3, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h4, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h5, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > h6, .elementor-6027 .elementor-element.elementor-element-78194be5.ob-harakiri > p{transform:rotate(0deg);}.elementor-6027 .elementor-element.elementor-element-78194be5 > div{text-indent:0px;mix-blend-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri .elementor-heading-title{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri div{writing-mode:inherit;}.elementor-6027 .elementor-element.elementor-element-5e64339c > .elementor-widget-container{margin:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-5e64339c{text-align:start;font-family:var( --e-global-typography-b7806b0-font-family ), Sans-serif;font-size:var( --e-global-typography-b7806b0-font-size );font-weight:var( --e-global-typography-b7806b0-font-weight );line-height:var( --e-global-typography-b7806b0-line-height );color:var( --e-global-color-a83c27c );}.elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > div, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h1, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h2, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h3, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h4, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h5, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > h6, .elementor-6027 .elementor-element.elementor-element-5e64339c.ob-harakiri > p{transform:rotate(0deg);}.elementor-6027 .elementor-element.elementor-element-5e64339c > div{text-indent:0px;mix-blend-mode:inherit;}html, body{overflow-x:auto;}:root{--page-title-display:none;}@media(max-width:1024px) and (min-width:768px){.elementor-6027 .elementor-element.elementor-element-58cb718{width:100%;}}@media(max-width:1024px){.elementor-6027 .elementor-element.elementor-element-1565f792{margin-top:-150px;margin-bottom:0px;padding:60px 30px 0px 30px;}.elementor-6027 .elementor-element.elementor-element-470892a3 > .elementor-element-populated{margin:060px 0px 0px 0px;--e-column-margin-right:0px;--e-column-margin-left:0px;padding:0px 0px 0px 0px;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 > .elementor-widget-container{margin:0em 1em 0em 1em;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 .elementor-heading-title{font-size:40px;line-height:1.2em;}.elementor-6027 .elementor-element.elementor-element-57287454{padding:60px 20px 60px 20px;}.elementor-6027 .elementor-element.elementor-element-58cb718 > .elementor-element-populated{margin:0em 0em 0em 0em;--e-column-margin-right:0em;--e-column-margin-left:0em;padding:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-78194be5 > .elementor-widget-container{margin:0em 1em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-78194be5{text-align:center;}.elementor-6027 .elementor-element.elementor-element-78194be5 .elementor-heading-title{font-size:var( --e-global-typography-15088bb-font-size );line-height:var( --e-global-typography-15088bb-line-height );word-spacing:var( --e-global-typography-15088bb-word-spacing );}.elementor-6027 .elementor-element.elementor-element-5e64339c > .elementor-widget-container{margin:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-5e64339c{font-size:var( --e-global-typography-b7806b0-font-size );line-height:var( --e-global-typography-b7806b0-line-height );}}@media(max-width:767px){.elementor-6027 .elementor-element.elementor-element-1565f792 > .elementor-container{min-height:29vh;}.elementor-6027 .elementor-element.elementor-element-1565f792{margin-top:-220px;margin-bottom:0px;padding:0150px 0px 0px 0px;}.elementor-6027 .elementor-element.elementor-element-470892a3 > .elementor-element-populated{margin:60px 0px 0px 0px;--e-column-margin-right:0px;--e-column-margin-left:0px;padding:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-3351e6b2{width:100%;max-width:100%;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 > .elementor-widget-container{margin:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-3351e6b2 .elementor-heading-title{font-size:32px;line-height:1.2em;}.elementor-6027 .elementor-element.elementor-element-57287454{padding:60px 20px 60px 20px;}.elementor-6027 .elementor-element.elementor-element-58cb718 > .elementor-element-populated{margin:0em 0em 0em 0em;--e-column-margin-right:0em;--e-column-margin-left:0em;}.elementor-6027 .elementor-element.elementor-element-78194be5 .elementor-heading-title{font-size:var( --e-global-typography-15088bb-font-size );line-height:var( --e-global-typography-15088bb-line-height );word-spacing:var( --e-global-typography-15088bb-word-spacing );}.elementor-6027 .elementor-element.elementor-element-5e64339c > .elementor-widget-container{margin:0em 0em 0em 0em;}.elementor-6027 .elementor-element.elementor-element-5e64339c{text-align:start;font-size:var( --e-global-typography-b7806b0-font-size );line-height:var( --e-global-typography-b7806b0-line-height );}}@media(min-width:1025px){.elementor-6027 .elementor-element.elementor-element-57287454 > .elementor-background-overlay{background-attachment:fixed;}}/* Start custom CSS for section, class: .elementor-element-1565f792 */<script>
import GUI from "https://cdn.jsdelivr.net/npm/lil-gui@0.18.2/+esm"

const canvasEl = document.querySelector("canvas");
const textureEl = document.createElement("canvas");
const textureCtx = textureEl.getContext("2d");

const fontOptions = {
    "Arial": "Arial, sans-serif",
    "Verdana": "Verdana, sans-serif",
    "Tahoma": "Tahoma, sans-serif",
    "Times New Roman": "Times New Roman, serif",
    "Georgia": "Georgia, serif",
    "Garamond": "Garamond, serif",
    "Courier New": "Courier New, monospace",
    "Brush Script MT": "Brush Script MT, cursive"
}

const params = {
    fontName: "Verdana",
    isBold: false,
    fontSize: 80,
    text: "fluid",
    pointerSize: null,
    color: {r: 1., g: .0, b: .5}
};

const pointer = {
    x: 0,
    y: 0,
    dx: 0,
    dy: 0,
    moved: false,
};


let outputColor, velocity, divergence, pressure, canvasTexture;
let isPreview = true;

const gl = canvasEl.getContext("webgl");
gl.getExtension("OES_texture_float");

const vertexShader = createShader(
    document.getElementById("vertShader").innerHTML,
    gl.VERTEX_SHADER);

const splatProgram = createProgram("fragShaderPoint");
const divergenceProgram = createProgram("fragShaderDivergence");
const pressureProgram = createProgram("fragShaderPressure");
const gradientSubtractProgram = createProgram("fragShaderGradientSubtract");
const advectionProgram = createProgram("fragShaderAdvection");
const outputShaderProgram = createProgram("fragShaderOutputShader");

gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
    -1, -1,
    -1, 1,
    1, 1,
    1, -1
]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 0, 2, 3]), gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);


createTextCanvasTexture();
initFBOs();
createControls();
setupEvents();
resizeCanvas();
window.addEventListener("resize", resizeCanvas);

render();

function createTextCanvasTexture() {
    canvasTexture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, canvasTexture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}

function updateTextCanvas() {
    textureCtx.fillStyle = "black";
    textureCtx.fillRect(0, 0, textureEl.width, textureEl.height);

    textureCtx.font = (params.isBold ? "bold" : "normal") + " " + (params.fontSize * devicePixelRatio) + "px " + fontOptions[params.fontName];
    textureCtx.fillStyle = "#ffffff";
    textureCtx.textAlign = "center";

    textureCtx.filter = "blur(3px)";

    const textBox = textureCtx.measureText(params.text);
    textureCtx.fillText(params.text, .5 * textureEl.width, .5 * textureEl.height + .5 * textBox.actualBoundingBoxAscent);

    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, canvasTexture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textureEl);
}

function createProgram(elId) {
    const shader = createShader(
        document.getElementById(elId).innerHTML,
        gl.FRAGMENT_SHADER);
    const program = createShaderProgram(vertexShader, shader);
    const uniforms = getUniforms(program);
    return {
        program, uniforms
    }
}

function createShaderProgram(vertexShader, fragmentShader) {
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        console.error("Unable to initialize the shader program: " + gl.getProgramInfoLog(program));
        return null;
    }

    return program;
}

function getUniforms(program) {
    let uniforms = [];
    let uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
    for (let i = 0; i < uniformCount; i++) {
        let uniformName = gl.getActiveUniform(program, i).name;
        uniforms[uniformName] = gl.getUniformLocation(program, uniformName);
    }
    return uniforms;
}

function createShader(sourceCode, type) {
    const shader = gl.createShader(type);
    gl.shaderSource(shader, sourceCode);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.error("An error occurred compiling the shaders: " + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }

    return shader;
}

function blit(target) {
    if (target == null) {
        gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    } else {
        gl.viewport(0, 0, target.width, target.height);
        gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo);
    }
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
}

function initFBOs() {
    const fboSize = [
        Math.floor(.5 * window.innerWidth),
        Math.floor(.5 * window.innerHeight),
    ]
    outputColor = createDoubleFBO(fboSize[0], fboSize[1]);
    velocity = createDoubleFBO(fboSize[0], fboSize[1], gl.RG);
    divergence = createFBO(fboSize[0], fboSize[1], gl.RGB);
    pressure = createDoubleFBO(fboSize[0], fboSize[1], gl.RGB);
}


function createFBO(w, h, type = gl.RGBA) {
    gl.activeTexture(gl.TEXTURE0);

    const texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texImage2D(gl.TEXTURE_2D, 0, type, w, h, 0, type, gl.FLOAT, null);

    const fbo = gl.createFramebuffer();
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    gl.viewport(0, 0, w, h);
    gl.clear(gl.COLOR_BUFFER_BIT);

    return {
        fbo,
        width: w,
        height: h,
        attach(id) {
            gl.activeTexture(gl.TEXTURE0 + id);
            gl.bindTexture(gl.TEXTURE_2D, texture);
            return id;
        }
    };
}

function createDoubleFBO(w, h, type) {
    let fbo1 = createFBO(w, h, type);
    let fbo2 = createFBO(w, h, type);

    return {
        width: w,
        height: h,
        texelSizeX: 1. / w,
        texelSizeY: 1. / h,
        read: () => {
            return fbo1;
        },
        write: () => {
            return fbo2;
        },
        swap() {
            let temp = fbo1;
            fbo1 = fbo2;
            fbo2 = temp;
        }
    }
}

function render(t) {

    const dt = 1 / 60;

    if (t && isPreview) {
        updateMousePosition(
            (.5 - .45 * Math.sin(.003 * t - 2)) * window.innerWidth,
            (.5 + .1 * Math.sin(.0025 * t) + .1 * Math.cos(.002 * t)) * window.innerHeight
        );
    }

    if (pointer.moved) {
        if (!isPreview) {
            pointer.moved = false;
        }

        gl.useProgram(splatProgram.program);
        gl.uniform1i(splatProgram.uniforms.u_input_texture, velocity.read().attach(1));
        gl.uniform1f(splatProgram.uniforms.u_ratio, canvasEl.width / canvasEl.height);
        gl.uniform2f(splatProgram.uniforms.u_point, pointer.x / canvasEl.width, 1 - pointer.y / canvasEl.height);
        gl.uniform3f(splatProgram.uniforms.u_point_value, pointer.dx, -pointer.dy, 1);
        gl.uniform1f(splatProgram.uniforms.u_point_size, params.pointerSize);
        blit(velocity.write());
        velocity.swap();

        gl.uniform1i(splatProgram.uniforms.u_input_texture, outputColor.read().attach(1));
        gl.uniform3f(splatProgram.uniforms.u_point_value, 1. - params.color.r, 1. - params.color.g, 1. - params.color.b);
        blit(outputColor.write());
        outputColor.swap();
    }

    gl.useProgram(divergenceProgram.program);
    gl.uniform2f(divergenceProgram.uniforms.u_texel, velocity.texelSizeX, velocity.texelSizeY);
    gl.uniform1i(divergenceProgram.uniforms.u_velocity_texture, velocity.read().attach(1));
    blit(divergence);

    gl.useProgram(pressureProgram.program);
    gl.uniform2f(pressureProgram.uniforms.u_texel, velocity.texelSizeX, velocity.texelSizeY);
    gl.uniform1i(pressureProgram.uniforms.u_divergence_texture, divergence.attach(1));

    for (let i = 0; i < 10; i++) {
        gl.uniform1i(pressureProgram.uniforms.u_pressure_texture, pressure.read().attach(2));
        blit(pressure.write());
        pressure.swap();
    }

    gl.useProgram(gradientSubtractProgram.program);
    gl.uniform2f(gradientSubtractProgram.uniforms.u_texel, velocity.texelSizeX, velocity.texelSizeY);
    gl.uniform1i(gradientSubtractProgram.uniforms.u_pressure_texture, pressure.read().attach(1));
    gl.uniform1i(gradientSubtractProgram.uniforms.u_velocity_texture, velocity.read().attach(2));
    blit(velocity.write());
    velocity.swap();

    gl.useProgram(advectionProgram.program);
    gl.uniform1f(advectionProgram.uniforms.u_use_text, 0);
    gl.uniform2f(advectionProgram.uniforms.u_texel, velocity.texelSizeX, velocity.texelSizeY);
    gl.uniform1i(advectionProgram.uniforms.u_velocity_texture, velocity.read().attach(1));
    gl.uniform1i(advectionProgram.uniforms.u_input_texture, velocity.read().attach(1));
    gl.uniform1f(advectionProgram.uniforms.u_dt, dt);
    blit(velocity.write());
    velocity.swap();

    gl.useProgram(advectionProgram.program);
    gl.uniform1f(advectionProgram.uniforms.u_use_text, 1);
    gl.uniform2f(advectionProgram.uniforms.u_texel, outputColor.texelSizeX, outputColor.texelSizeY);
    gl.uniform1i(advectionProgram.uniforms.u_input_texture, outputColor.read().attach(2));
    blit(outputColor.write());
    outputColor.swap();

    gl.useProgram(outputShaderProgram.program);
    gl.uniform1i(outputShaderProgram.uniforms.u_output_texture, outputColor.read().attach(1));

    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

    requestAnimationFrame(render);
}

function resizeCanvas() {
    params.pointerSize = 4 / window.innerHeight;
    canvasEl.width = textureEl.width = window.innerWidth;
    canvasEl.height = textureEl.height = window.innerHeight;
	 initFBOs();
    updateTextCanvas();
}

function setupEvents() {
    canvasEl.addEventListener("mousemove", (e) => {
        isPreview = false;
        updateMousePosition(e.pageX, e.pageY);
    });

    canvasEl.addEventListener("touchmove", (e) => {
        e.preventDefault();
        isPreview = false;
        updateMousePosition(e.targetTouches[0].pageX, e.targetTouches[0].pageY);
    });
}

function updateMousePosition(eX, eY) {
    pointer.moved = true;
    pointer.dx = 5 * (eX - pointer.x);
    pointer.dy = 5 * (eY - pointer.y);
    pointer.x = eX;
    pointer.y = eY;
}

function createControls() {
    const gui = new GUI();
	 gui.close();
	
    gui
        .add(params, "text")
        .onChange(updateTextCanvas);
    gui
        .add(params, "fontSize", 10, 300)
        .onChange(updateTextCanvas)
        .name("font size, px");
    gui
        .add(params, "isBold")
        .onChange(updateTextCanvas)
        .name("bold");
    gui
        .add(params, "fontName", Object.keys(fontOptions))
        .onChange(updateTextCanvas)
        .name("font");
    gui
        .addColor(params, "color");
}
<script>/* End custom CSS */
/* Start Custom Fonts CSS */@font-face {
	font-family: 'dk lemon yellow sun';
	font-style: normal;
	font-weight: normal;
	font-display: auto;
	src: url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.eot');
	src: url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.eot?#iefix') format('embedded-opentype'),
		url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.woff2') format('woff2'),
		url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.woff') format('woff'),
		url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.ttf') format('truetype'),
		url('https://www.eventek.fr/wp-content/uploads/2024/09/DK-Lemon-Yellow-Sun.svg#dklemonyellowsun') format('svg');
}
@font-face {
	font-family: 'dk lemon yellow sun';
	font-style: normal;
	font-weight: normal;
	font-display: auto;
	src: ;
}
/* End Custom Fonts CSS */