{"tag":"nuxt","articles":{"projects\/ulid-page":{"key":"projects\/ulid-page","type":"article","published":true,"meta":{"createdAt":"2023-08-04T17:23:50+02:00","publishedAt":"2023-08-04T17:23:50+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/ulid.page","displayUrl":null}],"category":"projects","subcategory":null,"slug":"ulid-page"},"content":{"en":{"slug":"ulid-page","title":"ulid.page","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ulid_page_small.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022296.67469879518\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAWCAYAAACosj4+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADWklEQVRIidWWuY5cRRSGv9ru2tPdM0ziBXsMFktAAjlCSOyCRyAi4Fl4AJ6FEEgQFgFISCSDmAA83vBsvd3aDsEdmhG422OZxfxRXdW993x16py\/Ss1nWXiCZFdNiAhffPk109mM4caA7e0tbt68zd27v+IKxysvv8TO1ct\/O5BalaGcM\/v7d8g545zDOcvh4THee2JKXL50AUEwxgBQOEddV\/8c0FmJCKBQqgfVWiMiKKWW87+PH1crtyxnIaaMZIE\/xdLL57NrWb+u2\/dm3Pj2FjFmPnjzWarSPBqQCBwcHBBDOM0QGGPwIXDxwsW1wR+kw6MF3\/9wj+OJ5+3Xdh4dKMbIz7\/cRmuNMYaidGwMNmgHDUcn0+V7u3tHfPXNHd56dcxkckJRloxGI0ARfMBYg1KKuhI+\/vBFPvn0u79k\/FxAzlleeP76Q1d+5dIIZx07VzeXmVwlAd5\/4xnqcmXY8xX1v6mVqN4Hdn\/co2lqjNaknJmcTBlstNRVRYwR5yxF4RiPR+zfusN8NmfrqU0OD46w1tI0NccnU0SEsnCklNje3lprDyuBrDWMx0MkC1orss80TU1dVVRVCZQoBdb2vxgNN0BgNpv3\/aZgvljgXIW1mkFb0rbNQzOkV05oTVkUhBiJMWGsoapL5osF9+8f9JAidJ0nxghATBHfecqiQJ1Wbl0Z2qZAKcVkMsX7sBZodXXRt7mzlrqpsMaSc2Y0HJJzQilNzhGFwlpLzoIIlGWDNoYYA4jgQyCmRNs2iAg557VGuhYo50zXeVB9TRXOAeBDWGavbWpSSstvfBQsQkwKazQiCUSwxpDP4eZrgQCyZHLqzzOlFCklnLV03jMabjAYtBhj6DqPUiBpgWRLUznKsgDAuT\/GjwWkjcaeHp6IMBoP+8BaIdIfrCEEQoxoregWnrZtSCkxmczoOk\/Kmc3xiK47xlrDYNCuBfr\/+NB5tPvTIZ99vkeIGa3628C7r1\/j+rXxfwPU+4sjpb7DCqexdqWTnEvqnfc+eqK2TJniuQcCFYXjytOX8CHQNDWTyRSjNc45smS00szmc7TSWGs4mUyJIZJyXnZjWRQsug5jDHLa+iFGZrP5owMppSgKB9K3vlJ6eWPsTU1x9lKmlCKESM75sTL0G3Jvlo2RDxkHAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ulid_page_small.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022296.67469879518\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ulid_page_big.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022593.34939759036\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAWCAYAAACosj4+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAADWklEQVRIidWWuY5cRRSGv9ru2tPdM0ziBXsMFktAAjlCSOyCRyAi4Fl4AJ6FEEgQFgFISCSDmAA83vBsvd3aDsEdmhG422OZxfxRXdW993x16py\/Ss1nWXiCZFdNiAhffPk109mM4caA7e0tbt68zd27v+IKxysvv8TO1ct\/O5BalaGcM\/v7d8g545zDOcvh4THee2JKXL50AUEwxgBQOEddV\/8c0FmJCKBQqgfVWiMiKKWW87+PH1crtyxnIaaMZIE\/xdLL57NrWb+u2\/dm3Pj2FjFmPnjzWarSPBqQCBwcHBBDOM0QGGPwIXDxwsW1wR+kw6MF3\/9wj+OJ5+3Xdh4dKMbIz7\/cRmuNMYaidGwMNmgHDUcn0+V7u3tHfPXNHd56dcxkckJRloxGI0ARfMBYg1KKuhI+\/vBFPvn0u79k\/FxAzlleeP76Q1d+5dIIZx07VzeXmVwlAd5\/4xnqcmXY8xX1v6mVqN4Hdn\/co2lqjNaknJmcTBlstNRVRYwR5yxF4RiPR+zfusN8NmfrqU0OD46w1tI0NccnU0SEsnCklNje3lprDyuBrDWMx0MkC1orss80TU1dVVRVCZQoBdb2vxgNN0BgNpv3\/aZgvljgXIW1mkFb0rbNQzOkV05oTVkUhBiJMWGsoapL5osF9+8f9JAidJ0nxghATBHfecqiQJ1Wbl0Z2qZAKcVkMsX7sBZodXXRt7mzlrqpsMaSc2Y0HJJzQilNzhGFwlpLzoIIlGWDNoYYA4jgQyCmRNs2iAg557VGuhYo50zXeVB9TRXOAeBDWGavbWpSSstvfBQsQkwKazQiCUSwxpDP4eZrgQCyZHLqzzOlFCklnLV03jMabjAYtBhj6DqPUiBpgWRLUznKsgDAuT\/GjwWkjcaeHp6IMBoP+8BaIdIfrCEEQoxoregWnrZtSCkxmczoOk\/Kmc3xiK47xlrDYNCuBfr\/+NB5tPvTIZ99vkeIGa3628C7r1\/j+rXxfwPU+4sjpb7DCqexdqWTnEvqnfc+eqK2TJniuQcCFYXjytOX8CHQNDWTyRSjNc45smS00szmc7TSWGs4mUyJIZJyXnZjWRQsug5jDHLa+iFGZrP5owMppSgKB9K3vlJ6eWPsTU1x9lKmlCKESM75sTL0G3Jvlo2RDxkHAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ulid_page_big.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022593.34939759036\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EULIDs are my favourite identifiers to use in projects, they\u0027re soooo cool!\nThere used to be a website that would generate, validate and decode ULIDs right in the browser,\nbut the domain expired and whoever was running it abandoned the project.\nSo I decided to recreate it and keep it alive!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ulid","vue","nuxt","identifier"],"hasMore":true,"image":"https:\/\/avris.it\/image\/ulid_page_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ulid_page_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ulid_page_mini.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 width=\u0022240\u0022 height=\u0022148.33734939759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ulid_page_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ulid_page_mini.png\u0022 alt=\u0022Screenshot of the website ulid.page\u0022 width=\u0022240\u0022 height=\u0022148.33734939759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EULIDs are my favourite identifiers to use in projects, they\u0027re soooo cool!\nThere used to be a website that would generate, validate and decode ULIDs right in the browser,\nbut the domain expired and whoever was running it abandoned the project.\nSo I decided to recreate it and keep it alive!\u003C\/p\u003E","words":51,"readTime":null,"lang":"en"}}},"projects\/corevalues":{"key":"projects\/corevalues","type":"article","published":true,"meta":{"createdAt":"2023-05-23T17:52:17+02:00","publishedAt":"2023-05-23T17:52:17+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/corevalues.avris.it\/","displayUrl":null}],"category":"projects","subcategory":null,"slug":"corevalues"},"content":{"en":{"slug":"corevalues","title":"corevalues","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/corevalues_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB7UlEQVRIie2Uy08bMRCHPz92m+x6H0Cg2U1EBRJFffH\/\/xH0AifUU2lzTIO6iCjrrN1DlSikSdpUjeDQn2T5MdbMZ49mxOnZG88zknxqgGX9B\/qdnh2QXmd4\/+4tk8mEJE1RSiGlZDgc0m61OD9\/zdXVNf1+j+\/VPZeXH3cPVFX3TKdTwvAFAN9GI+7uRpyenHBz84kwDLn98hXv\/22RinVlr5TCe49zjiAIsNY+sjVNg5QS5xwAJo6Z1PWje3+jjSlrnMM5h3ee2tYkxlBVFSZJEMDDwxgEKCmp65rptOHz7e1ugISUOGvxHoQURFGEc45Wu02gNVVVEYYhWmustWRZRm0tFxcfwHustcRxjLVTrq6v\/zi1a1P2VFr7Q7uSUoo8z8nzjMQY2lGbMAgQQuJcsxugNE3plQW9XklZFpRFSVl0KYounU6HIAiQUiKlRAiBEAIA7\/32QFJKsixjf3+PzsEBh4cdXh4dURRdyqKg3++T5xlaa4IgQGuFUnrey2bBZ\/OivPfoV8fHxCYmMQZjYqIowhhDYgxJYkiShDRNybKUvXxvHkwpNR+L++VXbyMBiMFg4GffN3O2vF6cF4Nteu22mlWhGI\/Hfp3DVeebgm8P5lnuBnqTE+\/9L0FWnS3a5nA\/CVddYlOf+QFNZKG7tQOrTAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/corevalues_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022252\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ewhat are the core values in your life?\nhere\u0027s an exercise that can help you discover them!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/corevalues_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022504\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB7UlEQVRIie2Uy08bMRCHPz92m+x6H0Cg2U1EBRJFffH\/\/xH0AifUU2lzTIO6iCjrrN1DlSikSdpUjeDQn2T5MdbMZ49mxOnZG88zknxqgGX9B\/qdnh2QXmd4\/+4tk8mEJE1RSiGlZDgc0m61OD9\/zdXVNf1+j+\/VPZeXH3cPVFX3TKdTwvAFAN9GI+7uRpyenHBz84kwDLn98hXv\/22RinVlr5TCe49zjiAIsNY+sjVNg5QS5xwAJo6Z1PWje3+jjSlrnMM5h3ee2tYkxlBVFSZJEMDDwxgEKCmp65rptOHz7e1ugISUOGvxHoQURFGEc45Wu02gNVVVEYYhWmustWRZRm0tFxcfwHustcRxjLVTrq6v\/zi1a1P2VFr7Q7uSUoo8z8nzjMQY2lGbMAgQQuJcsxugNE3plQW9XklZFpRFSVl0KYounU6HIAiQUiKlRAiBEAIA7\/32QFJKsixjf3+PzsEBh4cdXh4dURRdyqKg3++T5xlaa4IgQGuFUnrey2bBZ\/OivPfoV8fHxCYmMQZjYqIowhhDYgxJYkiShDRNybKUvXxvHkwpNR+L++VXbyMBiMFg4GffN3O2vF6cF4Nteu22mlWhGI\/Hfp3DVeebgm8P5lnuBnqTE+\/9L0FWnS3a5nA\/CVddYlOf+QFNZKG7tQOrTAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/corevalues_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022504\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ewhat are the core values in your life?\nhere\u0027s an exercise that can help you discover them!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["core values","values","growth","introspection","vue","nuxt"],"hasMore":false,"image":"https:\/\/avris.it\/image\/corevalues_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/corevalues_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/corevalues_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ewhat are the core values in your life?\nhere\u0027s an exercise that can help you discover them!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/corevalues_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/corevalues_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022126\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003Ewhat are the core values in your life?\nhere\u0027s an exercise that can help you discover them!\u003C\/p\u003E","words":17,"readTime":null,"lang":"en"}}},"projects\/code-doodle-gradient-progress-bar":{"key":"projects\/code-doodle-gradient-progress-bar","type":"article","published":true,"meta":{"createdAt":"2022-01-02T15:32:29+01:00","publishedAt":"2022-01-02T15:32:29+01:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/progressbar.avris.it","displayUrl":null},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/ProgressBar","displayUrl":null}],"category":"projects","subcategory":null,"slug":"code-doodle-gradient-progress-bar"},"content":{"en":{"slug":"code-doodle-gradient-progress-bar","title":"Code Doodle: a gradient progress bar","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_small.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022240\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADJklEQVRIibWWT0\/jVhTFf++P7SR2SJygiSGtVFBQqDKbqhJSRSWWVN1WfEU+Aiu6oGqrqk0W1QCaVIzIVChlqoY2JE3s2Im7YPCQIZPJMNOzee8+nWefe8+7zxbh6ZM4On\/GojC\/+BLpFhfmvyt091kTfv4OQ4jFNtQeI90icRwjXu6J4xhgKhZCPIij09UqflpjabWQIJl3k4ffjre4Gz+Uo4cvzvn76Q\/4WpGz3i5Kbz5G5goLiX8IdLr8MfA5AMKQKDnfOmFn72X9QQWNgg793jkAQykoOBo57zxN\/MTzg4MDtNaMRiOKxSKNRoONjQ22trbY39\/HdV0ymQwrKysANBoNrq6u2N3dJQgCarUarutOCzJzeexyOVmItCQ9zzrTBG58V+qGd3p6yng8xvM8Dg8PqVQqaK1RSnF8fEyr1aJQKNButymVShwdHbG2tkatVps67HEcI3ovfoz\/vXoy9c6sbWAacqYeVfgKjEdvFgxEUUS\/3yefzwMQhiGGYczdcwstLYV0psm+FFhZg5nOKZlkc3JyQq\/XI5vN0ul0CIKAbreLaZqkUikuLi5YX1\/n7OyMvb09crnc29s+Nk3ijD2dIdCLJZm0vp+BkAhuSuw4Do7jMBgM8H2farVKt9slDEOKxSKe51EqlVhdXQVe3UF356+viT+vv487vV9nli\/nmpjWtHVL4msM4QHQ7\/cJggApJVEUEUURmUwG3\/exLIswDAEYDAY4jsNwOMS27aRSMyskjTyG\/dFMQcORAGu6SjFWchDr9TqXl5dorbFtm1arhed5jMdjBoMBUkrK5TKpVIput0u9XmdnZ4ft7e1EwN0RQPz2z7fx79f1mYIAzLTCcc0k3pDf4IgbC9rtNsvLy0nrN5tNNjc3kVIymUySzJVSRFHEeDzGsqykO2dB\/DFsxn8Fz99IADBSCvWy68riM1IszeW\/D3Q7OOfp9U9zSaIvsJctpBIUVIW0yP1\/gh5Z60yy97vpdchQYGiFRRbg3oX2oea6HTzn5PqXhdRbSwZerkImfmXZrK\/3+8y1q0p8Yn+6kCDGYEQWwlg843f9H\/oPQE+Gnfb7BO8AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_small.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022240\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA simple doodling project \u2013 probably not that useful, but I enjoyed creating it \ud83e\udd37\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_big.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022480\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADJklEQVRIibWWT0\/jVhTFf++P7SR2SJygiSGtVFBQqDKbqhJSRSWWVN1WfEU+Aiu6oGqrqk0W1QCaVIzIVChlqoY2JE3s2Im7YPCQIZPJMNOzee8+nWefe8+7zxbh6ZM4On\/GojC\/+BLpFhfmvyt091kTfv4OQ4jFNtQeI90icRwjXu6J4xhgKhZCPIij09UqflpjabWQIJl3k4ffjre4Gz+Uo4cvzvn76Q\/4WpGz3i5Kbz5G5goLiX8IdLr8MfA5AMKQKDnfOmFn72X9QQWNgg793jkAQykoOBo57zxN\/MTzg4MDtNaMRiOKxSKNRoONjQ22trbY39\/HdV0ymQwrKysANBoNrq6u2N3dJQgCarUarutOCzJzeexyOVmItCQ9zzrTBG58V+qGd3p6yng8xvM8Dg8PqVQqaK1RSnF8fEyr1aJQKNButymVShwdHbG2tkatVps67HEcI3ovfoz\/vXoy9c6sbWAacqYeVfgKjEdvFgxEUUS\/3yefzwMQhiGGYczdcwstLYV0psm+FFhZg5nOKZlkc3JyQq\/XI5vN0ul0CIKAbreLaZqkUikuLi5YX1\/n7OyMvb09crnc29s+Nk3ijD2dIdCLJZm0vp+BkAhuSuw4Do7jMBgM8H2farVKt9slDEOKxSKe51EqlVhdXQVe3UF356+viT+vv487vV9nli\/nmpjWtHVL4msM4QHQ7\/cJggApJVEUEUURmUwG3\/exLIswDAEYDAY4jsNwOMS27aRSMyskjTyG\/dFMQcORAGu6SjFWchDr9TqXl5dorbFtm1arhed5jMdjBoMBUkrK5TKpVIput0u9XmdnZ4ft7e1EwN0RQPz2z7fx79f1mYIAzLTCcc0k3pDf4IgbC9rtNsvLy0nrN5tNNjc3kVIymUySzJVSRFHEeDzGsqykO2dB\/DFsxn8Fz99IADBSCvWy68riM1IszeW\/D3Q7OOfp9U9zSaIvsJctpBIUVIW0yP1\/gh5Z60yy97vpdchQYGiFRRbg3oX2oea6HTzn5PqXhdRbSwZerkImfmXZrK\/3+8y1q0p8Yn+6kCDGYEQWwlg843f9H\/oPQE+Gnfb7BO8AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_big.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022480\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA simple doodling project \u2013 probably not that useful, but I enjoyed creating it \ud83e\udd37\u003C\/p\u003E\n\u003Cp\u003EI liked the way Wendover Productions displayed the HDI score in their video\n\u003Ca href=\u0022https:\/\/www.youtube.com\/watch?v=W3qZIPiWKc4\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u201eThe News You Missed in 2021\u201d\u003C\/a\u003E,\nso of course I decided to create a widget like this for VueJS \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a demo:\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/progressbar.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022 class=\u0022btn btn-primary btn-lg d-block\u0022\u003E\nDemo\n\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EAnd here\u0027s how I made it:\u003C\/p\u003E\n\u003Cp\u003ETo minimise the initial bootsrapping, I picked a framework I already know and absolutely love:\n\u003Ca href=\u0022https:\/\/v3.nuxtjs.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Nuxt\u003C\/a\u003E.\nIts upcoming version, v3, cuts all the bootstrapping crap to the minimum, while remaining highly flexible.\nAll I had to do to start working were those commands:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs bash border\u0022\u003Enpx nuxi init ProgressBar\n\u003Cspan class=\u0022hljs-built_in\u0022\u003Ecd\u003C\/span\u003E ProgressBar\nyarn\nyarn dev -o\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWhat they do is fetch a project template, install dependencies, start a development server\nand open \u003Ccode\u003Ehttp:\/\/localhost:3000\/\u003C\/code\u003E in the browser.\u003C\/p\u003E\n\u003Cdiv class=\u0022alert alert-warning\u0022\u003E\n    Watch out: it\u0027s not the best idea to use v3 yet, this version is not stable!\n    I did, because I like experimenting and I want to see where the project is going,\n    but I had to pay the price (in this case: inability to generate a static website on production,\n    and a weird issue with including stylesheets that I made \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/ProgressBar\/-\/blob\/main\/app.vue#L117\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E an ugly workaround for\u003C\/a\u003E).\n\u003C\/div\u003E\n\u003Cp\u003EBootrapping done; now I can focus on work. It\u0027s a simple project, so only two files will be relevant:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Eapp.vue\u003C\/code\u003E is the main entrypoint, the homepage.\nIt contains what you see in the demo: just some introduction and lots of \u003Ccode\u003E\u0026lt;AvrisProgressBar\/\u0026gt;\u003C\/code\u003E components\nembedded to showcase their usage.\nI won\u0027t focus here on the \u003Ccode\u003Eapp.vue\u003C\/code\u003E code, because it\u0027s really straightforward \u2013\nyou can check it out \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/ProgressBar\/-\/blob\/main\/app.vue\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E.\nSidenote: if I ever need to add multiple pages, I\u0027ll just create a \u003Ccode\u003Eroutes\u003C\/code\u003E directory\nand move \u003Ccode\u003Eapp.vue\u003C\/code\u003E to the appropriate structure inside of that folder, it\u0027s as simple as that! \u2013\nand for the simplest case it\u0027s all already preconfigured and working!\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Ecomponents\/AvrisProgressBar.vue\u003C\/code\u003E is the actual component I\u0027ll be working on.\nNuxt automatically configures everything so that throughout the application\nyou can simply use the \u003Ccode\u003E\u0026lt;AvrisProgressBar\/\u0026gt;\u003C\/code\u003E tag.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EThe template is really simple:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Etemplate\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Ediv\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Eclass\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022outer\u0022\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003E:style\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022`background-color: ${colourOuter}`\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Ediv\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Eclass\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022inner\u0022\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003E:style\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022`width: ${percent}%; background-color: ${colourInner}`\u0022\u003C\/span\u003E\n             \u003Cspan class=\u0022hljs-attr\u0022\u003Erole\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022progressbar\u0022\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003E:aria-valuenow\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022percent\u0022\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Earia-valuemin\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u00220\u0022\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Earia-valuemax\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022100\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Ediv\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Ediv\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Etemplate\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAll we need is two divs:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ethe outer one, taking a full width of the container\nand coloured with the \u201emain\u201d colour depending on the value of the progress bar,\u003C\/li\u003E\n\u003Cli\u003Ethe inner one, taking a fraction of the outer div\u0027s width proportional to the progress bar\u0027s value\nand coloured with a shade slightly darker than the \u201emain\u201d colour.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAnd here\u0027s how I styled them:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs css border\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-selector-tag\u0022\u003Estyle\u003C\/span\u003E \u003Cspan class=\u0022hljs-selector-tag\u0022\u003Escoped\u003C\/span\u003E\u0026gt;\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.outer\u003C\/span\u003E {\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003E--apb-height\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E16px\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003E--apb-border-width\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E0px\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003E--apb-border-color\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E#aaa\u003C\/span\u003E;\n}\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.outer\u003C\/span\u003E {\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E100%\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eborder-radius\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Ecalc\u003C\/span\u003E(var(--apb-height) \/ \u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eheight\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Evar\u003C\/span\u003E(--apb-height);\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Emargin\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E4px\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Epadding\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Ecalc\u003C\/span\u003E(var(--apb-height) \/ \u003Cspan class=\u0022hljs-number\u0022\u003E4\u003C\/span\u003E - \u003Cspan class=\u0022hljs-built_in\u0022\u003Evar\u003C\/span\u003E(--apb-border-width));\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Edisplay\u003C\/span\u003E: inline-block;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eborder\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Evar\u003C\/span\u003E(--apb-border-width) solid \u003Cspan class=\u0022hljs-built_in\u0022\u003Evar\u003C\/span\u003E(--apb-border-color);\n}\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.outer\u003C\/span\u003E \u003Cspan class=\u0022hljs-selector-class\u0022\u003E.inner\u003C\/span\u003E {\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eheight\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Ecalc\u003C\/span\u003E(var(--apb-height) \/ \u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eborder-radius\u003C\/span\u003E: \u003Cspan class=\u0022hljs-built_in\u0022\u003Ecalc\u003C\/span\u003E(var(--apb-height) \/ \u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E);\n}\n\u0026lt;\/\u003Cspan class=\u0022hljs-selector-tag\u0022\u003Estyle\u003C\/span\u003E\u0026gt;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI used CSS variables so that each usage of this widget can override the default height and border.\u003C\/p\u003E\n\u003Cp\u003ENow all we need to do is calculate \u003Ccode\u003Epercent\u003C\/code\u003E, \u003Ccode\u003EcolourOuter\u003C\/code\u003E and \u003Ccode\u003EcolourInner\u003C\/code\u003E. Easy!\u003C\/p\u003E\n\u003Cp\u003ELet\u0027s start with declaring \u003Ccode\u003Eprops\u003C\/code\u003E of our component:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Escript\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\u003Cspan class=\u0022javascript\u0022\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eexport\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Edefault\u003C\/span\u003E {\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Eprops\u003C\/span\u003E: {\n        \u003Cspan class=\u0022hljs-attr\u0022\u003Evalue\u003C\/span\u003E: { \u003Cspan class=\u0022hljs-attr\u0022\u003Erequired\u003C\/span\u003E: \u003Cspan class=\u0022hljs-literal\u0022\u003Etrue\u003C\/span\u003E },\n        \u003Cspan class=\u0022hljs-attr\u0022\u003Emin\u003C\/span\u003E: { \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027default\u0027\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E },\n        \u003Cspan class=\u0022hljs-attr\u0022\u003Emax\u003C\/span\u003E: { \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027default\u0027\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E1000\u003C\/span\u003E },\n        \u003Cspan class=\u0022hljs-attr\u0022\u003Ecolours\u003C\/span\u003E: { \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027default\u0027\u003C\/span\u003E: \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E =\u0026gt;\u003C\/span\u003E {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E [\n                \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#ff0000\u0027\u003C\/span\u003E,\n                \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#ffff00\u0027\u003C\/span\u003E,\n                \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#00ff00\u0027\u003C\/span\u003E,\n            ];\n        }}\n    },\n};\n\u003C\/span\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Escript\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWe expect the user of our widget to provide a value (eg. \u003Ccode\u003E\u0026lt;AvrisProgressBar :value=\u0022123\u0022\/\u0026gt;\u003C\/code\u003E)\nand we allow them to overwrite the default values of \u003Ccode\u003Emin\u003C\/code\u003E (0), \u003Ccode\u003Emax\u003C\/code\u003E (1000) and \u003Ccode\u003Ecolours\u003C\/code\u003E (red, yellow, green)\nwith their own (eg. \u003Ccode\u003E\u0026lt;AvrisProgressBar :value=\u002269\u0022 :min=\u002224\u0022 :max=\u0022169\u0022\/\u0026gt;\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003ENow let\u0027s calculate the \u003Ccode\u003Epercent\u003C\/code\u003E.\nIt\u0027s pretty simple: we divide the current progress by the full range, and multiply by 100%.\nIf \u003Ccode\u003Emin == 0\u003C\/code\u003E, the formula is trivial: \u003Ccode\u003E100% * value \/ max\u003C\/code\u003E.\nBut in any other case we should add the \u003Ccode\u003Emin\u003C\/code\u003E to the formula:\n\u003Ccode\u003E100% * (value - min) \/ (max - min)\u003C\/code\u003E.\nPlus let\u0027s cut it at no less than 0 and no more than 100, just in case the user provides some weird input.\nHere\u0027s a Vue code that implements that:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Ecomputed: {\n    percent() {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E percent = \u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E * (\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.value - \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.min) \/ (\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.range);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (percent \u0026lt; \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E; }\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (percent \u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E; }\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E percent;\n    },\n    range() {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.max - \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.min;\n    },\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd for the remaining two properties that we need, let\u0027s first mock their values to simply be green and black respectively,\njust so that we can validate that \u003Ccode\u003Epercent\u003C\/code\u003E works well without worrying about the colours.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Ecomputed: {\n    colourOuter() {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#00ff00\u0027\u003C\/span\u003E;\n    },\n    colourInner() {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#000000\u0027\u003C\/span\u003E;\n    },\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOf course, in a full-blown, production-ready library, we should cover a lot more ground than in my simple doodle:\nsupporting multiple colour models, implementing colour mixing algorythms that adjust for human perception, etc.\nBut here I wanted to keep it simple:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ewe only support RGB,\u003C\/li\u003E\n\u003Cli\u003Ewe only support the HTML colour syntax with six digits (eg. \u003Ccode\u003E#C71585\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Ewe darken the colour by simply decreesing all of its RGB components by the same percent,\u003C\/li\u003E\n\u003Cli\u003Ewe mix the colours to create the gradient by simply calculating a weighted average for each RGB component.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EActually, that\u0027s my main purpose for creating this widget \u2013\nI\u0027m curious whether such a simple setup would give a visually pleasant effect.\nSpoiler alert: it\u0027s not perfect, but it works well enough indeed!\u003C\/p\u003E\n\u003Cp\u003ESo now, let\u0027s compute two more values that will help us in further calculations.\n\u003Ccode\u003EcoloursHighpoints\u003C\/code\u003E will be a map between the primary colours and the values where they should appear.\nIn the default case, we have \u003Ccode\u003En = 3\u003C\/code\u003E colours (red, yellow, green) and a range from 0 to 1000,\nso to spread them out evenly we\u0027d need red to be at 0, yellow at 500 and green at 1000.\nThe code below splits the available range into \u003Ccode\u003En - 1\u003C\/code\u003E sections (so in this case sections have a width of 500)\nand then produces points at: \u003Ccode\u003Emin\u003C\/code\u003E, \u003Ccode\u003Emin + range\u003C\/code\u003E, \u003Ccode\u003Emin + 2*range\u003C\/code\u003E, \u2026\nSo in our case the methods retuns a map like this: \u003Ccode\u003E{0: \u0022#ff0000\u0022, 500: \u0022#ffff00\u0022, 1000: \u0022#00ff00\u0022}\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003EcoloursHighpoints() {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E highpoints = {};\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E sectionRange = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.range \/ (\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.colours.length - \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Efor\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E i \u003Cspan class=\u0022hljs-keyword\u0022\u003Ein\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.colours) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E point = \u003Cspan class=\u0022hljs-built_in\u0022\u003EparseInt\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.min + i * sectionRange, \u003Cspan class=\u0022hljs-number\u0022\u003E10\u003C\/span\u003E);\n        highpoints[point] = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.colours[i];\n    }\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E highpoints;\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe next step would be to figure out which colours to mix for a given value.\nLet\u0027s say our \u003Ccode\u003Evalue = 400\u003C\/code\u003E. We know it\u0027s between 0 \/ red and 500 \/ yellow,\nso we expect it be an orange-ish yellow.\nBut how do we put that into code?\u003C\/p\u003E\n\u003Cp\u003EWe need a method that will return an object telling us what\u0027s the closest highpoint\nbefore our value, and what\u0027s the closest one after our value.\nLet\u0027s iterate over the highpoints and keep assigning their values to the variable \u003Ccode\u003Eleft\u003C\/code\u003E as long as it\u0027s smaller than \u003Ccode\u003Ethis.value\u003C\/code\u003E.\nAs soon as a highpoint appears that\u0027s higher than \u003Ccode\u003Ethis.value\u003C\/code\u003E, we assign it to the \u003Ccode\u003Eright\u003C\/code\u003E variable.\nAnd then let\u0027s handle the edge case of \u003Ccode\u003Evalue \u0026gt;= max\u003C\/code\u003E.\nHere\u0027s the code for that, and it produces the following output for our parameters: \u003Ccode\u003E{left: 0, right: 500}\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003EcoloursBetween() {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E left = \u003Cspan class=\u0022hljs-literal\u0022\u003Enull\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E right = \u003Cspan class=\u0022hljs-literal\u0022\u003Enull\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Efor\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E val \u003Cspan class=\u0022hljs-keyword\u0022\u003Eof\u003C\/span\u003E \u003Cspan class=\u0022hljs-built_in\u0022\u003EObject\u003C\/span\u003E.keys(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.coloursHighpoints)) {\n        val = \u003Cspan class=\u0022hljs-built_in\u0022\u003EparseInt\u003C\/span\u003E(val);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (val \u0026lt;= \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.value) {\n            left = val;\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Econtinue\u003C\/span\u003E;\n        }\n        right = val;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ebreak\u003C\/span\u003E;\n    }\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!right) {\n        right = left;\n    }\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E {left, right};\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EBefore we actually calculate our colours, let\u0027s prepare some helpers that we\u0027ll need:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003EhexToDec\u003C\/code\u003E and \u003Ccode\u003EdecToHex\u003C\/code\u003E \u2013 simply converting the number base and adding some hex-colour specific padding,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EsplitColour\u003C\/code\u003E: turns \u003Ccode\u003E#C71585\u003C\/code\u003E into \u003Ccode\u003E[199, 21, 133]\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EmergeColour\u003C\/code\u003E: turns \u003Ccode\u003E[199, 21, 133]\u003C\/code\u003E into \u003Ccode\u003E#C71585\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EadjustValue\u003C\/code\u003E: takes an RGB component and increases it by a given \u003Ccode\u003Epercent\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EshadeColour\u003C\/code\u003E: splits a colour into components, adjusts their value and merges them back into a colour,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EmixColours\u003C\/code\u003E: takes two colours and a ratio in which they should be mixed, splits them into components,\nfor each of them calculates a weighted average, and then merges them back into a colour.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Emethods: {\n    hexToDec(hex) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-built_in\u0022\u003EparseInt\u003C\/span\u003E(hex, \u003Cspan class=\u0022hljs-number\u0022\u003E16\u003C\/span\u003E);\n    },\n    decToHex(dec) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-built_in\u0022\u003EparseInt\u003C\/span\u003E(dec, \u003Cspan class=\u0022hljs-number\u0022\u003E10\u003C\/span\u003E).toString(\u003Cspan class=\u0022hljs-number\u0022\u003E16\u003C\/span\u003E).padStart(\u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u00270\u0027\u003C\/span\u003E);\n    },\n    splitColour(colour) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E [\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.hexToDec(colour.substring(\u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E)),\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.hexToDec(colour.substring(\u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E5\u003C\/span\u003E)),\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.hexToDec(colour.substring(\u003Cspan class=\u0022hljs-number\u0022\u003E5\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E7\u003C\/span\u003E)),\n        ];\n    },\n    mergeColour(r, g, b) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E`#\u003Cspan class=\u0022hljs-subst\u0022\u003E${\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.decToHex(r)}\u003C\/span\u003E\u003Cspan class=\u0022hljs-subst\u0022\u003E${\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.decToHex(g)}\u003C\/span\u003E\u003Cspan class=\u0022hljs-subst\u0022\u003E${\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.decToHex(b)}\u003C\/span\u003E`\u003C\/span\u003E;\n    },\n    adjustValue(val, percent) {\n        val = \u003Cspan class=\u0022hljs-built_in\u0022\u003EparseInt\u003C\/span\u003E(val * (\u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E + percent) \/ \u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (val \u0026gt; \u003Cspan class=\u0022hljs-number\u0022\u003E255\u003C\/span\u003E) { val = \u003Cspan class=\u0022hljs-number\u0022\u003E255\u003C\/span\u003E; }\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (val \u0026lt; \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E) { val = \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E; }\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E val;\n    },\n    shadeColour(colour, percent) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E [r, g, b] = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.splitColour(colour);\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.mergeColour(\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.adjustValue(r, percent),\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.adjustValue(g, percent),\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.adjustValue(b, percent),\n        );\n    },\n    mixColours(colour1, colour2, ratio) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E [r1, g1, b1] = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.splitColour(colour1);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E [r2, g2, b2] = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.splitColour(colour2);\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.mergeColour(\n            r1 * ratio + r2 * (\u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E - ratio),\n            g1 * ratio + g2 * (\u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E - ratio),\n            b1 * ratio + b2 * (\u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E - ratio),\n        );\n    },\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd now it\u0027s finally time to put it all together.\u003C\/p\u003E\n\u003Cp\u003ETo calculate \u003Ccode\u003EcolourOuter\u003C\/code\u003E we take the \u003Ccode\u003EcoloursBetween\u003C\/code\u003E and we calculate\nhow far away from \u003Ccode\u003Eleft\u003C\/code\u003E is our value.\nIn our case that\u0027s \u003Ccode\u003E(value - left) \/ (right - left) = (400 - 0) \/ (500 - 0) = 400 \/ 500 = 0.8\u003C\/code\u003E.\nWe will use that value as our weight when calculating the weighted average\nbetween the colour in the \u003Ccode\u003Eleft\u003C\/code\u003E highpoint and the colour in the \u003Ccode\u003Eright\u003C\/code\u003E highpoint.\u003C\/p\u003E\n\u003Cp\u003EAnd \u003Ccode\u003EcolourInner\u003C\/code\u003E will just be just \u003Ccode\u003EcolourOuter\u003C\/code\u003E darkened by 30%.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003EcolourOuter() {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E {left, right} = \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.coloursBetween;\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E ratio = (\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.value - left) \/ ((right - left) || \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E);\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.mixColours(\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.coloursHighpoints[left],\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.coloursHighpoints[right],\n        \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E - ratio,\n    );\n},\ncolourInner() {\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.shadeColour(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.colourOuter, \u003Cspan class=\u0022hljs-number\u0022\u003E-30\u003C\/span\u003E);\n},\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it, we\u0027re done!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["vue","nuxt","javascript","widget","progress bar","colours","gradient"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-progress-bar_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-progress-bar_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_mini.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 width=\u0022240\u0022 height=\u0022120\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA simple doodling project \u2013 probably not that useful, but I enjoyed creating it \ud83e\udd37\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-progress-bar_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-progress-bar_mini.png\u0022 alt=\u0022Screenshot of the visual effect: a number of progress bar with increasing values, and their colour gradually changes from red to yellow to green\u0022 width=\u0022240\u0022 height=\u0022120\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA simple doodling project \u2013 probably not that useful, but I enjoyed creating it \ud83e\udd37\u003C\/p\u003E\n\u003Cp\u003EI liked the way Wendover Productions displayed the HDI score in their video\n\u003Ca href=\u0022https:\/\/www.youtube.com\/watch?v=W3qZIPiWKc4\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u201eThe News You Missed in 2021\u201d\u003C\/a\u003E,\nso of course I decided to create a widget like this for VueJS \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a demo:\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/progressbar.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022 class=\u0022btn btn-primary btn-lg d-block\u0022\u003E\nDemo\n\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EAnd here\u0027s how I made it:\u003C\/p\u003E\n\u003Cp\u003ETo minimise the initial bootsrapping, I picked a framework I already know and absolutely love:\n\u003Ca href=\u0022https:\/\/v3.nuxtjs.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Nuxt\u003C\/a\u003E.\nIts upcoming version, v3, cuts all the bootstrapping crap to the minimum, while remaining highly flexible.\nAll I had to do to start working were those commands:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-bash\u0022\u003Enpx nuxi init ProgressBar\ncd ProgressBar\nyarn\nyarn dev -o\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWhat they do is fetch a project template, install dependencies, start a development server\nand open \u003Ccode\u003Ehttp:\/\/localhost:3000\/\u003C\/code\u003E in the browser.\u003C\/p\u003E\n\u003Cdiv class=\u0022alert alert-warning\u0022\u003E\n    Watch out: it\u0027s not the best idea to use v3 yet, this version is not stable!\n    I did, because I like experimenting and I want to see where the project is going,\n    but I had to pay the price (in this case: inability to generate a static website on production,\n    and a weird issue with including stylesheets that I made \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/ProgressBar\/-\/blob\/main\/app.vue#L117\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E an ugly workaround for\u003C\/a\u003E).\n\u003C\/div\u003E\n\u003Cp\u003EBootrapping done; now I can focus on work. It\u0027s a simple project, so only two files will be relevant:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Eapp.vue\u003C\/code\u003E is the main entrypoint, the homepage.\nIt contains what you see in the demo: just some introduction and lots of \u003Ccode\u003E\u0026lt;AvrisProgressBar\/\u0026gt;\u003C\/code\u003E components\nembedded to showcase their usage.\nI won\u0027t focus here on the \u003Ccode\u003Eapp.vue\u003C\/code\u003E code, because it\u0027s really straightforward \u2013\nyou can check it out \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/ProgressBar\/-\/blob\/main\/app.vue\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E here\u003C\/a\u003E.\nSidenote: if I ever need to add multiple pages, I\u0027ll just create a \u003Ccode\u003Eroutes\u003C\/code\u003E directory\nand move \u003Ccode\u003Eapp.vue\u003C\/code\u003E to the appropriate structure inside of that folder, it\u0027s as simple as that! \u2013\nand for the simplest case it\u0027s all already preconfigured and working!\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Ecomponents\/AvrisProgressBar.vue\u003C\/code\u003E is the actual component I\u0027ll be working on.\nNuxt automatically configures everything so that throughout the application\nyou can simply use the \u003Ccode\u003E\u0026lt;AvrisProgressBar\/\u0026gt;\u003C\/code\u003E tag.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EThe template is really simple:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-html\u0022\u003E\u0026lt;template\u0026gt;\n    \u0026lt;div class=\u0022outer\u0022 :style=\u0022`background-color: ${colourOuter}`\u0022\u0026gt;\n        \u0026lt;div class=\u0022inner\u0022 :style=\u0022`width: ${percent}%; background-color: ${colourInner}`\u0022\n             role=\u0022progressbar\u0022 :aria-valuenow=\u0022percent\u0022 aria-valuemin=\u00220\u0022 aria-valuemax=\u0022100\u0022\u0026gt;\u0026lt;\/div\u0026gt;\n    \u0026lt;\/div\u0026gt;\n\u0026lt;\/template\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAll we need is two divs:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ethe outer one, taking a full width of the container\nand coloured with the \u201emain\u201d colour depending on the value of the progress bar,\u003C\/li\u003E\n\u003Cli\u003Ethe inner one, taking a fraction of the outer div\u0027s width proportional to the progress bar\u0027s value\nand coloured with a shade slightly darker than the \u201emain\u201d colour.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAnd here\u0027s how I styled them:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-css\u0022\u003E\u0026lt;style scoped\u0026gt;\n.outer {\n    --apb-height: 16px;\n    --apb-border-width: 0px;\n    --apb-border-color: #aaa;\n}\n\n.outer {\n    width: 100%;\n    border-radius: calc(var(--apb-height) \/ 2);\n    height: var(--apb-height);\n    margin: 4px;\n    padding: calc(var(--apb-height) \/ 4 - var(--apb-border-width));\n    display: inline-block;\n    border: var(--apb-border-width) solid var(--apb-border-color);\n}\n.outer .inner {\n    height: calc(var(--apb-height) \/ 2);\n    border-radius: calc(var(--apb-height) \/ 2);\n}\n\u0026lt;\/style\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI used CSS variables so that each usage of this widget can override the default height and border.\u003C\/p\u003E\n\u003Cp\u003ENow all we need to do is calculate \u003Ccode\u003Epercent\u003C\/code\u003E, \u003Ccode\u003EcolourOuter\u003C\/code\u003E and \u003Ccode\u003EcolourInner\u003C\/code\u003E. Easy!\u003C\/p\u003E\n\u003Cp\u003ELet\u0027s start with declaring \u003Ccode\u003Eprops\u003C\/code\u003E of our component:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;script\u0026gt;\nexport default {\n    props: {\n        value: { required: true },\n        min: { \u0027default\u0027: 0 },\n        max: { \u0027default\u0027: 1000 },\n        colours: { \u0027default\u0027: () =\u0026gt; {\n            return [\n                \u0027#ff0000\u0027,\n                \u0027#ffff00\u0027,\n                \u0027#00ff00\u0027,\n            ];\n        }}\n    },\n};\n\u0026lt;\/script\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWe expect the user of our widget to provide a value (eg. \u003Ccode\u003E\u0026lt;AvrisProgressBar :value=\u0022123\u0022\/\u0026gt;\u003C\/code\u003E)\nand we allow them to overwrite the default values of \u003Ccode\u003Emin\u003C\/code\u003E (0), \u003Ccode\u003Emax\u003C\/code\u003E (1000) and \u003Ccode\u003Ecolours\u003C\/code\u003E (red, yellow, green)\nwith their own (eg. \u003Ccode\u003E\u0026lt;AvrisProgressBar :value=\u002269\u0022 :min=\u002224\u0022 :max=\u0022169\u0022\/\u0026gt;\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003ENow let\u0027s calculate the \u003Ccode\u003Epercent\u003C\/code\u003E.\nIt\u0027s pretty simple: we divide the current progress by the full range, and multiply by 100%.\nIf \u003Ccode\u003Emin == 0\u003C\/code\u003E, the formula is trivial: \u003Ccode\u003E100% * value \/ max\u003C\/code\u003E.\nBut in any other case we should add the \u003Ccode\u003Emin\u003C\/code\u003E to the formula:\n\u003Ccode\u003E100% * (value - min) \/ (max - min)\u003C\/code\u003E.\nPlus let\u0027s cut it at no less than 0 and no more than 100, just in case the user provides some weird input.\nHere\u0027s a Vue code that implements that:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Ecomputed: {\n    percent() {\n        let percent = 100 * (this.value - this.min) \/ (this.range);\n        if (percent \u0026lt; 0) { return 0; }\n        if (percent \u0026gt; 100) { return 100; }\n        return percent;\n    },\n    range() {\n        return this.max - this.min;\n    },\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd for the remaining two properties that we need, let\u0027s first mock their values to simply be green and black respectively,\njust so that we can validate that \u003Ccode\u003Epercent\u003C\/code\u003E works well without worrying about the colours.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Ecomputed: {\n    colourOuter() {\n        return \u0027#00ff00\u0027;\n    },\n    colourInner() {\n        return \u0027#000000\u0027;\n    },\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOf course, in a full-blown, production-ready library, we should cover a lot more ground than in my simple doodle:\nsupporting multiple colour models, implementing colour mixing algorythms that adjust for human perception, etc.\nBut here I wanted to keep it simple:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ewe only support RGB,\u003C\/li\u003E\n\u003Cli\u003Ewe only support the HTML colour syntax with six digits (eg. \u003Ccode\u003E#C71585\u003C\/code\u003E),\u003C\/li\u003E\n\u003Cli\u003Ewe darken the colour by simply decreesing all of its RGB components by the same percent,\u003C\/li\u003E\n\u003Cli\u003Ewe mix the colours to create the gradient by simply calculating a weighted average for each RGB component.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EActually, that\u0027s my main purpose for creating this widget \u2013\nI\u0027m curious whether such a simple setup would give a visually pleasant effect.\nSpoiler alert: it\u0027s not perfect, but it works well enough indeed!\u003C\/p\u003E\n\u003Cp\u003ESo now, let\u0027s compute two more values that will help us in further calculations.\n\u003Ccode\u003EcoloursHighpoints\u003C\/code\u003E will be a map between the primary colours and the values where they should appear.\nIn the default case, we have \u003Ccode\u003En = 3\u003C\/code\u003E colours (red, yellow, green) and a range from 0 to 1000,\nso to spread them out evenly we\u0027d need red to be at 0, yellow at 500 and green at 1000.\nThe code below splits the available range into \u003Ccode\u003En - 1\u003C\/code\u003E sections (so in this case sections have a width of 500)\nand then produces points at: \u003Ccode\u003Emin\u003C\/code\u003E, \u003Ccode\u003Emin + range\u003C\/code\u003E, \u003Ccode\u003Emin + 2*range\u003C\/code\u003E, \u2026\nSo in our case the methods retuns a map like this: \u003Ccode\u003E{0: \u0022#ff0000\u0022, 500: \u0022#ffff00\u0022, 1000: \u0022#00ff00\u0022}\u003C\/code\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003EcoloursHighpoints() {\n    const highpoints = {};\n    const sectionRange = this.range \/ (this.colours.length - 1);\n    for (let i in this.colours) {\n        const point = parseInt(this.min + i * sectionRange, 10);\n        highpoints[point] = this.colours[i];\n    }\n    return highpoints;\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe next step would be to figure out which colours to mix for a given value.\nLet\u0027s say our \u003Ccode\u003Evalue = 400\u003C\/code\u003E. We know it\u0027s between 0 \/ red and 500 \/ yellow,\nso we expect it be an orange-ish yellow.\nBut how do we put that into code?\u003C\/p\u003E\n\u003Cp\u003EWe need a method that will return an object telling us what\u0027s the closest highpoint\nbefore our value, and what\u0027s the closest one after our value.\nLet\u0027s iterate over the highpoints and keep assigning their values to the variable \u003Ccode\u003Eleft\u003C\/code\u003E as long as it\u0027s smaller than \u003Ccode\u003Ethis.value\u003C\/code\u003E.\nAs soon as a highpoint appears that\u0027s higher than \u003Ccode\u003Ethis.value\u003C\/code\u003E, we assign it to the \u003Ccode\u003Eright\u003C\/code\u003E variable.\nAnd then let\u0027s handle the edge case of \u003Ccode\u003Evalue \u0026gt;= max\u003C\/code\u003E.\nHere\u0027s the code for that, and it produces the following output for our parameters: \u003Ccode\u003E{left: 0, right: 500}\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003EcoloursBetween() {\n    let left = null;\n    let right = null;\n    for (let val of Object.keys(this.coloursHighpoints)) {\n        val = parseInt(val);\n        if (val \u0026lt;= this.value) {\n            left = val;\n            continue;\n        }\n        right = val;\n        break;\n    }\n    if (!right) {\n        right = left;\n    }\n    return {left, right};\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EBefore we actually calculate our colours, let\u0027s prepare some helpers that we\u0027ll need:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003EhexToDec\u003C\/code\u003E and \u003Ccode\u003EdecToHex\u003C\/code\u003E \u2013 simply converting the number base and adding some hex-colour specific padding,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EsplitColour\u003C\/code\u003E: turns \u003Ccode\u003E#C71585\u003C\/code\u003E into \u003Ccode\u003E[199, 21, 133]\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EmergeColour\u003C\/code\u003E: turns \u003Ccode\u003E[199, 21, 133]\u003C\/code\u003E into \u003Ccode\u003E#C71585\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EadjustValue\u003C\/code\u003E: takes an RGB component and increases it by a given \u003Ccode\u003Epercent\u003C\/code\u003E,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EshadeColour\u003C\/code\u003E: splits a colour into components, adjusts their value and merges them back into a colour,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003EmixColours\u003C\/code\u003E: takes two colours and a ratio in which they should be mixed, splits them into components,\nfor each of them calculates a weighted average, and then merges them back into a colour.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Emethods: {\n    hexToDec(hex) {\n        return parseInt(hex, 16);\n    },\n    decToHex(dec) {\n        return parseInt(dec, 10).toString(16).padStart(2, \u00270\u0027);\n    },\n    splitColour(colour) {\n        return [\n            this.hexToDec(colour.substring(1, 3)),\n            this.hexToDec(colour.substring(3, 5)),\n            this.hexToDec(colour.substring(5, 7)),\n        ];\n    },\n    mergeColour(r, g, b) {\n        return `#${this.decToHex(r)}${this.decToHex(g)}${this.decToHex(b)}`;\n    },\n    adjustValue(val, percent) {\n        val = parseInt(val * (100 + percent) \/ 100);\n        if (val \u0026gt; 255) { val = 255; }\n        if (val \u0026lt; 0) { val = 0; }\n        return val;\n    },\n    shadeColour(colour, percent) {\n        const [r, g, b] = this.splitColour(colour);\n\n        return this.mergeColour(\n            this.adjustValue(r, percent),\n            this.adjustValue(g, percent),\n            this.adjustValue(b, percent),\n        );\n    },\n    mixColours(colour1, colour2, ratio) {\n        const [r1, g1, b1] = this.splitColour(colour1);\n        const [r2, g2, b2] = this.splitColour(colour2);\n\n        return this.mergeColour(\n            r1 * ratio + r2 * (1 - ratio),\n            g1 * ratio + g2 * (1 - ratio),\n            b1 * ratio + b2 * (1 - ratio),\n        );\n    },\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd now it\u0027s finally time to put it all together.\u003C\/p\u003E\n\u003Cp\u003ETo calculate \u003Ccode\u003EcolourOuter\u003C\/code\u003E we take the \u003Ccode\u003EcoloursBetween\u003C\/code\u003E and we calculate\nhow far away from \u003Ccode\u003Eleft\u003C\/code\u003E is our value.\nIn our case that\u0027s \u003Ccode\u003E(value - left) \/ (right - left) = (400 - 0) \/ (500 - 0) = 400 \/ 500 = 0.8\u003C\/code\u003E.\nWe will use that value as our weight when calculating the weighted average\nbetween the colour in the \u003Ccode\u003Eleft\u003C\/code\u003E highpoint and the colour in the \u003Ccode\u003Eright\u003C\/code\u003E highpoint.\u003C\/p\u003E\n\u003Cp\u003EAnd \u003Ccode\u003EcolourInner\u003C\/code\u003E will just be just \u003Ccode\u003EcolourOuter\u003C\/code\u003E darkened by 30%.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003EcolourOuter() {\n    const {left, right} = this.coloursBetween;\n    const ratio = (this.value - left) \/ ((right - left) || 1);\n\n    return this.mixColours(\n        this.coloursHighpoints[left],\n        this.coloursHighpoints[right],\n        1 - ratio,\n    );\n},\ncolourInner() {\n    return this.shadeColour(this.colourOuter, -30);\n},\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it, we\u0027re done!\u003C\/p\u003E","words":1514,"readTime":7,"lang":"en"}}},"projects\/plss":{"key":"projects\/plss","type":"article","published":true,"meta":{"createdAt":"2021-06-24T17:51:50+02:00","publishedAt":"2021-06-24T17:51:50+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/plss.avris.it\/","displayUrl":null}],"category":"projects","subcategory":null,"slug":"plss"},"content":{"en":{"slug":"plss","title":"PLSS","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/plss_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022362\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEnElEQVRIic2XzY8URRjGf1XV3dPztTu7yy47CDKgEhPjGYMcjBcJf4HeuPpnaLiqRxI8m+hNwk2vGEOCgWgCYVeEXRWW3ZnZmdmZ6c+q8jBMsz2zwC4xynOrrn7fevqp5616W1hrLa8QnN2D9a0+v92+y9tHa7iuSxzHlMtl6vX6f0ZI7FYoSRL6\/T5CCAB2iyelxFqLMSabk1ICoJQiTdPsXcdx0FpjrUUIgRACay3WWmYA6fvIUmlPQjmFlDFUAazBGgvWEiiFAIpak0pJ8ITseCEArXU21lpjjEFrjed52ZyUEmMMPWOoOA7efhSKgy6d5u+IJwuOVdBagwApFcZolFIUCj5+ofDiPXgBlL+McJ6qlVOIaJ1o7TJCgNYgJUxZfiQKAwv+6IuwAiIhsBaEgKKv9k1o5s1P8WrvPk3\/SlfZYDCg1WqxuLhIsVg8UKJms0m\/30dKmRVAmqY0Go3Ma\/tB3kNxjDGGwjO8sb29zezsbFZdkx\/jOE4Wq\/XIa+O8w+GQWq02TWCCbC6zlJJ+v08YhlOB42rZC+O5nZ0d4jgGyMiM8yZJQqvVmoqddIwzOamUwvf97FnSbGLDEK9ez8o3gzHobpek3ebxpUsMbt1kY2JBp1YbnUFxjAkCHk3MH\/\/sc2bOnt2bkJQyRwYgWLlL2moxt\/jR1FZZYwgf3Kd\/8xaNixdHz9IUm6Y4c3NTauwHOQ9FUUQURVSr1QMnCoIA13VxXfeliIwxpZCUMvOBlBLHcfYMnMTmxkPu3buHtnp0YFqI4phiscDiwhKDIKDTaZNogxICKQVxnHL69HvMzS\/sTchaSxiGmSGFEPR+ukbabDF37hyB1pR23UHR+jqdH39g8eNPuHH9Z65cvcKjzb+plKt4jsNmq0kYRZz\/4AzgcO2XmwzCmCgMqZR8lCrw5RdfPZuQUopyuZyNtdbIxgnc+hEirZFS5irQVKv4Z94nlZLBsM\/CQo2i7zIMAtqdDnO1eY4de53zH57nu6vfc2RxGW0tnW6X5cNLdHeGhFH87C0zxmSlOTawXyrhz89jRxLmgoXv4zUaaMB1PEquy1+9Lkq5eK6H0Sn9\/g6\/rj2kVJ5DdIf8cX8FiaA36BGECUrlPTdlkEqlMtV2aK0nX8tBSslS\/TXKa2vEqyvMVH2ccolOr8edlRXSRDNTmWVzaxNjIE01vq9IkhQzkTtHKL5zm+blr6cWVJUyQimE65Jud7ATSUqnTnHbhNy4cZ1abQHPcegPexQ8n3feOszxxhu021ukScSJY0cYBiFJkuIohaPyR0mOUOF4g+ULF7A6xRqLLBSQE+fSXlDlMsNvvyFINOl2C2NHKlSrZTYeP0a6HjNFS6gT\/ny4iecpDs0fYnOrixV5Qv\/abR\/Hca6jnOw6xw3a2AKO4+B5023aq9d+rK6u\/t8cchAnT57MFNp9mx9UuHEPJMaxT1rggyJn6tnZWQ4vLUEc02q16AUB8a6\/iefhaL1OuVQCpUBr4iDAVYoHGxuEUfRyhIIgoLu9DUlCdzgkecH5sxtb7Ta9wSB3Zkkp8QoFvEJhRDKOCZPkuXlyW\/Yq4B\/hzVgT67VgxgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/plss_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022362\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/plss_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022724\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEnElEQVRIic2XzY8URRjGf1XV3dPztTu7yy47CDKgEhPjGYMcjBcJf4HeuPpnaLiqRxI8m+hNwk2vGEOCgWgCYVeEXRWW3ZnZmdmZ6c+q8jBMsz2zwC4xynOrrn7fevqp5616W1hrLa8QnN2D9a0+v92+y9tHa7iuSxzHlMtl6vX6f0ZI7FYoSRL6\/T5CCAB2iyelxFqLMSabk1ICoJQiTdPsXcdx0FpjrUUIgRACay3WWmYA6fvIUmlPQjmFlDFUAazBGgvWEiiFAIpak0pJ8ITseCEArXU21lpjjEFrjed52ZyUEmMMPWOoOA7efhSKgy6d5u+IJwuOVdBagwApFcZolFIUCj5+ofDiPXgBlL+McJ6qlVOIaJ1o7TJCgNYgJUxZfiQKAwv+6IuwAiIhsBaEgKKv9k1o5s1P8WrvPk3\/SlfZYDCg1WqxuLhIsVg8UKJms0m\/30dKmRVAmqY0Go3Ma\/tB3kNxjDGGwjO8sb29zezsbFZdkx\/jOE4Wq\/XIa+O8w+GQWq02TWCCbC6zlJJ+v08YhlOB42rZC+O5nZ0d4jgGyMiM8yZJQqvVmoqddIwzOamUwvf97FnSbGLDEK9ez8o3gzHobpek3ebxpUsMbt1kY2JBp1YbnUFxjAkCHk3MH\/\/sc2bOnt2bkJQyRwYgWLlL2moxt\/jR1FZZYwgf3Kd\/8xaNixdHz9IUm6Y4c3NTauwHOQ9FUUQURVSr1QMnCoIA13VxXfeliIwxpZCUMvOBlBLHcfYMnMTmxkPu3buHtnp0YFqI4phiscDiwhKDIKDTaZNogxICKQVxnHL69HvMzS\/sTchaSxiGmSGFEPR+ukbabDF37hyB1pR23UHR+jqdH39g8eNPuHH9Z65cvcKjzb+plKt4jsNmq0kYRZz\/4AzgcO2XmwzCmCgMqZR8lCrw5RdfPZuQUopyuZyNtdbIxgnc+hEirZFS5irQVKv4Z94nlZLBsM\/CQo2i7zIMAtqdDnO1eY4de53zH57nu6vfc2RxGW0tnW6X5cNLdHeGhFH87C0zxmSlOTawXyrhz89jRxLmgoXv4zUaaMB1PEquy1+9Lkq5eK6H0Sn9\/g6\/rj2kVJ5DdIf8cX8FiaA36BGECUrlPTdlkEqlMtV2aK0nX8tBSslS\/TXKa2vEqyvMVH2ccolOr8edlRXSRDNTmWVzaxNjIE01vq9IkhQzkTtHKL5zm+blr6cWVJUyQimE65Jud7ATSUqnTnHbhNy4cZ1abQHPcegPexQ8n3feOszxxhu021ukScSJY0cYBiFJkuIohaPyR0mOUOF4g+ULF7A6xRqLLBSQE+fSXlDlMsNvvyFINOl2C2NHKlSrZTYeP0a6HjNFS6gT\/ny4iecpDs0fYnOrixV5Qv\/abR\/Hca6jnOw6xw3a2AKO4+B5023aq9d+rK6u\/t8cchAnT57MFNp9mx9UuHEPJMaxT1rggyJn6tnZWQ4vLUEc02q16AUB8a6\/iefhaL1OuVQCpUBr4iDAVYoHGxuEUfRyhIIgoLu9DUlCdzgkecH5sxtb7Ta9wSB3Zkkp8QoFvEJhRDKOCZPkuXlyW\/Yq4B\/hzVgT67VgxgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/plss_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022724\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe Public Land Survey System (PLSS) is the surveying method developed and used in the United States to plat, or divide, real property for sale and settling. [wikipedia]\u003C\/p\u003E\n\u003Cp\u003EBureau of Land Management provides an interface to convert between PLSS and the universal system of latitude \u0026amp; longitude, but it\u0027s hard to call it a user friendly tool.\u003C\/p\u003E\n\u003Cp\u003EThis website is a wrapper on their API that makes it way easier to use.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["plss","latitude","longitude","coordinates","location","nuxt","vue","api"],"hasMore":true,"image":"https:\/\/avris.it\/image\/plss_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/plss_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/plss_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022181\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/plss_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/plss_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022181\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe Public Land Survey System (PLSS) is the surveying method developed and used in the United States to plat, or divide, real property for sale and settling. [wikipedia]\u003C\/p\u003E\n\u003Cp\u003EBureau of Land Management provides an interface to convert between PLSS and the universal system of latitude \u0026amp; longitude, but it\u0027s hard to call it a user friendly tool.\u003C\/p\u003E\n\u003Cp\u003EThis website is a wrapper on their API that makes it way easier to use.\u003C\/p\u003E","words":72,"readTime":null,"lang":"en"}}},"projects\/avris-counter":{"key":"projects\/avris-counter","type":"article","published":true,"meta":{"createdAt":"2020-10-04T20:50:17+02:00","publishedAt":"2020-10-04T20:50:17+02:00","group":null,"links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/counter.avris.it\/","displayUrl":"Website"},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Counter","displayUrl":null}],"category":"projects","subcategory":null,"slug":"avris-counter"},"content":{"en":{"slug":"avris-counter","title":"Avris Counter","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-counter_small.png\u0022 alt=\u0022Avris Counter screenshot\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022279.58165728077\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACwklEQVRIia2WwW7bRhCGv+UuuSQtwXZsA\/att16bUx6gfYM+RZ6wb9B7kwAFesrFrePGkpWEokXuzvQgS5Elam24\/gGCAGcx83Hm54BGRJSEuq6jKIrUkReVM8bsDYoIf7x7z9npKc18Tuk9fd+jKE0z5\/Xrn3DWviiQ2e6QMQZVXQPdzmagijHmPgard4gi5M4hIvQh4L0nxohEwVpLiAGbZRiTMR6PsPfwmzW262arQqtrFVwXxyCirLhFZR3PjOHj7x8JbcBZR+h7RIQsM4DirEMVVAURGayx80yXWhNu3mOM3EwmFHlOCHH9hs45xuPRg\/OrhCsN5dw8s69DOyPbVIzC1fVnokRiFNz9GHKXo6oURYFz7nFjsBxzXXrK0ifPJU0NShRZeiKz9GHpiUXXkTtH13XM2xZrLSJCkecUeQHLiX2\/A8YajHnYxUHwlKkB+hCTCZ4sVUxmcNYmTT3Yoc05\/315SV1XLLoOFaWqKs7OTv833766SVOLKN+aBlQRVfLcoaKUZflsEOeWH8azTK2qdH1IFmhuvjG9nAJw\/uMFzu83uQGKIk8Dp0y26lQSaNLw6a8rQhc5+eGUvEwUfEK+pKlVIcQXMvW9cpc2tdHtyIb6vufT9TVFXqAor46P18txO9l0OuXw8JAsy5JAj3XIwfBWNcZgrePmz8\/MrmbJJG9+fUNZVnz58pXRaLQ27rY2LfAsU4cYmd3eogonJ6\/2AhljaNuWu7sFdV3h\/fA2foonk6a2WUbta1SU9mu795w\/8KgutzrAYtGR525wfI8C7WsdLH8\/5os5dV1TVVUy0YffPjD5Z0Jz26BR8b7YASrHJT+\/\/eX5mzrLMg4ORnhf7CTYlh979F84ujiiKofhi6p48KsxVHdnU8N3w4UQmEyna7iu67g4Px9M1LZ3zNsWY+D46Ggv+CbINpyq8h88n7nO5mY7EAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-counter_small.png\u0022 alt=\u0022Avris Counter screenshot\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022279.58165728077\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s the simplest way to show a counter of visitors on your website \u2013 just copy-paste this simple HTML code!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-counter_big.png\u0022 alt=\u0022Avris Counter screenshot\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022559.16331456154\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACwklEQVRIia2WwW7bRhCGv+UuuSQtwXZsA\/att16bUx6gfYM+RZ6wb9B7kwAFesrFrePGkpWEokXuzvQgS5Elam24\/gGCAGcx83Hm54BGRJSEuq6jKIrUkReVM8bsDYoIf7x7z9npKc18Tuk9fd+jKE0z5\/Xrn3DWviiQ2e6QMQZVXQPdzmagijHmPgard4gi5M4hIvQh4L0nxohEwVpLiAGbZRiTMR6PsPfwmzW262arQqtrFVwXxyCirLhFZR3PjOHj7x8JbcBZR+h7RIQsM4DirEMVVAURGayx80yXWhNu3mOM3EwmFHlOCHH9hs45xuPRg\/OrhCsN5dw8s69DOyPbVIzC1fVnokRiFNz9GHKXo6oURYFz7nFjsBxzXXrK0ifPJU0NShRZeiKz9GHpiUXXkTtH13XM2xZrLSJCkecUeQHLiX2\/A8YajHnYxUHwlKkB+hCTCZ4sVUxmcNYmTT3Yoc05\/315SV1XLLoOFaWqKs7OTv833766SVOLKN+aBlQRVfLcoaKUZflsEOeWH8azTK2qdH1IFmhuvjG9nAJw\/uMFzu83uQGKIk8Dp0y26lQSaNLw6a8rQhc5+eGUvEwUfEK+pKlVIcQXMvW9cpc2tdHtyIb6vufT9TVFXqAor46P18txO9l0OuXw8JAsy5JAj3XIwfBWNcZgrePmz8\/MrmbJJG9+fUNZVnz58pXRaLQ27rY2LfAsU4cYmd3eogonJ6\/2AhljaNuWu7sFdV3h\/fA2foonk6a2WUbta1SU9mu795w\/8KgutzrAYtGR525wfI8C7WsdLH8\/5os5dV1TVVUy0YffPjD5Z0Jz26BR8b7YASrHJT+\/\/eX5mzrLMg4ORnhf7CTYlh979F84ujiiKofhi6p48KsxVHdnU8N3w4UQmEyna7iu67g4Px9M1LZ3zNsWY+D46Ggv+CbINpyq8h88n7nO5mY7EAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-counter_big.png\u0022 alt=\u0022Avris Counter screenshot\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022559.16331456154\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/counter.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        counter.avris.it\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s the simplest way to show a counter of visitors on your website \u2013 just copy-paste this simple HTML code!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["counter","visits","visitors","stats","image","html","nuxt","vue","javascript"],"hasMore":false,"image":"https:\/\/avris.it\/image\/avris-counter_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-counter_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-counter_mini.png\u0022 alt=\u0022Avris Counter screenshot\u0022 width=\u0022240\u0022 height=\u0022139.79082864039\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s the simplest way to show a counter of visitors on your website \u2013 just copy-paste this simple HTML code!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-counter_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-counter_mini.png\u0022 alt=\u0022Avris Counter screenshot\u0022 width=\u0022240\u0022 height=\u0022139.79082864039\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/counter.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Ecounter.avris.it\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s the simplest way to show a counter of visitors on your website \u2013 just copy-paste this simple HTML code!\u003C\/p\u003E","words":22,"readTime":null,"lang":"en"}}},"projects\/zaimki":{"key":"projects\/zaimki","type":"article","published":true,"meta":{"createdAt":"2020-07-25T12:32:20+02:00","publishedAt":"2020-07-25T12:32:20+02:00","group":"nonbinary","links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/zaimki.pl\/","displayUrl":null},{"icon":"globe-europe","colour":"primary","url":"https:\/\/pronouns.page\/","displayUrl":null},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Zaimki","displayUrl":null}],"category":"projects","subcategory":null,"slug":"zaimki"},"content":{"pl":{"slug":"zaimki","title":"Zaimki.pl","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022362.08219178082\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEZ0lEQVRIiZ2Xy3bbRgyGP8yFFCnZObFPe3rd9P0fprsu2nVzYiVpLFKiKM4MuqAoUyRlp8VqNMJgfgA\/MKAcDo0yEWMNMt0ERAQRA+h5vaQFMUYAQggw0rHG3DwziJv+v\/9ri1153MqToiKmVxBrcLkje7+GM9wlUCmly54xZtGptm2JMZFjMblD7IuemRrMHtfYMkOcRQTcJkeMoF3EeDe7QFWv1imlF+MTQIOutRaYJaY\/M93IHtaY3OEfSlY\/vsNtcj6HivKX97hNDsDT0xOqiqpS13WfGqBtW9r2dLH18ePTZb0\/HGiaBlXFOYdC77i9hmDGHg5etNuKeOwA+PLlH6qqZrv9hKoSY+R5t6Pe7wE4HA6EEFBVnp62bLdboOfPbrejbVsAqt2O3a5CVanqmg9\/f6BpmlmE5Ng0V5C6fw5o6nf8uwLj7SIXLgbOPEopMXUOek6lpCP9IWXDbzPmPQ4RGBn61O4oVitOXYevOsqy4Ni2aFK8dzjnuLu7m4FS1QuZx7zsAacr\/dccdFOvNus13ntAqPc1eZ6B9q3AGHMp6WkUbslSmY\/Bz\/SPx6OOQXWfX\/IqgBmF95ZoSlf9Zun\/sdvjduHucuzqpXpnddx9al7QK1w65MI6hsCfv\/9BXq447huss7z\/\/pHvfv7hzbPDWoxcA1oiol6tblttmyM\/\/fYrMUT0UclWOZoS4dRhvfs2RBNxAyEH8Y8r4LoDC8tcyB5XLzZFXstaX2lj50UwItjSXwOaHvwcKsqywFpLSglrLdbal7yfW793nqJYj+zLm+\/bNBt2gZ+zlDnv8D7j6\/NXsiwjNA3eObouUBQFRgQUAh2wuoCBN6pnkolbMovQu\/t76romxUToAnVdU5YlIUYy78l8zvp+g55byfT6W6C+tfzNvImZCy1iOodZAJTC52zuNmBHRt4YJ65tX+suRewqZSKCMYI1BkWJXWSz2aCqWGN5PlSoQFkUiLf\/vemN0jY8zuNzqooTzoU48sBaS+Y9yWr\/9jiHMYbS5ZTrcvZCvwZqCmB4iAcxk6HNITIraxFBjEFImHN5GhGOsWPVhn5suBGd4bIhGkvTxC3wcE7ZNL8xpouysZYQI4SIc47t7gt2bzl1HQ\/lPfl9uXjxrQd0Wm2zcz1vrg+L6UvbGNP3IARrLVVVEUKkbU9k3mOMuTl23Crxt2ZqadtWx+Htuo663rPf7\/HekZISY0AVnLPEmHDO9p0ZOQ\/ycJeXlPebywx+K0rDkHcVlRGP3LSDxpRQTZxOJ4qioKp2FEXB8djiJefh4e7NoW18+TQiAz2mabt8GCyFNsZIlmcc2yPG2svEV7cHvlbPhLq9TJX\/R17rR0sxJSXldOqHdUGoqqrnSkrU9Z66OZAWBrW5qbd5NHDYGINzbv50pJTw3uOdI4RACIEuBKzryZ15j4pSHw5Yayj9CpPPP4\/GoKYP71LaBplZyrK+xzjv+vcsBB4eLOZsYDzGWmsRN6nQyaW3JoBb5f8voc2F\/xkJVV0AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022362.08219178082\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPolska gramatyka jest skomplikowana i silnie zgenderyzowana. Nie oznacza to jednak, \u017ce niemo\u017cliwe jest u\u017cywanie innych form ni\u017c \u201eon\u201d i \u201eona\u201d.\u003C\/p\u003E\n\u003Cp\u003ETo narz\u0119dzie udost\u0119pnia linki do przyk\u0142ad\u00f3w u\u017cycia (w prostych zdaniach oraz w literaturze, prasie, filmach i serialach) zaimk\u00f3w i innych form p\u0142ciowych \u2013 nie tylko normatywnych \u201eon\u201d i \u201eona\u201d, lecz tak\u017ce form niebinarnych.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022724.16438356164\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEZ0lEQVRIiZ2Xy3bbRgyGP8yFFCnZObFPe3rd9P0fprsu2nVzYiVpLFKiKM4MuqAoUyRlp8VqNMJgfgA\/MKAcDo0yEWMNMt0ERAQRA+h5vaQFMUYAQggw0rHG3DwziJv+v\/9ri1153MqToiKmVxBrcLkje7+GM9wlUCmly54xZtGptm2JMZFjMblD7IuemRrMHtfYMkOcRQTcJkeMoF3EeDe7QFWv1imlF+MTQIOutRaYJaY\/M93IHtaY3OEfSlY\/vsNtcj6HivKX97hNDsDT0xOqiqpS13WfGqBtW9r2dLH18ePTZb0\/HGiaBlXFOYdC77i9hmDGHg5etNuKeOwA+PLlH6qqZrv9hKoSY+R5t6Pe7wE4HA6EEFBVnp62bLdboOfPbrejbVsAqt2O3a5CVanqmg9\/f6BpmlmE5Ng0V5C6fw5o6nf8uwLj7SIXLgbOPEopMXUOek6lpCP9IWXDbzPmPQ4RGBn61O4oVitOXYevOsqy4Ni2aFK8dzjnuLu7m4FS1QuZx7zsAacr\/dccdFOvNus13ntAqPc1eZ6B9q3AGHMp6WkUbslSmY\/Bz\/SPx6OOQXWfX\/IqgBmF95ZoSlf9Zun\/sdvjduHucuzqpXpnddx9al7QK1w65MI6hsCfv\/9BXq447huss7z\/\/pHvfv7hzbPDWoxcA1oiol6tblttmyM\/\/fYrMUT0UclWOZoS4dRhvfs2RBNxAyEH8Y8r4LoDC8tcyB5XLzZFXstaX2lj50UwItjSXwOaHvwcKsqywFpLSglrLdbal7yfW793nqJYj+zLm+\/bNBt2gZ+zlDnv8D7j6\/NXsiwjNA3eObouUBQFRgQUAh2wuoCBN6pnkolbMovQu\/t76romxUToAnVdU5YlIUYy78l8zvp+g55byfT6W6C+tfzNvImZCy1iOodZAJTC52zuNmBHRt4YJ65tX+suRewqZSKCMYI1BkWJXWSz2aCqWGN5PlSoQFkUiLf\/vemN0jY8zuNzqooTzoU48sBaS+Y9yWr\/9jiHMYbS5ZTrcvZCvwZqCmB4iAcxk6HNITIraxFBjEFImHN5GhGOsWPVhn5suBGd4bIhGkvTxC3wcE7ZNL8xpouysZYQI4SIc47t7gt2bzl1HQ\/lPfl9uXjxrQd0Wm2zcz1vrg+L6UvbGNP3IARrLVVVEUKkbU9k3mOMuTl23Crxt2ZqadtWx+Htuo663rPf7\/HekZISY0AVnLPEmHDO9p0ZOQ\/ycJeXlPebywx+K0rDkHcVlRGP3LSDxpRQTZxOJ4qioKp2FEXB8djiJefh4e7NoW18+TQiAz2mabt8GCyFNsZIlmcc2yPG2svEV7cHvlbPhLq9TJX\/R17rR0sxJSXldOqHdUGoqqrnSkrU9Z66OZAWBrW5qbd5NHDYGINzbv50pJTw3uOdI4RACIEuBKzryZ15j4pSHw5Yayj9CpPPP4\/GoKYP71LaBplZyrK+xzjv+vcsBB4eLOZsYDzGWmsRN6nQyaW3JoBb5f8voc2F\/xkJVV0AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022724.16438356164\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPolska gramatyka jest skomplikowana i silnie zgenderyzowana. Nie oznacza to jednak, \u017ce niemo\u017cliwe jest u\u017cywanie innych form ni\u017c \u201eon\u201d i \u201eona\u201d.\u003C\/p\u003E\n\u003Cp\u003ETo narz\u0119dzie udost\u0119pnia linki do przyk\u0142ad\u00f3w u\u017cycia (w prostych zdaniach oraz w literaturze, prasie, filmach i serialach) zaimk\u00f3w i innych form p\u0142ciowych \u2013 nie tylko normatywnych \u201eon\u201d i \u201eona\u201d, lecz tak\u017ce form niebinarnych.\u003C\/p\u003E\n\u003Cp\u003EDlaczego nale\u017cy je respektowa\u0107? Bo zwracanie si\u0119 do kogo\u015b tak, jak sobie \u017cyczy, jest podstaw\u0105 relacji spo\u0142ecznych. Nie powiesz do Ani \u201cFranku\u201d, nie powiesz \u201cna ty\u201d do osoby, z kt\u00f3r\u0105 jeste\u015b \u201cna pan\u201d, itp. A s\u0105 osoby, kt\u00f3re nie chc\u0105, by im m\u00f3wi\u0107 \u201con\u201d ani \u201cona\u201d. Czy to uszanujesz, \u015bwiadczy wy\u0142\u0105cznie o Tobie.\u003C\/p\u003E\n\u003Cp\u003EWarto wrzuci\u0107 link do swoich zaimk\u00f3w na swoje profile na portalach spo\u0142eczno\u015bciowych \u2013 nawet je\u015bli jeste\u015b cis i u\u017cywasz \u201eon\u201d lub \u201eona\u201d \u2013 poniewa\u017c dzi\u0119ki temu pokazujesz wsparcie dla spo\u0142eczno\u015bci trans i normalizujesz podawanie zaimk\u00f3w przez osoby, kt\u00f3rych zaimki nie s\u0105 oczywiste \u003Ca href=\u0022\/blog\/why-everyone-should-have-pronouns-in-their-bio\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-people-carry\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E (wi\u0119cej powod\u00f3w tutaj)\u003C\/a\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["zaimki","pronouns","gender","p\u0142e\u0107","javascript","nuxt","vue"],"hasMore":true,"image":"https:\/\/avris.it\/image\/zaimki_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022181.04109589041\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPolska gramatyka jest skomplikowana i silnie zgenderyzowana. Nie oznacza to jednak, \u017ce niemo\u017cliwe jest u\u017cywanie innych form ni\u017c \u201eon\u201d i \u201eona\u201d.\u003C\/p\u003E\n\u003Cp\u003ETo narz\u0119dzie udost\u0119pnia linki do przyk\u0142ad\u00f3w u\u017cycia (w prostych zdaniach oraz w literaturze, prasie, filmach i serialach) zaimk\u00f3w i innych form p\u0142ciowych \u2013 nie tylko normatywnych \u201eon\u201d i \u201eona\u201d, lecz tak\u017ce form niebinarnych.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022181.04109589041\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPolska gramatyka jest skomplikowana i silnie zgenderyzowana. Nie oznacza to jednak, \u017ce niemo\u017cliwe jest u\u017cywanie innych form ni\u017c \u201eon\u201d i \u201eona\u201d.\u003C\/p\u003E\n\u003Cp\u003ETo narz\u0119dzie udost\u0119pnia linki do przyk\u0142ad\u00f3w u\u017cycia (w prostych zdaniach oraz w literaturze, prasie, filmach i serialach) zaimk\u00f3w i innych form p\u0142ciowych \u2013 nie tylko normatywnych \u201eon\u201d i \u201eona\u201d, lecz tak\u017ce form niebinarnych.\u003C\/p\u003E\n\u003Cp\u003EDlaczego nale\u017cy je respektowa\u0107? Bo zwracanie si\u0119 do kogo\u015b tak, jak sobie \u017cyczy, jest podstaw\u0105 relacji spo\u0142ecznych. Nie powiesz do Ani \u201cFranku\u201d, nie powiesz \u201cna ty\u201d do osoby, z kt\u00f3r\u0105 jeste\u015b \u201cna pan\u201d, itp. A s\u0105 osoby, kt\u00f3re nie chc\u0105, by im m\u00f3wi\u0107 \u201con\u201d ani \u201cona\u201d. Czy to uszanujesz, \u015bwiadczy wy\u0142\u0105cznie o Tobie.\u003C\/p\u003E\n\u003Cp\u003EWarto wrzuci\u0107 link do swoich zaimk\u00f3w na swoje profile na portalach spo\u0142eczno\u015bciowych \u2013 nawet je\u015bli jeste\u015b cis i u\u017cywasz \u201eon\u201d lub \u201eona\u201d \u2013 poniewa\u017c dzi\u0119ki temu pokazujesz wsparcie dla spo\u0142eczno\u015bci trans i normalizujesz podawanie zaimk\u00f3w przez osoby, kt\u00f3rych zaimki nie s\u0105 oczywiste \u003Ca href=\u0022\/blog\/why-everyone-should-have-pronouns-in-their-bio.lite\u0022\u003E (wi\u0119cej powod\u00f3w tutaj)\u003C\/a\u003E.\u003C\/p\u003E","words":177,"readTime":null,"lang":"pl"},"en":{"slug":"pronouns","title":"Pronouns.page","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360.10899182561\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEuUlEQVRIiY2XyXLjRhKGv8wqrJLIVtty2OOJ6YMPfv93mNPc5iUc0SORrYUEiKWq5gCgBJAQ5YxgBIDKyvxzT0pd10FECCEAICKoKmukqohI5DsnEcF7v\/jN+Ywxq3LnZIEIpt0daXdH0i8lofeoVcQqYhTfOGyREnpHcB4xSvnbl4WwEALe+whuDTTAjx\/P5ElKqhZTpkujAaZr6X2JvclINjn5rxvEKppYggsktxnu1IIIru4wZRoNmQOae+ucJrBJmpBkKWIvI6EAUYwKxe9bwigre7gj+VLQFVDRUv5+T\/7LHbd\/PPB0eF4A2e9\/RIV1XeOci6CedrsF4OA9NrFoatcBLaz0gXZ\/pHup47eqrnl9e4vvLy+vVHVFXQ88zjnqulqcd12PiNC2LcfjkaZpAGiahu\/\/e+RwOFyAAZC6roOMXgqdo3s9DQcIqoK9L1GznuSMPAHwzq1y9P3yuxpFYziH+3Maknp8qbuGo68AIc8znHPoa4+oIECaptSnE1mastlsBpFjZc0rc54\/53l2rYrhLGRFUZBmGdvthqqq8N5jjCKjYOccRnVRvt77q8l8\/n4O8JykruvI4RuHe2tmwubuXacQwnuZcskbQiAEv\/imoiAgRkl\/KhdndhITAH\/q6ffNewyngw+e\/\/vv\/5BkGTebW54f9yDwzz++8dOvv3x6F0CsXABaeKh\/aWi\/VzC5VeTT59f9M653ZEVGVuQYa\/\/2XbXK7Z8\/XwKKHmoc7tAiyML7k4vnNITieiOcMePPckdVESOkX1dCNlEnjld\/JE1TRMB5T1EUuL4DBGMNXdsBA5jtdrsYER9Vz1QQF4BWjFh26hAoioKmaajqGu88p\/rE29TEek+eZ1iboMZcHR1zWlP8Ee9iluV5TpZleO9xveNpt6PtWlSUqqrouo6mafDekWmCXhmgn4G6CigWgAhqBuUAN2UJAbquw3vHqWt4fHzi7fUN8QwJeqbkQ0Ur4VzjjVxTLkwd2SZ2tCpgrcUYgxrDdrul6Tr+2n9n97TD1d0qgM9oWlW89zjn6Pueruvey\/6jJPvIqmu8c29MXpsS+7yzny9tdhIuIpxOJ56fXzgcDyQ24du3fy2YnXNXK+kcwFrSfzY6IiAAay0IPDw8sLm74+lph6pyf\/+Fx8cnQgjYxNI2LWqUPMu5uSmjot1+j4xWex8QEb5+vY\/Kdrs9Tduw3WzI8zyCnHvbzvtIYGiCiU3ijFLVcdkaLqgoaZaOOaU49z6nEpvgvSdNM7x3gCw8kqQJCDjnCRCH9gWgiBSw1pCmSZzs1prY1MqyjAm+RqpKmiYURbG6Uxs1OHX0fReH9sV6UlVVuBbX+eI+V\/x3CuCjUj\/v2nMD7RzMoXP8dagXF6a\/SGH+HMK7hRAbZD\/em95FJBZCP3pcVKOR27LgH0USFzwRWc6yABxPJ9q2o24a7m5KnPf0vYuxttbQ9w4BfAjDChsGsM57GMEnxoAMO7rzfkx0jzUGRLgtC8K4PQ5yBygXa39iLSEMbrzzFtMH0BRUwXsIwqHwbDcbRiTEXj+P\/PnKsbocrWyYx+MxnnY+UE1Vs8gduVg\/5FzY2OVFJD6vKZzIeY8Cd8mQP8YYRIT\/A4gozUxo6rCGAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360.10899182561\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWe all have pronouns. They\u0027re those words that we use instead of calling someone by their name every time we mention them. Most people use \u201che\/him\u201d and \u201cshe\/her\u201d, so we automatically assume which one to call them based on someone\u0027s looks. But it\u0027s actually not that simple\u2026\u003C\/p\u003E\n\u003Cp\u003EGender is complicated. Some people \u201cdon\u0027t look like\u201d their gender. Some prefer being called in a different way from what you\u0027d assume. Some people don\u0027t fit into the boxes of \u201cmale\u201d or \u201cfemale\u201d and prefer more neutral language.\u003C\/p\u003E\n\u003Cp\u003EThis tool lets you share a link to your pronouns, with example sentences, so that you can show people how you like to be called.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720.21798365123\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEuUlEQVRIiY2XyXLjRhKGv8wqrJLIVtty2OOJ6YMPfv93mNPc5iUc0SORrYUEiKWq5gCgBJAQ5YxgBIDKyvxzT0pd10FECCEAICKoKmukqohI5DsnEcF7v\/jN+Ywxq3LnZIEIpt0daXdH0i8lofeoVcQqYhTfOGyREnpHcB4xSvnbl4WwEALe+whuDTTAjx\/P5ElKqhZTpkujAaZr6X2JvclINjn5rxvEKppYggsktxnu1IIIru4wZRoNmQOae+ucJrBJmpBkKWIvI6EAUYwKxe9bwigre7gj+VLQFVDRUv5+T\/7LHbd\/PPB0eF4A2e9\/RIV1XeOci6CedrsF4OA9NrFoatcBLaz0gXZ\/pHup47eqrnl9e4vvLy+vVHVFXQ88zjnqulqcd12PiNC2LcfjkaZpAGiahu\/\/e+RwOFyAAZC6roOMXgqdo3s9DQcIqoK9L1GznuSMPAHwzq1y9P3yuxpFYziH+3Maknp8qbuGo68AIc8znHPoa4+oIECaptSnE1mastlsBpFjZc0rc54\/53l2rYrhLGRFUZBmGdvthqqq8N5jjCKjYOccRnVRvt77q8l8\/n4O8JykruvI4RuHe2tmwubuXacQwnuZcskbQiAEv\/imoiAgRkl\/KhdndhITAH\/q6ffNewyngw+e\/\/vv\/5BkGTebW54f9yDwzz++8dOvv3x6F0CsXABaeKh\/aWi\/VzC5VeTT59f9M653ZEVGVuQYa\/\/2XbXK7Z8\/XwKKHmoc7tAiyML7k4vnNITieiOcMePPckdVESOkX1dCNlEnjld\/JE1TRMB5T1EUuL4DBGMNXdsBA5jtdrsYER9Vz1QQF4BWjFh26hAoioKmaajqGu88p\/rE29TEek+eZ1iboMZcHR1zWlP8Ee9iluV5TpZleO9xveNpt6PtWlSUqqrouo6mafDekWmCXhmgn4G6CigWgAhqBuUAN2UJAbquw3vHqWt4fHzi7fUN8QwJeqbkQ0Ur4VzjjVxTLkwd2SZ2tCpgrcUYgxrDdrul6Tr+2n9n97TD1d0qgM9oWlW89zjn6Pueruvey\/6jJPvIqmu8c29MXpsS+7yzny9tdhIuIpxOJ56fXzgcDyQ24du3fy2YnXNXK+kcwFrSfzY6IiAAay0IPDw8sLm74+lph6pyf\/+Fx8cnQgjYxNI2LWqUPMu5uSmjot1+j4xWex8QEb5+vY\/Kdrs9Tduw3WzI8zyCnHvbzvtIYGiCiU3ijFLVcdkaLqgoaZaOOaU49z6nEpvgvSdNM7x3gCw8kqQJCDjnCRCH9gWgiBSw1pCmSZzs1prY1MqyjAm+RqpKmiYURbG6Uxs1OHX0fReH9sV6UlVVuBbX+eI+V\/x3CuCjUj\/v2nMD7RzMoXP8dagXF6a\/SGH+HMK7hRAbZD\/em95FJBZCP3pcVKOR27LgH0USFzwRWc6yABxPJ9q2o24a7m5KnPf0vYuxttbQ9w4BfAjDChsGsM57GMEnxoAMO7rzfkx0jzUGRLgtC8K4PQ5yBygXa39iLSEMbrzzFtMH0BRUwXsIwqHwbDcbRiTEXj+P\/PnKsbocrWyYx+MxnnY+UE1Vs8gduVg\/5FzY2OVFJD6vKZzIeY8Cd8mQP8YYRIT\/A4gozUxo6rCGAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720.21798365123\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWe all have pronouns. They\u0027re those words that we use instead of calling someone by their name every time we mention them. Most people use \u201che\/him\u201d and \u201cshe\/her\u201d, so we automatically assume which one to call them based on someone\u0027s looks. But it\u0027s actually not that simple\u2026\u003C\/p\u003E\n\u003Cp\u003EGender is complicated. Some people \u201cdon\u0027t look like\u201d their gender. Some prefer being called in a different way from what you\u0027d assume. Some people don\u0027t fit into the boxes of \u201cmale\u201d or \u201cfemale\u201d and prefer more neutral language.\u003C\/p\u003E\n\u003Cp\u003EThis tool lets you share a link to your pronouns, with example sentences, so that you can show people how you like to be called.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["pronouns","gender","javascript","nuxt","vue"],"hasMore":false,"image":"https:\/\/avris.it\/image\/pronouns_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022180.05449591281\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWe all have pronouns. They\u0027re those words that we use instead of calling someone by their name every time we mention them. Most people use \u201che\/him\u201d and \u201cshe\/her\u201d, so we automatically assume which one to call them based on someone\u0027s looks. But it\u0027s actually not that simple\u2026\u003C\/p\u003E\n\u003Cp\u003EGender is complicated. Some people \u201cdon\u0027t look like\u201d their gender. Some prefer being called in a different way from what you\u0027d assume. Some people don\u0027t fit into the boxes of \u201cmale\u201d or \u201cfemale\u201d and prefer more neutral language.\u003C\/p\u003E\n\u003Cp\u003EThis tool lets you share a link to your pronouns, with example sentences, so that you can show people how you like to be called.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022180.05449591281\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWe all have pronouns. They\u0027re those words that we use instead of calling someone by their name every time we mention them. Most people use \u201che\/him\u201d and \u201cshe\/her\u201d, so we automatically assume which one to call them based on someone\u0027s looks. But it\u0027s actually not that simple\u2026\u003C\/p\u003E\n\u003Cp\u003EGender is complicated. Some people \u201cdon\u0027t look like\u201d their gender. Some prefer being called in a different way from what you\u0027d assume. Some people don\u0027t fit into the boxes of \u201cmale\u201d or \u201cfemale\u201d and prefer more neutral language.\u003C\/p\u003E\n\u003Cp\u003EThis tool lets you share a link to your pronouns, with example sentences, so that you can show people how you like to be called.\u003C\/p\u003E","words":112,"readTime":null,"lang":"en"}}}}}