javascriptcssvue.jsfont-sizetext-shadow

Dynamically changing text-shadow x-y-offset depending on a font-size


So we got some vue video-edition tool with ability to add text and apply text-shadow effects on it with default presets and also some custom text-shadows allowed, or changed by customizing chosen preset. Also user can change font-size by scaling the vdr (vue-grag-resize) element and that's where the problems begin. Drag-resize component with text

Our shadows presets have absolute x-y-offset values and when font-size changing shadow offsets should be changed also, but seems same to the user. We ofcourse can parse current shadow effect to different shadows and change x-y-offset, but i don't invent any good way to do it. Font-size and offsets doesn't seem to be correlated properties.. Whats the best way to change x-y-offset depending on a font-size?

Complicated one:

text-shadow: 0 -1px 0 #fff, 0 1px 0 #2e2e2e, 0 2px 0 #2c2c2c, 0 3px 0 #2a2a2a, 0 4px 0 #282828, 0 5px 0 #262626, 0 6px 0 #242424, 0 7px 0 #222, 0 8px 0 #202020, 0 9px 0 #1e1e1e, 0 10px 0 #1c1c1c, 0 11px 0 #1a1a1a, 0 12px 0 #181818, 0 13px 0 #161616, 0 14px 0 #141414, 0 15px 0 #121212, 0 22px 30px rgba(0,0,0,0.9);

Simple one:

text-shadow: -4px 3px 0 #3a50d9, -14px 7px 0 #0a0e27;

Solution

  • So i've made not the best but at least working implementation for complex shadow, it doesn't work on every shadow right now, but i'm pretty close to better implementation, if someone interested or will be stuck with such a problem here is a snippet: (be careful, it won't work with inset and you should modify parseShadowToArray, and also colors should be in #01234500 notation, but feel free to modify it if you need!)

    function replacePxWithEmEquivalent(shadowStr, fontSize=16) {
        console.log(fontSize);
        const shadowArr = parseShadowStrToArray(shadowStr);
        let resultShadowStr = shadowArr.reduce((acc, shadowObj, i) => {
            return acc + `${(shadowObj.x_offset/fontSize)}em ${(shadowObj.y_offset/fontSize)}em ${(shadowObj.blur_radius/fontSize)}em ${(shadowObj.color)}${i === shadowArr.length-1 ? '' : ", "} `
        }, "");
        resultShadowStr = resultShadowStr.slice(0, -1);
        return resultShadowStr;
    }
    
    function parseShadowStrToArray(shadowStr) {
        const shadows = [];
        let shadowStrArray = shadowStr.replaceAll('px', '');
        shadowStrArray = shadowStrArray.split(',');
        shadowStrArray = shadowStrArray.map(shadowStr => shadowStr[0] === ' ' ? shadowStr.substring(1) : shadowStr);
        shadowStrArray.map(shadowStr => {
            const shadowParts = shadowStr.split(' ');
            shadows.push({
                x_offset: parseInt(shadowParts[0]),
                y_offset: parseInt(shadowParts[1]),
                blur_radius: parseInt(shadowParts[2]),
                color: shadowParts[3],
            })
        }
        );
    
        return shadows;
    }